From 563d3973c1ac46ffa146f08f2d8691abd931b4c4 Mon Sep 17 00:00:00 2001 From: Sotr Date: Fri, 3 Aug 2018 02:50:23 +0800 Subject: [PATCH] Base 1.13 implementation --- scripts/build.sh | 4 + scripts/inst.sh | 5 +- sources/pom.xml | 66 +- .../java/co/aikar/timings/TimingHandler.java | 215 --- .../antixray/PacketPlayOutMapChunkInfo.java | 85 - .../java/io/akarin/api/internal/Akari.java | 4 +- .../api/internal/mixin/IMixinChunk.java | 28 - .../internal/mixin/IMixinRealTimeTicking.java | 30 - .../api/internal/mixin/IMixinWorldServer.java | 16 - .../server/core/AkarinGlobalConfig.java | 65 +- .../server/mixin/bootstrap/Bootstrap.java | 2 + .../mixin/bootstrap/ParallelRegistry.java | 139 -- .../server/mixin/core/MixinCommandBan.java | 61 - .../server/mixin/core/MixinCommandBanIp.java | 49 - .../server/mixin/core/MixinCommandKick.java | 44 - .../server/mixin/core/MixinFileIOThread.java | 56 + .../mixin/core/MixinItemMonsterEgg.java | 4 +- .../akarin/server/mixin/core/MixinMCUtil.java | 15 +- .../mixin/core/MixinMinecraftServer.java | 113 +- .../server/mixin/core/MixinTimingHandler.java | 4 +- .../mixin/core/MixinVersionCommand.java | 12 +- .../akarin/server/mixin/core/MixinWorld.java | 36 - .../server/mixin/core/MixinWorldManager.java | 4 +- .../server/mixin/core/MixinWorldServer.java | 9 - .../akarin/server/mixin/cps/MixinChunk.java | 130 -- .../mixin/cps/MixinChunkProviderServer.java | 27 +- .../server/mixin/cps/MixinCraftWorld.java | 4 +- .../server/mixin/lighting/MixinChunk.java | 671 ------- .../lighting/MixinChunkProviderServer.java | 51 - .../server/mixin/lighting/MixinWorld.java | 45 - .../mixin/lighting/MixinWorldServer.java | 375 ---- .../nsc/NonblockingServerConnection.java | 25 +- .../mixin/nsc/OptimisticNetworkManager.java | 62 - .../mixin/optimization/MixinEntity.java | 4 +- .../MixinEntityHorseAbstract.java | 14 +- .../MixinEntityTameableAnimal.java | 18 +- .../MixinPersistentCollection.java | 5 +- .../MixinTileEntityEnchantTable.java | 2 +- .../mixin/optimization/PandaRedstoneWire.java | 508 ----- .../mixin/optimization/WeakBigTree.java | 26 - .../optimization/WeakEnchantmentManager.java | 95 - .../server/mixin/realtime/MixinEntity.java | 56 - .../mixin/realtime/MixinEntityAgeable.java | 51 - .../realtime/MixinEntityExperienceOrb.java | 55 - .../mixin/realtime/MixinEntityHuman.java | 61 - .../mixin/realtime/MixinEntityInsentient.java | 50 - .../mixin/realtime/MixinEntityItem.java | 55 - .../mixin/realtime/MixinEntityPlayer.java | 51 - .../realtime/MixinEntityZombieVillager.java | 47 - .../mixin/realtime/MixinMinecraftServer.java | 30 - .../mixin/realtime/MixinPlayerConnection.java | 58 - .../realtime/MixinPlayerInteractManager.java | 49 - .../realtime/MixinTileEntityBrewingStand.java | 48 - .../realtime/MixinTileEntityFurnace.java | 64 - .../server/mixin/realtime/MixinWorld.java | 46 - .../mixin/realtime/MixinWorldServer.java | 61 - .../main/java/net/minecraft/server/Chunk.java | 1550 --------------- .../minecraft/server/EnchantmentManager.java | 432 ----- .../java/net/minecraft/server/Entity.java | 1669 ++++++++++------- .../net/minecraft/server/EntityPlayer.java | 723 +++---- .../net/minecraft/server/EntityTracker.java | 90 +- .../minecraft/server/EntityTrackerEntry.java | 658 ------- .../net/minecraft/server/EnumDirection.java | 317 ---- .../net/minecraft/server/FileIOThread.java | 82 + .../net/minecraft/server/ItemEnderEye.java | 44 +- .../net/minecraft/server/MinecraftServer.java | 1106 ++++++----- .../net/minecraft/server/NetworkManager.java | 224 +-- .../server/PacketPlayOutMapChunk.java | 76 +- .../net/minecraft/server/PlayerChunk.java | 314 ---- .../net/minecraft/server/PlayerChunkMap.java | 573 ++++++ .../minecraft/server/PlayerConnection.java | 1424 +++++++------- .../java/net/minecraft/server/PlayerList.java | 1541 --------------- .../net/minecraft/server/RegionFileCache.java | 127 -- .../java/net/minecraft/server/RegistryID.java | 161 -- .../net/minecraft/server/TileEntitySkull.java | 116 +- .../java/net/minecraft/server/WorldData.java | 821 ++++---- .../net/minecraft/server/WorldServer.java | 880 ++++----- .../org/bukkit/craftbukkit/CraftServer.java | 234 ++- .../craftbukkit/entity/CraftPlayer.java | 252 +-- .../main/resources/configurations/bukkit.yml | 2 +- .../main/resources/mixins.akarin.core.json | 9 +- .../mixins.akarin.optimization.lighting.json | 15 - .../mixins.akarin.optimization.pandawire.json | 10 - .../mixins.akarin.optimization.realtime.json | 24 - work/Paper | 2 +- 85 files changed, 4751 insertions(+), 12635 deletions(-) delete mode 100644 sources/src/main/java/co/aikar/timings/TimingHandler.java delete mode 100644 sources/src/main/java/com/destroystokyo/paper/antixray/PacketPlayOutMapChunkInfo.java delete mode 100644 sources/src/main/java/io/akarin/api/internal/mixin/IMixinChunk.java delete mode 100644 sources/src/main/java/io/akarin/api/internal/mixin/IMixinRealTimeTicking.java delete mode 100644 sources/src/main/java/io/akarin/api/internal/mixin/IMixinWorldServer.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/bootstrap/ParallelRegistry.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBan.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBanIp.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/core/MixinCommandKick.java create mode 100644 sources/src/main/java/io/akarin/server/mixin/core/MixinFileIOThread.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/core/MixinWorld.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/cps/MixinChunk.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunkProviderServer.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorld.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java delete 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/PandaRedstoneWire.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/optimization/WeakBigTree.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/optimization/WeakEnchantmentManager.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntity.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityAgeable.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityExperienceOrb.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityHuman.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityInsentient.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityItem.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityPlayer.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityZombieVillager.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinMinecraftServer.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerConnection.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerInteractManager.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityBrewingStand.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityFurnace.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorld.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorldServer.java delete mode 100644 sources/src/main/java/net/minecraft/server/Chunk.java delete mode 100644 sources/src/main/java/net/minecraft/server/EnchantmentManager.java delete mode 100644 sources/src/main/java/net/minecraft/server/EntityTrackerEntry.java delete mode 100644 sources/src/main/java/net/minecraft/server/EnumDirection.java create mode 100644 sources/src/main/java/net/minecraft/server/FileIOThread.java delete mode 100644 sources/src/main/java/net/minecraft/server/PlayerChunk.java create mode 100644 sources/src/main/java/net/minecraft/server/PlayerChunkMap.java delete mode 100644 sources/src/main/java/net/minecraft/server/PlayerList.java delete mode 100644 sources/src/main/java/net/minecraft/server/RegionFileCache.java delete mode 100644 sources/src/main/java/net/minecraft/server/RegistryID.java delete mode 100644 sources/src/main/resources/mixins.akarin.optimization.lighting.json delete mode 100644 sources/src/main/resources/mixins.akarin.optimization.pandawire.json delete mode 100644 sources/src/main/resources/mixins.akarin.optimization.realtime.json diff --git a/scripts/build.sh b/scripts/build.sh index 34710c4a7..37af8390e 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -4,6 +4,7 @@ set -e basedir="$(cd "$1" && pwd -P)" workdir="$basedir/work" +version="ver/1.13" paperbasedir="$basedir/work/Paper" paperworkdir="$basedir/work/Paper/work" @@ -16,6 +17,7 @@ if [ "$2" == "--setup" ] || [ "$3" == "--setup" ] || [ "$4" == "--setup" ]; then rm Minecraft/ -r fi git clone https://github.com/Akarin-project/Minecraft.git + cd "Minecraft" && git checkout "$version" fi cd "$paperbasedir" @@ -25,6 +27,8 @@ fi echo "[Akarin] Ready to build" ( + cd "$paperworkdir/BuildData" && git checkout "$version" + cd "$paperbasedir" echo "[Akarin] Touch sources.." cd "$paperbasedir" diff --git a/scripts/inst.sh b/scripts/inst.sh index c333d9516..79f9bda20 100755 --- a/scripts/inst.sh +++ b/scripts/inst.sh @@ -2,9 +2,10 @@ ( set -e -basedir="$pwd" +basedir="$(pwd -P)" +version="pre/1.13" -(git submodule update --init --remote && chmod +x scripts/build.sh && ./scripts/build.sh "$basedir" "$1" "$2" "$3") || ( +(git submodule update --init --remote && cd "work/Paper" && git checkout "$version" && cd "$basedir" && chmod +x scripts/build.sh && ./scripts/build.sh "$basedir" "$1" "$2" "$3") || ( echo "Failed to build Akarin" exit 1 ) || exit 1 diff --git a/sources/pom.xml b/sources/pom.xml index 1b2a35df1..94a15ae9e 100644 --- a/sources/pom.xml +++ b/sources/pom.xml @@ -3,22 +3,22 @@ 4.0.0 akarin jar - 1.12.2-R0.4-RELEASE + 1.13-R0.1-SNAPSHOT Akarin https://github.com/Akarin-project/Akarin UTF-8 - 1.12.2-R0.1-SNAPSHOT - 1.12.2 - 1_12_R1 + 1.13-R0.1-SNAPSHOT + 1.13 + 1_13_R1 git-Bukkit- yyyyMMdd-HHmm 1.8 1.8 - + com.destroystokyo.paper paper-parent @@ -26,13 +26,6 @@ - - - io.netty - netty-all - 4.1.24.Final - compile - com.destroystokyo.paper paper-api @@ -46,21 +39,27 @@ provided - net.sf.jopt-simple - jopt-simple - 5.0.4 + org.spigotmc + minecraft-server + ${minecraft.version}-SNAPSHOT + compile + + + org.ow2.asm + asm + 6.2 compile org.xerial sqlite-jdbc - 3.21.0.1 + 3.23.1 runtime mysql mysql-connector-java - 5.1.45 + 5.1.46 runtime @@ -107,7 +106,7 @@ log4j-iostreams 2.8.1 - + com.lmax @@ -129,12 +128,12 @@ 1.3 test - + io.akarin legacylauncher - 1.25 + 2.0 org.spongepowered @@ -190,7 +189,7 @@ 1.3 git-Akarin- - ../.. + ../.. @@ -243,7 +242,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.1.0 + 3.1.1 package @@ -287,15 +286,15 @@ - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + @@ -315,8 +314,7 @@ org.apache.maven.plugins maven-surefire-plugin - - 2.20 + 2.12.4 ${basedir}/target/test-server @@ -340,7 +338,7 @@ org.codehaus.mojo animal-sniffer-maven-plugin - 1.16 + 1.17 process-classes diff --git a/sources/src/main/java/co/aikar/timings/TimingHandler.java b/sources/src/main/java/co/aikar/timings/TimingHandler.java deleted file mode 100644 index 72950f91d..000000000 --- a/sources/src/main/java/co/aikar/timings/TimingHandler.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * This file is licensed under the MIT License (MIT). - * - * Copyright (c) 2014 Daniel Ennis - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package co.aikar.timings; - -import co.aikar.util.LoadingIntMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import org.bukkit.Bukkit; - -import java.util.logging.Level; - -/** - * Akarin Changes Note - * 1) Add volatile to fields (safety issue) - */ -class TimingHandler implements Timing { - - private static int idPool = 1; - final int id = idPool++; - - final String name; - private final boolean verbose; - - private final Int2ObjectOpenHashMap children = new LoadingIntMap<>(TimingData::new); - - final TimingData record; - private final TimingHandler groupHandler; - - private volatile long start = 0; // Akarin - volatile - private volatile int timingDepth = 0; // Akarin - volatile - private boolean added; - private boolean timed; - private boolean enabled; - private TimingHandler parent; - - TimingHandler(TimingIdentifier id) { - if (id.name.startsWith("##")) { - verbose = true; - this.name = id.name.substring(3); - } else { - this.name = id.name; - verbose = false; - } - - this.record = new TimingData(this.id); - this.groupHandler = id.groupHandler; - - TimingIdentifier.getGroup(id.group).handlers.add(this); - checkEnabled(); - } - - final void checkEnabled() { - enabled = Timings.timingsEnabled && (!verbose || Timings.verboseEnabled); - } - - void processTick(boolean violated) { - if (timingDepth != 0 || record.getCurTickCount() == 0) { - timingDepth = 0; - start = 0; - return; - } - - record.processTick(violated); - for (TimingData handler : children.values()) { - handler.processTick(violated); - } - } - - @Override - public Timing startTimingIfSync() { - if (Bukkit.isPrimaryThread()) { - startTiming(); - } - return this; - } - - @Override - public void stopTimingIfSync() { - if (Bukkit.isPrimaryThread()) { - stopTiming(); - } - } - - @Override - public Timing startTiming() { - if (enabled && ++timingDepth == 1) { - start = System.nanoTime(); - parent = TimingsManager.CURRENT; - TimingsManager.CURRENT = this; - } - return this; - } - - @Override - public void stopTiming() { - if (enabled && --timingDepth == 0 && start != 0) { - if (!Bukkit.isPrimaryThread()) { - Bukkit.getLogger().log(Level.SEVERE, "stopTiming called async for " + name); - new Throwable().printStackTrace(); - start = 0; - return; - } - addDiff(System.nanoTime() - start); - start = 0; - } - } - - @Override - public void abort() { - if (enabled && timingDepth > 0) { - start = 0; - } - } - - void addDiff(long diff) { - if (TimingsManager.CURRENT == this) { - TimingsManager.CURRENT = parent; - if (parent != null) { - parent.children.get(id).add(diff); - } - } - record.add(diff); - if (!added) { - added = true; - timed = true; - TimingsManager.HANDLERS.add(this); - } - if (groupHandler != null) { - groupHandler.addDiff(diff); - groupHandler.children.get(id).add(diff); - } - } - - /** - * Reset this timer, setting all values to zero. - * - * @param full - */ - void reset(boolean full) { - record.reset(); - if (full) { - timed = false; - } - start = 0; - timingDepth = 0; - added = false; - children.clear(); - checkEnabled(); - } - - @Override - public TimingHandler getTimingHandler() { - return this; - } - - @Override - public boolean equals(Object o) { - return (this == o); - } - - @Override - public int hashCode() { - return id; - } - - /** - * This is simply for the Closeable interface so it can be used with - * try-with-resources () - */ - @Override - public void close() { - stopTimingIfSync(); - } - - public boolean isSpecial() { - return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK; - } - - boolean isTimed() { - return timed; - } - - public boolean isEnabled() { - return enabled; - } - - TimingData[] cloneChildren() { - final TimingData[] clonedChildren = new TimingData[children.size()]; - int i = 0; - for (TimingData child : children.values()) { - clonedChildren[i++] = child.clone(); - } - return clonedChildren; - } -} diff --git a/sources/src/main/java/com/destroystokyo/paper/antixray/PacketPlayOutMapChunkInfo.java b/sources/src/main/java/com/destroystokyo/paper/antixray/PacketPlayOutMapChunkInfo.java deleted file mode 100644 index d8519224a..000000000 --- a/sources/src/main/java/com/destroystokyo/paper/antixray/PacketPlayOutMapChunkInfo.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.destroystokyo.paper.antixray; - -import io.netty.buffer.ByteBuf; -import net.minecraft.server.Chunk; -import net.minecraft.server.DataPalette; -import net.minecraft.server.IBlockData; -import net.minecraft.server.PacketPlayOutMapChunk; - -/** - * Akarin Changes Note - * 1) byte[] -> ByteBuf (compatibility) - */ -public class PacketPlayOutMapChunkInfo { - - private final PacketPlayOutMapChunk packetPlayOutMapChunk; - private final Chunk chunk; - private final int chunkSectionSelector; - private ByteBuf data; // Akarin - byte[] -> ByteBuf - private final int[] bitsPerValue = new int[16]; - private final DataPalette[] dataPalettes = new DataPalette[16]; - private final int[] dataBitsIndexes = new int[16]; - private final IBlockData[][] predefinedBlockData = new IBlockData[16][]; - - public PacketPlayOutMapChunkInfo(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 byte[] getData() { - return data.array(); // Akarin - } - - public void setData(ByteBuf data) { // Akarin - byte[] -> ByteBuf - this.data = data; - } - - public int getBitsPerValue(int chunkSectionIndex) { - return bitsPerValue[chunkSectionIndex]; - } - - public void setBitsPerValue(int chunkSectionIndex, int bitsPerValue) { - this.bitsPerValue[chunkSectionIndex] = bitsPerValue; - } - - public DataPalette getDataPalette(int chunkSectionIndex) { - return 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; - } - - public IBlockData[] getPredefinedBlockData(int chunkSectionIndex) { - return predefinedBlockData[chunkSectionIndex]; - } - - public void setPredefinedBlockData(int chunkSectionIndex, IBlockData[] predefinedBlockData) { - this.predefinedBlockData[chunkSectionIndex] = predefinedBlockData; - } - - public boolean isWritten(int chunkSectionIndex) { - return bitsPerValue[chunkSectionIndex] != 0; - } -} diff --git a/sources/src/main/java/io/akarin/api/internal/Akari.java b/sources/src/main/java/io/akarin/api/internal/Akari.java index 9095df37c..4566c4b48 100644 --- a/sources/src/main/java/io/akarin/api/internal/Akari.java +++ b/sources/src/main/java/io/akarin/api/internal/Akari.java @@ -96,9 +96,9 @@ public abstract class Akari { */ public final static Timing worldTiming = getTiming("Akarin - Full World Tick"); - public final static Timing entityCallbackTiming = getTiming("Akarin - Entity Callback"); + public final static Timing entityCallbackTiming = getTiming("Akarin - Entity Parallell Await"); - public final static Timing callbackTiming = getTiming("Akarin - Callback"); + public final static Timing callbackTiming = getTiming("Akarin - Callback Queue"); private static Timing getTiming(String name) { try { diff --git a/sources/src/main/java/io/akarin/api/internal/mixin/IMixinChunk.java b/sources/src/main/java/io/akarin/api/internal/mixin/IMixinChunk.java deleted file mode 100644 index 7dd2723b1..000000000 --- a/sources/src/main/java/io/akarin/api/internal/mixin/IMixinChunk.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.akarin.api.internal.mixin; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.Nullable; - -import net.minecraft.server.Chunk; -import net.minecraft.server.EnumSkyBlock; - -public interface IMixinChunk { - AtomicInteger getPendingLightUpdates(); - - long getLightUpdateTime(); - - boolean areNeighborsLoaded(); - - @Nullable Chunk getNeighborChunk(int index); - - CopyOnWriteArrayList getQueuedLightingUpdates(EnumSkyBlock type); - - List getNeighbors(); - - void setNeighborChunk(int index, @Nullable Chunk chunk); - - void setLightUpdateTime(long time); -} \ No newline at end of file diff --git a/sources/src/main/java/io/akarin/api/internal/mixin/IMixinRealTimeTicking.java b/sources/src/main/java/io/akarin/api/internal/mixin/IMixinRealTimeTicking.java deleted file mode 100644 index 24fcdd905..000000000 --- a/sources/src/main/java/io/akarin/api/internal/mixin/IMixinRealTimeTicking.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.api.internal.mixin; - -public interface IMixinRealTimeTicking { - - long getRealTimeTicks(); -} \ No newline at end of file diff --git a/sources/src/main/java/io/akarin/api/internal/mixin/IMixinWorldServer.java b/sources/src/main/java/io/akarin/api/internal/mixin/IMixinWorldServer.java deleted file mode 100644 index 03f5ad0ae..000000000 --- a/sources/src/main/java/io/akarin/api/internal/mixin/IMixinWorldServer.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.akarin.api.internal.mixin; - -import java.util.List; -import java.util.concurrent.ExecutorService; - -import net.minecraft.server.BlockPosition; -import net.minecraft.server.Chunk; -import net.minecraft.server.EnumSkyBlock; - -public interface IMixinWorldServer { - boolean updateLightAsync(EnumSkyBlock lightType, BlockPosition pos, Chunk chunk); - - boolean checkLightAsync(EnumSkyBlock lightType, BlockPosition pos, Chunk currentChunk, List neighbors); - - ExecutorService getLightingExecutor(); -} \ No newline at end of file diff --git a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java index 97d4e2e43..b3187a0fe 100644 --- a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java +++ b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java @@ -185,16 +185,6 @@ public class AkarinGlobalConfig { keepAliveTimeout = getSeconds(getString("core.keep-alive-response-timeout", "30s")) * 1000; } - public static int asyncLightingThreads; - private static void asyncLightingThreads() { - asyncLightingThreads = getInt("core.async-lighting.executor-threads", 4); - } - - public static boolean asyncLightingWorkStealing; - private static void asyncLightingWorkStealing() { - asyncLightingWorkStealing = getBoolean("core.async-lighting.use-work-stealing", false); - } - public static boolean throwOnAsyncCaught; private static void throwOnAsyncCaught() { throwOnAsyncCaught = getBoolean("core.thread-safe.async-catcher.throw-on-caught", true); @@ -210,56 +200,6 @@ public class AkarinGlobalConfig { noResponseDoGC = getBoolean("alternative.gc-before-stuck-restart", true); } - public static String messageKick; - private static void messageKick() { - messageKick = getString("messages.disconnect.kick-player", "Kicked by an operator."); - } - - public static String messageBan; - private static void messageBan() { - messageBan = getString("messages.disconnect.ban-player-name", "You are banned from this server! %s %s"); - } - - public static String messageBanReason; - private static void messageBanReason() { - messageBanReason = getString("messages.disconnect.ban-reason", "\nReason: "); - } - - public static String messageBanExpires; - private static void messageBanExpires() { - messageBanExpires = getString("messages.disconnect.ban-expires", "\nYour ban will be removed on "); - } - - public static String messageBanIp; - private static void messageBanIp() { - messageBanIp = getString("messages.disconnect.ban-player-ip", "Your IP address is banned from this server! %s %s"); - } - - public static String messageDupLogin; - private static void messageDupLogin() { - messageDupLogin = getString("messages.disconnect.kick-player-duplicate-login", "You logged in from another location"); - } - - public static String messageJoin; - private static void messageJoin() { - messageJoin = getString("messages.connect.player-join-server", "§e%s joined the game"); - } - - public static String messageJoinRenamed; - private static void messageJoinRenamed() { - messageJoinRenamed = getString("messages.connect.renamed-player-join-server", "§e%s (formerly known as %s) joined the game"); - } - - public static String messageKickKeepAlive; - private static void messagekickKeepAlive() { - messageKickKeepAlive = getString("messages.disconnect.kick-player-timeout-keep-alive", "Timed out"); - } - - public static String messagePlayerQuit; - private static void messagePlayerQuit() { - messagePlayerQuit = getString("messages.disconnect.player-quit-server", "§e%s left the game"); - } - public static String serverBrandName; private static void serverBrandName() { serverBrandName = getString("alternative.modified-server-brand-name", ""); @@ -294,4 +234,9 @@ public class AkarinGlobalConfig { private static void forceHardcoreDifficulty() { forceHardcoreDifficulty = getBoolean("alternative.force-difficulty-on-hardcore", true); } + + public static int fileIOThreads; + private static void fileIOThreads() { + fileIOThreads = getInt("core.chunk-save-threads", 2); + } } diff --git a/sources/src/main/java/io/akarin/server/mixin/bootstrap/Bootstrap.java b/sources/src/main/java/io/akarin/server/mixin/bootstrap/Bootstrap.java index 24751302f..fc43841ff 100644 --- a/sources/src/main/java/io/akarin/server/mixin/bootstrap/Bootstrap.java +++ b/sources/src/main/java/io/akarin/server/mixin/bootstrap/Bootstrap.java @@ -41,6 +41,7 @@ public abstract class Bootstrap { Akari.logger.warn("Visit our website for latest information https://akarin.io/"); } + /* @Redirect(method = "main", at = @At( value = "INVOKE_STRING", target = "Ljava/io/PrintStream;println(Ljava/lang/String;)V", @@ -49,4 +50,5 @@ public abstract class Bootstrap { private static void notifyLoading(PrintStream stream, String text) { Akari.logger.info("Loading libraries as parallel capable.."); } + */ } diff --git a/sources/src/main/java/io/akarin/server/mixin/bootstrap/ParallelRegistry.java b/sources/src/main/java/io/akarin/server/mixin/bootstrap/ParallelRegistry.java deleted file mode 100644 index 8a899b9c1..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/bootstrap/ParallelRegistry.java +++ /dev/null @@ -1,139 +0,0 @@ -package io.akarin.server.mixin.bootstrap; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import io.akarin.api.internal.Akari; -import net.minecraft.server.BiomeBase; -import net.minecraft.server.Block; -import net.minecraft.server.BlockFire; -import net.minecraft.server.DispenserRegistry; -import net.minecraft.server.Enchantment; -import net.minecraft.server.EntityTypes; -import net.minecraft.server.Item; -import net.minecraft.server.MobEffectList; -import net.minecraft.server.PotionBrewer; -import net.minecraft.server.PotionRegistry; -import net.minecraft.server.SoundEffect; - -@Mixin(value = DispenserRegistry.class, remap = false) -public abstract class ParallelRegistry { - /** - * Registry order: SoundEffect -> Block - */ - private static final ExecutorService STAGE_BLOCK = Executors.newSingleThreadExecutor(Akari.STAGE_FACTORY); - /** - * Registry order: Item -> PotionBrewer & orderless: BlockFire, BiomeBase (After STAGE_BLOCK) - */ - private static final ExecutorService STAGE_BLOCK_BASE = Executors.newFixedThreadPool(3, Akari.STAGE_FACTORY); - - /** - * Registry order: MobEffectList -> PotionRegistry & orderless: Enchantment, EntityTypes - */ - private static final ExecutorService STAGE_STANDALONE = Executors.newFixedThreadPool(3, Akari.STAGE_FACTORY); - - // We should keep the original order in codes thought orderless in runtime - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/SoundEffect.b()V" - )) - private static void soundEffect() { - STAGE_BLOCK.execute(() -> { - SoundEffect.b(); - Block.w(); - - STAGE_BLOCK_BASE.execute(() -> BlockFire.e()); // This single task only cost ~4ms, however, firing a task only takes ~1ms - STAGE_BLOCK_BASE.execute(() -> { - Item.t(); - PotionBrewer.a(); - }); - STAGE_BLOCK_BASE.execute(() -> BiomeBase.q()); - }); - } - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/Block.w()V" - )) - private static void block() {} // STAGE_BLOCK - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/BlockFire.e()V" - )) - private static void blockFire() {} // STAGE_BLOCK_BASE - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/MobEffectList.k()V" - )) - private static void mobEffectList() {} // STAGE_STANDALONE - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/Enchantment.g()V" - )) - private static void enchantment() { - STAGE_STANDALONE.execute(() -> Enchantment.g()); - STAGE_STANDALONE.execute(() -> EntityTypes.c()); - STAGE_STANDALONE.execute(() -> { - MobEffectList.k(); - PotionRegistry.b(); - }); - } - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/Item.t()V" - )) - private static void item() {} // STAGE_BLOCK_BASE - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/PotionRegistry.b()V" - )) - private static void potionRegistry() {} // STAGE_STANDALONE - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/PotionBrewer.a()V" - )) - private static void potionBrewer() {} // STAGE_BLOCK_BASE - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/EntityTypes.c()V" - )) - private static void entityTypes() {} // STAGE_STANDALONE - - @Redirect(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/BiomeBase.q()V" - )) - private static void biomeBase() {} // STAGE_BLOCK_BASE - - @Inject(method = "c()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/DispenserRegistry.b()V", - shift = At.Shift.BEFORE - )) - private static void await(CallbackInfo info) throws InterruptedException { - // Shutdown BLOCK and STANDALONE stage - STAGE_STANDALONE.shutdown(); - STAGE_BLOCK.shutdown(); - STAGE_BLOCK.awaitTermination(10, TimeUnit.MINUTES); - - STAGE_BLOCK_BASE.shutdown(); // This must after STAGE_BLOCK terminated - STAGE_BLOCK_BASE.awaitTermination(20, TimeUnit.MINUTES); - - STAGE_STANDALONE.awaitTermination(30, TimeUnit.MINUTES); // Behind the shutdown of BLOCK_BASE should faster - } - -} diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBan.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBan.java deleted file mode 100644 index a6fdb0684..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBan.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.akarin.server.mixin.core; - -import java.util.Date; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import com.mojang.authlib.GameProfile; - -import io.akarin.api.internal.Akari; -import io.akarin.server.core.AkarinGlobalConfig; -import net.minecraft.server.CommandAbstract; -import net.minecraft.server.CommandBan; -import net.minecraft.server.CommandException; -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.ExceptionUsage; -import net.minecraft.server.GameProfileBanEntry; -import net.minecraft.server.ICommand; -import net.minecraft.server.ICommandListener; -import net.minecraft.server.MinecraftServer; - -@Mixin(value = CommandBan.class, remap = false) -public abstract class MixinCommandBan { - @Overwrite - public void execute(MinecraftServer server, ICommandListener sender, String[] args) throws CommandException { - if (args.length >= 1 && args[0].length() > 1) { - GameProfile profile = server.getUserCache().getProfile(args[0]); - - if (profile == null) { - throw new CommandException("commands.ban.failed", new Object[] {args[0]}); - } else { - // Akarin start - use string - boolean hasReason = true; // Akarin - String message = null; - if (args.length >= 2) { - message = ""; - for (int i = 2; i < args.length; i++) { - message = message + args[i]; - } - } else { - hasReason = false; // Akarin - message = Akari.EMPTY_STRING; // Akarin - modify message - } - // Akarin end - - GameProfileBanEntry entry = new GameProfileBanEntry(profile, (Date) null, sender.getName(), (Date) null, message); - - server.getPlayerList().getProfileBans().add(entry); - EntityPlayer entityplayer = server.getPlayerList().getPlayer(args[0]); - - if (entityplayer != null) { - entityplayer.playerConnection.disconnect(hasReason ? message : AkarinGlobalConfig.messageBan); - } - - CommandAbstract.a(sender, (ICommand) this, "commands.ban.success", args[0]); // OBFHELPER: notifyCommandListener - } - } else { - throw new ExceptionUsage("commands.ban.usage"); - } - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBanIp.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBanIp.java deleted file mode 100644 index 58634d80c..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandBanIp.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.akarin.server.mixin.core; - -import java.util.Date; -import java.util.List; -import javax.annotation.Nullable; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import io.akarin.api.internal.Akari; -import io.akarin.server.core.AkarinGlobalConfig; -import net.minecraft.server.CommandAbstract; -import net.minecraft.server.CommandBanIp; -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.ICommand; -import net.minecraft.server.ICommandListener; -import net.minecraft.server.IpBanEntry; -import net.minecraft.server.MinecraftServer; - -@Mixin(value = CommandBanIp.class, remap = false) -public abstract class MixinCommandBanIp { - @Overwrite // OBFHELPER: banIp - protected void a(MinecraftServer server, ICommandListener sender, String args, @Nullable String banReason) { - // Akarin start - modify message - boolean hasReason = true; - if (banReason == null) { - banReason = Akari.EMPTY_STRING; - hasReason = false; - } - // Akarin end - IpBanEntry ipbanentry = new IpBanEntry(args, (Date) null, sender.getName(), (Date) null, banReason); - - server.getPlayerList().getIPBans().add(ipbanentry); - List withIpPlayers = server.getPlayerList().b(args); // OBFHELPER: getPlayersMatchingAddress - String[] banPlayerNames = new String[withIpPlayers.size()]; - - for (int i = 0; i < banPlayerNames.length; i++) { - EntityPlayer each = withIpPlayers.get(i); - banPlayerNames[i] = each.getName(); - each.playerConnection.disconnect(hasReason ? banReason : AkarinGlobalConfig.messageBanIp); // Akarin - } - - if (withIpPlayers.isEmpty()) { - CommandAbstract.a(sender, (ICommand) this, "commands.banip.success", args); // OBFHELPER: notifyCommandListener - } else { - CommandAbstract.a(sender, (ICommand) this, "commands.banip.success.players", args, CommandAbstract.a(banPlayerNames)); // OBFHELPER: notifyCommandListener - joinNiceString - } - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandKick.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandKick.java deleted file mode 100644 index 1bfe2534a..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinCommandKick.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.akarin.server.mixin.core; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import io.akarin.server.core.AkarinGlobalConfig; -import net.minecraft.server.CommandAbstract; -import net.minecraft.server.CommandException; -import net.minecraft.server.CommandKick; -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.ExceptionPlayerNotFound; -import net.minecraft.server.ExceptionUsage; -import net.minecraft.server.ICommand; -import net.minecraft.server.ICommandListener; -import net.minecraft.server.MinecraftServer; - -@Mixin(value = CommandKick.class, remap = false) -public abstract class MixinCommandKick { - @Overwrite - public void execute(MinecraftServer server, ICommandListener sender, String[] args) throws CommandException { - if (args.length > 0 && args[0].length() > 1) { - EntityPlayer target = server.getPlayerList().getPlayer(args[0]); - - if (target == null) { - throw new ExceptionPlayerNotFound("commands.generic.player.notFound", args[0]); - } else { - if (args.length >= 2) { - // Akarin start - use string - String message = ""; - for (int i = 2; i < args.length; i++) { - message = message + args[i]; - } - target.playerConnection.disconnect(message); - CommandAbstract.a(sender, (ICommand) this, "commands.kick.success.reason", target.getName(), message); // OBFHELPER: notifyCommandListener - // Akarin end - } else { - target.playerConnection.disconnect(AkarinGlobalConfig.messageKick); // Akarin - CommandAbstract.a(sender, (ICommand) this, "commands.kick.success", target.getName()); // OBFHELPER: notifyCommandListener - } - } - } else { - throw new ExceptionUsage("commands.kick.usage"); - } - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinFileIOThread.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinFileIOThread.java new file mode 100644 index 000000000..242fe7ec5 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinFileIOThread.java @@ -0,0 +1,56 @@ +package io.akarin.server.mixin.core; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import com.destroystokyo.paper.PaperConfig; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import io.akarin.server.core.AkarinGlobalConfig; +import net.minecraft.server.FileIOThread; +import net.minecraft.server.IAsyncChunkSaver; + +@Mixin(value = FileIOThread.class, remap = false) +public abstract class MixinFileIOThread { + private final Executor executor = Executors.newFixedThreadPool(AkarinGlobalConfig.fileIOThreads, new ThreadFactoryBuilder().setNameFormat("Akarin File IO Thread - %1$d").setPriority(1).build()); + private final AtomicInteger queuedChunkCounter = new AtomicInteger(0); + + @Shadow(aliases = "f") private volatile boolean isAwaitFinish; + + @Overwrite // OBFHELPER: saveChunk + public void a(IAsyncChunkSaver iasyncchunksaver) { + queuedChunkCounter.incrementAndGet(); + executor.execute(() -> writeChunk(iasyncchunksaver)); + } + + /** + * Process a chunk, re-add to the queue if unsuccessful + */ + private void writeChunk(IAsyncChunkSaver iasyncchunksaver) { + if (!iasyncchunksaver.a()) { // PAIL: WriteNextIO() -> Returns if the write was unsuccessful + queuedChunkCounter.decrementAndGet(); + + if (PaperConfig.enableFileIOThreadSleep) { + try { + Thread.sleep(isAwaitFinish ? 0L : 2L); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } else { + writeChunk(iasyncchunksaver); + } + } + + @Overwrite // OBFHELPER: waitForFinish + public void b() throws InterruptedException { + isAwaitFinish = true; + while (queuedChunkCounter.get() != 0) Thread.sleep(9L); + isAwaitFinish = false; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinItemMonsterEgg.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinItemMonsterEgg.java index 23c182188..1a1287d88 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinItemMonsterEgg.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinItemMonsterEgg.java @@ -14,10 +14,10 @@ import net.minecraft.server.ItemMonsterEgg; public abstract class MixinItemMonsterEgg { @Redirect(method = "a*", at = @At( value = "FIELD", - target = "net/minecraft/server/Blocks.MOB_SPAWNER:Lnet/minecraft/server/Block;", + target = "net/minecraft/server/Blocks.SPAWNER:Lnet/minecraft/server/Block;", opcode = Opcodes.GETSTATIC )) private boolean configurable(Block target) { - return target == Blocks.MOB_SPAWNER && AkarinGlobalConfig.allowSpawnerModify; + return target == Blocks.SPAWNER && AkarinGlobalConfig.allowSpawnerModify; } } diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinMCUtil.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinMCUtil.java index 1e04036dc..b97c81fb9 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinMCUtil.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinMCUtil.java @@ -14,9 +14,21 @@ import net.minecraft.server.MinecraftServer; @Mixin(value = MCUtil.class, remap = false) public abstract class MixinMCUtil { + @Overwrite + public static void ensureMain(String reason, Runnable run) { + if (AsyncCatcher.enabled && !Akari.isPrimaryThread()) { // Akarin + if (reason != null) { + new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); + } + MinecraftServer.getServer().processQueue.add(run); + return; + } + run.run(); + } + @Overwrite public static T ensureMain(String reason, Supplier run) { - if (AsyncCatcher.enabled && !Akari.isPrimaryThread()) { + if (AsyncCatcher.enabled && !Akari.isPrimaryThread()) { // Akarin new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); Waitable wait = new Waitable() { @Override @@ -32,7 +44,6 @@ public abstract class MixinMCUtil { } return null; } - return run.get(); } } 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 f25ef3a8d..60e0298e2 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 @@ -2,15 +2,10 @@ package io.akarin.server.mixin.core; import java.util.List; import java.util.Queue; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; -import org.bukkit.World; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor; -import org.bukkit.event.inventory.InventoryMoveItemEvent; -import org.bukkit.event.world.WorldLoadEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -22,21 +17,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import co.aikar.timings.MinecraftTimings; import io.akarin.api.internal.Akari; -import io.akarin.api.internal.Akari.AssignableFactory; import io.akarin.api.internal.mixin.IMixinLockProvider; import io.akarin.server.core.AkarinGlobalConfig; import io.akarin.server.core.AkarinSlackScheduler; -import net.minecraft.server.BlockPosition; import net.minecraft.server.CrashReport; import net.minecraft.server.CustomFunctionData; import net.minecraft.server.ITickable; import net.minecraft.server.MinecraftServer; import net.minecraft.server.MojangStatisticsGenerator; -import net.minecraft.server.PlayerList; import net.minecraft.server.ReportedException; import net.minecraft.server.ServerConnection; import net.minecraft.server.SystemUtils; -import net.minecraft.server.TileEntityHopper; import net.minecraft.server.WorldServer; @Mixin(value = MinecraftServer.class, remap = false) @@ -50,17 +41,19 @@ public abstract class MixinMinecraftServer { @Inject(method = "run()V", at = @At( value = "INVOKE", - target = "net/minecraft/server/MinecraftServer.aw()J", + target = "net/minecraft/server/SystemUtils.b()J", shift = At.Shift.BEFORE )) private void prerun(CallbackInfo info) { primaryThread.setPriority(AkarinGlobalConfig.primaryThreadPriority < Thread.NORM_PRIORITY ? Thread.NORM_PRIORITY : (AkarinGlobalConfig.primaryThreadPriority > Thread.MAX_PRIORITY ? 10 : AkarinGlobalConfig.primaryThreadPriority)); + /* for (int i = 0; i < worlds.size(); ++i) { WorldServer world = worlds.get(i); TileEntityHopper.skipHopperEvents = world.paperConfig.disableHopperMoveEvents || InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; } + */ AkarinSlackScheduler.get().boot(); } @@ -75,76 +68,18 @@ public abstract class MixinMinecraftServer { @Overwrite public void a(MojangStatisticsGenerator generator) {} - @Overwrite - public void b(MojangStatisticsGenerator generator) {} - - /* - * Parallel spawn chunks generation - */ - @Shadow public abstract boolean isRunning(); - @Shadow(aliases = "a_") protected abstract void output(String s, int i); - @Shadow(aliases = "t") protected abstract void enablePluginsPostWorld(); - - private void prepareChunks(WorldServer world, int index) { - MinecraftServer.LOGGER.info("Preparing start region for level " + index + " (Seed: " + world.getSeed() + ")"); - BlockPosition spawnPos = world.getSpawn(); - long lastRecord = System.currentTimeMillis(); - - int preparedChunks = 0; - short radius = world.paperConfig.keepLoadedRange; - for (int skipX = -radius; skipX <= radius && isRunning(); skipX += 16) { - for (int skipZ = -radius; skipZ <= radius && isRunning(); skipZ += 16) { - long now = System.currentTimeMillis(); - - if (now - lastRecord > 1000L) { - output("Preparing spawn area (level " + index + ") ", preparedChunks * 100 / 625); - lastRecord = now; - } - - preparedChunks++; - world.getChunkProviderServer().getChunkAt(spawnPos.getX() + skipX >> 4, spawnPos.getZ() + skipZ >> 4); - } - } - } - - @Overwrite - protected void l() throws InterruptedException { - ExecutorCompletionService executor = new ExecutorCompletionService<>(Executors.newFixedThreadPool(worlds.size(), new AssignableFactory())); - - for (int index = 0; index < worlds.size(); index++) { - WorldServer world = this.worlds.get(index); - if (!world.getWorld().getKeepSpawnInMemory()) continue; - - int fIndex = index; - executor.submit(() -> prepareChunks(world, fIndex), null); - } - - for (WorldServer world : this.worlds) { - if (world.getWorld().getKeepSpawnInMemory()) executor.take(); - } - if (WorldLoadEvent.getHandlerList().getRegisteredListeners().length != 0) { - for (WorldServer world : this.worlds) { - this.server.getPluginManager().callEvent(new WorldLoadEvent(world.getWorld())); - } - } - - enablePluginsPostWorld(); - } - /* * Parallel world ticking */ @Shadow public CraftServer server; - @Shadow @Mutable protected Queue> j; + @Shadow @Mutable protected Queue> g; @Shadow public Queue processQueue; @Shadow private int ticks; @Shadow public List worlds; - @Shadow(aliases = "v") private PlayerList playerList; - @Shadow(aliases = "o") @Final private List tickables; + @Shadow(aliases = "l") @Final private List tickables; - @Shadow public abstract PlayerList getPlayerList(); - @Shadow(aliases = "an") public abstract ServerConnection serverConnection(); - @Shadow(aliases = "aL") public abstract CustomFunctionData functionManager(); + @Shadow public abstract CustomFunctionData getFunctionData(); + @Shadow public abstract ServerConnection getServerConnection(); private boolean tickEntities(WorldServer world) { try { @@ -178,7 +113,7 @@ public abstract class MixinMinecraftServer { } @Overwrite - public void D() throws InterruptedException { + public void w() throws InterruptedException { Runnable runnable; MinecraftTimings.bukkitSchedulerTimer.startTiming(); this.server.getScheduler().mainThreadHeartbeat(this.ticks); @@ -186,12 +121,16 @@ public abstract class MixinMinecraftServer { MinecraftTimings.minecraftSchedulerTimer.startTiming(); FutureTask task; - int count = j.size(); - while (count-- > 0 && (task = j.poll()) != null) { + int count = g.size(); + while (count-- > 0 && (task = g.poll()) != null) { SystemUtils.a(task, MinecraftServer.LOGGER); } MinecraftTimings.minecraftSchedulerTimer.stopTiming(); + MinecraftTimings.commandFunctionsTimer.startTiming(); + getFunctionData().Y_(); + MinecraftTimings.commandFunctionsTimer.stopTiming(); + MinecraftTimings.processQueueTimer.startTiming(); while ((runnable = processQueue.poll()) != null) runnable.run(); MinecraftTimings.processQueueTimer.stopTiming(); @@ -214,6 +153,8 @@ public abstract class MixinMinecraftServer { WorldServer world = worlds.get(i < worlds.size() ? i : 0); synchronized (((IMixinLockProvider) world).lock()) { tickEntities(world); + world.getTracker().updatePlayers(); + world.explosionDensityCache.clear(); // Paper - Optimize explosions } } }, null); @@ -222,7 +163,6 @@ public abstract class MixinMinecraftServer { WorldServer world = worlds.get(i); synchronized (((IMixinLockProvider) world).lock()) { tickWorld(world); - world.explosionDensityCache.clear(); // Paper - Optimize explosions } } @@ -243,35 +183,18 @@ public abstract class MixinMinecraftServer { while ((runnable = Akari.callbackQueue.poll()) != null) runnable.run(); Akari.callbackTiming.stopTiming(); - for (int i = 0; i < worlds.size(); ++i) { - WorldServer world = worlds.get(i); - tickUnsafeSync(world); - } - MinecraftTimings.connectionTimer.startTiming(); - serverConnection().c(); + getServerConnection().c(); MinecraftTimings.connectionTimer.stopTiming(); Akari.callbackTiming.startTiming(); while ((runnable = Akari.callbackQueue.poll()) != null) runnable.run(); Akari.callbackTiming.stopTiming(); - MinecraftTimings.commandFunctionsTimer.startTiming(); - functionManager().e(); - MinecraftTimings.commandFunctionsTimer.stopTiming(); - MinecraftTimings.tickablesTimer.startTiming(); for (int i = 0; i < this.tickables.size(); ++i) { - tickables.get(i).e(); + tickables.get(i).Y_(); } MinecraftTimings.tickablesTimer.stopTiming(); } - - public void tickUnsafeSync(WorldServer world) { - world.timings.doChunkMap.startTiming(); - world.manager.flush(); - world.timings.doChunkMap.stopTiming(); - - world.getTracker().updatePlayers(); - } } diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java index b3fca0e5e..3a915fec0 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java @@ -37,8 +37,8 @@ public abstract class MixinTimingHandler { @SuppressWarnings({"rawtypes", "unchecked"}) @Inject(method = "startTiming", at = @At("HEAD"), cancellable = true) - public void onStartTiming(CallbackInfoReturnable ci) { - if (!Akari.isPrimaryThread(false)) ci.setReturnValue(this); // Avoid modify any field + public void onStartTiming(CallbackInfoReturnable cir) { + if (!Akari.isPrimaryThread(false)) cir.setReturnValue(this); // Avoid modify any field } @Overwrite diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinVersionCommand.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinVersionCommand.java index 0a885f214..a9a29410c 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinVersionCommand.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinVersionCommand.java @@ -15,7 +15,7 @@ import net.minecraft.server.MCUtil; @Mixin(value = VersionCommand.class, remap = false) public abstract class MixinVersionCommand { - @Shadow private static int getFromRepo(String repo, String hash) { return 0; } + @Shadow private static int getFromRepo(String repo, String branch, String hash) { return 0; } /** * Match current version with repository and calculate the distance @@ -26,7 +26,7 @@ public abstract class MixinVersionCommand { @Overwrite private static int getDistance(String repo, String verInfo) { verInfo = verInfo.replace("\"", ""); - return getFromRepo("Akarin-project/Akarin", verInfo); + return getFromRepo("Akarin-project/Akarin", "ver/1.13", verInfo); } /** @@ -37,7 +37,7 @@ public abstract class MixinVersionCommand { @Overwrite private static int getFromJenkins(int currentVer) { String[] parts = Bukkit.getVersion().substring("git-Akarin-".length()).split("[-\\s]"); - return getFromRepo("Akarin-project/Akarin", parts[0]); + return getFromRepo("Akarin-project/Akarin","ver/1.13", parts[0]); } @Shadow private boolean hasVersion; @@ -82,7 +82,7 @@ public abstract class MixinVersionCommand { } } if (!hasVersion) { - obtainVersion(sender); + obtainVersionAsync(sender); if (AkarinGlobalConfig.legacyVersioningCompat) currentSender = sender; } } @@ -90,7 +90,7 @@ public abstract class MixinVersionCommand { @Overwrite private void obtainVersion() { if (AkarinGlobalConfig.legacyVersioningCompat) { - obtainVersion(currentSender); + obtainVersionAsync(currentSender); currentSender = null; // try release } else { Akari.logger.warn("A legacy version lookup was caught, legacy-versioning-compat enabled forcely!"); @@ -99,7 +99,7 @@ public abstract class MixinVersionCommand { } } - private void obtainVersion(CommandSender sender) { + private void obtainVersionAsync(CommandSender sender) { // We post all things because a custom version is rare (expiring is not rare), // and we'd better post this task as early as we can, since it's a will (horrible destiny). MCUtil.scheduleAsyncTask(() -> { diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinWorld.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinWorld.java deleted file mode 100644 index 11277f5d2..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinWorld.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.akarin.server.mixin.core; - -import java.util.List; - -import javax.annotation.Nullable; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import net.minecraft.server.AxisAlignedBB; -import net.minecraft.server.Entity; -import net.minecraft.server.World; - -/** - * Fixes MC-103516(https://bugs.mojang.com/browse/MC-103516) - */ -@Mixin(value = World.class, remap = false) -public abstract class MixinWorld { - @Shadow public abstract List getEntities(@Nullable Entity entity, AxisAlignedBB box); - - /** - * Returns true if there are no solid, live entities in the specified AxisAlignedBB, excluding the given entity - */ - @Overwrite - public boolean a(AxisAlignedBB box, @Nullable Entity target) { // OBFHELPER: checkNoEntityCollision - List list = this.getEntities(null, box); - - for (Entity each : list) { - if (!each.dead && each.i && each != target && (target == null || !each.x(target))) { // OBFHELPER: preventEntitySpawning - isRidingSameEntity - return false; - } - } - return true; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldManager.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldManager.java index c79cab5f5..8105b54f9 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldManager.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldManager.java @@ -16,9 +16,9 @@ public abstract class MixinWorldManager { @Overwrite public void a(Entity entity) { - this.world.getTracker().entriesLock.lock(); // Akarin + this.world.getTracker().entriesLock.writeLock().lock(); // Akarin this.world.getTracker().track(entity); - this.world.getTracker().entriesLock.unlock(); // Akarin + this.world.getTracker().entriesLock.writeLock().unlock(); // Akarin if (entity instanceof EntityPlayer) { this.world.worldProvider.a((EntityPlayer) entity); diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldServer.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldServer.java index 28fcffe46..ef9f68241 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldServer.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinWorldServer.java @@ -1,20 +1,11 @@ package io.akarin.server.mixin.core; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - import io.akarin.api.internal.mixin.IMixinLockProvider; import net.minecraft.server.WorldServer; @Mixin(value = WorldServer.class, remap = false) public abstract class MixinWorldServer implements IMixinLockProvider { - @Redirect(method = "doTick()V", at = @At( - value = "INVOKE", - target = "net/minecraft/server/PlayerChunkMap.flush()V" - )) - public void onFlush() {} // Migrated to main thread - private final Object tickLock = new Object(); @Override diff --git a/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunk.java b/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunk.java deleted file mode 100644 index 2939743c8..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunk.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.cps; - -import java.util.List; -import javax.annotation.Nullable; - -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.google.common.collect.Lists; - -import io.akarin.api.internal.mixin.IMixinChunk; -import net.minecraft.server.BlockPosition; -import net.minecraft.server.Chunk; -import net.minecraft.server.EnumDirection; -import net.minecraft.server.MCUtil; -import net.minecraft.server.World; - -@Mixin(value = Chunk.class, remap = false) -public abstract class MixinChunk implements IMixinChunk { - private Chunk[] neighborChunks = new Chunk[4]; - private static final EnumDirection[] CARDINAL_DIRECTIONS = new EnumDirection[] {EnumDirection.NORTH, EnumDirection.SOUTH, EnumDirection.EAST, EnumDirection.WEST}; - - @Shadow @Final public World world; - @Shadow @Final public int locX; - @Shadow @Final public int locZ; - - @Override - public Chunk getNeighborChunk(int index) { - return this.neighborChunks[index]; - } - - @Override - public void setNeighborChunk(int index, @Nullable Chunk chunk) { - this.neighborChunks[index] = chunk; - } - - @Override - public List getNeighbors() { - List neighborList = Lists.newArrayList(); - for (Chunk neighbor : this.neighborChunks) { - if (neighbor != null) { - neighborList.add(neighbor); - } - } - return neighborList; - } - - @Override - public boolean areNeighborsLoaded() { - for (int i = 0; i < 4; i++) { - if (this.neighborChunks[i] == null) { - return false; - } - } - return true; - } - - private static int directionToIndex(EnumDirection direction) { - switch (direction) { - case NORTH: - return 0; - case SOUTH: - return 1; - case EAST: - return 2; - case WEST: - return 3; - default: - throw new IllegalArgumentException("Unexpected direction"); - } - } - - @Inject(method = "addEntities", at = @At("RETURN")) - public void onLoadReturn(CallbackInfo ci) { - BlockPosition origin = new BlockPosition(locX, 0, locZ); - for (EnumDirection direction : CARDINAL_DIRECTIONS) { - BlockPosition shift = origin.shift(direction); - Chunk neighbor = MCUtil.getLoadedChunkWithoutMarkingActive(world.getChunkProvider(), shift.getX(), shift.getZ()); - if (neighbor != null) { - int neighborIndex = directionToIndex(direction); - int oppositeNeighborIndex = directionToIndex(direction.opposite()); - this.setNeighborChunk(neighborIndex, neighbor); - ((IMixinChunk) neighbor).setNeighborChunk(oppositeNeighborIndex, (Chunk) (Object) this); - } - } - } - - @Inject(method = "removeEntities", at = @At("RETURN")) - public void onUnload(CallbackInfo ci) { - BlockPosition origin = new BlockPosition(locX, 0, locZ); - for (EnumDirection direction : CARDINAL_DIRECTIONS) { - BlockPosition shift = origin.shift(direction); - Chunk neighbor = MCUtil.getLoadedChunkWithoutMarkingActive(world.getChunkProvider(), shift.getX(), shift.getZ()); - if (neighbor != null) { - int neighborIndex = directionToIndex(direction); - int oppositeNeighborIndex = directionToIndex(direction.opposite()); - this.setNeighborChunk(neighborIndex, null); - ((IMixinChunk) neighbor).setNeighborChunk(oppositeNeighborIndex, null); - } - } - } -} 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 index 6fb3d9b55..7a4727bab 100644 --- a/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java +++ b/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java @@ -13,6 +13,7 @@ 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; @@ -20,9 +21,10 @@ import net.minecraft.server.WorldServer; public abstract class MixinChunkProviderServer { @Shadow @Final public WorldServer world; @Shadow public Long2ObjectOpenHashMap chunks; + @Shadow(aliases = "f") @Final private ChunkTaskScheduler scheduler; public void unload(Chunk chunk) { - if (this.world.worldProvider.c(chunk.locX, chunk.locZ)) { + 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); @@ -40,6 +42,7 @@ public abstract class MixinChunkProviderServer { long unloadAfter = world.paperConfig.delayChunkUnloadsBy; SlackActivityAccountant activityAccountant = world.getMinecraftServer().slackActivityAccountant; activityAccountant.startActivity(0.5); + ObjectIterator> it = chunks.long2ObjectEntrySet().fastIterator(); int remainingChunks = chunks.size(); int targetSize = Math.min(remainingChunks - 100, (int) (remainingChunks * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive @@ -47,26 +50,24 @@ public abstract class MixinChunkProviderServer { while (it.hasNext()) { Entry entry = it.next(); Chunk chunk = entry.getValue(); - if (chunk == null) continue; - if (chunk.isUnloading()) { + if (chunk != null && chunk.isUnloading()) { if (chunk.scheduledForUnload != null) { - if (now - chunk.scheduledForUnload > unloadAfter) { - chunk.scheduledForUnload = null; - } else continue; + if (now - chunk.scheduledForUnload <= unloadAfter) continue; } - if (!unloadChunk(chunk, true)) { // Event cancelled - // If a plugin cancelled it, we shouldn't trying unload it for a while - chunk.setShouldUnload(false); - continue; + if (unloadChunk(chunk, true)) { + it.remove(); } + chunk.setShouldUnload(false); + chunk.scheduledForUnload = null; - it.remove(); - if (--remainingChunks <= targetSize || activityAccountant.activityTimeIsExhausted()) break; // more slack since the target size not work as intended + if (--remainingChunks <= targetSize && activityAccountant.activityTimeIsExhausted()) break; } } activityAccountant.endActivity(); + + this.scheduler.a(); this.chunkLoader.b(); // OBFHELPER: chunkTick } return false; @@ -74,7 +75,7 @@ public abstract class MixinChunkProviderServer { @Redirect(method = "unloadChunk", at = @At( value = "INVOKE", - target = "it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.remove(J)Ljava/lang/Object;" + target = "it/unimi/dsi/fastutil/longs/Long2ObjectMap.remove(J)Ljava/lang/Object;" )) private Object remove(Long2ObjectOpenHashMap chunks, long chunkHash) { return null; 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 index 0e755a9f5..0415e3d76 100644 --- a/sources/src/main/java/io/akarin/server/mixin/cps/MixinCraftWorld.java +++ b/sources/src/main/java/io/akarin/server/mixin/cps/MixinCraftWorld.java @@ -19,7 +19,7 @@ public abstract class MixinCraftWorld { @Redirect(method = "processChunkGC()V", at = @At( value = "INVOKE", - target = "java/util/Set.contains(Ljava/lang/Object;)Z", + target = "it/unimi/dsi/fastutil/longs/LongSet.contains(J)Z", opcode = Opcodes.INVOKEINTERFACE )) public boolean checkUnloading(Set set, Object chunkHash) { @@ -28,7 +28,7 @@ public abstract class MixinCraftWorld { @Redirect(method = "regenerateChunk", at = @At( value = "INVOKE", - target = "java/util/Set.remove(Ljava/lang/Object;)Z", + target = "it/unimi/dsi/fastutil/longs/LongSet.remove(J)Z", opcode = Opcodes.INVOKEINTERFACE )) public boolean regenChunk(Set set, Object chunkHash) { diff --git a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java deleted file mode 100644 index a69215412..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunk.java +++ /dev/null @@ -1,671 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.lighting; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.Nullable; - -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.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import io.akarin.api.internal.Akari; -import io.akarin.api.internal.mixin.IMixinChunk; -import io.akarin.api.internal.mixin.IMixinWorldServer; -import net.minecraft.server.BlockPosition; -import net.minecraft.server.Blocks; -import net.minecraft.server.Chunk; -import net.minecraft.server.ChunkSection; -import net.minecraft.server.EnumDirection; -import net.minecraft.server.EnumSkyBlock; -import net.minecraft.server.IBlockData; -import net.minecraft.server.MCUtil; -import net.minecraft.server.TileEntity; -import net.minecraft.server.World; -import net.minecraft.server.BlockPosition.MutableBlockPosition; - -@Mixin(value = Chunk.class, remap = false, priority = 1001) -public abstract class MixinChunk implements IMixinChunk { - - // Keeps track of block positions in this chunk currently queued for sky light update - private CopyOnWriteArrayList queuedSkyLightingUpdates = new CopyOnWriteArrayList<>(); - // Keeps track of block positions in this chunk currently queued for block light update - private CopyOnWriteArrayList queuedBlockLightingUpdates = new CopyOnWriteArrayList<>(); - private AtomicInteger pendingLightUpdates = new AtomicInteger(); - private long lightUpdateTime; - private static ExecutorService lightExecutorService; - - @Shadow(aliases = "m") private boolean isGapLightingUpdated; - @Shadow(aliases = "r") private boolean ticked; - @Shadow @Final private ChunkSection[] sections; - @Shadow @Final public int locX; - @Shadow @Final public int locZ; - @Shadow @Final public World world; - @Shadow @Final public int[] heightMap; - /** Which columns need their skylightMaps updated. */ - @Shadow(aliases = "i") @Final private boolean[] updateSkylightColumns; - /** Queue containing the BlockPosition of tile entities queued for creation */ - @Shadow(aliases = "y") @Final private ConcurrentLinkedQueue tileEntityPosQueue; - /** Boolean value indicating if the terrain is populated. */ - @Shadow(aliases = "done") private boolean isTerrainPopulated; - @Shadow(aliases = "lit") private boolean isLightPopulated; - /** Lowest value in the heightmap. */ - @Shadow(aliases = "v") private int heightMapMinimum; - - @Shadow(aliases = "b") public abstract int getHeightValue(int x, int z); - @Shadow(aliases = "g") @Nullable public abstract TileEntity createNewTileEntity(BlockPosition pos); - @Shadow(aliases = "a") @Nullable public abstract TileEntity getTileEntity(BlockPosition pos, Chunk.EnumTileEntityState state); - @Shadow @Final public abstract IBlockData getBlockData(BlockPosition pos); - @Shadow @Final public abstract IBlockData getBlockData(int x, int y, int z); - @Shadow public abstract boolean isUnloading(); - /** Checks the height of a block next to a sky-visible block and schedules a lighting update as necessary */ - @Shadow(aliases = "b") public abstract void checkSkylightNeighborHeight(int x, int z, int maxValue); - @Shadow(aliases = "a") public abstract void updateSkylightNeighborHeight(int x, int z, int startY, int endY); - @Shadow(aliases = "z") public abstract void setSkylightUpdated(); - @Shadow(aliases = "g") public abstract int getTopFilledSegment(); - @Shadow public abstract void markDirty(); - - @Inject(method = "", at = @At("RETURN")) - public void onConstruct(World worldIn, int x, int z, CallbackInfo ci) { - lightExecutorService = ((IMixinWorldServer) worldIn).getLightingExecutor(); - } - - @Override - public AtomicInteger getPendingLightUpdates() { - return this.pendingLightUpdates; - } - - @Override - public long getLightUpdateTime() { - return this.lightUpdateTime; - } - - @Override - public void setLightUpdateTime(long time) { - this.lightUpdateTime = time; - } - - @Inject(method = "b(Z)V", at = @At("HEAD"), cancellable = true) - private void onTickHead(boolean skipRecheckGaps, CallbackInfo ci) { - final List neighbors = this.getSurroundingChunks(); - if (this.isGapLightingUpdated && this.world.worldProvider.m() && !skipRecheckGaps && !neighbors.isEmpty()) { // OBFHELPER: hasSkyLight - lightExecutorService.execute(() -> { - this.recheckGapsAsync(neighbors); - }); - this.isGapLightingUpdated = false; - } - - this.ticked = true; - - if ((true || !this.isLightPopulated) && this.isTerrainPopulated && !neighbors.isEmpty()) { - lightExecutorService.execute(() -> { - this.checkLightAsync(neighbors); - }); - // set to true to avoid requeuing the same task when not finished - this.isLightPopulated = true; - } - - while (!this.tileEntityPosQueue.isEmpty()) { - BlockPosition blockpos = this.tileEntityPosQueue.poll(); - - if (this.getTileEntity(blockpos, Chunk.EnumTileEntityState.CHECK) == null && this.getBlockData(blockpos).getBlock().isTileEntity()) { // OBFHELPER: getTileEntity - TileEntity tileentity = this.createNewTileEntity(blockpos); - this.world.setTileEntity(blockpos, tileentity); - this.world.b(blockpos, blockpos); // OBFHELPER: markBlockRangeForRenderUpdate - } - } - ci.cancel(); - } - - @Redirect(method = "b(III)V", at = @At(value = "INVOKE", target = "net/minecraft/server/World.getHighestBlockYAt(Lnet/minecraft/server/BlockPosition;)Lnet/minecraft/server/BlockPosition;")) - private BlockPosition onCheckSkylightGetHeight(World world, BlockPosition pos) { - final Chunk chunk = this.getLightChunk(pos.getX() >> 4, pos.getZ() >> 4, null); - if (chunk == null) { - return BlockPosition.ZERO; - } - - return new BlockPosition(pos.getX(), chunk.b(pos.getX() & 15, pos.getZ() & 15), pos.getZ()); // OBFHELPER: getHeightValue - } - - @Redirect(method = "a(IIII)V", at = @At(value = "INVOKE", target = "net/minecraft/server/World.areChunksLoaded(Lnet/minecraft/server/BlockPosition;I)Z")) - private boolean onAreaLoadedSkyLightNeighbor(World world, BlockPosition pos, int radius) { - return this.isAreaLoaded(); - } - - @Redirect(method = "a(IIII)V", at = @At(value = "INVOKE", target = "net/minecraft/server/World.c(Lnet/minecraft/server/EnumSkyBlock;Lnet/minecraft/server/BlockPosition;)Z")) - private boolean onCheckLightForSkylightNeighbor(World world, EnumSkyBlock enumSkyBlock, BlockPosition pos) { - return this.checkWorldLightFor(enumSkyBlock, pos); - } - - @Inject(method = "h(Z)V", at = @At("HEAD"), cancellable = true) - private void onRecheckGaps(CallbackInfo ci) { - if (this.world.getMinecraftServer().isStopped() || lightExecutorService.isShutdown()) { - return; - } - - if (this.isUnloading()) { - return; - } - final List neighborChunks = this.getSurroundingChunks(); - if (neighborChunks.isEmpty()) { - this.isGapLightingUpdated = true; - return; - } - - if (Akari.isPrimaryThread()) { - try { - lightExecutorService.execute(() -> { - this.recheckGapsAsync(neighborChunks); - }); - } catch (RejectedExecutionException ex) { - // This could happen if ServerHangWatchdog kills the server - // between the start of the method and the execute() call. - if (!this.world.getMinecraftServer().isStopped() && !lightExecutorService.isShutdown()) { - throw ex; - } - } - } else { - this.recheckGapsAsync(neighborChunks); - } - ci.cancel(); - } - - /** - * Rechecks chunk gaps async. - * - * @param neighbors A thread-safe list of surrounding neighbor chunks - */ - private void recheckGapsAsync(List neighbors) { - this.isLightPopulated = false; - - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 16; ++j) { - if (this.updateSkylightColumns[i + j * 16]) { - this.updateSkylightColumns[i + j * 16] = false; - int k = this.getHeightValue(i, j); - int l = this.locX * 16 + i; - int i1 = this.locZ * 16 + j; - int j1 = Integer.MAX_VALUE; - - for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { - final Chunk chunk = this.getLightChunk((l + enumfacing.getAdjacentX()) >> 4, (i1 + enumfacing.getAdjacentZ()) >> 4, neighbors); - if (chunk == null || chunk.isUnloading()) { - continue; - } - j1 = Math.min(j1, chunk.w()); // OBFHELPER: getLowestHeight - } - - this.checkSkylightNeighborHeight(l, i1, j1); - - for (EnumDirection enumfacing1 : EnumDirection.EnumDirectionLimit.HORIZONTAL) { - this.checkSkylightNeighborHeight(l + enumfacing1.getAdjacentX(), i1 + enumfacing1.getAdjacentZ(), k); - } - } - } - - this.isGapLightingUpdated = false; - } - } - - @Redirect(method = "n()V", at = @At(value = "INVOKE", target = "net/minecraft/server/World.getType(Lnet/minecraft/server/BlockPosition;)Lnet/minecraft/server/IBlockData;")) - private IBlockData onRelightChecksGetBlockData(World world, BlockPosition pos) { - Chunk chunk = MCUtil.getLoadedChunkWithoutMarkingActive(world.getChunkProvider(), pos.getX() >> 4, pos.getZ() >> 4); - - final IMixinChunk spongeChunk = (IMixinChunk) chunk; - if (chunk == null || chunk.isUnloading() || !spongeChunk.areNeighborsLoaded()) { - return Blocks.AIR.getBlockData(); - } - - return chunk.getBlockData(pos); - } - - @Redirect(method = "n()V", at = @At(value = "INVOKE", target = "net/minecraft/server/World.w(Lnet/minecraft/server/BlockPosition;)Z")) - private boolean onRelightChecksCheckLight(World world, BlockPosition pos) { - return this.checkWorldLight(pos); - } - - // Avoids grabbing chunk async during light check - @Redirect(method = "e(II)Z", at = @At(value = "INVOKE", target = "net/minecraft/server/World.w(Lnet/minecraft/server/BlockPosition;)Z")) - private boolean onCheckLightWorld(World world, BlockPosition pos) { - return this.checkWorldLight(pos); - } - - @Inject(method = "o()V", at = @At("HEAD"), cancellable = true) - private void checkLightHead(CallbackInfo ci) { - if (this.world.getMinecraftServer().isStopped() || lightExecutorService.isShutdown()) { - return; - } - - if (this.isUnloading()) { - return; - } - final List neighborChunks = this.getSurroundingChunks(); - if (neighborChunks.isEmpty()) { - this.isLightPopulated = false; - return; - } - - if (Akari.isPrimaryThread()) { - try { - lightExecutorService.execute(() -> { - this.checkLightAsync(neighborChunks); - }); - } catch (RejectedExecutionException ex) { - // This could happen if ServerHangWatchdog kills the server - // between the start of the method and the execute() call. - if (!this.world.getMinecraftServer().isStopped() && !lightExecutorService.isShutdown()) { - throw ex; - } - } - } else { - this.checkLightAsync(neighborChunks); - } - ci.cancel(); - } - - /** - * Checks light async. - * - * @param neighbors A thread-safe list of surrounding neighbor chunks - */ - private void checkLightAsync(List neighbors) { - this.isTerrainPopulated = true; - this.isLightPopulated = true; - BlockPosition blockpos = new BlockPosition(this.locX << 4, 0, this.locZ << 4); - - if (this.world.worldProvider.m()) { // OBFHELPER: hasSkyLight - CHECK_LIGHT: - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 16; ++j) { - if (!this.checkLightAsync(i, j, neighbors)) { - this.isLightPopulated = false; - break CHECK_LIGHT; - } - } - } - - if (this.isLightPopulated) { - for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { - int k = enumfacing.c() == EnumDirection.EnumAxisDirection.POSITIVE ? 16 : 1; // OBFHELPER: getAxisDirection - final BlockPosition pos = blockpos.shift(enumfacing, k); - final Chunk chunk = this.getLightChunk(pos.getX() >> 4, pos.getZ() >> 4, neighbors); - if (chunk == null) { - continue; - } - chunk.a(enumfacing.opposite()); // OBFHELPER: checkLightSide - } - - this.setSkylightUpdated(); - } - } - } - - /** - * Checks light async. - * - * @param x The x position of chunk - * @param z The z position of chunk - * @param neighbors A thread-safe list of surrounding neighbor chunks - * @return True if light update was successful, false if not - */ - private boolean checkLightAsync(int x, int z, List neighbors) { - int i = this.getTopFilledSegment(); - boolean flag = false; - boolean flag1 = false; - MutableBlockPosition blockpos$mutableblockpos = new MutableBlockPosition((this.locX << 4) + x, 0, (this.locZ << 4) + z); - - for (int j = i + 16 - 1; j > this.world.getSeaLevel() || j > 0 && !flag1; --j) { - blockpos$mutableblockpos.setValues(blockpos$mutableblockpos.getX(), j, blockpos$mutableblockpos.getZ()); - int k = this.getBlockData(blockpos$mutableblockpos).c(); // OBFHELPER: getLightOpacity - - if (k == 255 && blockpos$mutableblockpos.getY() < this.world.getSeaLevel()) { - flag1 = true; - } - - if (!flag && k > 0) { - flag = true; - } else if (flag && k == 0 && !this.checkWorldLight(blockpos$mutableblockpos, neighbors)) { - return false; - } - } - - for (int l = blockpos$mutableblockpos.getY(); l > 0; --l) { - blockpos$mutableblockpos.setValues(blockpos$mutableblockpos.getX(), l, blockpos$mutableblockpos.getZ()); - - if (this.getBlockData(blockpos$mutableblockpos).d() > 0) { // getLightValue - this.checkWorldLight(blockpos$mutableblockpos, neighbors); - } - } - - return true; - } - - /** - * Thread-safe method to retrieve a chunk during async light updates. - * - * @param chunkX The x position of chunk. - * @param chunkZ The z position of chunk. - * @param neighbors A thread-safe list of surrounding neighbor chunks - * @return The chunk if available, null if not - */ - private Chunk getLightChunk(int chunkX, int chunkZ, List neighbors) { - final Chunk currentChunk = (Chunk) (Object) this; - if (currentChunk.a(chunkX, chunkZ)) { // OBFHELPER: isAtLocation - if (currentChunk.isUnloading()) { - return null; - } - return currentChunk; - } - if (neighbors == null) { - neighbors = this.getSurroundingChunks(); - if (neighbors.isEmpty()) { - return null; - } - } - for (Chunk neighbor : neighbors) { - if (neighbor.a(chunkX, chunkZ)) { // OBFHELPER: isAtLocation - if (neighbor.isUnloading()) { - return null; - } - return neighbor; - } - } - - return null; - } - - /** - * Checks if surrounding chunks are loaded thread-safe. - * - * @return True if surrounded chunks are loaded, false if not - */ - private boolean isAreaLoaded() { - if (!this.areNeighborsLoaded()) { - return false; - } - - // add diagonal chunks - final Chunk southEastChunk = ((IMixinChunk) this.getNeighborChunk(0)).getNeighborChunk(2); - if (southEastChunk == null) { - return false; - } - - final Chunk southWestChunk = ((IMixinChunk) this.getNeighborChunk(0)).getNeighborChunk(3); - if (southWestChunk == null) { - return false; - } - - final Chunk northEastChunk = ((IMixinChunk) this.getNeighborChunk(1)).getNeighborChunk(2); - if (northEastChunk == null) { - return false; - } - - final Chunk northWestChunk = ((IMixinChunk) this.getNeighborChunk(1)).getNeighborChunk(3); - if (northWestChunk == null) { - return false; - } - - return true; - } - - /** - * Gets surrounding chunks thread-safe. - * - * @return The list of surrounding chunks, empty list if not loaded - */ - private List getSurroundingChunks() { - if (!this.areNeighborsLoaded()) { - return Collections.emptyList(); - } - - // add diagonal chunks - final Chunk southEastChunk = ((IMixinChunk) this.getNeighborChunk(0)).getNeighborChunk(2); - if (southEastChunk == null) { - return Collections.emptyList(); - } - - final Chunk southWestChunk = ((IMixinChunk) this.getNeighborChunk(0)).getNeighborChunk(3); - if (southWestChunk == null) { - return Collections.emptyList(); - } - - final Chunk northEastChunk = ((IMixinChunk) this.getNeighborChunk(1)).getNeighborChunk(2); - if (northEastChunk == null) { - return Collections.emptyList(); - } - - final Chunk northWestChunk = ((IMixinChunk) this.getNeighborChunk(1)).getNeighborChunk(3); - if (northWestChunk == null) { - return Collections.emptyList(); - } - - List chunkList = this.getNeighbors(); - chunkList.add(southEastChunk); - chunkList.add(southWestChunk); - chunkList.add(northEastChunk); - chunkList.add(northWestChunk); - return chunkList; - } - - @Inject(method = "c(III)V", at = @At("HEAD"), cancellable = true) - private void onRelightBlock(int x, int y, int z, CallbackInfo ci) { - lightExecutorService.execute(() -> { - this.relightBlockAsync(x, y, z); - }); - ci.cancel(); - } - - /** - * Relight's a block async. - * - * @param x The x position - * @param y The y position - * @param z The z position - */ - private void relightBlockAsync(int x, int y, int z) { - int i = this.heightMap[z << 4 | x] & 255; - int j = i; - - if (y > i) { - j = y; - } - - while (j > 0 && this.getBlockData(x, j - 1, z).c() == 0) { // OBFHELPER: getLightOpacity - --j; - } - - if (j != i) { - this.markBlocksDirtyVerticalAsync(x + this.locX * 16, z + this.locZ * 16, j, i); - this.heightMap[z << 4 | x] = j; - int k = this.locX * 16 + x; - int l = this.locZ * 16 + z; - - if (this.world.worldProvider.m()) { // OBFHELPER: hasSkyLight - if (j < i) { - for (int j1 = j; j1 < i; ++j1) { - ChunkSection extendedblockstorage2 = this.sections[j1 >> 4]; - - if (extendedblockstorage2 != Chunk.EMPTY_CHUNK_SECTION) { - extendedblockstorage2.a(x, j1 & 15, z, 15); // OBFHELPER: setSkyLight - // this.world.m(new BlockPosition((this.locX << 4) + x, j1, (this.locZ << 4) + z)); // OBFHELPER: notifyLightSet - client side - } - } - } else { - for (int i1 = i; i1 < j; ++i1) { - ChunkSection extendedblockstorage = this.sections[i1 >> 4]; - - if (extendedblockstorage != Chunk.EMPTY_CHUNK_SECTION) { - extendedblockstorage.a(x, i1 & 15, z, 0); // OBFHELPER: setSkyLight - // this.world.m(new BlockPosition((this.locX << 4) + x, i1, (this.locZ << 4) + z)); // OBFHELPER: notifyLightSet - client side - } - } - } - - int k1 = 15; - - while (j > 0 && k1 > 0) { - --j; - int i2 = this.getBlockData(x, j, z).c(); - - if (i2 == 0) { - i2 = 1; - } - - k1 -= i2; - - if (k1 < 0) { - k1 = 0; - } - - ChunkSection extendedblockstorage1 = this.sections[j >> 4]; - - if (extendedblockstorage1 != Chunk.EMPTY_CHUNK_SECTION) { - extendedblockstorage1.a(x, j & 15, z, k1); // OBFHELPER: setSkyLight - } - } - } - - int l1 = this.heightMap[z << 4 | x]; - int j2 = i; - int k2 = l1; - - if (l1 < i) { - j2 = l1; - k2 = i; - } - - if (l1 < this.heightMapMinimum) { - this.heightMapMinimum = l1; - } - - if (this.world.worldProvider.m()) { // OBFHELPER: hasSkyLight - for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { - this.updateSkylightNeighborHeight(k + enumfacing.getAdjacentX(), l + enumfacing.getAdjacentZ(), j2, k2); // OBFHELPER: updateSkylightNeighborHeight - } - - this.updateSkylightNeighborHeight(k, l, j2, k2); - } - - this.markDirty(); - } - } - - /** - * Marks a vertical line of blocks as dirty async. - * Instead of calling world directly, we pass chunk safely for async light method. - * - * @param x1 - * @param z1 - * @param x2 - * @param z2 - */ - private void markBlocksDirtyVerticalAsync(int x1, int z1, int x2, int z2) { - if (x2 > z2) { - int i = z2; - z2 = x2; - x2 = i; - } - - if (this.world.worldProvider.m()) { // OBFHELPER: hasSkyLight - for (int j = x2; j <= z2; ++j) { - final BlockPosition pos = new BlockPosition(x1, j, z1); - final Chunk chunk = this.getLightChunk(pos.getX() >> 4, pos.getZ() >> 4, null); - if (chunk == null) { - continue; - } - ((IMixinWorldServer) this.world).updateLightAsync(EnumSkyBlock.SKY, new BlockPosition(x1, j, z1), chunk); - } - } - - this.world.b(x1, x2, z1, x1, z2, z1); // OBFHELPER: markBlockRangeForRenderUpdate - } - - /** - * Checks world light thread-safe. - * - * @param lightType The type of light to check - * @param pos The block position - * @return True if light update was successful, false if not - */ - private boolean checkWorldLightFor(EnumSkyBlock lightType, BlockPosition pos) { - final Chunk chunk = this.getLightChunk(pos.getX() >> 4, pos.getZ() >> 4, null); - if (chunk == null) { - return false; - } - - return ((IMixinWorldServer) this.world).updateLightAsync(lightType, pos, chunk); - } - - private boolean checkWorldLight(BlockPosition pos) { - return this.checkWorldLight(pos, null); - } - - /** - * Checks world light async. - * - * @param pos The block position - * @param neighbors A thread-safe list of surrounding neighbor chunks - * @return True if light update was successful, false if not - */ - private boolean checkWorldLight(BlockPosition pos, List neighbors) { - boolean flag = false; - final Chunk chunk = this.getLightChunk(pos.getX() >> 4, pos.getZ() >> 4, neighbors); - if (chunk == null) { - return false; - } - - if (this.world.worldProvider.m()) { // OBFHELPER: hasSkyLight - flag |= ((IMixinWorldServer) this.world).updateLightAsync(EnumSkyBlock.SKY, pos, chunk); - } - - flag = flag | ((IMixinWorldServer) this.world).updateLightAsync(EnumSkyBlock.BLOCK, pos, chunk); - return flag; - } - - /** - * Gets the list of block positions currently queued for lighting updates. - * - * @param type The light type - * @return The list of queued block positions, empty if none - */ - @Override - public CopyOnWriteArrayList getQueuedLightingUpdates(EnumSkyBlock type) { - if (type == EnumSkyBlock.SKY) { - return this.queuedSkyLightingUpdates; - } - return this.queuedBlockLightingUpdates; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunkProviderServer.java b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunkProviderServer.java deleted file mode 100644 index aa384fcba..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinChunkProviderServer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.lighting; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.Redirect; - -import io.akarin.api.internal.mixin.IMixinChunk; -import net.minecraft.server.ChunkProviderServer; -import net.minecraft.server.WorldServer; - -@Mixin(value = ChunkProviderServer.class, remap = false, priority = 1001) -public abstract class MixinChunkProviderServer { - @Shadow @Final public WorldServer world; - - @Redirect(method = "unloadChunks", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/Chunk;isUnloading()Z" - )) - public boolean shouldUnload(IMixinChunk chunk) { - if (chunk.getPendingLightUpdates().get() > 0 || this.world.getTime() - chunk.getLightUpdateTime() < 20) { - return false; - } - return true; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorld.java b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorld.java deleted file mode 100644 index d09d94a33..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorld.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.lighting; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import net.minecraft.server.BlockPosition; -import net.minecraft.server.Chunk; -import net.minecraft.server.EnumSkyBlock; -import net.minecraft.server.IChunkProvider; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.World; - -@Mixin(value = World.class, remap = false, priority = 1002) -public abstract class MixinWorld { - @Shadow protected IChunkProvider chunkProvider; - @Shadow int[] J; // OBFHELPER: lightUpdateBlockList - - @Shadow(aliases = "c") public abstract boolean checkLightFor(EnumSkyBlock lightType, BlockPosition pos); - @Shadow public abstract MinecraftServer getMinecraftServer(); - @Shadow public abstract boolean areChunksLoaded(BlockPosition center, int radius, boolean allowEmpty); - @Shadow public abstract Chunk getChunkIfLoaded(int x, int z); -} diff --git a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java b/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java deleted file mode 100644 index 0157daa83..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/lighting/MixinWorldServer.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.lighting; - -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.annotation.Nullable; - -import org.spongepowered.asm.mixin.Mixin; -import com.google.common.util.concurrent.ThreadFactoryBuilder; - -import io.akarin.api.internal.Akari; -import io.akarin.api.internal.mixin.IMixinChunk; -import io.akarin.api.internal.mixin.IMixinWorldServer; -import io.akarin.server.core.AkarinGlobalConfig; -import net.minecraft.server.BlockPosition; -import net.minecraft.server.Chunk; -import net.minecraft.server.EnumDirection; -import net.minecraft.server.EnumSkyBlock; -import net.minecraft.server.IBlockData; -import net.minecraft.server.MCUtil; -import net.minecraft.server.MathHelper; -import net.minecraft.server.WorldServer; -import net.minecraft.server.BlockPosition.PooledBlockPosition; - -@Mixin(value = WorldServer.class, remap = false, priority = 1002) -public abstract class MixinWorldServer extends MixinWorld implements IMixinWorldServer { - - private static final int NUM_XZ_BITS = 4; - private static final int NUM_SHORT_Y_BITS = 8; - private static final short XZ_MASK = 0xF; - private static final short Y_SHORT_MASK = 0xFF; - - private final static ExecutorService lightExecutorService = getExecutorService(); - private static ExecutorService getExecutorService() { - return AkarinGlobalConfig.asyncLightingWorkStealing ? - Executors.newFixedThreadPool(AkarinGlobalConfig.asyncLightingThreads, new ThreadFactoryBuilder().setNameFormat("Akarin Async Light Thread").build()) - : - Executors.newWorkStealingPool(AkarinGlobalConfig.asyncLightingThreads); - } - - @Override - public boolean checkLightFor(EnumSkyBlock lightType, BlockPosition pos) { // OBFHELPER: checkLightFor - return updateLightAsync(lightType, pos, null); - } - - @Override - public boolean checkLightAsync(EnumSkyBlock lightType, BlockPosition pos, Chunk currentChunk, List neighbors) { - // Sponge - This check is not needed as neighbors are checked in updateLightAsync - if (false && !this.areChunksLoaded(pos, 17, false)) { - return false; - } else { - final IMixinChunk spongeChunk = (IMixinChunk) currentChunk; - int recheckIndex = 0; - int blockIndex = 0; - int current = this.getLightForAsync(lightType, pos, currentChunk, neighbors); // Sponge - use thread safe method - int rawLight = this.getRawBlockLightAsync(lightType, pos, currentChunk, neighbors); // Sponge - use thread safe method - int x = pos.getX(); - int y = pos.getY(); - int z = pos.getZ(); - - if (rawLight > current) { - this.J[blockIndex++] = 133152; // OBFHELPER: lightUpdateBlockList - } else if (rawLight < current) { - this.J[blockIndex++] = 133152 | current << 18; // OBFHELPER: lightUpdateBlockList - - while (recheckIndex < blockIndex) { - int blockData = this.J[recheckIndex++]; // OBFHELPER: lightUpdateBlockList - int i2 = (blockData & 63) - 32 + x; - int j2 = (blockData >> 6 & 63) - 32 + y; - int k2 = (blockData >> 12 & 63) - 32 + z; - int l2 = blockData >> 18 & 15; - BlockPosition blockpos = new BlockPosition(i2, j2, k2); - int lightLevel = this.getLightForAsync(lightType, blockpos, currentChunk, neighbors); // Sponge - use thread safe method - - if (lightLevel == l2) { - this.setLightForAsync(lightType, blockpos, 0, currentChunk, neighbors); // Sponge - use thread safe method - - if (l2 > 0) { - int j3 = MathHelper.a(i2 - x); // abs - int k3 = MathHelper.a(j2 - y); - int l3 = MathHelper.a(k2 - z); - - if (j3 + k3 + l3 < 17) { - PooledBlockPosition mutableBlockpos = PooledBlockPosition.aquire(); - - for (EnumDirection enumfacing : EnumDirection.values()) { - int i4 = i2 + enumfacing.getAdjacentX(); - int j4 = j2 + enumfacing.getAdjacentX(); - int k4 = k2 + enumfacing.getAdjacentX(); - mutableBlockpos.setValues(i4, j4, k4); - // Sponge start - get chunk safely - final Chunk pooledChunk = this.getLightChunk(mutableBlockpos, currentChunk, neighbors); - if (pooledChunk == null) { - continue; - } - int opacity = Math.max(1, pooledChunk.getBlockData(mutableBlockpos).c()); // OBFHELPER: getLightOpacity - lightLevel = this.getLightForAsync(lightType, mutableBlockpos, currentChunk, neighbors); - // Sponge end - - if (lightLevel == l2 - opacity && blockIndex < this.J.length) { // OBFHELPER: lightUpdateBlockList - this.J[blockIndex++] = i4 - x + 32 | j4 - y + 32 << 6 | k4 - z + 32 << 12 | l2 - opacity << 18; // OBFHELPER: lightUpdateBlockList - } - } - - mutableBlockpos.free(); - } - } - } - } - - recheckIndex = 0; - } - - while (recheckIndex < blockIndex) { - int i5 = this.J[recheckIndex++]; // OBFHELPER: lightUpdateBlockList - int j5 = (i5 & 63) - 32 + x; - int k5 = (i5 >> 6 & 63) - 32 + y; - int l5 = (i5 >> 12 & 63) - 32 + z; - BlockPosition blockpos1 = new BlockPosition(j5, k5, l5); - int i6 = this.getLightForAsync(lightType, blockpos1, currentChunk, neighbors); // Sponge - use thread safe method - int j6 = this.getRawBlockLightAsync(lightType, blockpos1, currentChunk, neighbors); // Sponge - use thread safe method - - if (j6 != i6) { - this.setLightForAsync(lightType, blockpos1, j6, currentChunk, neighbors); // Sponge - use thread safe method - - if (j6 > i6) { - int k6 = Math.abs(j5 - x); - int l6 = Math.abs(k5 - y); - int i7 = Math.abs(l5 - z); - boolean flag = blockIndex < this.J.length - 6; // OBFHELPER: lightUpdateBlockList - - if (k6 + l6 + i7 < 17 && flag) { - // Sponge start - use thread safe method getLightForAsync - if (this.getLightForAsync(lightType, blockpos1.west(), currentChunk, neighbors) < j6) { - this.J[blockIndex++] = j5 - 1 - x + 32 + (k5 - y + 32 << 6) + (l5 - z + 32 << 12); // OBFHELPER: lightUpdateBlockList - } - - if (this.getLightForAsync(lightType, blockpos1.east(), currentChunk, neighbors) < j6) { - this.J[blockIndex++] = j5 + 1 - x + 32 + (k5 - y + 32 << 6) + (l5 - z + 32 << 12); // OBFHELPER: lightUpdateBlockList - } - - if (this.getLightForAsync(lightType, blockpos1.down(), currentChunk, neighbors) < j6) { - this.J[blockIndex++] = j5 - x + 32 + (k5 - 1 - y + 32 << 6) + (l5 - z + 32 << 12); // OBFHELPER: lightUpdateBlockList - } - - if (this.getLightForAsync(lightType, blockpos1.up(), currentChunk, neighbors) < j6) { - this.J[blockIndex++] = j5 - x + 32 + (k5 + 1 - y + 32 << 6) + (l5 - z + 32 << 12); // OBFHELPER: lightUpdateBlockList - } - - if (this.getLightForAsync(lightType, blockpos1.north(), currentChunk, neighbors) < j6) { - this.J[blockIndex++] = j5 - x + 32 + (k5 - y + 32 << 6) + (l5 - 1 - z + 32 << 12); // OBFHELPER: lightUpdateBlockList - } - - if (this.getLightForAsync(lightType, blockpos1.south(), currentChunk, neighbors) < j6) { - this.J[blockIndex++] = j5 - x + 32 + (k5 - y + 32 << 6) + (l5 + 1 - z + 32 << 12); // OBFHELPER: lightUpdateBlockList - } - // Sponge end - } - } - } - } - - // Sponge start - Asynchronous light updates - spongeChunk.getQueuedLightingUpdates(lightType).remove((Short) this.blockPosToShort(pos)); - spongeChunk.getPendingLightUpdates().decrementAndGet(); - for (Chunk neighborChunk : neighbors) { - final IMixinChunk neighbor = (IMixinChunk) neighborChunk; - neighbor.getPendingLightUpdates().decrementAndGet(); - } - // Sponge end - return true; - } - } - - @Override - public boolean updateLightAsync(EnumSkyBlock lightType, BlockPosition pos, @Nullable Chunk currentChunk) { - if (this.getMinecraftServer().isStopped() || lightExecutorService.isShutdown()) { - return false; - } - - if (currentChunk == null) { - currentChunk = MCUtil.getLoadedChunkWithoutMarkingActive(chunkProvider, pos.getX() >> 4, pos.getZ() >> 4); - } - - final IMixinChunk spongeChunk = (IMixinChunk) currentChunk; - if (currentChunk == null || currentChunk.isUnloading() || !spongeChunk.areNeighborsLoaded()) { - return false; - } - - final short shortPos = this.blockPosToShort(pos); - if (spongeChunk.getQueuedLightingUpdates(lightType).contains(shortPos)) { - return false; - } - - final Chunk chunk = currentChunk; - spongeChunk.getQueuedLightingUpdates(lightType).add(shortPos); - spongeChunk.getPendingLightUpdates().incrementAndGet(); - spongeChunk.setLightUpdateTime(chunk.getWorld().getTime()); - - List neighbors = spongeChunk.getNeighbors(); - // add diagonal chunks - Chunk southEastChunk = ((IMixinChunk) spongeChunk.getNeighborChunk(0)).getNeighborChunk(2); - Chunk southWestChunk = ((IMixinChunk) spongeChunk.getNeighborChunk(0)).getNeighborChunk(3); - Chunk northEastChunk = ((IMixinChunk) spongeChunk.getNeighborChunk(1)).getNeighborChunk(2); - Chunk northWestChunk = ((IMixinChunk) spongeChunk.getNeighborChunk(1)).getNeighborChunk(3); - if (southEastChunk != null) { - neighbors.add(southEastChunk); - } - if (southWestChunk != null) { - neighbors.add(southWestChunk); - } - if (northEastChunk != null) { - neighbors.add(northEastChunk); - } - if (northWestChunk != null) { - neighbors.add(northWestChunk); - } - - for (Chunk neighborChunk : neighbors) { - final IMixinChunk neighbor = (IMixinChunk) neighborChunk; - neighbor.getPendingLightUpdates().incrementAndGet(); - neighbor.setLightUpdateTime(chunk.getWorld().getTime()); - } - - if (Akari.isPrimaryThread()) { // Akarin - lightExecutorService.execute(() -> { - this.checkLightAsync(lightType, pos, chunk, neighbors); - }); - } else { - this.checkLightAsync(lightType, pos, chunk, neighbors); - } - - return true; - } - - @Override - public ExecutorService getLightingExecutor() { - return lightExecutorService; - } - - // Thread safe methods to retrieve a chunk during async light updates - // Each method avoids calling getLoadedChunk and instead accesses the passed neighbor chunk list to avoid concurrency issues - public Chunk getLightChunk(BlockPosition pos, Chunk currentChunk, List neighbors) { - if (currentChunk.a(pos.getX() >> 4, pos.getZ() >> 4)) { // OBFHELPER: isAtLocation - if (currentChunk.isUnloading()) { - return null; - } - return currentChunk; - } - for (Chunk neighbor : neighbors) { - if (neighbor.a(pos.getX() >> 4, pos.getZ() >> 4)) { // OBFHELPER: isAtLocation - if (neighbor.isUnloading()) { - return null; - } - return neighbor; - } - } - - return null; - } - - private int getLightForAsync(EnumSkyBlock lightType, BlockPosition pos, Chunk currentChunk, List neighbors) { - if (pos.getY() < 0) { - pos = new BlockPosition(pos.getX(), 0, pos.getZ()); - } - if (!pos.isValidLocation()) { - return lightType.c; // OBFHELPER: defaultLightValue - } - - final Chunk chunk = this.getLightChunk(pos, currentChunk, neighbors); - if (chunk == null || chunk.isUnloading()) { - return lightType.c; // OBFHELPER: defaultLightValue - } - - return chunk.getBrightness(lightType, pos); - } - - private int getRawBlockLightAsync(EnumSkyBlock lightType, BlockPosition pos, Chunk currentChunk, List neighbors) { - final Chunk chunk = getLightChunk(pos, currentChunk, neighbors); - if (chunk == null || chunk.isUnloading()) { - return lightType.c; // OBFHELPER: defaultLightValue - } - if (lightType == EnumSkyBlock.SKY && chunk.c(pos)) { // OBFHELPER: canSeeSky - return 15; - } else { - IBlockData blockData = chunk.getBlockData(pos); - int blockLight = blockData.d(); // getLightValue - int rawLight = lightType == EnumSkyBlock.SKY ? 0 : blockLight; - int opacity = blockData.c(); // OBFHELPER: getLightOpacity - - if (opacity >= 15 && blockLight > 0) { - opacity = 1; - } - - if (opacity < 1) { - opacity = 1; - } - - if (opacity >= 15) { - return 0; - } else if (rawLight >= 14) { - return rawLight; - } else { - for (EnumDirection facing : EnumDirection.values()) { - BlockPosition blockpos = pos.shift(facing); - int current = this.getLightForAsync(lightType, blockpos, currentChunk, neighbors) - opacity; - - if (current > rawLight) { - rawLight = current; - } - - if (rawLight >= 14) { - return rawLight; - } - } - - return rawLight; - } - } - } - - public void setLightForAsync(EnumSkyBlock type, BlockPosition pos, int lightValue, Chunk currentChunk, List neighbors) { - if (pos.isValidLocation()) { - final Chunk chunk = this.getLightChunk(pos, currentChunk, neighbors); - if (chunk != null && !chunk.isUnloading()) { - chunk.a(type, pos, lightValue); // OBFHELPER: setLightFor - // this.notifyLightSet(pos); // client side - } - } - } - - private short blockPosToShort(BlockPosition pos) { - short serialized = (short) setNibble(0, pos.getX() & XZ_MASK, 0, NUM_XZ_BITS); - serialized = (short) setNibble(serialized, pos.getY() & Y_SHORT_MASK, 1, NUM_SHORT_Y_BITS); - serialized = (short) setNibble(serialized, pos.getZ() & XZ_MASK, 3, NUM_XZ_BITS); - return serialized; - } - - /** - * Modifies bits in an integer. - * - * @param num Integer to modify - * @param data Bits of data to add - * @param which Index of nibble to start at - * @param bitsToReplace The number of bits to replace starting from nibble index - * @return The modified integer - */ - private int setNibble(int num, int data, int which, int bitsToReplace) { - return (num & ~(bitsToReplace << (which * 4)) | (data << (which * 4))); - } -} 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 2b1b7446d..66e1d00e2 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 @@ -32,8 +32,6 @@ import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; import net.minecraft.server.ChatComponentText; import net.minecraft.server.EnumProtocolDirection; import net.minecraft.server.HandshakeListener; @@ -54,16 +52,16 @@ public abstract class NonblockingServerConnection { /** * Contains all endpoints added to this NetworkSystem */ - @Shadow(aliases = "g") @Mutable @Final private List endPoints; + @Shadow(aliases = "f") @Mutable @Final private List endPoints; /** * A list containing all NetworkManager instances of all endpoints */ - @Shadow(aliases = "h") @Mutable @Final private List networkManagers; + @Shadow(aliases = "g") @Mutable @Final private List networkManagers; @Overwrite private void addPending() {} // just keep compatibility - @Shadow(aliases = "f") @Final private MinecraftServer server; + @Shadow(aliases = "e") @Final private MinecraftServer server; /** * Adds channels (endpoint) that listens on publicly accessible network ports @@ -77,13 +75,13 @@ public abstract class NonblockingServerConnection { Class channelClass; EventLoopGroup loopGroup; - if (Epoll.isAvailable() && this.server.af()) { // OBFHELPER: MinecraftServer::useNativeTransport + if (Epoll.isAvailable() && this.server.X()) { // OBFHELPER: MinecraftServer::useNativeTransport channelClass = EpollServerSocketChannel.class; - loopGroup = ServerConnection.b.c(); + loopGroup = ServerConnection.b.a(); logger.info("Using epoll channel type"); } else { channelClass = NioServerSocketChannel.class; - loopGroup = ServerConnection.a.c(); + loopGroup = ServerConnection.a.a(); logger.info("Using nio channel type"); } @@ -122,12 +120,12 @@ public abstract class NonblockingServerConnection { } } - @Shadow public volatile boolean d; // OBFHELPER: neverTerminate + @Shadow public volatile boolean c; // OBFHELPER: neverTerminate /** * Shuts down all open endpoints */ public void b() { - this.d = false; + this.c = false; try { synchronized (endPoints) { // safe fixes for (ChannelFuture channel : endPoints) channel.channel().close().sync(); @@ -144,12 +142,7 @@ public abstract class NonblockingServerConnection { logger.warn("Failed to handle packet for {}", manager.getSocketAddress(), ex); final ChatComponentText message = new ChatComponentText("Internal server error"); - manager.sendPacket(new PacketPlayOutKickDisconnect(message), new GenericFutureListener>() { - @Override - public void operationComplete(Future future) throws Exception { - manager.close(message); - } - }, new GenericFutureListener[0]); + manager.sendPacket(new PacketPlayOutKickDisconnect(message), (future) -> manager.close(message)); manager.stopReading(); } } 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 deleted file mode 100644 index 122a28d6b..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/nsc/OptimisticNetworkManager.java +++ /dev/null @@ -1,62 +0,0 @@ -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>[] genericFutureListeners); - - @SuppressWarnings("unchecked") - private static final QueuedPacket SIGNAL_PACKET = new QueuedPacket(null); - - @Overwrite // OBFHELPER: trySendQueue - private boolean m() { - 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.getGenericFutureListeners()); // 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/MixinEntity.java b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntity.java index bc440a694..d52ae2a61 100644 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntity.java +++ b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntity.java @@ -19,7 +19,7 @@ public abstract class MixinEntity { private int lastLavaCheck = Integer.MIN_VALUE; @Overwrite // OBFHELPER: isInLava - public boolean au() { + public boolean ax() { /* * This originally comes from Migot (https://github.com/Poweruser/Migot/commit/cafbf1707107d2a3aa6232879f305975bb1f0285) * Thanks @Poweruser @@ -27,7 +27,7 @@ public abstract class MixinEntity { int currentTick = MinecraftServer.currentTick; if (this.lastLavaCheck != currentTick) { this.lastLavaCheck = currentTick; - this.isInLava = this.world.a(this.getBoundingBox().grow(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), Material.LAVA); + this.isInLava = this.world.a(this.getBoundingBox().f(0.10000000149011612D, 0.4000000059604645D, 0.10000000149011612D), Material.LAVA); } return this.isInLava; } diff --git a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityHorseAbstract.java b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityHorseAbstract.java index 3f41574c0..0528211ed 100644 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityHorseAbstract.java +++ b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityHorseAbstract.java @@ -24,6 +24,7 @@ */ package io.akarin.server.mixin.optimization; +import java.util.Optional; import java.util.UUID; import javax.annotation.Nullable; @@ -33,16 +34,15 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import com.google.common.base.Optional; - import net.minecraft.server.DataWatcherObject; import net.minecraft.server.Entity; import net.minecraft.server.EntityHorseAbstract; +import net.minecraft.server.EntityTypes; import net.minecraft.server.World; @Mixin(value = EntityHorseAbstract.class, remap = false) public abstract class MixinEntityHorseAbstract extends Entity { - @Shadow(aliases = "bJ") @Final private static DataWatcherObject> OWNER_UNIQUE_ID; + @Shadow(aliases = "bO") @Final private static DataWatcherObject> OWNER_UNIQUE_ID; @Nullable private Optional cachedOwnerId; @@ -50,12 +50,12 @@ public abstract class MixinEntityHorseAbstract extends Entity { @Overwrite public UUID getOwnerUUID() { if (cachedOwnerId == null) cachedOwnerId = datawatcher.get(OWNER_UNIQUE_ID); - return cachedOwnerId.orNull(); + return cachedOwnerId.orElse(null); } @Overwrite public void setOwnerUUID(@Nullable UUID uuid) { - cachedOwnerId = Optional.fromNullable(uuid); + cachedOwnerId = Optional.ofNullable(uuid); datawatcher.set(OWNER_UNIQUE_ID, cachedOwnerId); } @@ -63,7 +63,7 @@ public abstract class MixinEntityHorseAbstract extends Entity { * Extends from superclass * @param world */ - public MixinEntityHorseAbstract(World world) { - super(world); + public MixinEntityHorseAbstract(EntityTypes entitytypes, World world) { + super(entitytypes, world); } } diff --git a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityTameableAnimal.java b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityTameableAnimal.java index cb5a95663..1daab4ab2 100644 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityTameableAnimal.java +++ b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinEntityTameableAnimal.java @@ -24,6 +24,7 @@ */ package io.akarin.server.mixin.optimization; +import java.util.Optional; import java.util.UUID; import javax.annotation.Nullable; @@ -33,37 +34,36 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import com.google.common.base.Optional; - import net.minecraft.server.DataWatcherObject; import net.minecraft.server.Entity; import net.minecraft.server.EntityTameableAnimal; +import net.minecraft.server.EntityTypes; import net.minecraft.server.World; @Mixin(value = EntityTameableAnimal.class, remap = false) public abstract class MixinEntityTameableAnimal extends Entity { - @Shadow @Final protected static DataWatcherObject> by; + @Shadow @Final protected static DataWatcherObject> bD; @Nullable private Optional cachedOwnerId; @Nullable @Overwrite public UUID getOwnerUUID() { - if (cachedOwnerId == null) cachedOwnerId = datawatcher.get(by); - return cachedOwnerId.orNull(); + if (cachedOwnerId == null) cachedOwnerId = datawatcher.get(bD); + return cachedOwnerId.orElse(null); } @Overwrite public void setOwnerUUID(@Nullable UUID uuid) { - cachedOwnerId = Optional.fromNullable(uuid); - datawatcher.set(by, cachedOwnerId); + cachedOwnerId = Optional.ofNullable(uuid); + datawatcher.set(bD, cachedOwnerId); } /** * Extends from superclass * @param world */ - public MixinEntityTameableAnimal(World world) { - super(world); + public MixinEntityTameableAnimal(EntityTypes entitytypes, World world) { + super(entitytypes, world); } } 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 index ad972c276..bedd37b97 100644 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinPersistentCollection.java +++ b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinPersistentCollection.java @@ -18,13 +18,13 @@ import net.minecraft.server.PersistentCollection; @Mixin(value = PersistentCollection.class, remap = false) public abstract class MixinPersistentCollection { - @Shadow(aliases = "b") @Final private IDataManager dataManager; + @Shadow(aliases = "c") @Final private IDataManager dataManager; @Overwrite private void a(PersistentBase persistentbase) { if (this.dataManager == null) return; - File file = this.dataManager.getDataFile(persistentbase.id); + File file = this.dataManager.getDataFile(persistentbase.getId()); if (file == null) return; NBTTagCompound nbttagcompound = new NBTTagCompound(); @@ -33,6 +33,7 @@ public abstract class MixinPersistentCollection { // Akarin start MCUtil.scheduleAsyncTask(() -> { try { + nbttagcompound.setInt("DataVersion", 1519); FileOutputStream fileoutputstream = new FileOutputStream(file); NBTCompressedStreamTools.a(nbttagcompound, fileoutputstream); diff --git a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinTileEntityEnchantTable.java b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinTileEntityEnchantTable.java index f5fedc9ae..b7c3e81ae 100644 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinTileEntityEnchantTable.java +++ b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinTileEntityEnchantTable.java @@ -7,5 +7,5 @@ import net.minecraft.server.TileEntityEnchantTable; @Mixin(value = TileEntityEnchantTable.class, remap = false) public abstract class MixinTileEntityEnchantTable { @Overwrite - public void e() {} // No tickable + public void Y_() {} // No tickable } diff --git a/sources/src/main/java/io/akarin/server/mixin/optimization/PandaRedstoneWire.java b/sources/src/main/java/io/akarin/server/mixin/optimization/PandaRedstoneWire.java deleted file mode 100644 index 4581d3f77..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/PandaRedstoneWire.java +++ /dev/null @@ -1,508 +0,0 @@ -package io.akarin.server.mixin.optimization; - -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.ArrayUtils; -import org.bukkit.event.block.BlockRedstoneEvent; -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -import net.minecraft.server.BaseBlockPosition; -import net.minecraft.server.Block; -import net.minecraft.server.BlockDiodeAbstract; -import net.minecraft.server.BlockObserver; -import net.minecraft.server.BlockPiston; -import net.minecraft.server.BlockPosition; -import net.minecraft.server.BlockRedstoneComparator; -import net.minecraft.server.BlockRedstoneTorch; -import net.minecraft.server.BlockRedstoneWire; -import net.minecraft.server.BlockRepeater; -import net.minecraft.server.Blocks; -import net.minecraft.server.EnumDirection; -import net.minecraft.server.IBlockAccess; -import net.minecraft.server.IBlockData; -import net.minecraft.server.Material; -import net.minecraft.server.World; - -@Mixin(value = BlockRedstoneWire.class, remap = false) -public abstract class PandaRedstoneWire extends Block { - - protected PandaRedstoneWire(Material material) { - super(material); - } - - /** Positions that need to be turned off **/ - private List turnOff = Lists.newArrayList(); - /** Positions that need to be checked to be turned on **/ - private List turnOn = Lists.newArrayList(); - /** Positions of wire that was updated already (Ordering determines update order and is therefore required!) **/ - private final Set updatedRedstoneWire = Sets.newLinkedHashSet(); - - /** Ordered arrays of the facings; Needed for the update order. - * I went with a vertical-first order here, but vertical last would work to. - * However it should be avoided to update the vertical axis between the horizontal ones as this would cause unneeded directional behavior. **/ - private static final EnumDirection[] facingsHorizontal = {EnumDirection.WEST, EnumDirection.EAST, EnumDirection.NORTH, EnumDirection.SOUTH}; - private static final EnumDirection[] facingsVertical = {EnumDirection.DOWN, EnumDirection.UP}; - private static final EnumDirection[] facings = ArrayUtils.addAll(facingsVertical, facingsHorizontal); - - /** Offsets for all surrounding blocks that need to receive updates **/ - private static final BaseBlockPosition[] surroundingBlocksOffset; - static { - Set set = Sets.newLinkedHashSet(); - for (EnumDirection facing : facings) { - set.add(facing.getDirectionPosition()); - } - for (EnumDirection facing1 : facings) { - BaseBlockPosition v1 = facing1.getDirectionPosition(); - for (EnumDirection facing2 : facings) { - BaseBlockPosition v2 = facing2.getDirectionPosition(); - set.add(new BaseBlockPosition(v1.getX() + v2.getX(), v1.getY() + v2.getY(), v1.getZ() + v2.getZ())); - } - } - set.remove(BaseBlockPosition.ZERO); - surroundingBlocksOffset = set.toArray(new BaseBlockPosition[set.size()]); - } - - @Shadow(aliases = "g") private boolean canProvidePower; - @Shadow public abstract int getPower(World world, BlockPosition pos, int strength); - @Shadow(aliases = "b") public abstract boolean isPowerSourceAt(IBlockAccess worldIn, BlockPosition pos, EnumDirection side); - - @Inject(method = "e", at = @At("HEAD"), cancellable = true) - private void onUpdateSurroundingRedstone(World worldIn, BlockPosition pos, IBlockData state, CallbackInfoReturnable cir) { - this.updateSurroundingRedstone(worldIn, pos); - cir.setReturnValue(state); - } - - @Inject(method = "a*", at = @At("HEAD"), cancellable = true) - private void onCalculateCurrentChanges(World worldIn, BlockPosition pos1, BlockPosition pos2, IBlockData state, CallbackInfoReturnable cir) { - this.calculateCurrentChanges(worldIn, pos1); - cir.setReturnValue(state); - } - - /** - * Recalculates all surrounding wires and causes all needed updates - * - * @author panda - * - * @param world World - * @param pos Position that needs updating - */ - private void updateSurroundingRedstone(World world, BlockPosition pos) { - // Recalculate the connected wires - this.calculateCurrentChanges(world, pos); - - // Set to collect all the updates, to only execute them once. Ordering required. - Set blocksNeedingUpdate = Sets.newLinkedHashSet(); - - // Add the needed updates - for (BlockPosition posi : this.updatedRedstoneWire) { - this.addBlocksNeedingUpdate(world, posi, blocksNeedingUpdate); - } - // Add all other updates to keep known behaviors - // They are added in a backwards order because it preserves a commonly used behavior with the update order - Iterator it = Lists.newLinkedList(this.updatedRedstoneWire).descendingIterator(); - while (it.hasNext()) { - this.addAllSurroundingBlocks(it.next(), blocksNeedingUpdate); - } - // Remove updates on the wires as they just were updated - blocksNeedingUpdate.removeAll(this.updatedRedstoneWire); - /* - * Avoid unnecessary updates on the just updated wires A huge scale test - * showed about 40% more ticks per second It's probably less in normal - * usage but likely still worth it - */ - this.updatedRedstoneWire.clear(); - - // Execute updates - for (BlockPosition posi : blocksNeedingUpdate) { - world.applyPhysics(posi, (BlockRedstoneWire) (Object) this, false); - } - } - - /** - * Turns on or off all connected wires - * - * @param worldIn World - * @param position Position of the wire that received the update - */ - private void calculateCurrentChanges(World worldIn, BlockPosition position) { - // Turn off all connected wires first if needed - if (worldIn.getType(position).getBlock() == (BlockRedstoneWire) (Object) this) { - turnOff.add(position); - } else { - // In case this wire was removed, check the surrounding wires - this.checkSurroundingWires(worldIn, position); - } - - while (!turnOff.isEmpty()) { - BlockPosition pos = turnOff.remove(0); - IBlockData state = worldIn.getType(pos); - int oldPower = state.get(BlockRedstoneWire.POWER).intValue(); - this.canProvidePower = false; - int blockPower = worldIn.z(pos); // OBFHELPER: isBlockIndirectlyGettingPowered - this.canProvidePower = true; - int wirePower = this.getSurroundingWirePower(worldIn, pos); - - // Lower the strength as it moved a block - wirePower--; - int newPower = Math.max(blockPower, wirePower); - - // Akarin start - BlockRedstoneEvent - if (oldPower != newPower) { - BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), oldPower, newPower); - worldIn.getServer().getPluginManager().callEvent(event); - newPower = event.getNewCurrent(); - } - // Akarin end - - // Power lowered? - if (newPower < oldPower) { - // If it's still powered by a direct source (but weaker) mark for turn on - if (blockPower > 0 && !this.turnOn.contains(pos)) { - this.turnOn.add(pos); - } - // Set all the way to off for now, because wires that were powered by this need to update first - setWireState(worldIn, pos, state, 0); - // Power rose? - } else if (newPower > oldPower) { - // Set new Power - this.setWireState(worldIn, pos, state, newPower); - } - // Check if surrounding wires need to change based on the current/new state and add them to the lists - this.checkSurroundingWires(worldIn, pos); - } - // Now all needed wires are turned off. Time to turn them on again if there is a power source. - while (!this.turnOn.isEmpty()) { - BlockPosition pos = this.turnOn.remove(0); - IBlockData state = worldIn.getType(pos); - int oldPower = state.get(BlockRedstoneWire.POWER).intValue(); - this.canProvidePower = false; - int blockPower = worldIn.z(pos); // OBFHELPER: isBlockIndirectlyGettingPowered - this.canProvidePower = true; - int wirePower = this.getSurroundingWirePower(worldIn, pos); - // Lower the strength as it moved a block - wirePower--; - int newPower = Math.max(blockPower, wirePower); - - // Akarin start - BlockRedstoneEvent - BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), oldPower, newPower); - worldIn.getServer().getPluginManager().callEvent(event); - newPower = event.getNewCurrent(); - // Akarin end - - if (newPower > oldPower) { - setWireState(worldIn, pos, state, newPower); - } else if (newPower < oldPower) { - // Add warning - } - // Check if surrounding wires need to change based on the current/new state and add them to the lists - this.checkSurroundingWires(worldIn, pos); - } - this.turnOff.clear(); - this.turnOn.clear(); - } - - /** - * Checks if an wire needs to be marked for update depending on the power next to it - * - * @author panda - * - * @param worldIn World - * @param pos Position of the wire that might need to change - * @param otherPower Power of the wire next to it - */ - private void addWireToList(World worldIn, BlockPosition pos, int otherPower) { - IBlockData state = worldIn.getType(pos); - if (state.getBlock() == (BlockRedstoneWire) (Object) this) { - int power = state.get(BlockRedstoneWire.POWER).intValue(); - // Could get powered stronger by the neighbor? - if (power < (otherPower - 1) && !this.turnOn.contains(pos)) { - // Mark for turn on check. - this.turnOn.add(pos); - } - // Should have powered the neighbor? Probably was powered by it and is in turn off phase. - if (power > otherPower && !this.turnOff.contains(pos)) { - // Mark for turn off check. - this.turnOff.add(pos); - } - } - } - - /** - * Checks if the wires around need to get updated depending on this wires state. - * Checks all wires below before the same layer before on top to keep - * some more rotational symmetry around the y-axis. - * - * @author panda - * - * @param worldIn World - * @param pos Position of the wire - */ - private void checkSurroundingWires(World worldIn, BlockPosition pos) { - IBlockData state = worldIn.getType(pos); - int ownPower = 0; - if (state.getBlock() == (BlockRedstoneWire) (Object) this) { - ownPower = state.get(BlockRedstoneWire.POWER).intValue(); - } - // Check wires on the same layer first as they appear closer to the wire - for (EnumDirection facing : facingsHorizontal) { - BlockPosition offsetPos = pos.shift(facing); - if (facing.getAxis().isHorizontal()) { - this.addWireToList(worldIn, offsetPos, ownPower); - } - } - for (EnumDirection facingVertical : facingsVertical) { - BlockPosition offsetPos = pos.shift(facingVertical); - boolean solidBlock = worldIn.getType(offsetPos).k(); // OBFHELPER: isBlockNormalCube - for (EnumDirection facingHorizontal : facingsHorizontal) { - // wire can travel upwards if the block on top doesn't cut the wire (is non-solid) - // it can travel down if the block below is solid and the block "diagonal" doesn't cut off the wire (is non-solid) - if ((facingVertical == EnumDirection.UP && !solidBlock) || (facingVertical == EnumDirection.DOWN && solidBlock && !worldIn.getType(offsetPos.shift(facingHorizontal)).k())) { // OBFHELPER: isBlockNormalCube - this.addWireToList(worldIn, offsetPos.shift(facingHorizontal), ownPower); - } - } - } - } - - /** - * Gets the maximum power of the surrounding wires - * - * @author panda - * - * @param worldIn World - * @param pos Position of the asking wire - * @return The maximum power of the wires that could power the wire at pos - */ - private int getSurroundingWirePower(World worldIn, BlockPosition pos) { - int wirePower = 0; - for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { - BlockPosition offsetPos = pos.shift(enumfacing); - // Wires on the same layer - wirePower = this.getPower(worldIn, offsetPos, wirePower); - - // Block below the wire need to be solid (Upwards diode of slabs/stairs/glowstone) and no block should cut the wire - if(worldIn.getType(offsetPos).l() && !worldIn.getType(pos.up()).l()) { // OBFHELPER: isNormalCube - wirePower = this.getPower(worldIn, offsetPos.up(), wirePower); - // Only get from power below if no block is cutting the wire - } else if (!worldIn.getType(offsetPos).l()) { // OBFHELPER: isNormalCube - wirePower = this.getPower(worldIn, offsetPos.down(), wirePower); - } - } - return wirePower; - } - - /** - * Adds all blocks that need to receive an update from a redstone change in this position. - * This means only blocks that actually could change. - * - * @author panda - * - * @param worldIn World - * @param pos Position of the wire - * @param set Set to add the update positions too - */ - private void addBlocksNeedingUpdate(World worldIn, BlockPosition pos, Set set) { - List connectedSides = this.getSidesToPower(worldIn, pos); - // Add the blocks next to the wire first (closest first order) - for (EnumDirection facing : facings) { - BlockPosition offsetPos = pos.shift(facing); - // canConnectTo() is not the nicest solution here as it returns true for e.g. the front of a repeater - // canBlockBePowereFromSide catches these cases - if (!connectedSides.contains(facing.opposite()) && facing != EnumDirection.DOWN - && (!facing.getAxis().isHorizontal() || canConnectToBlock(worldIn.getType(offsetPos), facing))) continue; - if (this.canBlockBePoweredFromSide(worldIn.getType(offsetPos), facing, true)) - set.add(offsetPos); - } - // Later add blocks around the surrounding blocks that get powered - for (EnumDirection facing : facings) { - BlockPosition offsetPos = pos.shift(facing); - if (!connectedSides.contains(facing.opposite()) && facing != EnumDirection.DOWN || !worldIn.getType(offsetPos).l()) continue; // OBFHELPER: isNormalCube - for (EnumDirection facing1 : facings) { - if (this.canBlockBePoweredFromSide(worldIn.getType(offsetPos.shift(facing1)), facing1, false)) - set.add(offsetPos.shift(facing1)); - } - } - } - - /** - * Checks if a block can get powered from a side. - * This behavior would better be implemented per block type as follows: - * - return false as default. (blocks that are not affected by redstone don't need to be updated, it doesn't really hurt if they are either) - * - return true for all blocks that can get powered from all side and change based on it (doors, fence gates, trap doors, note blocks, lamps, dropper, hopper, TNT, rails, possibly more) - * - implement own logic for pistons, repeaters, comparators and redstone torches - * The current implementation was chosen to keep everything in one class. - * - * Why is this extra check needed? - * 1. It makes sure that many old behaviors still work (QC + Pistons). - * 2. It prevents updates from "jumping". - * Or rather it prevents this wire to update a block that would get powered by the next one of the same line. - * This is to prefer as it makes understanding the update order of the wire really easy. The signal "travels" from the power source. - * - * @author panda - * - * @param state State of the block - * @param side Side from which it gets powered - * @param isWire True if it's powered by a wire directly, False if through a block - * @return True if the block can change based on the power level it gets on the given side, false otherwise - */ - private boolean canBlockBePoweredFromSide(IBlockData state, EnumDirection side, boolean isWire) { - if (state.getBlock() instanceof BlockPiston && state.get(BlockPiston.FACING) == side.opposite()) { - return false; - } - if (state.getBlock() instanceof BlockDiodeAbstract && state.get(BlockDiodeAbstract.FACING) != side.opposite()) { - if (isWire && state.getBlock() instanceof BlockRedstoneComparator - && state.get(BlockRedstoneComparator.FACING).k() != side.getAxis() && side.getAxis().isHorizontal()) { - return true; - } - return false; - } - if (state.getBlock() instanceof BlockRedstoneTorch) { - if (isWire || state.get(BlockRedstoneTorch.FACING) != side) { - return false; - } - } - return true; - } - - /** - * Creates a list of all horizontal sides that can get powered by a wire. - * The list is ordered the same as the facingsHorizontal. - * - * @param worldIn World - * @param pos Position of the wire - * @return List of all facings that can get powered by this wire - */ - private List getSidesToPower(World worldIn, BlockPosition pos) { - List retval = Lists.newArrayList(); - for (EnumDirection facing : facingsHorizontal) { - if (isPowerSourceAt(worldIn, pos, facing)) - retval.add(facing); - } - if (retval.isEmpty()) return Lists.newArrayList(facingsHorizontal); - boolean northsouth = retval.contains(EnumDirection.NORTH) || retval.contains(EnumDirection.SOUTH); - boolean eastwest = retval.contains(EnumDirection.EAST) || retval.contains(EnumDirection.WEST); - if (northsouth) { - retval.remove(EnumDirection.EAST); - retval.remove(EnumDirection.WEST); - } - if (eastwest) { - retval.remove(EnumDirection.NORTH); - retval.remove(EnumDirection.SOUTH); - } - return retval; - } - - /** - * Adds all surrounding positions to a set. - * This is the neighbor blocks, as well as their neighbors - * - * @param pos - * @param set - */ - private void addAllSurroundingBlocks(BlockPosition pos, Set set) { - for (BaseBlockPosition vect : surroundingBlocksOffset) { - set.add(pos.a(vect)); // OBFHELPER: add - } - } - - /** - * Sets the block state of a wire with a new power level and marks for updates - * - * @author panda - * - * @param worldIn World - * @param pos Position at which the state needs to be set - * @param state Old state - * @param power Power it should get set to - */ - private void setWireState(World worldIn, BlockPosition pos, IBlockData state, int power) { - state = state.set(BlockRedstoneWire.POWER, Integer.valueOf(power)); - worldIn.setTypeAndData(pos, state, 2); - updatedRedstoneWire.add(pos); - } - - /** - * @author panda - * @reason Uses local surrounding block offset list for notifications. - * - * @param world The world - * @param pos The position - * @param state The block state - */ - @Override - @Overwrite - public void onPlace(World world, BlockPosition pos, IBlockData state) { - this.updateSurroundingRedstone(world, pos); - for (BaseBlockPosition vec : surroundingBlocksOffset) { - world.applyPhysics(pos.a(vec), this, false); // OBFHELPER: add - } - } - - /** - * @author panda - * @reason Uses local surrounding block offset list for notifications. - * - * @param world The world - * @param pos The position - */ - @Override - @Overwrite - public void remove(World world, BlockPosition pos, IBlockData state) { - super.remove(world, pos, state); - this.updateSurroundingRedstone(world, pos); - for (BaseBlockPosition vec : surroundingBlocksOffset) { - world.applyPhysics(pos.a(vec), this, false); // OBFHELPER: add - } - } - - /** - * @author panda - * @reason Changed to use getSidesToPower() to avoid duplicate implementation. - * - * @param blockState The block state - * @param blockAccess The block access - * @param pos The position - * @param side The side - */ - @Override - @Overwrite - public int b(IBlockData blockState, IBlockAccess blockAccess, BlockPosition pos, EnumDirection side) { // OBFHELPER: getWeakPower - if (!this.canProvidePower) { - return 0; - } else { - if (side == EnumDirection.UP || this.getSidesToPower((World) blockAccess, pos).contains(side)) { - return blockState.get(BlockRedstoneWire.POWER).intValue(); - } else { - return 0; - } - } - } - - private static boolean canConnectToBlock(IBlockData blockState, @Nullable EnumDirection side) { - Block block = blockState.getBlock(); - - if (block == Blocks.REDSTONE_WIRE) { - return true; - } else if (Blocks.UNPOWERED_REPEATER.D(blockState)) { // OBFHELPER: isSameDiode - EnumDirection enumdirection1 = blockState.get(BlockRepeater.FACING); - - return enumdirection1 == side || enumdirection1.opposite() == side; - } else if (Blocks.dk == blockState.getBlock()) { - return side == blockState.get(BlockObserver.FACING); // OBFHELPER: OBSERVER - } else { - return blockState.m() && side != null; // OBFHELPER: canProvidePower - } - } - -} diff --git a/sources/src/main/java/io/akarin/server/mixin/optimization/WeakBigTree.java b/sources/src/main/java/io/akarin/server/mixin/optimization/WeakBigTree.java deleted file mode 100644 index 707baecc6..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/WeakBigTree.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.akarin.server.mixin.optimization; - -import java.util.Random; - -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import net.minecraft.server.BlockPosition; -import net.minecraft.server.World; -import net.minecraft.server.WorldGenBigTree; - -/** - * Fixes MC-128547(https://bugs.mojang.com/browse/MC-128547) - */ -@Mixin(value = WorldGenBigTree.class, remap = false) -public abstract class WeakBigTree { - @Shadow(aliases = "l") private World worldReference; - - @Inject(method = "generate", at = @At("RETURN")) - private void clearWorldRef(World world, Random random, BlockPosition pos, CallbackInfoReturnable info) { - world = null; // Akarin - remove references to world objects to avoid memory leaks - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/optimization/WeakEnchantmentManager.java b/sources/src/main/java/io/akarin/server/mixin/optimization/WeakEnchantmentManager.java deleted file mode 100644 index 5e952b042..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/WeakEnchantmentManager.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.optimization; - -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 net.minecraft.server.DamageSource; -import net.minecraft.server.EnchantmentManager; -import net.minecraft.server.Entity; -import net.minecraft.server.EntityHuman; -import net.minecraft.server.EntityLiving; -import net.minecraft.server.ItemStack; - -/** - * Fixes MC-128547(https://bugs.mojang.com/browse/MC-128547) - */ -@Mixin(value = EnchantmentManager.class, remap = false) -public abstract class WeakEnchantmentManager { - @Shadow(aliases = "a") @Final private static EnchantmentManager.EnchantmentModifierProtection protection; - @Shadow(aliases = "c") @Final private static EnchantmentManager.EnchantmentModifierThorns thorns; - @Shadow(aliases = "d") @Final private static EnchantmentManager.EnchantmentModifierArthropods arthropods; - - @Shadow private static void a(EnchantmentManager.EnchantmentModifier modifier, Iterable iterable) {} - @Shadow private static void a(EnchantmentManager.EnchantmentModifier modifier, ItemStack itemstack) {} - - @Overwrite - public static int a(Iterable iterable, DamageSource damageSource) { - protection.a = 0; // OBFHELPER: damageModifier - protection.b = damageSource; - a(protection, iterable); // OBFHELPER: applyEnchantmentModifierArray - protection.b = null; // Akarin - Remove reference to Damagesource - return protection.a; - } - - @Overwrite - public static void a(EntityLiving user, Entity attacker) { // OBFHELPER: applyThornEnchantments - thorns.b = attacker; - thorns.a = user; - if (user != null) { - a(thorns, user.aQ()); // OBFHELPER: applyEnchantmentModifierArray - getEquipmentAndArmor - } - - if (attacker instanceof EntityHuman) { - a(thorns, user.getItemInMainHand()); // OBFHELPER: applyEnchantmentModifier - } - - // Akarin Start - remove references to entity objects to avoid memory leaks - thorns.b = null; - thorns.a = null; - // Akarin end - } - - @Overwrite - public static void b(EntityLiving user, Entity target) { // OBFHELPER: applyArthropodEnchantments - arthropods.a = user; - arthropods.b = target; - if (user != null) { - a(arthropods, user.aQ()); // OBFHELPER: applyEnchantmentModifierArray - getEquipmentAndArmor - } - - if (user instanceof EntityHuman) { - a(arthropods, user.getItemInMainHand()); // OBFHELPER: applyEnchantmentModifier - } - - // Akarin Start - remove references to entity objects to avoid memory leaks - arthropods.a = null; - arthropods.b = null; - // Akarin end - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntity.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntity.java deleted file mode 100644 index 972ee72db..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntity.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.Entity; -import net.minecraft.server.World; - -@Mixin(value = Entity.class, remap = false, priority = 1001) -public abstract class MixinEntity { - private static final String ENTITY_RIDABLE_COOLDOWN_FIELD = "Lnet/minecraft/entity/Entity;j:I"; // PUTFIELD: rideCooldown - private static final String ENTITY_PORTAL_COUNTER_FIELD = "Lnet/minecraft/entity/Entity;al:I"; // PUTFIELD: portalCounter - @Shadow protected int j; - @Shadow protected int al; - @Shadow public World world; - - // OBFHELPER: onEntityUpdate - @Redirect(method = "Y()V", at = @At(value = "FIELD", target = ENTITY_RIDABLE_COOLDOWN_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupEntityCooldown(Entity self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.world).getRealTimeTicks(); - this.j = Math.max(0, this.j - ticks); // OBFHELPER: rideCooldown - } - - @Redirect(method = "Y()V", at = @At(value = "FIELD", target = ENTITY_PORTAL_COUNTER_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupPortalCounter(Entity self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.world).getRealTimeTicks(); - this.al += ticks; // OBFHELPER: portalCounter - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityAgeable.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityAgeable.java deleted file mode 100644 index 9ee712b3e..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityAgeable.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.EntityAgeable; - -@Mixin(value = EntityAgeable.class, remap = false) -public abstract class MixinEntityAgeable { - private static final String ENTITY_AGEABLE_SET_GROWING_AGE_METHOD = "Lnet/minecraft/entity/EntityAgeable;setAgeRaw(I)V"; - - // OBFHELPER: onLivingUpdate - @Redirect(method = "n()V", at = @At(value = "INVOKE", target = ENTITY_AGEABLE_SET_GROWING_AGE_METHOD, ordinal = 0)) - public void fixupGrowingUp(EntityAgeable self, int age) { - // Subtract the one the original update method added - int diff = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks() - 1; - self.setAgeRaw(Math.min(0, age + diff)); - } - - @Redirect(method = "n()V", at = @At(value = "INVOKE", target = ENTITY_AGEABLE_SET_GROWING_AGE_METHOD, ordinal = 1)) - public void fixupBreedingCooldown(EntityAgeable self, int age) { - // Subtract the one the original update method added - int diff = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks() - 1; - self.setAgeRaw(Math.max(0, age - diff)); - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityExperienceOrb.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityExperienceOrb.java deleted file mode 100644 index 331c38ee9..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityExperienceOrb.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.EntityExperienceOrb; - -@Mixin(value = EntityExperienceOrb.class, remap = false) -public abstract class MixinEntityExperienceOrb { - private static final String ENTITY_XP_DELAY_PICKUP_FIELD = "Lnet/minecraft/entity/item/EntityExperienceOrb;c:I"; // PUTFIELD: delayBeforeCanPickup - private static final String ENTITY_XP_AGE_FIELD = "Lnet/minecraft/entity/item/EntityExperienceOrb;b:I"; // PUTFIELD: xpOrbAge - @Shadow public int c; // OBFHELPER: delayBeforeCanPickup - @Shadow public int b; // OBFHELPER: xpOrbAge - - // OBFHELPER: onUpdate - @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_XP_DELAY_PICKUP_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupPickupDelay(EntityExperienceOrb self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.c = Math.max(0, this.c - ticks); // OBFHELPER: delayBeforeCanPickup - } - - @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_XP_AGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupAge(EntityExperienceOrb self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.b += ticks; // OBFHELPER: xpOrbAge - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityHuman.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityHuman.java deleted file mode 100644 index b489ac23d..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityHuman.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.EntityHuman; - -@Mixin(value = EntityHuman.class, remap = false) -public abstract class MixinEntityHuman { - private static final String ENTITY_PLAYER_XP_COOLDOWN_FIELD = "Lnet/minecraft/entity/player/EntityHuman;bD:I"; // PUTFIELD: xpCooldown - private static final String ENTITY_PLAYER_SLEEP_TIMER_FIELD = "Lnet/minecraft/entity/player/EntityHuman;sleepTicks:I"; - @Shadow public int bD; - @Shadow private int sleepTicks; - - // OBFHELPER: onUpdate - @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_XP_COOLDOWN_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupXpCooldown(EntityHuman self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.bD = Math.max(0, this.bD - ticks); // OBFHELPER: xpCooldown - } - - @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_SLEEP_TIMER_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupSleepTimer(EntityHuman self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.sleepTicks += ticks; - } - - @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_SLEEP_TIMER_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 2)) - public void fixupWakeTimer(EntityHuman self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.sleepTicks += ticks; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityInsentient.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityInsentient.java deleted file mode 100644 index 010e7e6ab..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityInsentient.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.EntityInsentient; -import net.minecraft.server.EntityLiving; -import net.minecraft.server.World; - -@Mixin(value = EntityInsentient.class, remap = false) -public abstract class MixinEntityInsentient extends EntityLiving { - private static final String ENTITY_LIVING_AGE_FIELD = "Lnet/minecraft/entity/EntityInsentient;ticksFarFromPlayer:I"; - - public MixinEntityInsentient(World world) { - super(world); - } - - @Redirect(method = "doTick()V", at = @At(value = "FIELD", target = ENTITY_LIVING_AGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupEntityDespawnAge(EntityInsentient self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.ticksFarFromPlayer += ticks; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityItem.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityItem.java deleted file mode 100644 index 1c56aae6a..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityItem.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.EntityItem; - -@Mixin(value = EntityItem.class, remap = false) -public abstract class MixinEntityItem { - private static final String ENTITY_ITEM_DELAY_PICKUP_FIELD = "Lnet/minecraft/entity/item/EntityItem;pickupDelay:I"; - private static final String ENTITY_ITEM_AGE_FIELD = "Lnet/minecraft/entity/item/EntityItem;age:I"; - @Shadow public int age; - @Shadow private int pickupDelay; - - // OBFHELPER: onUpdate - @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_ITEM_DELAY_PICKUP_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupPickupDelay(EntityItem self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.pickupDelay = Math.max(0, this.pickupDelay - ticks); - } - - @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_ITEM_AGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupAge(EntityItem self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.age += ticks; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityPlayer.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityPlayer.java deleted file mode 100644 index 0a9976e2b..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityPlayer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.Entity; -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.World; - -@Mixin(value = EntityPlayer.class, remap = false) -public abstract class MixinEntityPlayer extends Entity { - private static final String ENTITY_PLAYER_MP_PORTAL_COOLDOWN_FIELD = "Lnet/minecraft/entity/player/EntityPlayer;portalCooldown:I"; - - public MixinEntityPlayer(World worldIn) { - super(worldIn); - } - - // OBFHELPER: decrementTimeUntilPortal - @Redirect(method = "I()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_MP_PORTAL_COOLDOWN_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupPortalCooldown(EntityPlayer self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - this.portalCooldown = Math.max(0, this.portalCooldown - ticks); - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityZombieVillager.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityZombieVillager.java deleted file mode 100644 index 6057452ac..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityZombieVillager.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.EntityZombieVillager; - -@Mixin(value = EntityZombieVillager.class, remap = false) -public abstract class MixinEntityZombieVillager { - private static final String ENTITY_ZOMBIE_GET_CONVERSION_BOOST_METHOD = "Lnet/minecraft/entity/monster/EntityZombieVillager;du()I"; // INVOKE: getConversionProgress - - @Shadow(aliases = "du") protected abstract int getConversionProgress(); - - // OBFHELPER: onUpdate - @Redirect(method = "B_()V", at = @At(value = "INVOKE", target = ENTITY_ZOMBIE_GET_CONVERSION_BOOST_METHOD, ordinal = 0)) - public int fixupConversionTimeBoost(EntityZombieVillager self) { - int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); - return this.getConversionProgress() * ticks; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinMinecraftServer.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinMinecraftServer.java deleted file mode 100644 index 9b74001d2..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinMinecraftServer.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.MinecraftServer; - -@Mixin(value = MinecraftServer.class, remap = false, priority = 1001) -public abstract class MixinMinecraftServer implements IMixinRealTimeTicking { - private static long lastTickNanos = System.nanoTime(); - private static long realTimeTicks = 1; - - @Inject(method = "C()V", at = @At("HEAD")) // OBFHELPER: fullTick - public void onTickUpdateRealTimeTicks(CallbackInfo ci) { - long currentNanos = System.nanoTime(); - realTimeTicks = (currentNanos - lastTickNanos) / 50000000; - if (realTimeTicks < 1) { - realTimeTicks = 1; - } - lastTickNanos = currentNanos; - } - - @Override - public long getRealTimeTicks() { - return realTimeTicks; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerConnection.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerConnection.java deleted file mode 100644 index 766100ae4..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerConnection.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.PlayerConnection; - -@Mixin(value = PlayerConnection.class, remap = false) -public abstract class MixinPlayerConnection { - private static final String NET_HANDLER_PLAY_CHAT_SPAM_FIELD = "Lnet/minecraft/network/PlayerConnection;chatThrottle:I"; - private static final String NET_HANDLER_PLAY_DROP_SPAM_FIELD = "Lnet/minecraft/network/PlayerConnection;itemDropThreshold:I"; - @Shadow private volatile int chatThrottle; - @Shadow(aliases = "j") private int itemDropThreshold; - @Shadow @Final private MinecraftServer minecraftServer; - - // OBFHELPER: update - @Redirect(method = "e()V", at = @At(value = "FIELD", target = NET_HANDLER_PLAY_CHAT_SPAM_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupChatSpamCheck(PlayerConnection self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.minecraftServer).getRealTimeTicks(); - this.chatThrottle = Math.max(0, this.chatThrottle - ticks); - } - - @Redirect(method = "e()V", at = @At(value = "FIELD", target = NET_HANDLER_PLAY_DROP_SPAM_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupDropSpamCheck(PlayerConnection self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.minecraftServer).getRealTimeTicks(); - this.itemDropThreshold = Math.max(0, this.itemDropThreshold - ticks); - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerInteractManager.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerInteractManager.java deleted file mode 100644 index 9da5ce455..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerInteractManager.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.PlayerInteractManager; -import net.minecraft.server.World; - -@Mixin(value = PlayerInteractManager.class, remap = false) -public abstract class MixinPlayerInteractManager { - private static final String PLAYER_INTERACTION_BLOCK_DAMAGE_FIELD = "Lnet/minecraft/server/management/PlayerInteractManager;currentTick:I"; - @Shadow public World world; - @Shadow private int currentTick; - - // OBFHELPER: updateBlockRemoving - @Redirect(method = "a()V", at = @At(value = "FIELD", target = PLAYER_INTERACTION_BLOCK_DAMAGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupDiggingTime(PlayerInteractManager self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.world.getMinecraftServer()).getRealTimeTicks(); - this.currentTick += ticks; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityBrewingStand.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityBrewingStand.java deleted file mode 100644 index e3af414bd..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityBrewingStand.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.TileEntity; -import net.minecraft.server.TileEntityBrewingStand; - -@Mixin(value = TileEntityBrewingStand.class, remap = false) -public abstract class MixinTileEntityBrewingStand extends TileEntity { - private static final String BREWING_STAND_BREW_TIME_FIELD = "Lnet/minecraft/tileentity/TileEntityBrewingStand;brewTime:I"; - @Shadow private int brewTime; - - // OBFHELPER: update - @Redirect(method = "e()V", at = @At(value = "FIELD", target = BREWING_STAND_BREW_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupBrewTime(TileEntityBrewingStand self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); - this.brewTime = Math.max(0, this.brewTime - ticks); - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityFurnace.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityFurnace.java deleted file mode 100644 index 0ffdf5de1..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityFurnace.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.spongepowered.asm.lib.Opcodes; -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 io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.MathHelper; -import net.minecraft.server.TileEntity; -import net.minecraft.server.TileEntityFurnace; - -@Mixin(value = TileEntityFurnace.class, remap = false) -public abstract class MixinTileEntityFurnace extends TileEntity { - private static final String FURNACE_BURN_TIME_FIELD = "Lnet/minecraft/tileentity/TileEntityFurnace;burnTime:I"; - private static final String FURNACE_COOK_TIME_FIELD = "Lnet/minecraft/tileentity/TileEntityFurnace;cookTime:I"; - @Shadow private int burnTime; - @Shadow private int cookTime; - @Shadow private int cookTimeTotal; - - // OBFHELPER: update - @Redirect(method = "e()V", at = @At(value = "FIELD", target = FURNACE_BURN_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupBurnTime(TileEntityFurnace self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); - this.burnTime = Math.max(0, this.burnTime - ticks); - } - - @Redirect(method = "e()V", at = @At(value = "FIELD", target = FURNACE_COOK_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) - public void fixupCookTime(TileEntityFurnace self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); - this.cookTime = Math.min(this.cookTimeTotal, this.cookTime + ticks); - } - - @Redirect(method = "e()V", at = @At(value = "FIELD", target = FURNACE_COOK_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 3)) - public void fixupCookTimeCooldown(TileEntityFurnace self, int modifier) { - int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); - this.cookTime = MathHelper.clamp(this.cookTime - (2 * ticks), 0, this.cookTimeTotal); - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorld.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorld.java deleted file mode 100644 index d614f77a4..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorld.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import javax.annotation.Nullable; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.World; - -@Mixin(value = World.class, remap = false, priority = 1001) -public abstract class MixinWorld implements IMixinRealTimeTicking { - @Shadow @Nullable public abstract MinecraftServer getMinecraftServer(); - - @Override - public long getRealTimeTicks() { - if (this.getMinecraftServer() != null) { - return ((IMixinRealTimeTicking) this.getMinecraftServer()).getRealTimeTicks(); - } - return 1; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorldServer.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorldServer.java deleted file mode 100644 index 88d4da4c0..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorldServer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of Sponge, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package io.akarin.server.mixin.realtime; - -import org.bukkit.World.Environment; -import org.bukkit.generator.ChunkGenerator; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import io.akarin.api.internal.mixin.IMixinRealTimeTicking; -import net.minecraft.server.IDataManager; -import net.minecraft.server.MethodProfiler; -import net.minecraft.server.World; -import net.minecraft.server.WorldData; -import net.minecraft.server.WorldProvider; -import net.minecraft.server.WorldServer; - -@Mixin(value = WorldServer.class, remap = false, priority = 1001) -public abstract class MixinWorldServer extends World implements IMixinRealTimeTicking { - - protected MixinWorldServer(IDataManager idatamanager, WorldData worlddata, WorldProvider worldprovider, MethodProfiler methodprofiler, boolean flag, ChunkGenerator gen, Environment env) { - super(idatamanager, worlddata, worldprovider, methodprofiler, flag, gen, env); - } - - @Inject(method = "doTick()V", at = @At("HEAD")) - public void fixTimeOfDay(CallbackInfo ci) { - if (this.getGameRules().getBoolean("doDaylightCycle")) { - // Subtract the one the original tick method is going to add - long diff = this.getRealTimeTicks() - 1; - // Don't set if we're not changing it as other mods might be listening for changes - if (diff > 0) { - this.worldData.setDayTime(this.worldData.getDayTime() + diff); - } - } - } - -} diff --git a/sources/src/main/java/net/minecraft/server/Chunk.java b/sources/src/main/java/net/minecraft/server/Chunk.java deleted file mode 100644 index cc6416146..000000000 --- a/sources/src/main/java/net/minecraft/server/Chunk.java +++ /dev/null @@ -1,1550 +0,0 @@ -package net.minecraft.server; - -import com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode; -import com.destroystokyo.paper.exception.ServerInternalException; -import com.google.common.base.Predicate; -import com.google.common.collect.Queues; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ConcurrentLinkedQueue; -import javax.annotation.Nullable; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import com.google.common.collect.Lists; // CraftBukkit -import org.bukkit.Server; // CraftBukkit -import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - -/** - * Akarin Changes Note - * 1) Add volatile to fields (async lighting) - * 2) Expose private methods (async lighting) - */ -public class Chunk { - - private static final Logger e = LogManager.getLogger(); - public static final ChunkSection a = null; public static final ChunkSection EMPTY_CHUNK_SECTION = Chunk.a; // Paper - OBFHELPER - private final ChunkSection[] sections; - private final byte[] g; - private final int[] h; - private final boolean[] i; - private boolean j; public boolean isLoaded() { return j; } // Paper - OBFHELPER - public final World world; - public final int[] heightMap; - public Long scheduledForUnload; // Paper - delay chunk unloads - private static final Logger logger = LogManager.getLogger(); // Paper - public final int locX; - public final int locZ; - private boolean m; - public final Map tileEntities; - public final List[] entitySlices; // Spigot - // Paper start - public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); - public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); - private class TileEntityHashMap extends java.util.HashMap { - @Override - public TileEntity put(BlockPosition key, TileEntity value) { - TileEntity replaced = super.put(key, value); - if (replaced != null) { - replaced.setCurrentChunk(null); - tileEntityCounts.decrement(replaced.tileEntityKeyString); - } - if (value != null) { - value.setCurrentChunk(Chunk.this); - tileEntityCounts.increment(value.tileEntityKeyString); - } - return replaced; - } - - @Override - public TileEntity remove(Object key) { - TileEntity removed = super.remove(key); - if (removed != null) { - removed.setCurrentChunk(null); - tileEntityCounts.decrement(removed.tileEntityKeyString); - } - return removed; - } - } - public final PaperLightingQueue.LightingQueue lightingQueue = new PaperLightingQueue.LightingQueue(this); // Akarin - public - // Paper end - private volatile boolean done; // Akarin - volatile - private volatile boolean lit; // Akarin - volatile - private volatile boolean r; private boolean isTicked() { return r; }; // Paper - OBFHELPER // Akarin - volatile - private boolean s; - private boolean t; - private long lastSaved; - private int v; - private long w; - private int x; - private final ConcurrentLinkedQueue y; - public boolean d; public void setShouldUnload(boolean unload) { this.d = unload; } public boolean isUnloading() { return d; } // Paper - OBFHELPER - protected gnu.trove.map.hash.TObjectIntHashMap entityCount = new gnu.trove.map.hash.TObjectIntHashMap(); // Spigot - - // Paper start - // Track the number of minecarts and items - // Keep this synced with entitySlices.add() and entitySlices.remove() - private final int[] itemCounts = new int[16]; - private final int[] inventoryEntityCounts = new int[16]; - // Paper end - - // CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking - private int neighbors = 0x1 << 12; - public long chunkKey; - - public boolean areNeighborsLoaded(final int radius) { - switch (radius) { - case 2: - return this.neighbors == Integer.MAX_VALUE >> 6; - case 1: - final int mask = - // x z offset x z offset x z offset - (0x1 << (1 * 5 + 1 + 12)) | (0x1 << (0 * 5 + 1 + 12)) | (0x1 << (-1 * 5 + 1 + 12)) | - (0x1 << (1 * 5 + 0 + 12)) | (0x1 << (0 * 5 + 0 + 12)) | (0x1 << (-1 * 5 + 0 + 12)) | - (0x1 << (1 * 5 + -1 + 12)) | (0x1 << (0 * 5 + -1 + 12)) | (0x1 << (-1 * 5 + -1 + 12)); - return (this.neighbors & mask) == mask; - default: - throw new UnsupportedOperationException(String.valueOf(radius)); - } - } - - public void setNeighborLoaded(final int x, final int z) { - this.neighbors |= 0x1 << (x * 5 + 12 + z); - } - - public void setNeighborUnloaded(final int x, final int z) { - this.neighbors &= ~(0x1 << (x * 5 + 12 + z)); - } - // CraftBukkit end - - public Chunk(World world, int i, int j) { - this.sections = new ChunkSection[16]; - this.g = new byte[256]; - this.h = new int[256]; - this.i = new boolean[256]; - this.tileEntities = new TileEntityHashMap(); // Paper - this.x = 4096; - this.y = Queues.newConcurrentLinkedQueue(); - this.entitySlices = (List[]) (new List[16]); // Spigot - this.world = world; - this.locX = i; - this.locZ = j; - this.heightMap = new int[256]; - - for (int k = 0; k < this.entitySlices.length; ++k) { - this.entitySlices[k] = new org.bukkit.craftbukkit.util.UnsafeList(); // Spigot - } - - Arrays.fill(this.h, -999); - Arrays.fill(this.g, (byte) -1); - // CraftBukkit start - this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); - this.chunkKey = ChunkCoordIntPair.a(this.locX, this.locZ); - } - - public org.bukkit.Chunk bukkitChunk; - public boolean mustSave; - // CraftBukkit end - - public Chunk(World world, ChunkSnapshot chunksnapshot, int i, int j) { - this(world, i, j); - boolean flag = true; - boolean flag1 = world.worldProvider.m(); - - for (int k = 0; k < 16; ++k) { - for (int l = 0; l < 16; ++l) { - for (int i1 = 0; i1 < 256; ++i1) { - IBlockData iblockdata = chunksnapshot.a(k, i1, l); - - if (iblockdata.getMaterial() != Material.AIR) { - int j1 = i1 >> 4; - - if (this.sections[j1] == Chunk.a) { - this.sections[j1] = new ChunkSection(j1 << 4, flag1, world.chunkPacketBlockController.getPredefinedBlockData(this, j1)); // Paper - Anti-Xray - Add predefined block data - } - - this.sections[j1].setType(k, i1 & 15, l, iblockdata); - } - } - } - } - - } - - public boolean a(int i, int j) { - return i == this.locX && j == this.locZ; - } - - public int e(BlockPosition blockposition) { - return this.b(blockposition.getX() & 15, blockposition.getZ() & 15); - } - - public int b(int i, int j) { - return this.heightMap[j << 4 | i]; - } - - @Nullable - private ChunkSection y() { - for (int i = this.sections.length - 1; i >= 0; --i) { - if (this.sections[i] != Chunk.a) { - return this.sections[i]; - } - } - - return null; - } - - public int g() { - ChunkSection chunksection = this.y(); - - return chunksection == null ? 0 : chunksection.getYPosition(); - } - - public ChunkSection[] getSections() { - return this.sections; - } - - public void initLighting() { - int i = this.g(); - - this.v = Integer.MAX_VALUE; - - for (int j = 0; j < 16; ++j) { - int k = 0; - - while (k < 16) { - this.h[j + (k << 4)] = -999; - int l = i + 16; - - while (true) { - if (l > 0) { - if (this.d(j, l - 1, k) == 0) { - --l; - continue; - } - - this.heightMap[k << 4 | j] = l; - if (l < this.v) { - this.v = l; - } - } - - if (this.world.worldProvider.m()) { - l = 15; - int i1 = i + 16 - 1; - - do { - int j1 = this.d(j, i1, k); - - if (j1 == 0 && l != 15) { - j1 = 1; - } - - l -= j1; - if (l > 0) { - ChunkSection chunksection = this.sections[i1 >> 4]; - - if (chunksection != Chunk.a) { - chunksection.a(j, i1 & 15, k, l); - this.world.m(new BlockPosition((this.locX << 4) + j, i1, (this.locZ << 4) + k)); - } - } - - --i1; - } while (i1 > 0 && l > 0); - } - - ++k; - break; - } - } - } - - this.s = true; - } - - private void d(int i, int j) { - this.i[i + j * 16] = true; - this.m = true; - } - - private void h(boolean flag) { - this.world.methodProfiler.a("recheckGaps"); - if (this.world.areChunksLoaded(new BlockPosition(this.locX * 16 + 8, 0, this.locZ * 16 + 8), 16)) { - this.runOrQueueLightUpdate(() -> recheckGaps(flag)); // Paper - Queue light update - } - } - - private void recheckGaps(boolean flag) { - if (true) { - // Paper end - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 16; ++j) { - if (this.i[i + j * 16]) { - this.i[i + j * 16] = false; - int k = this.b(i, j); - int l = this.locX * 16 + i; - int i1 = this.locZ * 16 + j; - int j1 = Integer.MAX_VALUE; - - Iterator iterator; - EnumDirection enumdirection; - - for (iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); iterator.hasNext(); j1 = Math.min(j1, this.world.d(l + enumdirection.getAdjacentX(), i1 + enumdirection.getAdjacentZ()))) { - enumdirection = (EnumDirection) iterator.next(); - } - - this.b(l, i1, j1); - iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); - - while (iterator.hasNext()) { - enumdirection = (EnumDirection) iterator.next(); - this.b(l + enumdirection.getAdjacentX(), i1 + enumdirection.getAdjacentZ(), k); - } - - if (flag) { - this.world.methodProfiler.b(); - return; - } - } - } - } - - this.m = false; - } - - this.world.methodProfiler.b(); - } - - private void b(int i, int j, int k) { - int l = this.world.getHighestBlockYAt(new BlockPosition(i, 0, j)).getY(); - - if (l > k) { - this.a(i, j, k, l + 1); - } else if (l < k) { - this.a(i, j, l, k + 1); - } - - } - - private void a(int i, int j, int k, int l) { - if (l > k && this.world.areChunksLoaded(new BlockPosition(i, 0, j), 16)) { - for (int i1 = k; i1 < l; ++i1) { - this.world.c(EnumSkyBlock.SKY, new BlockPosition(i, i1, j)); - } - - this.s = true; - } - - } - - private void c(int i, int j, int k) { - int l = this.heightMap[k << 4 | i] & 255; - int i1 = l; - - if (j > l) { - i1 = j; - } - - while (i1 > 0 && this.d(i, i1 - 1, k) == 0) { - --i1; - } - - if (i1 != l) { - this.world.a(i + this.locX * 16, k + this.locZ * 16, i1, l); - this.heightMap[k << 4 | i] = i1; - int j1 = this.locX * 16 + i; - int k1 = this.locZ * 16 + k; - int l1; - int i2; - - if (this.world.worldProvider.m()) { - ChunkSection chunksection; - - if (i1 < l) { - for (l1 = i1; l1 < l; ++l1) { - chunksection = this.sections[l1 >> 4]; - if (chunksection != Chunk.a) { - chunksection.a(i, l1 & 15, k, 15); - this.world.m(new BlockPosition((this.locX << 4) + i, l1, (this.locZ << 4) + k)); - } - } - } else { - for (l1 = l; l1 < i1; ++l1) { - chunksection = this.sections[l1 >> 4]; - if (chunksection != Chunk.a) { - chunksection.a(i, l1 & 15, k, 0); - this.world.m(new BlockPosition((this.locX << 4) + i, l1, (this.locZ << 4) + k)); - } - } - } - - l1 = 15; - - while (i1 > 0 && l1 > 0) { - --i1; - i2 = this.d(i, i1, k); - if (i2 == 0) { - i2 = 1; - } - - l1 -= i2; - if (l1 < 0) { - l1 = 0; - } - - ChunkSection chunksection1 = this.sections[i1 >> 4]; - - if (chunksection1 != Chunk.a) { - chunksection1.a(i, i1 & 15, k, l1); - } - } - } - - l1 = this.heightMap[k << 4 | i]; - i2 = l; - int j2 = l1; - - if (l1 < l) { - i2 = l1; - j2 = l; - } - - if (l1 < this.v) { - this.v = l1; - } - - if (this.world.worldProvider.m()) { - Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); - - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - - this.a(j1 + enumdirection.getAdjacentX(), k1 + enumdirection.getAdjacentZ(), i2, j2); - } - - this.a(j1, k1, i2, j2); - } - - this.s = true; - } - } - - public int b(BlockPosition blockposition) { - return this.getBlockData(blockposition).c(); - } - - private int d(int i, int j, int k) { - return this.a(i, j, k).c(); - } - - // Paper start - Optimize getBlockData to reduce instructions - public final IBlockData getBlockData(final BlockPosition pos) { - return getBlockData(pos.getX(), pos.getY(), pos.getZ()); - } - - public final IBlockData getBlockData(final int x, final int y, final int z) { - // Method body / logic copied from below - final int i = y >> 4; - if (y >= 0 && i < this.sections.length && this.sections[i] != null) { - // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) - return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); - } - return Blocks.AIR.getBlockData(); - } - - public IBlockData a(final int i, final int j, final int k) { - return getBlockData(i, j, k); - } - - public IBlockData unused(final int i, final int j, final int k) { - // Paper end - if (this.world.N() == WorldType.DEBUG_ALL_BLOCK_STATES) { - IBlockData iblockdata = null; - - if (j == 60) { - iblockdata = Blocks.BARRIER.getBlockData(); - } - - if (j == 70) { - iblockdata = ChunkProviderDebug.c(i, k); - } - - return iblockdata == null ? Blocks.AIR.getBlockData() : iblockdata; - } else { - try { - if (j >= 0 && j >> 4 < this.sections.length) { - ChunkSection chunksection = this.sections[j >> 4]; - - if (chunksection != Chunk.a) { - return chunksection.getType(i & 15, j & 15, k & 15); - } - } - - return Blocks.AIR.getBlockData(); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Getting block state"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - - crashreportsystemdetails.a("Location", new CrashReportCallable() { - public String a() throws Exception { - return CrashReportSystemDetails.a(i, j, k); - } - - public Object call() throws Exception { - return this.a(); - } - }); - throw new ReportedException(crashreport); - } - } - } - - @Nullable - public IBlockData a(BlockPosition blockposition, IBlockData iblockdata) { - int i = blockposition.getX() & 15; - int j = blockposition.getY(); - int k = blockposition.getZ() & 15; - int l = k << 4 | i; - - if (j >= this.h[l] - 1) { - this.h[l] = -999; - } - - int i1 = this.heightMap[l]; - IBlockData iblockdata1 = this.getBlockData(blockposition); - - if (iblockdata1 == iblockdata) { - return null; - } else { - Block block = iblockdata.getBlock(); - Block block1 = iblockdata1.getBlock(); - ChunkSection chunksection = this.sections[j >> 4]; - boolean flag = false; - - if (chunksection == Chunk.a) { - if (block == Blocks.AIR) { - return null; - } - - chunksection = new ChunkSection(j >> 4 << 4, this.world.worldProvider.m(), this.world.chunkPacketBlockController.getPredefinedBlockData(this, j >> 4)); // Paper - Anti-Xray - Add predefined block data - this.sections[j >> 4] = chunksection; - flag = j >= i1; - } - - chunksection.setType(i, j & 15, k, iblockdata); - if (block1 != block) { - if (!this.world.isClientSide) { - block1.remove(this.world, blockposition, iblockdata1); - } else if (block1 instanceof ITileEntity) { - this.world.s(blockposition); - } - } - - if (chunksection.getType(i, j & 15, k).getBlock() != block) { - return null; - } else { - if (flag) { - this.initLighting(); - } else { - this.runOrQueueLightUpdate(() -> { // Paper - Queue light update - int j1 = iblockdata.c(); - int k1 = iblockdata1.c(); - - if (j1 > 0) { - if (j >= i1) { - this.c(i, j + 1, k); - } - } else if (j == i1 - 1) { - this.c(i, j, k); - } - - if (j1 != k1 && (j1 < k1 || this.getBrightness(EnumSkyBlock.SKY, blockposition) > 0 || this.getBrightness(EnumSkyBlock.BLOCK, blockposition) > 0)) { - this.d(i, k); - } - }); // Paper - } - - TileEntity tileentity; - - if (block1 instanceof ITileEntity) { - tileentity = this.a(blockposition, Chunk.EnumTileEntityState.CHECK); - if (tileentity != null) { - tileentity.invalidateBlockCache(); - } - } - - // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. - if (!this.world.isClientSide && block1 != block && (!this.world.captureBlockStates || block instanceof BlockTileEntity)) { - block.onPlace(this.world, blockposition, iblockdata); - } - - if (block instanceof ITileEntity) { - tileentity = this.a(blockposition, Chunk.EnumTileEntityState.CHECK); - if (tileentity == null) { - tileentity = ((ITileEntity) block).a(this.world, block.toLegacyData(iblockdata)); - this.world.setTileEntity(blockposition, tileentity); - } - - if (tileentity != null) { - tileentity.invalidateBlockCache(); - } - } - - this.s = true; - return iblockdata1; - } - } - } - - public int getBrightness(EnumSkyBlock enumskyblock, BlockPosition blockposition) { - int i = blockposition.getX() & 15; - int j = blockposition.getY(); - int k = blockposition.getZ() & 15; - ChunkSection chunksection = this.sections[j >> 4]; - - return chunksection == Chunk.a ? (this.c(blockposition) ? enumskyblock.c : 0) : (enumskyblock == EnumSkyBlock.SKY ? (!this.world.worldProvider.m() ? 0 : chunksection.b(i, j & 15, k)) : (enumskyblock == EnumSkyBlock.BLOCK ? chunksection.c(i, j & 15, k) : enumskyblock.c)); - } - - public void a(EnumSkyBlock enumskyblock, BlockPosition blockposition, int i) { - int j = blockposition.getX() & 15; - int k = blockposition.getY(); - int l = blockposition.getZ() & 15; - ChunkSection chunksection = this.sections[k >> 4]; - - if (chunksection == Chunk.a) { - chunksection = new ChunkSection(k >> 4 << 4, this.world.worldProvider.m(), this.world.chunkPacketBlockController.getPredefinedBlockData(this, k >> 4)); // Paper - Anti-Xray - Add predefined block data - this.sections[k >> 4] = chunksection; - this.initLighting(); - } - - this.s = true; - if (enumskyblock == EnumSkyBlock.SKY) { - if (this.world.worldProvider.m()) { - chunksection.a(j, k & 15, l, i); - } - } else if (enumskyblock == EnumSkyBlock.BLOCK) { - chunksection.b(j, k & 15, l, i); - } - - } - - public final int getLightSubtracted(BlockPosition blockposition, int i) { return this.a(blockposition, i); } // Paper - OBFHELPER - public int a(BlockPosition blockposition, int i) { - int j = blockposition.getX() & 15; - int k = blockposition.getY(); - int l = blockposition.getZ() & 15; - ChunkSection chunksection = this.sections[k >> 4]; - - if (chunksection == Chunk.a) { - return this.world.worldProvider.m() && i < EnumSkyBlock.SKY.c ? EnumSkyBlock.SKY.c - i : 0; - } else { - int i1 = !this.world.worldProvider.m() ? 0 : chunksection.b(j, k & 15, l); - - i1 -= i; - int j1 = chunksection.c(j, k & 15, l); - - if (j1 > i1) { - i1 = j1; - } - - return i1; - } - } - - public void a(Entity entity) { - this.t = true; - int i = MathHelper.floor(entity.locX / 16.0D); - int j = MathHelper.floor(entity.locZ / 16.0D); - - if (i != this.locX || j != this.locZ) { - Chunk.e.warn("Wrong location! ({}, {}) should be ({}, {}), {}", Integer.valueOf(i), Integer.valueOf(j), Integer.valueOf(this.locX), Integer.valueOf(this.locZ), entity); - entity.die(); - } - - int k = MathHelper.floor(entity.locY / 16.0D); - - if (k < 0) { - k = 0; - } - - if (k >= this.entitySlices.length) { - k = this.entitySlices.length - 1; - } - - entity.aa = true; - entity.ab = this.locX; - entity.ac = k; - entity.ad = this.locZ; - - // Paper start - List entitySlice = this.entitySlices[k]; - boolean inThis = entitySlice.contains(entity); - if (entity.entitySlice != null || inThis) { - if (entity.entitySlice == entitySlice || inThis) { - LogManager.getLogger().warn(entity + " was already in this chunk section! Report this to https://github.com/PaperMC/Paper/issues/1223"); - new Throwable().printStackTrace(); - return; - } else { - LogManager.getLogger().warn(entity + " is still in another ChunkSection! Report this to https://github.com/PaperMC/Paper/issues/1223"); - - Chunk chunk = entity.getCurrentChunk(); - if (chunk != null) { - if (chunk != this) { - LogManager.getLogger().warn(entity + " was in another chunk at that! " + chunk.locX + "," + chunk.locZ); - } - chunk.removeEntity(entity); - } else { - removeEntity(entity); - } - new Throwable().printStackTrace(); - } - } - entity.entitySlice = entitySlice; - entitySlice.add(entity); - - this.markDirty(); - entity.setCurrentChunk(this); - entityCounts.increment(entity.entityKeyString); - if (entity instanceof EntityItem) { - itemCounts[k]++; - } else if (entity instanceof IInventory) { - inventoryEntityCounts[k]++; - } - // Paper end - // Spigot start - increment creature type count - // Keep this synced up with World.a(Class) - if (entity instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) entity; - if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { - return; - } - } - for ( EnumCreatureType creatureType : EnumCreatureType.values() ) - { - if ( creatureType.a().isAssignableFrom( entity.getClass() ) ) - { - this.entityCount.adjustOrPutValue( creatureType.a(), 1, 1 ); - } - } - // Spigot end - } - - public void removeEntity(Entity entity) { b(entity); } // Paper - OBFHELPER - public void b(Entity entity) { - this.a(entity, entity.ac); - } - - public void a(Entity entity, int i) { - if (i < 0) { - i = 0; - } - - if (i >= this.entitySlices.length) { - i = this.entitySlices.length - 1; - } - - // Paper start - if (!this.entitySlices[i].remove(entity)) { return; } - if (entitySlices[i] == entity.entitySlice) { - entity.entitySlice = null; - } else { - LogManager.getLogger().warn(entity + " was removed from a entitySlice we did not expect. Report this to https://github.com/PaperMC/Paper/issues/1223"); - new Throwable().printStackTrace(); - } - this.markDirty(); - entity.setCurrentChunk(null); - entityCounts.decrement(entity.entityKeyString); - if (entity instanceof EntityItem) { - itemCounts[i]--; - } else if (entity instanceof IInventory) { - inventoryEntityCounts[i]--; - } - // Paper end - // Spigot start - decrement creature type count - // Keep this synced up with World.a(Class) - if (entity instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) entity; - if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { - return; - } - } - for ( EnumCreatureType creatureType : EnumCreatureType.values() ) - { - if ( creatureType.a().isAssignableFrom( entity.getClass() ) ) - { - this.entityCount.adjustValue( creatureType.a(), -1 ); - } - } - // Spigot end - } - - public boolean c(BlockPosition blockposition) { - int i = blockposition.getX() & 15; - int j = blockposition.getY(); - int k = blockposition.getZ() & 15; - - return j >= this.heightMap[k << 4 | i]; - } - - @Nullable - private TileEntity g(BlockPosition blockposition) { - IBlockData iblockdata = this.getBlockData(blockposition); - Block block = iblockdata.getBlock(); - - return !block.isTileEntity() ? null : ((ITileEntity) block).a(this.world, iblockdata.getBlock().toLegacyData(iblockdata)); - } - - @Nullable public final TileEntity getTileEntityImmediately(BlockPosition pos) { return this.a(pos, EnumTileEntityState.IMMEDIATE); } // Paper - OBFHELPER - @Nullable - public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { - // CraftBukkit start - TileEntity tileentity = null; - if (world.captureBlockStates) { - tileentity = world.capturedTileEntities.get(blockposition); - } - if (tileentity == null) { - tileentity = (TileEntity) this.tileEntities.get(blockposition); - } - // CraftBukkit end - - if (tileentity == null) { - if (chunk_enumtileentitystate == Chunk.EnumTileEntityState.IMMEDIATE) { - tileentity = this.g(blockposition); - this.world.setTileEntity(blockposition, tileentity); - } else if (chunk_enumtileentitystate == Chunk.EnumTileEntityState.QUEUED) { - this.y.add(blockposition); - } - } else if (tileentity.y()) { - this.tileEntities.remove(blockposition); - return null; - } - - return tileentity; - } - - public void a(TileEntity tileentity) { - this.a(tileentity.getPosition(), tileentity); - if (this.j) { - this.world.a(tileentity); - } - - } - - public void a(BlockPosition blockposition, TileEntity tileentity) { - tileentity.a(this.world); - tileentity.setPosition(blockposition); - if (this.getBlockData(blockposition).getBlock() instanceof ITileEntity) { - if (this.tileEntities.containsKey(blockposition)) { - ((TileEntity) this.tileEntities.get(blockposition)).z(); - } - - tileentity.A(); - this.tileEntities.put(blockposition, tileentity); - // CraftBukkit start - // Paper start - Remove invalid mob spawner tile entities - } else if (tileentity instanceof TileEntityMobSpawner && org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) != org.bukkit.Material.MOB_SPAWNER) { - this.tileEntities.remove(blockposition); - // Paper end - } else { - // Paper start - ServerInternalException e = new ServerInternalException( - "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," - + tileentity.position.getY() + "," + tileentity.position.getZ() - + " (" + CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) + ") where there was no entity tile!\n" + - "Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); - e.printStackTrace(); - ServerInternalException.reportInternalException(e); - - if (this.world.paperConfig.removeCorruptTEs) { - this.removeTileEntity(tileentity.getPosition()); - this.markDirty(); - org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); - } - // Paper end - // CraftBukkit end - } - } - - public void removeTileEntity(BlockPosition blockposition) { this.d(blockposition); } // Paper - OBFHELPER - public void d(BlockPosition blockposition) { - if (this.j) { - TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); - - if (tileentity != null) { - tileentity.z(); - } - } - - } - - public void addEntities() { - this.j = true; - this.world.b(this.tileEntities.values()); - List[] aentityslice = this.entitySlices; // Spigot - int i = aentityslice.length; - - for (int j = 0; j < i; ++j) { - List entityslice = aentityslice[j]; // Spigot - // Paper start - DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode; - if (mode == DuplicateUUIDMode.DELETE || mode == DuplicateUUIDMode.REGEN) { - Map thisChunk = new HashMap<>(); - for (Iterator iterator = ((List) entityslice).iterator(); iterator.hasNext(); ) { - Entity entity = iterator.next(); - if (entity.dead) continue; - Entity other = ((WorldServer) world).entitiesByUUID.get(entity.uniqueID); - if (other == null) { - other = thisChunk.get(entity.uniqueID); - } - if (other != null && !other.dead) { - switch (mode) { - case REGEN: { - entity.setUUID(UUID.randomUUID()); - logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); - break; - } - case DELETE: { - logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); - entity.die(); - iterator.remove(); - break; - } - } - } - thisChunk.put(entity.uniqueID, entity); - } - } - // Paper end - - this.world.a((Collection) entityslice); - } - - } - - public void removeEntities() { - this.j = false; - Iterator iterator = this.tileEntities.values().iterator(); - - while (iterator.hasNext()) { - TileEntity tileentity = (TileEntity) iterator.next(); - // Spigot Start - if ( tileentity instanceof IInventory ) - { - for ( org.bukkit.entity.HumanEntity h : Lists.newArrayList((List) ( (IInventory) tileentity ).getViewers() ) ) - { - if ( h instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity ) - { - ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } - // Spigot End - - this.world.b(tileentity); - } - - List[] aentityslice = this.entitySlices; // Spigot - int i = aentityslice.length; - - for (int j = 0; j < i; ++j) { - // CraftBukkit start - List newList = Lists.newArrayList(aentityslice[j]); - java.util.Iterator iter = newList.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - // Spigot Start - if ( entity instanceof IInventory ) - { - for ( org.bukkit.entity.HumanEntity h : Lists.newArrayList( (List) ( (IInventory) entity ).getViewers() ) ) - { - if ( h instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity ) - { - ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } - // Spigot End - - // Do not pass along players, as doing so can get them stuck outside of time. - // (which for example disables inventory icon updates and prevents block breaking) - if (entity instanceof EntityPlayer) { - iter.remove(); - } - } - - this.world.c(newList); - // CraftBukkit end - } - - } - - public void markDirty() { - this.s = true; - } - - public void a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, Predicate predicate) { - int i = MathHelper.floor((axisalignedbb.b - 2.0D) / 16.0D); - int j = MathHelper.floor((axisalignedbb.e + 2.0D) / 16.0D); - - i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); - j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); - - for (int k = i; k <= j; ++k) { - if (!this.entitySlices[k].isEmpty()) { - Iterator iterator = this.entitySlices[k].iterator(); - - // Paper start - Don't search for inventories if we have none, and that is all we want - /* - * We check if they want inventories by seeing if it is the static `IEntitySelector.c` - * - * Make sure the inventory selector stays in sync. - * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` - */ - if (predicate == IEntitySelector.c && inventoryEntityCounts[k] <= 0) continue; - // Paper end - while (iterator.hasNext()) { - Entity entity1 = (Entity) iterator.next(); - - if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { - if (predicate == null || predicate.apply(entity1)) { - list.add(entity1); - } - - Entity[] aentity = entity1.bb(); - - if (aentity != null) { - Entity[] aentity1 = aentity; - int l = aentity.length; - - for (int i1 = 0; i1 < l; ++i1) { - Entity entity2 = aentity1[i1]; - - if (entity2 != entity && entity2.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.apply(entity2))) { - list.add(entity2); - } - } - } - } - } - } - } - - } - - public void a(Class oclass, AxisAlignedBB axisalignedbb, List list, Predicate predicate) { - int i = MathHelper.floor((axisalignedbb.b - 2.0D) / 16.0D); - int j = MathHelper.floor((axisalignedbb.e + 2.0D) / 16.0D); - - i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); - j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); - - // Paper start - int[] counts; - if (EntityItem.class.isAssignableFrom(oclass)) { - counts = itemCounts; - } else if (IInventory.class.isAssignableFrom(oclass)) { - counts = inventoryEntityCounts; - } else { - counts = null; - } - // Paper end - for (int k = i; k <= j; ++k) { - if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - - if (oclass.isInstance(entity) && entity.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.apply((T) entity))) { // CraftBukkit - fix decompile error // Spigot - instance check - list.add((T) entity); // Fix decompile error - } - } - } - - } - - public boolean a(boolean flag) { - if (flag) { - if (this.t && this.world.getTime() != this.lastSaved || this.s) { - return true; - } - } - // This !flag section should say if s(isModified) or t(hasEntities), then check auto save - return ((this.s || this.t) && this.world.getTime() >= this.lastSaved + world.paperConfig.autoSavePeriod); // Paper - Make world configurable and incremental - } - - public Random a(long i) { - return new Random(this.world.getSeed() + (long) (this.locX * this.locX * 4987142) + (long) (this.locX * 5947611) + (long) (this.locZ * this.locZ) * 4392871L + (long) (this.locZ * 389711) ^ i); - } - - public boolean isEmpty() { - return false; - } - - // CraftBukkit start - public void loadNearby(IChunkProvider ichunkprovider, ChunkGenerator chunkgenerator, boolean newChunk) { - world.timings.syncChunkLoadPostTimer.startTiming(); // Paper - Server server = world.getServer(); - if (server != null) { - /* - * If it's a new world, the first few chunks are generated inside - * the World constructor. We can't reliably alter that, so we have - * no way of creating a CraftWorld/CraftServer at that point. - */ - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, newChunk)); - } - - // Update neighbor counts - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - if (x == 0 && z == 0) { - continue; - } - - Chunk neighbor = getWorld().getChunkIfLoaded(locX + x, locZ + z); - if (neighbor != null) { - neighbor.setNeighborLoaded(-x, -z); - setNeighborLoaded(x, z); - } - } - } - // CraftBukkit end - world.timings.syncChunkLoadPostTimer.stopTiming(); // Paper - world.timings.syncChunkLoadPopulateNeighbors.startTiming(); // Paper - Chunk chunk = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ - 1); // Paper - Chunk chunk1 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ); // Paper - Chunk chunk2 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ + 1); // Paper - Chunk chunk3 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ); // Paper - - if (chunk1 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ + 1) != null) { // Paper - this.a(chunkgenerator); - } - - if (chunk3 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ + 1) != null) { // Paper - chunk3.a(chunkgenerator); - } - - if (chunk != null && chunk1 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ - 1) != null) { // Paper - chunk.a(chunkgenerator); - } - - if (chunk != null && chunk3 != null) { - Chunk chunk4 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ - 1); // Paper - - if (chunk4 != null) { - chunk4.a(chunkgenerator); - } - } - world.timings.syncChunkLoadPopulateNeighbors.stopTiming(); // Paper - - } - - protected void a(ChunkGenerator chunkgenerator) { - if (this.isDone()) { - if (chunkgenerator.a(this, this.locX, this.locZ)) { - this.markDirty(); - } - } else { - this.o(); - chunkgenerator.recreateStructures(this.locX, this.locZ); - - // CraftBukkit start - BlockSand.instaFall = true; - Random random = new Random(); - random.setSeed(world.getSeed()); - long xRand = random.nextLong() / 2L * 2L + 1L; - long zRand = random.nextLong() / 2L * 2L + 1L; - random.setSeed((long) locX * xRand + (long) locZ * zRand ^ world.getSeed()); - - org.bukkit.World world = this.world.getWorld(); - if (world != null) { - this.world.populating = true; - try { - for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { - populator.populate(world, random, bukkitChunk); - } - } finally { - this.world.populating = false; - } - } - BlockSand.instaFall = false; - this.world.getServer().getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); - // CraftBukkit end - this.markDirty(); - } - - } - - public BlockPosition f(BlockPosition blockposition) { - int i = blockposition.getX() & 15; - int j = blockposition.getZ() & 15; - int k = i | j << 4; - BlockPosition blockposition1 = new BlockPosition(blockposition.getX(), this.h[k], blockposition.getZ()); - - if (blockposition1.getY() == -999) { - int l = this.g() + 15; - - blockposition1 = new BlockPosition(blockposition.getX(), l, blockposition.getZ()); - int i1 = -1; - - while (blockposition1.getY() > 0 && i1 == -1) { - IBlockData iblockdata = this.getBlockData(blockposition1); - Material material = iblockdata.getMaterial(); - - if (!material.isSolid() && !material.isLiquid()) { - blockposition1 = blockposition1.down(); - } else { - i1 = blockposition1.getY() + 1; - } - } - - this.h[k] = i1; - } - - return new BlockPosition(blockposition.getX(), this.h[k], blockposition.getZ()); - } - - public void b(boolean flag) { - if (this.m && this.world.worldProvider.m() && !flag) { - this.h(this.world.isClientSide); - } - - this.r = true; - if (!this.lit && this.done && this.world.spigotConfig.randomLightUpdates) { // Spigot - also use random light updates setting to determine if we should relight - this.o(); - } - - while (!this.y.isEmpty()) { - BlockPosition blockposition = (BlockPosition) this.y.poll(); - - if (this.a(blockposition, Chunk.EnumTileEntityState.CHECK) == null && this.getBlockData(blockposition).getBlock().isTileEntity()) { - TileEntity tileentity = this.g(blockposition); - - this.world.setTileEntity(blockposition, tileentity); - this.world.b(blockposition, blockposition); - } - } - - } - - public boolean isReady() { - // Spigot Start - /* - * As of 1.7, Mojang added a check to make sure that only chunks which have been lit are sent to the client. - * Unfortunately this interferes with our modified chunk ticking algorithm, which will only tick chunks distant from the player on a very infrequent basis. - * We cannot unfortunately do this lighting stage during chunk gen as it appears to put a lot more noticeable load on the server, than when it is done at play time. - * For now at least we will simply send all chunks, in accordance with pre 1.7 behaviour. - */ - // Paper Start - // if randomLightUpdates are disabled, we should always return true, otherwise chunks may never send - // to the client due to not being lit, otherwise retain standard behavior and only send properly lit chunks. - return !this.world.spigotConfig.randomLightUpdates || (this.isTicked() && this.done && this.lit); - // Paper End - // Spigot End - } - - public boolean j() { - return this.r; - } - - public ChunkCoordIntPair k() { - return new ChunkCoordIntPair(this.locX, this.locZ); - } - - public boolean c(int i, int j) { - if (i < 0) { - i = 0; - } - - if (j >= 256) { - j = 255; - } - - for (int k = i; k <= j; k += 16) { - ChunkSection chunksection = this.sections[k >> 4]; - - if (chunksection != Chunk.a && !chunksection.a()) { - return false; - } - } - - return true; - } - - public void a(ChunkSection[] achunksection) { - if (this.sections.length != achunksection.length) { - Chunk.e.warn("Could not set level chunk sections, array length is {} instead of {}", Integer.valueOf(achunksection.length), Integer.valueOf(this.sections.length)); - } else { - System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); - } - } - - public BiomeBase getBiome(BlockPosition blockposition, WorldChunkManager worldchunkmanager) { - int i = blockposition.getX() & 15; - int j = blockposition.getZ() & 15; - int k = this.g[j << 4 | i] & 255; - BiomeBase biomebase; - - if (k == 255) { - biomebase = worldchunkmanager.getBiome(blockposition, Biomes.c); - k = BiomeBase.a(biomebase); - this.g[j << 4 | i] = (byte) (k & 255); - } - - biomebase = BiomeBase.getBiome(k); - return biomebase == null ? Biomes.c : biomebase; - } - - public byte[] getBiomeIndex() { - return this.g; - } - - public void a(byte[] abyte) { - if (this.g.length != abyte.length) { - Chunk.e.warn("Could not set level chunk biomes, array length is {} instead of {}", Integer.valueOf(abyte.length), Integer.valueOf(this.g.length)); - } else { - System.arraycopy(abyte, 0, this.g, 0, this.g.length); - } - } - - public void m() { - this.x = 0; - } - - public void n() { - if (this.x < 4096) { - BlockPosition blockposition = new BlockPosition(this.locX << 4, 0, this.locZ << 4); - - for (int i = 0; i < 8; ++i) { - if (this.x >= 4096) { - return; - } - - int j = this.x % 16; - int k = this.x / 16 % 16; - int l = this.x / 256; - - ++this.x; - - for (int i1 = 0; i1 < 16; ++i1) { - BlockPosition blockposition1 = blockposition.a(k, (j << 4) + i1, l); - boolean flag = i1 == 0 || i1 == 15 || k == 0 || k == 15 || l == 0 || l == 15; - - if (this.sections[j] == Chunk.a && flag || this.sections[j] != Chunk.a && this.sections[j].getType(k, i1, l).getMaterial() == Material.AIR) { - EnumDirection[] aenumdirection = EnumDirection.values(); - int j1 = aenumdirection.length; - - for (int k1 = 0; k1 < j1; ++k1) { - EnumDirection enumdirection = aenumdirection[k1]; - BlockPosition blockposition2 = blockposition1.shift(enumdirection); - - if (this.world.getType(blockposition2).d() > 0) { - this.world.w(blockposition2); - } - } - - this.world.w(blockposition1); - } - } - } - - } - } - - public void o() { - world.timings.lightChunk.startTiming(); // Paper - this.done = true; - this.lit = true; - BlockPosition blockposition = new BlockPosition(this.locX << 4, 0, this.locZ << 4); - - if (this.world.worldProvider.m()) { - if (this.world.areChunksLoadedBetween(blockposition.a(-1, 0, -1), blockposition.a(16, this.world.getSeaLevel(), 16))) { - label42: - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 16; ++j) { - if (!this.e(i, j)) { - this.lit = false; - break label42; - } - } - } - - if (this.lit) { - Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); - - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - int k = enumdirection.c() == EnumDirection.EnumAxisDirection.POSITIVE ? 16 : 1; - - this.world.getChunkAtWorldCoords(blockposition.shift(enumdirection, k)).a(enumdirection.opposite()); - } - - this.z(); - } - } else { - this.lit = false; - } - } - - world.timings.lightChunk.stopTiming(); // Paper - } - - private void z() { - for (int i = 0; i < this.i.length; ++i) { - this.i[i] = true; - } - - this.h(false); - } - - public void a(EnumDirection enumdirection) { // Akarin - private -> public - if (this.done) { - int i; - - if (enumdirection == EnumDirection.EAST) { - for (i = 0; i < 16; ++i) { - this.e(15, i); - } - } else if (enumdirection == EnumDirection.WEST) { - for (i = 0; i < 16; ++i) { - this.e(0, i); - } - } else if (enumdirection == EnumDirection.SOUTH) { - for (i = 0; i < 16; ++i) { - this.e(i, 15); - } - } else if (enumdirection == EnumDirection.NORTH) { - for (i = 0; i < 16; ++i) { - this.e(i, 0); - } - } - - } - } - - private boolean e(int i, int j) { - int k = this.g(); - boolean flag = false; - boolean flag1 = false; - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition((this.locX << 4) + i, 0, (this.locZ << 4) + j); - - int l; - - for (l = k + 16 - 1; l > this.world.getSeaLevel() || l > 0 && !flag1; --l) { - blockposition_mutableblockposition.c(blockposition_mutableblockposition.getX(), l, blockposition_mutableblockposition.getZ()); - int i1 = this.b((BlockPosition) blockposition_mutableblockposition); - - if (i1 == 255 && blockposition_mutableblockposition.getY() < this.world.getSeaLevel()) { - flag1 = true; - } - - if (!flag && i1 > 0) { - flag = true; - } else if (flag && i1 == 0 && !this.world.w(blockposition_mutableblockposition)) { - return false; - } - } - - for (l = blockposition_mutableblockposition.getY(); l > 0; --l) { - blockposition_mutableblockposition.c(blockposition_mutableblockposition.getX(), l, blockposition_mutableblockposition.getZ()); - if (this.getBlockData(blockposition_mutableblockposition).d() > 0) { - this.world.w(blockposition_mutableblockposition); - } - } - - return true; - } - - public boolean p() { - return this.j; - } - - public World getWorld() { - return this.world; - } - - public int[] r() { - return this.heightMap; - } - - public void a(int[] aint) { - if (this.heightMap.length != aint.length) { - Chunk.e.warn("Could not set level chunk heightmap, array length is {} instead of {}", Integer.valueOf(aint.length), Integer.valueOf(this.heightMap.length)); - } else { - System.arraycopy(aint, 0, this.heightMap, 0, this.heightMap.length); - } - } - - public Map getTileEntities() { - return this.tileEntities; - } - - public List[] getEntitySlices() { - return this.entitySlices; - } - - public boolean isDone() { - return this.done; - } - - public void d(boolean flag) { - this.done = flag; - } - - public boolean v() { - return this.lit; - } - - public void e(boolean flag) { - this.lit = flag; - } - - public void f(boolean flag) { - this.s = flag; - } - - public void g(boolean flag) { - this.t = flag; - } - - public void setLastSaved(long i) { - this.lastSaved = i; - } - - public int w() { - return this.v; - } - - public long x() { - return world.paperConfig.useInhabitedTime ? this.w : 0; // Paper - } - - public void c(long i) { - this.w = i; - } - - // Paper start - public void runOrQueueLightUpdate(Runnable runnable) { - if (this.world.paperConfig.queueLightUpdates) { - lightingQueue.add(runnable); - } else { - runnable.run(); - } - } - // Paper end - - public static enum EnumTileEntityState { - - IMMEDIATE, QUEUED, CHECK; - - private EnumTileEntityState() {} - } -} diff --git a/sources/src/main/java/net/minecraft/server/EnchantmentManager.java b/sources/src/main/java/net/minecraft/server/EnchantmentManager.java deleted file mode 100644 index 10e89e7e9..000000000 --- a/sources/src/main/java/net/minecraft/server/EnchantmentManager.java +++ /dev/null @@ -1,432 +0,0 @@ -package net.minecraft.server; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Map.Entry; - -/** - * Akarin Changes Note - * 1) Expose private members (cause mixin errors) - */ -public class EnchantmentManager { - - private static final EnchantmentManager.EnchantmentModifierProtection a = new EnchantmentManager.EnchantmentModifierProtection(null); - private static final EnchantmentManager.EnchantmentModifierDamage b = new EnchantmentManager.EnchantmentModifierDamage(null); - private static final EnchantmentManager.EnchantmentModifierThorns c = new EnchantmentManager.EnchantmentModifierThorns(null); - private static final EnchantmentManager.EnchantmentModifierArthropods d = new EnchantmentManager.EnchantmentModifierArthropods(null); - - public static int getEnchantmentLevel(Enchantment enchantment, ItemStack itemstack) { - if (itemstack.isEmpty()) { - return 0; - } else { - NBTTagList nbttaglist = itemstack.getEnchantments(); - - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound = nbttaglist.get(i); - Enchantment enchantment1 = Enchantment.c(nbttagcompound.getShort("id")); - short short0 = nbttagcompound.getShort("lvl"); - - if (enchantment1 == enchantment) { - return short0; - } - } - - return 0; - } - } - - public static Map a(ItemStack itemstack) { - LinkedHashMap linkedhashmap = Maps.newLinkedHashMap(); - NBTTagList nbttaglist = itemstack.getItem() == Items.ENCHANTED_BOOK ? ItemEnchantedBook.h(itemstack) : itemstack.getEnchantments(); - - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound = nbttaglist.get(i); - Enchantment enchantment = Enchantment.c(nbttagcompound.getShort("id")); - short short0 = nbttagcompound.getShort("lvl"); - - linkedhashmap.put(enchantment, Integer.valueOf(short0)); - } - - return linkedhashmap; - } - - public static void a(Map map, ItemStack itemstack) { - NBTTagList nbttaglist = new NBTTagList(); - Iterator iterator = map.entrySet().iterator(); - - while (iterator.hasNext()) { - Entry entry = (Entry) iterator.next(); - Enchantment enchantment = (Enchantment) entry.getKey(); - - if (enchantment != null) { - int i = ((Integer) entry.getValue()).intValue(); - NBTTagCompound nbttagcompound = new NBTTagCompound(); - - nbttagcompound.setShort("id", (short) Enchantment.getId(enchantment)); - nbttagcompound.setShort("lvl", (short) i); - nbttaglist.add(nbttagcompound); - if (itemstack.getItem() == Items.ENCHANTED_BOOK) { - ItemEnchantedBook.a(itemstack, new WeightedRandomEnchant(enchantment, i)); - } - } - } - - if (nbttaglist.isEmpty()) { - if (itemstack.hasTag()) { - itemstack.getTag().remove("ench"); - } - } else if (itemstack.getItem() != Items.ENCHANTED_BOOK) { - itemstack.a("ench", nbttaglist); - } - - } - - private static void a(EnchantmentManager.EnchantmentModifier enchantmentmanager_enchantmentmodifier, ItemStack itemstack) { - if (!itemstack.isEmpty()) { - NBTTagList nbttaglist = itemstack.getEnchantments(); - - for (int i = 0; i < nbttaglist.size(); ++i) { - short short0 = nbttaglist.get(i).getShort("id"); - short short1 = nbttaglist.get(i).getShort("lvl"); - - if (Enchantment.c(short0) != null) { - enchantmentmanager_enchantmentmodifier.a(Enchantment.c(short0), short1); - } - } - - } - } - - private static void a(EnchantmentManager.EnchantmentModifier enchantmentmanager_enchantmentmodifier, Iterable iterable) { - Iterator iterator = iterable.iterator(); - - while (iterator.hasNext()) { - ItemStack itemstack = (ItemStack) iterator.next(); - - a(enchantmentmanager_enchantmentmodifier, itemstack); - } - - } - - public static int a(Iterable iterable, DamageSource damagesource) { - EnchantmentManager.a.a = 0; - EnchantmentManager.a.b = damagesource; - a(EnchantmentManager.a, iterable); - return EnchantmentManager.a.a; - } - - public static float a(ItemStack itemstack, EnumMonsterType enummonstertype) { - EnchantmentManager.b.a = 0.0F; - EnchantmentManager.b.b = enummonstertype; - a(EnchantmentManager.b, itemstack); - return EnchantmentManager.b.a; - } - - public static float a(EntityLiving entityliving) { - int i = a(Enchantments.r, entityliving); - - return i > 0 ? EnchantmentSweeping.e(i) : 0.0F; - } - - public static void a(EntityLiving entityliving, Entity entity) { - EnchantmentManager.c.b = entity; - EnchantmentManager.c.a = entityliving; - if (entityliving != null) { - a(EnchantmentManager.c, entityliving.aQ()); - } - - if (entity instanceof EntityHuman) { - a(EnchantmentManager.c, entityliving.getItemInMainHand()); - } - - } - - public static void b(EntityLiving entityliving, Entity entity) { - EnchantmentManager.d.a = entityliving; - EnchantmentManager.d.b = entity; - if (entityliving != null) { - a(EnchantmentManager.d, entityliving.aQ()); - } - - if (entityliving instanceof EntityHuman) { - a(EnchantmentManager.d, entityliving.getItemInMainHand()); - } - - } - - public static int a(Enchantment enchantment, EntityLiving entityliving) { - List list = enchantment.a(entityliving); - - if (list == null) { - return 0; - } else { - int i = 0; - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - ItemStack itemstack = (ItemStack) iterator.next(); - int j = getEnchantmentLevel(enchantment, itemstack); - - if (j > i) { - i = j; - } - } - - return i; - } - } - - public static int b(EntityLiving entityliving) { - return a(Enchantments.KNOCKBACK, entityliving); - } - - public static int getFireAspectEnchantmentLevel(EntityLiving entityliving) { - return a(Enchantments.FIRE_ASPECT, entityliving); - } - - public static int getOxygenEnchantmentLevel(EntityLiving entityliving) { - return a(Enchantments.OXYGEN, entityliving); - } - - public static int e(EntityLiving entityliving) { - return a(Enchantments.DEPTH_STRIDER, entityliving); - } - - public static int getDigSpeedEnchantmentLevel(EntityLiving entityliving) { - return a(Enchantments.DIG_SPEED, entityliving); - } - - public static int b(ItemStack itemstack) { - return getEnchantmentLevel(Enchantments.LUCK, itemstack); - } - - public static int c(ItemStack itemstack) { - return getEnchantmentLevel(Enchantments.LURE, itemstack); - } - - public static int g(EntityLiving entityliving) { - return a(Enchantments.LOOT_BONUS_MOBS, entityliving); - } - - public static boolean h(EntityLiving entityliving) { - return a(Enchantments.WATER_WORKER, entityliving) > 0; - } - - public static boolean i(EntityLiving entityliving) { - return a(Enchantments.j, entityliving) > 0; - } - - public static boolean d(ItemStack itemstack) { - return getEnchantmentLevel(Enchantments.k, itemstack) > 0; - } - - public static boolean shouldNotDrop(ItemStack itemstack) { - return getEnchantmentLevel(Enchantments.D, itemstack) > 0; - } - - public static ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, EntityLiving entityliving) { return b(enchantment, entityliving); } // Paper - OBFHELPER - public static ItemStack b(Enchantment enchantment, EntityLiving entityliving) { - List list = enchantment.a(entityliving); - - if (list.isEmpty()) { - return ItemStack.a; - } else { - ArrayList arraylist = Lists.newArrayList(); - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - ItemStack itemstack = (ItemStack) iterator.next(); - - if (!itemstack.isEmpty() && getEnchantmentLevel(enchantment, itemstack) > 0) { - arraylist.add(itemstack); - } - } - - return arraylist.isEmpty() ? ItemStack.a : (ItemStack) arraylist.get(entityliving.getRandom().nextInt(arraylist.size())); - } - } - - public static int a(Random random, int i, int j, ItemStack itemstack) { - Item item = itemstack.getItem(); - int k = item.c(); - - if (k <= 0) { - return 0; - } else { - if (j > 15) { - j = 15; - } - - int l = random.nextInt(8) + 1 + (j >> 1) + random.nextInt(j + 1); - - return i == 0 ? Math.max(l / 3, 1) : (i == 1 ? l * 2 / 3 + 1 : Math.max(l, j * 2)); - } - } - - public static ItemStack a(Random random, ItemStack itemstack, int i, boolean flag) { - List list = b(random, itemstack, i, flag); - boolean flag1 = itemstack.getItem() == Items.BOOK; - - if (flag1) { - itemstack = new ItemStack(Items.ENCHANTED_BOOK); - } - - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - WeightedRandomEnchant weightedrandomenchant = (WeightedRandomEnchant) iterator.next(); - - if (flag1) { - ItemEnchantedBook.a(itemstack, weightedrandomenchant); - } else { - itemstack.addEnchantment(weightedrandomenchant.enchantment, weightedrandomenchant.level); - } - } - - return itemstack; - } - - public static List b(Random random, ItemStack itemstack, int i, boolean flag) { - ArrayList arraylist = Lists.newArrayList(); - Item item = itemstack.getItem(); - int j = item.c(); - - if (j <= 0) { - return arraylist; - } else { - i += 1 + random.nextInt(j / 4 + 1) + random.nextInt(j / 4 + 1); - float f = (random.nextFloat() + random.nextFloat() - 1.0F) * 0.15F; - - i = MathHelper.clamp(Math.round(i + i * f), 1, Integer.MAX_VALUE); - List list = a(i, itemstack, flag); - - if (!list.isEmpty()) { - arraylist.add(WeightedRandom.a(random, list)); - - while (random.nextInt(50) <= i) { - a(list, (WeightedRandomEnchant) SystemUtils.a(arraylist)); - if (list.isEmpty()) { - break; - } - - arraylist.add(WeightedRandom.a(random, list)); - i /= 2; - } - } - - return arraylist; - } - } - - public static void a(List list, WeightedRandomEnchant weightedrandomenchant) { - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - if (!weightedrandomenchant.enchantment.c(((WeightedRandomEnchant) iterator.next()).enchantment)) { - iterator.remove(); - } - } - - } - - public static List a(int i, ItemStack itemstack, boolean flag) { - ArrayList arraylist = Lists.newArrayList(); - Item item = itemstack.getItem(); - boolean flag1 = itemstack.getItem() == Items.BOOK; - Iterator iterator = Enchantment.enchantments.iterator(); - - while (iterator.hasNext()) { - Enchantment enchantment = (Enchantment) iterator.next(); - - if ((!enchantment.isTreasure() || flag) && (enchantment.itemTarget.canEnchant(item) || flag1)) { - for (int j = enchantment.getMaxLevel(); j > enchantment.getStartLevel() - 1; --j) { - if (i >= enchantment.a(j) && i <= enchantment.b(j)) { - arraylist.add(new WeightedRandomEnchant(enchantment, j)); - break; - } - } - } - } - - return arraylist; - } - - public static final class EnchantmentModifierArthropods implements EnchantmentManager.EnchantmentModifier { // Akarin - private -> public - - public EntityLiving a; - public Entity b; - - private EnchantmentModifierArthropods() {} - - @Override - public void a(Enchantment enchantment, int i) { - enchantment.a(this.a, this.b, i); - } - - EnchantmentModifierArthropods(Object object) { - this(); - } - } - - public static final class EnchantmentModifierThorns implements EnchantmentManager.EnchantmentModifier { // Akarin - private -> public - - public EntityLiving a; - public Entity b; - - private EnchantmentModifierThorns() {} - - @Override - public void a(Enchantment enchantment, int i) { - enchantment.b(this.a, this.b, i); - } - - EnchantmentModifierThorns(Object object) { - this(); - } - } - - static final class EnchantmentModifierDamage implements EnchantmentManager.EnchantmentModifier { - - public float a; - public EnumMonsterType b; - - private EnchantmentModifierDamage() {} - - @Override - public void a(Enchantment enchantment, int i) { - this.a += enchantment.a(i, this.b); - } - - EnchantmentModifierDamage(Object object) { - this(); - } - } - - public static final class EnchantmentModifierProtection implements EnchantmentManager.EnchantmentModifier { // Akarin - private -> public - - public int a; - public DamageSource b; - - private EnchantmentModifierProtection() {} - - @Override - public void a(Enchantment enchantment, int i) { - this.a += enchantment.a(i, this.b); - } - - EnchantmentModifierProtection(Object object) { - this(); - } - } - - public interface EnchantmentModifier { // Akarin - private -> public - - void a(Enchantment enchantment, int i); - } -} diff --git a/sources/src/main/java/net/minecraft/server/Entity.java b/sources/src/main/java/net/minecraft/server/Entity.java index f1cae87cf..f229cf74c 100644 --- a/sources/src/main/java/net/minecraft/server/Entity.java +++ b/sources/src/main/java/net/minecraft/server/Entity.java @@ -9,6 +9,8 @@ import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Locale; +import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.UUID; @@ -22,6 +24,7 @@ import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.TravelAgent; import org.bukkit.block.BlockFace; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Hanging; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Vehicle; @@ -38,6 +41,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.event.entity.EntityAirChangeEvent; import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.event.entity.EntityDropItemEvent; import org.bukkit.event.entity.EntityPortalEvent; import org.bukkit.plugin.PluginManager; // CraftBukkit end @@ -46,7 +50,7 @@ import org.bukkit.plugin.PluginManager; * Akarin Changes Note * 1) Random -> LightRandom (performance) */ -public abstract class Entity implements ICommandListener, KeyedObject { // Paper +public abstract class Entity implements INamableTileEntity, ICommandListener, KeyedObject { // Paper // CraftBukkit start private static final int CURRENT_LEVEL = 2; @@ -72,25 +76,31 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper protected CraftEntity bukkitEntity; EntityTrackerEntry tracker; // Paper + Throwable addedToWorldStack; // Paper - entity debug public CraftEntity getBukkitEntity() { if (bukkitEntity == null) { bukkitEntity = CraftEntity.getEntity(world.getServer(), this); } return bukkitEntity; } - Throwable addedToWorldStack; // Paper - entity debug - // CraftBukikt end - private static final Logger a = LogManager.getLogger(); - private static final List b = Collections.emptyList(); - private static final AxisAlignedBB c = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D); - private static double f = 1.0D; - private static int entityCount; + @Override + public CommandSender getBukkitSender(CommandListenerWrapper wrapper) { + return getBukkitEntity(); + } + // CraftBukkit end + + protected static final Logger i = LogManager.getLogger(); + private static final List a = Collections.emptyList(); + private static final AxisAlignedBB b = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D); + private static double c = 1.0D; + private static int entityCount = 1; // Paper - MC-111480 - ID 0 is treated as special for DataWatchers, start 1 + private final EntityTypes g; public EntityTypes getEntityType() { return g; } // Paper - OBFHELPER private int id; - public boolean i; public boolean blocksEntitySpawning() { return i; } // Paper - OBFHELPER + public boolean j; public boolean blocksEntitySpawning() { return j; } // Paper - OBFHELPER public final List passengers; - protected int j; - private Entity au;public void setVehicle(Entity entity) { this.au = entity; } // Paper // OBFHELPER + protected int k; + private Entity ax; public boolean attachedToPlayer; public World world; public double lastX; @@ -99,19 +109,6 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public double locX; public double locY; public double locZ; - // Paper start - getters to implement HopperPusher - public double getX() { - return locX; - } - - public double getY() { - return locY; - } - - public double getZ() { - return locZ; - } - // Paper end public double motX; public double motY; public double motZ; @@ -122,63 +119,66 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper private AxisAlignedBB boundingBox; public boolean onGround; public boolean positionChanged; - public boolean B; public boolean C; + public boolean D; public boolean velocityChanged; - protected boolean E; - private boolean aw; + protected boolean F; + private boolean az; public boolean dead; + public boolean shouldBeRemoved; // Paper public float width; public float length; - public float I; public float J; public float K; + public float L; public float fallDistance; - private int ax; - private float ay; - public double M; + private float aA; + private float aB; public double N; public double O; - public float P; + public double P; + public float Q; public boolean noclip; - public float R; + public float S; protected Random random; public int ticksLived; public int fireTicks; - public boolean inWater; // Spigot - protected -> public // PAIL + public boolean inWater; + protected double W; + protected boolean X; public int noDamageTicks; protected boolean justCreated; protected boolean fireProof; protected DataWatcher datawatcher; - protected static final DataWatcherObject Z = DataWatcher.a(Entity.class, DataWatcherRegistry.a); - private static final DataWatcherObject aA = DataWatcher.a(Entity.class, DataWatcherRegistry.b); - private static final DataWatcherObject aB = DataWatcher.a(Entity.class, DataWatcherRegistry.d); - private static final DataWatcherObject aC = DataWatcher.a(Entity.class, DataWatcherRegistry.h); - private static final DataWatcherObject aD = DataWatcher.a(Entity.class, DataWatcherRegistry.h); - private static final DataWatcherObject aE = DataWatcher.a(Entity.class, DataWatcherRegistry.h); - public boolean aa; public boolean isAddedToChunk() { return aa; } // Paper - OBFHELPER - public int ab; public int getChunkX() { return ab; } // Paper - OBFHELPER - public int ac; public int getChunkY() { return ac; } // Paper - OBFHELPER - public int ad; public int getChunkZ() { return ad; } // Paper - OBFHELPER - public boolean ah; + protected static final DataWatcherObject ac = DataWatcher.a(Entity.class, DataWatcherRegistry.a); + private static final DataWatcherObject aD = DataWatcher.a(Entity.class, DataWatcherRegistry.b); + private static final DataWatcherObject> aE = DataWatcher.a(Entity.class, DataWatcherRegistry.f); + private static final DataWatcherObject aF = DataWatcher.a(Entity.class, DataWatcherRegistry.i); + private static final DataWatcherObject aG = DataWatcher.a(Entity.class, DataWatcherRegistry.i); + private static final DataWatcherObject aH = DataWatcher.a(Entity.class, DataWatcherRegistry.i); + public boolean inChunk; public boolean isAddedToChunk() { return inChunk; } // Paper - OBFHELPER + public int ae; public int getChunkX() { return ae; } // Paper - OBFHELPER + public int af; public int getChunkY() { return af; } // Paper - OBFHELPER + public int ag; public int getChunkZ() { return ag; } // Paper - OBFHELPER + public boolean ak; public boolean impulse; public int portalCooldown; - protected boolean ak; public boolean inPortal() { return ak; } // Paper - OBFHELPER - protected int al; + protected boolean an; public boolean inPortal() { return an; } // Paper - OBFHELPER + protected int ao; public int dimension; - protected BlockPosition an; - protected Vec3D ao; - protected EnumDirection ap; + protected BlockPosition aq; + protected Vec3D ar; + protected EnumDirection as; private boolean invulnerable; protected UUID uniqueID; - protected String ar; - private final CommandObjectiveExecutor aG; + protected String au; public boolean glowing; - private final Set aH; - private boolean aI; - private final double[] aJ; - private long aK; + private final Set aJ; + private boolean aK; + private final double[] aL; + private long aM; // CraftBukkit start + public boolean persist = true; public boolean valid; public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only public boolean forceExplosionKnockback; // SPIGOT-949 @@ -199,22 +199,22 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } // CraftBukkit end - public Entity(World world) { + public Entity(EntityTypes entitytypes, World world) { this.id = Entity.entityCount++; this.passengers = Lists.newArrayList(); - this.boundingBox = Entity.c; + this.boundingBox = Entity.b; this.width = 0.6F; this.length = 1.8F; - this.ax = 1; - this.ay = 1.0F; + this.aA = 1.0F; + this.aB = 1.0F; this.random = SHARED_RANDOM; // Paper this.fireTicks = -this.getMaxFireTicks(); this.justCreated = true; this.uniqueID = MathHelper.a(this.random); - this.ar = this.uniqueID.toString(); - this.aG = new CommandObjectiveExecutor(); - this.aH = Sets.newHashSet(); - this.aJ = new double[] { 0.0D, 0.0D, 0.0D}; + this.au = this.uniqueID.toString(); + this.aJ = Sets.newHashSet(); + this.aL = new double[] { 0.0D, 0.0D, 0.0D}; + this.g = entitytypes; this.world = world; this.setPosition(0.0D, 0.0D, 0.0D); if (world != null) { @@ -227,45 +227,44 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper // Spigot end this.datawatcher = new DataWatcher(this); - this.datawatcher.register(Entity.Z, Byte.valueOf((byte) 0)); - this.datawatcher.register(Entity.aA, Integer.valueOf(300)); - this.datawatcher.register(Entity.aC, Boolean.valueOf(false)); - this.datawatcher.register(Entity.aB, ""); - this.datawatcher.register(Entity.aD, Boolean.valueOf(false)); - this.datawatcher.register(Entity.aE, Boolean.valueOf(false)); - this.i(); + this.datawatcher.register(Entity.ac, Byte.valueOf((byte) 0)); + this.datawatcher.register(Entity.aD, Integer.valueOf(this.bf())); + this.datawatcher.register(Entity.aF, Boolean.valueOf(false)); + this.datawatcher.register(Entity.aE, Optional.empty()); + this.datawatcher.register(Entity.aG, Boolean.valueOf(false)); + this.datawatcher.register(Entity.aH, Boolean.valueOf(false)); + this.x_(); + } + + public EntityTypes P() { + return this.g; } public int getId() { return this.id; } - public void h(int i) { + public void f(int i) { this.id = i; } public Set getScoreboardTags() { - return this.aH; + return this.aJ; } public boolean addScoreboardTag(String s) { - if (this.aH.size() >= 1024) { - return false; - } else { - this.aH.add(s); - return true; - } + return this.aJ.size() >= 1024 ? false : this.aJ.add(s); } public boolean removeScoreboardTag(String s) { - return this.aH.remove(s); + return this.aJ.remove(s); } public void killEntity() { this.die(); } - protected abstract void i(); + protected abstract void x_(); public DataWatcher getDataWatcher() { return this.datawatcher; @@ -344,18 +343,19 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.locX = d0; this.locY = d1; this.locZ = d2; + if (valid) world.entityJoinedWorld(this, false); // Paper - ensure Entity is moved to its proper chunk float f = this.width / 2.0F; float f1 = this.length; this.a(new AxisAlignedBB(d0 - (double) f, d1, d2 - (double) f, d0 + (double) f, d1 + (double) f1, d2 + (double) f)); } - public void B_() { + public void tick() { if (!this.world.isClientSide) { - this.setFlag(6, this.aW()); + this.setFlag(6, this.bc()); } - this.Y(); + this.W(); } // CraftBukkit start @@ -363,16 +363,16 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle if (!this.world.isClientSide && this.world instanceof WorldServer) { this.world.methodProfiler.a("portal"); - if (this.ak) { + if (this.an) { MinecraftServer minecraftserver = this.world.getMinecraftServer(); if (true || minecraftserver.getAllowNether()) { // CraftBukkit if (!this.isPassenger()) { - int i = this.Z(); + int i = this.X(); - if (this.al++ >= i) { - this.al = i; - this.portalCooldown = this.aM(); + if (this.ao++ >= i) { + this.ao = i; + this.portalCooldown = this.aQ(); byte b0; if (this.world.worldProvider.getDimensionManager().getDimensionID() == -1) { @@ -381,39 +381,39 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper b0 = -1; } - this.b(b0); + this.d(b0); } } - this.ak = false; + this.an = false; } } else { - if (this.al > 0) { - this.al -= 4; + if (this.ao > 0) { + this.ao -= 4; } - if (this.al < 0) { - this.al = 0; + if (this.ao < 0) { + this.ao = 0; } } - this.I(); - this.world.methodProfiler.b(); + this.E(); + this.world.methodProfiler.e(); } } // CraftBukkit end - public void Y() { + public void W() { this.world.methodProfiler.a("entityBaseTick"); - if (this.isPassenger() && this.bJ().dead) { + if (this.isPassenger() && this.getVehicle().dead) { this.stopRiding(); } - if (this.j > 0) { - --this.j; + if (this.k > 0) { + --this.k; } - this.I = this.J; + this.J = this.K; this.lastX = this.locX; this.lastY = this.locY; this.lastZ = this.locZ; @@ -423,16 +423,16 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper /* if (!this.world.isClientSide && this.world instanceof WorldServer) { this.world.methodProfiler.a("portal"); - if (this.ak) { + if (this.an) { MinecraftServer minecraftserver = this.world.getMinecraftServer(); if (minecraftserver.getAllowNether()) { if (!this.isPassenger()) { - int i = this.Z(); + int i = this.X(); - if (this.al++ >= i) { - this.al = i; - this.portalCooldown = this.aM(); + if (this.ao++ >= i) { + this.ao = i; + this.portalCooldown = this.aQ(); byte b0; if (this.world.worldProvider.getDimensionManager().getDimensionID() == -1) { @@ -441,29 +441,29 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper b0 = -1; } - this.b(b0); + this.d(b0); } } - this.ak = false; + this.an = false; } } else { - if (this.al > 0) { - this.al -= 4; + if (this.ao > 0) { + this.ao -= 4; } - if (this.al < 0) { - this.al = 0; + if (this.ao < 0) { + this.ao = 0; } } - this.I(); - this.world.methodProfiler.b(); + this.E(); + this.world.methodProfiler.e(); } */ - this.as(); - this.aq(); + this.av(); + this.r(); if (this.world.isClientSide) { this.extinguish(); } else if (this.fireTicks > 0) { @@ -481,7 +481,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - if (this.au()) { + if (this.ax()) { this.burnFromLava(); this.fallDistance *= 0.5F; } @@ -490,7 +490,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper // Extracted to own function /* if (this.locY < -64.0D) { - this.ac(); + this.aa(); } */ this.checkAndDoHeightDamage(); @@ -501,29 +501,25 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } this.justCreated = false; - this.world.methodProfiler.b(); - } - - // Paper start - Configurable top of nether void damage - private boolean paperNetherCheck() { - return this.world.paperConfig.netherVoidTopDamage && this.world.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER && this.locY >= 128.0D; + this.world.methodProfiler.e(); } + // Paper start protected void checkAndDoHeightDamage() { - if (this.locY < -64.0D || paperNetherCheck()) { + if (this.locY < -64.0D || (this.world.paperConfig.netherVoidTopDamage && this.world.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER && this.locY >= 128.0D)) { this.kill(); } } // Paper end - protected void I() { + protected void E() { if (this.portalCooldown > 0) { --this.portalCooldown; } } - public int Z() { + public int X() { return 1; } @@ -572,19 +568,17 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.fireTicks = 0; } - protected final void kill() { this.ac(); } // Paper - OBFHELPER - protected void ac() { + protected final void kill() { this.aa(); } // Paper - OBFHELPER + protected void aa() { this.die(); } public boolean c(double d0, double d1, double d2) { - AxisAlignedBB axisalignedbb = this.getBoundingBox().d(d0, d1, d2); - - return this.b(axisalignedbb); + return this.b(this.getBoundingBox().d(d0, d1, d2)); } private boolean b(AxisAlignedBB axisalignedbb) { - return this.world.getCubes(this, axisalignedbb).isEmpty() && !this.world.containsLiquid(axisalignedbb); + return this.world.getCubes(this, axisalignedbb) && !this.world.containsLiquid(axisalignedbb); } public void move(EnumMoveType enummovetype, double d0, double d1, double d2) { @@ -592,28 +586,12 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.a(this.getBoundingBox().d(d0, d1, d2)); this.recalcPosition(); } else { - // CraftBukkit start - Don't do anything if we aren't moving - // We need to do this regardless of whether or not we are moving thanks to portals - try { - this.checkBlockCollisions(); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Checking entity block collision"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being checked for collision"); - - this.appendEntityCrashDetails(crashreportsystemdetails); - throw new ReportedException(crashreport); - } - // Check if we're moving - if (d0 == 0 && d1 == 0 && d2 == 0 && this.isVehicle() && this.isPassenger()) { - return; - } - // CraftBukkit end if (enummovetype == EnumMoveType.PISTON) { long i = this.world.getTime(); - if (i != this.aK) { - Arrays.fill(this.aJ, 0.0D); - this.aK = i; + if (i != this.aM) { + Arrays.fill(this.aL, 0.0D); + this.aM = i; } int j; @@ -621,17 +599,17 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper if (d0 != 0.0D) { j = EnumDirection.EnumAxis.X.ordinal(); - d3 = MathHelper.a(d0 + this.aJ[j], -0.51D, 0.51D); - d0 = d3 - this.aJ[j]; - this.aJ[j] = d3; + d3 = MathHelper.a(d0 + this.aL[j], -0.51D, 0.51D); + d0 = d3 - this.aL[j]; + this.aL[j] = d3; if (Math.abs(d0) <= 9.999999747378752E-6D) { return; } } else if (d1 != 0.0D) { j = EnumDirection.EnumAxis.Y.ordinal(); - d3 = MathHelper.a(d1 + this.aJ[j], -0.51D, 0.51D); - d1 = d3 - this.aJ[j]; - this.aJ[j] = d3; + d3 = MathHelper.a(d1 + this.aL[j], -0.51D, 0.51D); + d1 = d3 - this.aL[j]; + this.aL[j] = d3; if (Math.abs(d1) <= 9.999999747378752E-6D) { return; } @@ -641,9 +619,9 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } j = EnumDirection.EnumAxis.Z.ordinal(); - d3 = MathHelper.a(d2 + this.aJ[j], -0.51D, 0.51D); - d2 = d3 - this.aJ[j]; - this.aJ[j] = d3; + d3 = MathHelper.a(d2 + this.aL[j], -0.51D, 0.51D); + d2 = d3 - this.aL[j]; + this.aL[j] = d3; if (Math.abs(d2) <= 9.999999747378752E-6D) { return; } @@ -655,8 +633,8 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper double d5 = this.locY; double d6 = this.locZ; - if (this.E) { - this.E = false; + if (this.F) { + this.F = false; d0 *= 0.25D; d1 *= 0.05000000074505806D; d2 *= 0.25D; @@ -670,7 +648,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper double d9 = d2; if ((enummovetype == EnumMoveType.SELF || enummovetype == EnumMoveType.PLAYER) && this.onGround && this.isSneaking() && this instanceof EntityHuman) { - for (double d10 = 0.05D; d0 != 0.0D && this.world.getCubes(this, this.getBoundingBox().d(d0, (double) (-this.P), 0.0D)).isEmpty(); d7 = d0) { + for (double d10 = 0.05D; d0 != 0.0D && this.world.getCubes(this, this.getBoundingBox().d(d0, (double) (-this.Q), 0.0D)); d7 = d0) { if (d0 < 0.05D && d0 >= -0.05D) { d0 = 0.0D; } else if (d0 > 0.0D) { @@ -680,7 +658,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - for (; d2 != 0.0D && this.world.getCubes(this, this.getBoundingBox().d(0.0D, (double) (-this.P), d2)).isEmpty(); d9 = d2) { + for (; d2 != 0.0D && this.world.getCubes(this, this.getBoundingBox().d(0.0D, (double) (-this.Q), d2)); d9 = d2) { if (d2 < 0.05D && d2 >= -0.05D) { d2 = 0.0D; } else if (d2 > 0.0D) { @@ -690,7 +668,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - for (; d0 != 0.0D && d2 != 0.0D && this.world.getCubes(this, this.getBoundingBox().d(d0, (double) (-this.P), d2)).isEmpty(); d9 = d2) { + for (; d0 != 0.0D && d2 != 0.0D && this.world.getCubes(this, this.getBoundingBox().d(d0, (double) (-this.Q), d2)); d9 = d2) { if (d0 < 0.05D && d0 >= -0.05D) { d0 = 0.0D; } else if (d0 > 0.0D) { @@ -710,131 +688,106 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - List list = this.world.getCubes(this, this.getBoundingBox().b(d0, d1, d2)); AxisAlignedBB axisalignedbb = this.getBoundingBox(); - int k; - int l; - if (d1 != 0.0D) { - k = 0; + if (d0 != 0.0D || d1 != 0.0D || d2 != 0.0D) { + VoxelShape voxelshape = this.world.a(this, this.getBoundingBox(), d0, d1, d2); - for (l = list.size(); k < l; ++k) { - d1 = ((AxisAlignedBB) list.get(k)).b(this.getBoundingBox(), d1); - } - - this.a(this.getBoundingBox().d(0.0D, d1, 0.0D)); - } - - if (d0 != 0.0D) { - k = 0; - - for (l = list.size(); k < l; ++k) { - d0 = ((AxisAlignedBB) list.get(k)).a(this.getBoundingBox(), d0); + if (d1 != 0.0D) { + d1 = VoxelShapes.a(EnumDirection.EnumAxis.Y, this.getBoundingBox(), voxelshape, d1); + this.a(this.getBoundingBox().d(0.0D, d1, 0.0D)); } if (d0 != 0.0D) { - this.a(this.getBoundingBox().d(d0, 0.0D, 0.0D)); - } - } - - if (d2 != 0.0D) { - k = 0; - - for (l = list.size(); k < l; ++k) { - d2 = ((AxisAlignedBB) list.get(k)).c(this.getBoundingBox(), d2); + d0 = VoxelShapes.a(EnumDirection.EnumAxis.X, this.getBoundingBox(), voxelshape, d0); + if (d0 != 0.0D) { + this.a(this.getBoundingBox().d(d0, 0.0D, 0.0D)); + } } if (d2 != 0.0D) { - this.a(this.getBoundingBox().d(0.0D, 0.0D, d2)); + d2 = VoxelShapes.a(EnumDirection.EnumAxis.Z, this.getBoundingBox(), voxelshape, d2); + if (d2 != 0.0D) { + this.a(this.getBoundingBox().d(0.0D, 0.0D, d2)); + } } } boolean flag = this.onGround || d1 != d8 && d1 < 0.0D; // CraftBukkit - decompile error double d11; - if (this.P > 0.0F && flag && (d7 != d0 || d9 != d2)) { + if (this.Q > 0.0F && flag && (d7 != d0 || d9 != d2)) { double d12 = d0; double d13 = d1; double d14 = d2; AxisAlignedBB axisalignedbb1 = this.getBoundingBox(); this.a(axisalignedbb); - d1 = (double) this.P; - List list1 = this.world.getCubes(this, this.getBoundingBox().b(d7, d1, d9)); - AxisAlignedBB axisalignedbb2 = this.getBoundingBox(); - AxisAlignedBB axisalignedbb3 = axisalignedbb2.b(d7, 0.0D, d9); + d0 = d7; + 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); + AxisAlignedBB axisalignedbb2 = this.getBoundingBox(); + AxisAlignedBB axisalignedbb3 = axisalignedbb2.b(d7, 0.0D, d9); - d11 = d1; - int i1 = 0; + d11 = VoxelShapes.a(EnumDirection.EnumAxis.Y, axisalignedbb3, voxelshape1, d1); + if (d11 != 0.0D) { + axisalignedbb2 = axisalignedbb2.d(0.0D, d11, 0.0D); + } - for (int j1 = list1.size(); i1 < j1; ++i1) { - d11 = ((AxisAlignedBB) list1.get(i1)).b(axisalignedbb3, d11); + double d15 = VoxelShapes.a(EnumDirection.EnumAxis.X, axisalignedbb2, voxelshape1, d7); + + if (d15 != 0.0D) { + axisalignedbb2 = axisalignedbb2.d(d15, 0.0D, 0.0D); + } + + double d16 = VoxelShapes.a(EnumDirection.EnumAxis.Z, axisalignedbb2, voxelshape1, 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); + + if (d17 != 0.0D) { + axisalignedbb4 = axisalignedbb4.d(0.0D, d17, 0.0D); + } + + double d18 = VoxelShapes.a(EnumDirection.EnumAxis.X, axisalignedbb4, voxelshape1, d7); + + if (d18 != 0.0D) { + axisalignedbb4 = axisalignedbb4.d(d18, 0.0D, 0.0D); + } + + double d19 = VoxelShapes.a(EnumDirection.EnumAxis.Z, axisalignedbb4, voxelshape1, d9); + + if (d19 != 0.0D) { + axisalignedbb4 = axisalignedbb4.d(0.0D, 0.0D, d19); + } + + double d20 = d15 * d15 + d16 * d16; + double d21 = d18 * d18 + d19 * d19; + + if (d20 > d21) { + d0 = d15; + d2 = d16; + d1 = -d11; + this.a(axisalignedbb2); + } else { + d0 = d18; + d2 = d19; + d1 = -d17; + this.a(axisalignedbb4); + } + + d1 = VoxelShapes.a(EnumDirection.EnumAxis.Y, this.getBoundingBox(), voxelshape1, d1); + if (d1 != 0.0D) { + this.a(this.getBoundingBox().d(0.0D, d1, 0.0D)); + } } - axisalignedbb2 = axisalignedbb2.d(0.0D, d11, 0.0D); - double d15 = d7; - int k1 = 0; - - for (int l1 = list1.size(); k1 < l1; ++k1) { - d15 = ((AxisAlignedBB) list1.get(k1)).a(axisalignedbb2, d15); - } - - axisalignedbb2 = axisalignedbb2.d(d15, 0.0D, 0.0D); - double d16 = d9; - int i2 = 0; - - for (int j2 = list1.size(); i2 < j2; ++i2) { - d16 = ((AxisAlignedBB) list1.get(i2)).c(axisalignedbb2, d16); - } - - axisalignedbb2 = axisalignedbb2.d(0.0D, 0.0D, d16); - AxisAlignedBB axisalignedbb4 = this.getBoundingBox(); - double d17 = d1; - int k2 = 0; - - for (int l2 = list1.size(); k2 < l2; ++k2) { - d17 = ((AxisAlignedBB) list1.get(k2)).b(axisalignedbb4, d17); - } - - axisalignedbb4 = axisalignedbb4.d(0.0D, d17, 0.0D); - double d18 = d7; - int i3 = 0; - - for (int j3 = list1.size(); i3 < j3; ++i3) { - d18 = ((AxisAlignedBB) list1.get(i3)).a(axisalignedbb4, d18); - } - - axisalignedbb4 = axisalignedbb4.d(d18, 0.0D, 0.0D); - double d19 = d9; - int k3 = 0; - - for (int l3 = list1.size(); k3 < l3; ++k3) { - d19 = ((AxisAlignedBB) list1.get(k3)).c(axisalignedbb4, d19); - } - - axisalignedbb4 = axisalignedbb4.d(0.0D, 0.0D, d19); - double d20 = d15 * d15 + d16 * d16; - double d21 = d18 * d18 + d19 * d19; - - if (d20 > d21) { - d0 = d15; - d2 = d16; - d1 = -d11; - this.a(axisalignedbb2); - } else { - d0 = d18; - d2 = d19; - d1 = -d17; - this.a(axisalignedbb4); - } - - int i4 = 0; - - for (int j4 = list1.size(); i4 < j4; ++i4) { - d1 = ((AxisAlignedBB) list1.get(i4)).b(this.getBoundingBox(), d1); - } - - this.a(this.getBoundingBox().d(0.0D, d1, 0.0D)); if (d12 * d12 + d14 * d14 >= d0 * d0 + d2 * d2) { d0 = d12; d1 = d13; @@ -843,20 +796,20 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - this.world.methodProfiler.b(); + this.world.methodProfiler.e(); this.world.methodProfiler.a("rest"); this.recalcPosition(); this.positionChanged = d7 != d0 || d9 != d2; - this.B = d1 != d8; // CraftBukkit - decompile error - this.onGround = this.B && d8 < 0.0D; - this.C = this.positionChanged || this.B; - l = MathHelper.floor(this.locX); - int k4 = MathHelper.floor(this.locY - 0.20000000298023224D); - int l4 = MathHelper.floor(this.locZ); - BlockPosition blockposition = new BlockPosition(l, k4, l4); + this.C = d1 != d8; // CraftBukkit - decompile error + this.onGround = this.C && d8 < 0.0D; + this.D = this.positionChanged || this.C; + int k = MathHelper.floor(this.locX); + int l = MathHelper.floor(this.locY - 0.20000000298023224D); + int i1 = MathHelper.floor(this.locZ); + BlockPosition blockposition = new BlockPosition(k, l, i1); IBlockData iblockdata = this.world.getType(blockposition); - if (iblockdata.getMaterial() == Material.AIR) { + if (iblockdata.isAir()) { BlockPosition blockposition1 = blockposition.down(); IBlockData iblockdata1 = this.world.getType(blockposition1); Block block = iblockdata1.getBlock(); @@ -879,7 +832,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper Block block1 = iblockdata.getBlock(); if (d8 != d1) { - block1.a(this.world, this); + block1.a((IBlockAccess) this.world, this); } // CraftBukkit start @@ -917,12 +870,12 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper block1.stepOn(this.world, blockposition, this); } - this.J = (float) ((double) this.J + (double) MathHelper.sqrt(d22 * d22 + d11 * d11) * 0.6D); - this.K = (float) ((double) this.K + (double) MathHelper.sqrt(d22 * d22 + d23 * d23 + d11 * d11) * 0.6D); - if (this.K > (float) this.ax && iblockdata.getMaterial() != Material.AIR) { - this.ax = (int) this.K + 1; + this.K = (float) ((double) this.K + (double) MathHelper.sqrt(d22 * d22 + d11 * d11) * 0.6D); + this.L = (float) ((double) this.L + (double) MathHelper.sqrt(d22 * d22 + d23 * d23 + d11 * d11) * 0.6D); + if (this.L > this.aA && !iblockdata.isAir()) { + this.aA = this.ab(); if (this.isInWater()) { - Entity entity = this.isVehicle() && this.bE() != null ? this.bE() : this; + Entity entity = this.isVehicle() && this.bO() != null ? this.bO() : this; float f = entity == this ? 0.35F : 0.4F; float f1 = MathHelper.sqrt(entity.motX * entity.motX * 0.20000000298023224D + entity.motY * entity.motY + entity.motZ * entity.motZ * 0.20000000298023224D) * f; @@ -930,17 +883,15 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper f1 = 1.0F; } - this.a(this.ae(), f1, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + this.d(f1); } else { - this.a(blockposition, block1); + this.a(blockposition, iblockdata); } - } else if (this.K > this.ay && this.ah() && iblockdata.getMaterial() == Material.AIR) { - this.ay = this.d(this.K); + } else if (this.L > this.aB && this.ah() && iblockdata.isAir()) { + this.aB = this.e(this.L); } } - // CraftBukkit start - Move to the top of the method - /* try { this.checkBlockCollisions(); } catch (Throwable throwable) { @@ -950,12 +901,10 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.appendEntityCrashDetails(crashreportsystemdetails); throw new ReportedException(crashreport); } - */ - // CraftBukkit end - boolean flag1 = this.an(); + boolean flag1 = this.ap(); - if (this.world.e(this.getBoundingBox().shrink(0.001D))) { + if (this.world.b(this.getBoundingBox().shrink(0.001D))) { this.burn(1); if (!flag1) { ++this.fireTicks; @@ -975,78 +924,143 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } if (flag1 && this.isBurning()) { - this.a(SoundEffects.bW, 0.7F, 1.6F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + this.a(SoundEffects.ENTITY_GENERIC_EXTINGUISH_FIRE, 0.7F, 1.6F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); this.fireTicks = -this.getMaxFireTicks(); } - this.world.methodProfiler.b(); + this.world.methodProfiler.e(); } } + protected float ab() { + return (float) ((int) this.L + 1); + } + public void recalcPosition() { AxisAlignedBB axisalignedbb = this.getBoundingBox(); this.locX = (axisalignedbb.a + axisalignedbb.d) / 2.0D; this.locY = axisalignedbb.b; this.locZ = (axisalignedbb.c + axisalignedbb.f) / 2.0D; + if (valid) world.entityJoinedWorld(this, false); // Paper - ensure Entity is moved to its proper chunk + } + + protected SoundEffect ad() { + return SoundEffects.ENTITY_GENERIC_SWIM; } protected SoundEffect ae() { - return SoundEffects.ca; + return SoundEffects.ENTITY_GENERIC_SPLASH; } protected SoundEffect af() { - return SoundEffects.bZ; + return SoundEffects.ENTITY_GENERIC_SPLASH; } protected void checkBlockCollisions() { AxisAlignedBB axisalignedbb = this.getBoundingBox(); - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.d(axisalignedbb.a + 0.001D, axisalignedbb.b + 0.001D, axisalignedbb.c + 0.001D); - BlockPosition.PooledBlockPosition blockposition_pooledblockposition1 = BlockPosition.PooledBlockPosition.d(axisalignedbb.d - 0.001D, axisalignedbb.e - 0.001D, axisalignedbb.f - 0.001D); - BlockPosition.PooledBlockPosition blockposition_pooledblockposition2 = BlockPosition.PooledBlockPosition.s(); + BlockPosition.b blockposition_b = BlockPosition.b.d(axisalignedbb.a + 0.001D, axisalignedbb.b + 0.001D, axisalignedbb.c + 0.001D); + Throwable throwable = null; - if (this.world.areChunksLoadedBetween(blockposition_pooledblockposition, blockposition_pooledblockposition1)) { - for (int i = blockposition_pooledblockposition.getX(); i <= blockposition_pooledblockposition1.getX(); ++i) { - for (int j = blockposition_pooledblockposition.getY(); j <= blockposition_pooledblockposition1.getY(); ++j) { - for (int k = blockposition_pooledblockposition.getZ(); k <= blockposition_pooledblockposition1.getZ(); ++k) { - blockposition_pooledblockposition2.f(i, j, k); - IBlockData iblockdata = this.world.getType(blockposition_pooledblockposition2); + try { + BlockPosition.b blockposition_b1 = BlockPosition.b.d(axisalignedbb.d - 0.001D, axisalignedbb.e - 0.001D, axisalignedbb.f - 0.001D); + Throwable throwable1 = null; - try { - iblockdata.getBlock().a(this.world, (BlockPosition) blockposition_pooledblockposition2, iblockdata, this); - this.a(iblockdata); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Colliding entity with block"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being collided with"); + try { + BlockPosition.b blockposition_b2 = BlockPosition.b.r(); + Throwable throwable2 = null; - CrashReportSystemDetails.a(crashreportsystemdetails, blockposition_pooledblockposition2, iblockdata); - throw new ReportedException(crashreport); + try { + if (this.world.areChunksLoadedBetween(blockposition_b, blockposition_b1)) { + for (int i = blockposition_b.getX(); i <= blockposition_b1.getX(); ++i) { + for (int j = blockposition_b.getY(); j <= blockposition_b1.getY(); ++j) { + for (int k = blockposition_b.getZ(); k <= blockposition_b1.getZ(); ++k) { + blockposition_b2.f(i, j, k); + IBlockData iblockdata = this.world.getType(blockposition_b2); + + try { + iblockdata.a(this.world, blockposition_b2, this); + this.a(iblockdata); + } catch (Throwable throwable3) { + CrashReport crashreport = CrashReport.a(throwable3, "Colliding entity with block"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being collided with"); + + CrashReportSystemDetails.a(crashreportsystemdetails, blockposition_b2, iblockdata); + throw new ReportedException(crashreport); + } + } + } } } + } catch (Throwable throwable4) { + throwable2 = throwable4; + throw throwable4; + } finally { + if (blockposition_b2 != null) { + if (throwable2 != null) { + try { + blockposition_b2.close(); + } catch (Throwable throwable5) { + throwable2.addSuppressed(throwable5); + } + } else { + blockposition_b2.close(); + } + } + + } + } catch (Throwable throwable6) { + throwable1 = throwable6; + throw throwable6; + } finally { + if (blockposition_b1 != null) { + if (throwable1 != null) { + try { + blockposition_b1.close(); + } catch (Throwable throwable7) { + throwable1.addSuppressed(throwable7); + } + } else { + blockposition_b1.close(); + } + } + + } + } catch (Throwable throwable8) { + throwable = throwable8; + throw throwable8; + } finally { + if (blockposition_b != null) { + if (throwable != null) { + try { + blockposition_b.close(); + } catch (Throwable throwable9) { + throwable.addSuppressed(throwable9); + } + } else { + blockposition_b.close(); } } + } - blockposition_pooledblockposition.t(); - blockposition_pooledblockposition1.t(); - blockposition_pooledblockposition2.t(); } protected void a(IBlockData iblockdata) {} - protected void a(BlockPosition blockposition, Block block) { - SoundEffectType soundeffecttype = block.getStepSound(); + protected void a(BlockPosition blockposition, IBlockData iblockdata) { + if (!iblockdata.getMaterial().isLiquid()) { + SoundEffectType soundeffecttype = this.world.getType(blockposition.up()).getBlock() == Blocks.SNOW ? Blocks.SNOW.getStepSound() : iblockdata.getBlock().getStepSound(); - if (this.world.getType(blockposition.up()).getBlock() == Blocks.SNOW_LAYER) { - soundeffecttype = Blocks.SNOW_LAYER.getStepSound(); - this.a(soundeffecttype.d(), soundeffecttype.a() * 0.15F, soundeffecttype.b()); - } else if (!block.getBlockData().getMaterial().isLiquid()) { this.a(soundeffecttype.d(), soundeffecttype.a() * 0.15F, soundeffecttype.b()); } - } - protected float d(float f) { + protected void d(float f) { + this.a(this.ad(), f, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + } + + protected float e(float f) { return 0.0F; } @@ -1056,25 +1070,25 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public void a(SoundEffect soundeffect, float f, float f1) { if (!this.isSilent()) { - this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, soundeffect, this.bK(), f, f1); + this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, soundeffect, this.bV(), f, f1); } } public boolean isSilent() { - return ((Boolean) this.datawatcher.get(Entity.aD)).booleanValue(); + return ((Boolean) this.datawatcher.get(Entity.aG)).booleanValue(); } public void setSilent(boolean flag) { - this.datawatcher.set(Entity.aD, Boolean.valueOf(flag)); + this.datawatcher.set(Entity.aG, Boolean.valueOf(flag)); } public boolean isNoGravity() { - return ((Boolean) this.datawatcher.get(Entity.aE)).booleanValue(); + return ((Boolean) this.datawatcher.get(Entity.aH)).booleanValue(); } public void setNoGravity(boolean flag) { - this.datawatcher.set(Entity.aE, Boolean.valueOf(flag)); + this.datawatcher.set(Entity.aH, Boolean.valueOf(flag)); } protected boolean playStepSound() { @@ -1110,54 +1124,99 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return this.fireProof; } - public void e(float f, float f1) { + public void c(float f, float f1) { if (this.isVehicle()) { - Iterator iterator = this.bF().iterator(); + Iterator iterator = this.bP().iterator(); while (iterator.hasNext()) { Entity entity = (Entity) iterator.next(); - entity.e(f, f1); + entity.c(f, f1); } } } - public boolean an() { - if (this.inWater) { - return true; - } else { - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.d(this.locX, this.locY, this.locZ); - - if (!this.world.isRainingAt(blockposition_pooledblockposition) && !this.world.isRainingAt(blockposition_pooledblockposition.e(this.locX, this.locY + (double) this.length, this.locZ))) { - blockposition_pooledblockposition.t(); - return false; - } else { - blockposition_pooledblockposition.t(); - return true; - } - } - } - public boolean isInWater() { return this.inWater; } + private boolean p() { + BlockPosition.b blockposition_b = BlockPosition.b.b(this); + Throwable throwable = null; + + boolean flag; + + try { + flag = this.world.isRainingAt(blockposition_b) || this.world.isRainingAt(blockposition_b.e(this.locX, this.locY + (double) this.length, this.locZ)); + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; + } finally { + if (blockposition_b != null) { + if (throwable != null) { + try { + blockposition_b.close(); + } catch (Throwable throwable2) { + throwable.addSuppressed(throwable2); + } + } else { + blockposition_b.close(); + } + } + + } + + return flag; + } + + private boolean q() { + return this.world.getType(new BlockPosition(this)).getBlock() == Blocks.BUBBLE_COLUMN; + } + + public boolean ao() { + return this.isInWater() || this.p(); + } + public boolean ap() { - return this.world.a(this.getBoundingBox().grow(0.0D, -20.0D, 0.0D).shrink(0.001D), Material.WATER, this); + return this.isInWater() || this.p() || this.q(); } public boolean aq() { + // Paper start return this.doWaterMovement(); } public boolean doWaterMovement() { // Paper end - if (this.bJ() instanceof EntityBoat) { + return this.isInWater() || this.q(); + } + + public boolean ar() { + return this.X && this.isInWater(); + } + + private void r() { + this.at(); + this.s(); + this.as(); + } + + public void as() { + if (this.isSwimming()) { + this.setSwimming(this.isSprinting() && this.isInWater() && !this.isPassenger()); + } else { + this.setSwimming(this.isSprinting() && this.ar() && !this.isPassenger()); + } + + } + + public boolean at() { + if (this.getVehicle() instanceof EntityBoat) { this.inWater = false; - } else if (this.world.a(this.getBoundingBox().grow(0.0D, -0.4000000059604645D, 0.0D).shrink(0.001D), Material.WATER, this)) { + } else if (this.b(TagsFluid.a)) { if (!this.inWater && !this.justCreated) { - this.ar(); + this.au(); } this.fallDistance = 0.0F; @@ -1170,8 +1229,12 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return this.inWater; } - protected void ar() { - Entity entity = this.isVehicle() && this.bE() != null ? this.bE() : this; + private void s() { + this.X = this.a(TagsFluid.a); + } + + protected void au() { + Entity entity = this.isVehicle() && this.bO() != null ? this.bO() : this; float f = entity == this ? 0.2F : 0.9F; float f1 = MathHelper.sqrt(entity.motX * entity.motX * 0.20000000298023224D + entity.motY * entity.motY + entity.motZ * entity.motZ * 0.20000000298023224D) * f; @@ -1179,7 +1242,12 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper f1 = 1.0F; } - this.a(this.af(), f1, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + if ((double) f1 < 0.25D) { + this.a(this.ae(), f1, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + } else { + this.a(this.af(), f1, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + } + float f2 = (float) MathHelper.floor(this.getBoundingBox().b); int i; @@ -1189,25 +1257,25 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper for (i = 0; (float) i < 1.0F + this.width * 20.0F; ++i) { f3 = (this.random.nextFloat() * 2.0F - 1.0F) * this.width; f4 = (this.random.nextFloat() * 2.0F - 1.0F) * this.width; - this.world.addParticle(EnumParticle.WATER_BUBBLE, this.locX + (double) f3, (double) (f2 + 1.0F), this.locZ + (double) f4, this.motX, this.motY - (double) (this.random.nextFloat() * 0.2F), this.motZ, new int[0]); + this.world.addParticle(Particles.e, this.locX + (double) f3, (double) (f2 + 1.0F), this.locZ + (double) f4, this.motX, this.motY - (double) (this.random.nextFloat() * 0.2F), this.motZ); } for (i = 0; (float) i < 1.0F + this.width * 20.0F; ++i) { f3 = (this.random.nextFloat() * 2.0F - 1.0F) * this.width; f4 = (this.random.nextFloat() * 2.0F - 1.0F) * this.width; - this.world.addParticle(EnumParticle.WATER_SPLASH, this.locX + (double) f3, (double) (f2 + 1.0F), this.locZ + (double) f4, this.motX, this.motY, this.motZ, new int[0]); + this.world.addParticle(Particles.R, this.locX + (double) f3, (double) (f2 + 1.0F), this.locZ + (double) f4, this.motX, this.motY, this.motZ); } } - public void as() { + public void av() { if (this.isSprinting() && !this.isInWater()) { - this.at(); + this.aw(); } } - protected void at() { + protected void aw() { int i = MathHelper.floor(this.locX); int j = MathHelper.floor(this.locY - 0.20000000298023224D); int k = MathHelper.floor(this.locZ); @@ -1215,36 +1283,28 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper IBlockData iblockdata = this.world.getType(blockposition); if (iblockdata.i() != EnumRenderType.INVISIBLE) { - this.world.addParticle(EnumParticle.BLOCK_CRACK, this.locX + ((double) this.random.nextFloat() - 0.5D) * (double) this.width, this.getBoundingBox().b + 0.1D, this.locZ + ((double) this.random.nextFloat() - 0.5D) * (double) this.width, -this.motX * 4.0D, 1.5D, -this.motZ * 4.0D, new int[] { Block.getCombinedId(iblockdata)}); + this.world.addParticle(new ParticleParamBlock(Particles.d, iblockdata), this.locX + ((double) this.random.nextFloat() - 0.5D) * (double) this.width, this.getBoundingBox().b + 0.1D, this.locZ + ((double) this.random.nextFloat() - 0.5D) * (double) this.width, -this.motX * 4.0D, 1.5D, -this.motZ * 4.0D); } } - public boolean a(Material material) { - if (this.bJ() instanceof EntityBoat) { + public boolean a(Tag tag) { + if (this.getVehicle() instanceof EntityBoat) { return false; } else { double d0 = this.locY + (double) this.getHeadHeight(); BlockPosition blockposition = new BlockPosition(this.locX, d0, this.locZ); - IBlockData iblockdata = this.world.getType(blockposition); + Fluid fluid = this.world.b(blockposition); - if (iblockdata.getMaterial() == material) { - float f = BlockFluids.b(iblockdata.getBlock().toLegacyData(iblockdata)) - 0.11111111F; - float f1 = (float) (blockposition.getY() + 1) - f; - boolean flag = d0 < (double) f1; - - return !flag && this instanceof EntityHuman ? false : flag; - } else { - return false; - } + return fluid.a(tag) && d0 < (double) ((float) blockposition.getY() + fluid.f() + 0.11111111F); } } - public boolean au() { - return this.world.a(this.getBoundingBox().grow(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), Material.LAVA); + public boolean ax() { + return this.world.a(this.getBoundingBox().f(0.10000000149011612D, 0.4000000059604645D, 0.10000000149011612D), Material.LAVA); } - public void b(float f, float f1, float f2, float f3) { + public void a(float f, float f1, float f2, float f3) { float f4 = f * f + f1 * f1 + f2 * f2; if (f4 >= 1.0E-4F) { @@ -1266,12 +1326,12 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - public float aw() { + public float az() { BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(MathHelper.floor(this.locX), 0, MathHelper.floor(this.locZ)); if (this.world.isLoaded(blockposition_mutableblockposition)) { blockposition_mutableblockposition.p(MathHelper.floor(this.locY + (double) this.getHeadHeight())); - return this.world.n(blockposition_mutableblockposition); + return this.world.A(blockposition_mutableblockposition); } else { return 0.0F; } @@ -1325,9 +1385,9 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.lastX = this.locX; this.lastY = this.locY; this.lastZ = this.locZ; - this.M = this.locX; - this.N = this.locY; - this.O = this.locZ; + this.N = this.locX; + this.O = this.locY; + this.P = this.locZ; this.yaw = f; this.pitch = f1; this.setPosition(this.locX, this.locY, this.locZ); @@ -1373,6 +1433,14 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return d0 * d0 + d1 * d1 + d2 * d2; } + public double a(Vec3D vec3d) { + double d0 = this.locX - vec3d.x; + double d1 = this.locY - vec3d.y; + double d2 = this.locZ - vec3d.z; + + return d0 * d0 + d1 * d1 + d2 * d2; + } + public void d(EntityHuman entityhuman) {} public void collide(Entity entity) { @@ -1396,8 +1464,8 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper d1 *= d3; d0 *= 0.05000000074505806D; d1 *= 0.05000000074505806D; - d0 *= (double) (1.0F - this.R); - d1 *= (double) (1.0F - this.R); + d0 *= (double) (1.0F - this.S); + d1 *= (double) (1.0F - this.S); if (!this.isVehicle()) { this.f(-d0, 0.0D, -d1); } @@ -1418,7 +1486,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.impulse = true; } - protected void ax() { + protected void aA() { this.velocityChanged = true; } @@ -1426,32 +1494,35 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper if (this.isInvulnerable(damagesource)) { return false; } else { - this.ax(); + this.aA(); return false; } } - public Vec3D e(float f) { - if (f == 1.0F) { - return this.f(this.pitch, this.yaw); - } else { - float f1 = this.lastPitch + (this.pitch - this.lastPitch) * f; - float f2 = this.lastYaw + (this.yaw - this.lastYaw) * f; - - return this.f(f1, f2); - } + public final Vec3D f(float f) { + return this.d(this.g(f), this.h(f)); } - protected final Vec3D f(float f, float f1) { - float f2 = MathHelper.cos(-f1 * 0.017453292F - 3.1415927F); - float f3 = MathHelper.sin(-f1 * 0.017453292F - 3.1415927F); - float f4 = -MathHelper.cos(-f * 0.017453292F); - float f5 = MathHelper.sin(-f * 0.017453292F); - - return new Vec3D((double) (f3 * f4), (double) f5, (double) (f2 * f4)); + public float g(float f) { + return f == 1.0F ? this.pitch : this.lastPitch + (this.pitch - this.lastPitch) * f; } - public Vec3D f(float f) { + public float h(float f) { + return f == 1.0F ? this.yaw : this.lastYaw + (this.yaw - this.lastYaw) * f; + } + + protected final Vec3D d(float f, float f1) { + float f2 = f * 0.017453292F; + float f3 = -f1 * 0.017453292F; + float f4 = MathHelper.cos(f3); + float f5 = MathHelper.sin(f3); + float f6 = MathHelper.cos(f2); + float f7 = MathHelper.sin(f2); + + return new Vec3D((double) (f5 * f6), (double) (-f7), (double) (f4 * f6)); + } + + public Vec3D i(float f) { if (f == 1.0F) { return new Vec3D(this.locX, this.locY + (double) this.getHeadHeight(), this.locZ); } else { @@ -1481,7 +1552,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public boolean c(NBTTagCompound nbttagcompound) { String s = this.getSaveID(); - if (!this.dead && s != null) { + if (this.persist && !this.dead && s != null) { // CraftBukkit - persist flag nbttagcompound.setString("id", s); this.save(nbttagcompound); return true; @@ -1491,31 +1562,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public boolean d(NBTTagCompound nbttagcompound) { - String s = this.getSaveID(); - - if (!this.dead && s != null && !this.isPassenger()) { - nbttagcompound.setString("id", s); - this.save(nbttagcompound); - return true; - } else { - return false; - } - } - - public static void b(DataConverterManager dataconvertermanager) { - dataconvertermanager.a(DataConverterTypes.ENTITY, new DataInspector() { - public NBTTagCompound a(DataConverter dataconverter, NBTTagCompound nbttagcompound, int i) { - if (nbttagcompound.hasKeyOfType("Passengers", 9)) { - NBTTagList nbttaglist = nbttagcompound.getList("Passengers", 10); - - for (int j = 0; j < nbttaglist.size(); ++j) { - nbttaglist.a(j, dataconverter.a(DataConverterTypes.ENTITY, nbttaglist.get(j), i)); - } - } - - return nbttagcompound; - } - }); + return this.isPassenger() ? false : this.c(nbttagcompound); } public NBTTagCompound save(NBTTagCompound nbttagcompound) { @@ -1550,15 +1597,16 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper nbttagcompound.setInt("Bukkit.updateLevel", CURRENT_LEVEL); nbttagcompound.setInt("Spigot.ticksLived", this.ticksLived); // CraftBukkit end - if (this.hasCustomName()) { - nbttagcompound.setString("CustomName", this.getCustomName()); + IChatBaseComponent ichatbasecomponent = this.getCustomName(); + + if (ichatbasecomponent != null) { + nbttagcompound.setString("CustomName", IChatBaseComponent.ChatSerializer.a(ichatbasecomponent)); } if (this.getCustomNameVisible()) { nbttagcompound.setBoolean("CustomNameVisible", this.getCustomNameVisible()); } - this.aG.b(nbttagcompound); if (this.isSilent()) { nbttagcompound.setBoolean("Silent", this.isSilent()); } @@ -1574,14 +1622,14 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper NBTTagList nbttaglist; Iterator iterator; - if (!this.aH.isEmpty()) { + if (!this.aJ.isEmpty()) { nbttaglist = new NBTTagList(); - iterator = this.aH.iterator(); + iterator = this.aJ.iterator(); while (iterator.hasNext()) { String s = (String) iterator.next(); - nbttaglist.add(new NBTTagString(s)); + nbttaglist.add((NBTBase) (new NBTTagString(s))); } nbttagcompound.set("Tags", nbttaglist); @@ -1590,14 +1638,14 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.b(nbttagcompound); if (this.isVehicle()) { nbttaglist = new NBTTagList(); - iterator = this.bF().iterator(); + iterator = this.bP().iterator(); while (iterator.hasNext()) { Entity entity = (Entity) iterator.next(); NBTTagCompound nbttagcompound1 = new NBTTagCompound(); if (entity.c(nbttagcompound1)) { - nbttaglist.add(nbttagcompound1); + nbttaglist.add((NBTBase) nbttagcompound1); } } @@ -1631,9 +1679,9 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper NBTTagList nbttaglist1 = nbttagcompound.getList("Motion", 6); NBTTagList nbttaglist2 = nbttagcompound.getList("Rotation", 5); - this.motX = nbttaglist1.f(0); - this.motY = nbttaglist1.f(1); - this.motZ = nbttaglist1.f(2); + this.motX = nbttaglist1.k(0); + this.motY = nbttaglist1.k(1); + this.motZ = nbttaglist1.k(2); /* CraftBukkit start - Moved section down if (Math.abs(this.motX) > 10.0D) { @@ -1649,21 +1697,21 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } // CraftBukkit end */ - this.locX = nbttaglist.f(0); - this.locY = nbttaglist.f(1); - this.locZ = nbttaglist.f(2); - this.M = this.locX; - this.N = this.locY; - this.O = this.locZ; + this.locX = nbttaglist.k(0); + this.locY = nbttaglist.k(1); + this.locZ = nbttaglist.k(2); + this.N = this.locX; + this.O = this.locY; + this.P = this.locZ; this.lastX = this.locX; this.lastY = this.locY; this.lastZ = this.locZ; - this.yaw = nbttaglist2.g(0); - this.pitch = nbttaglist2.g(1); + this.yaw = nbttaglist2.l(0); + this.pitch = nbttaglist2.l(1); this.lastYaw = this.yaw; this.lastPitch = this.pitch; this.setHeadRotation(this.yaw); - this.h(this.yaw); + this.k(this.yaw); this.fallDistance = nbttagcompound.getFloat("FallDistance"); this.fireTicks = nbttagcompound.getShort("Fire"); this.setAirTicks(nbttagcompound.getShort("Air")); @@ -1676,32 +1724,31 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.portalCooldown = nbttagcompound.getInt("PortalCooldown"); if (nbttagcompound.b("UUID")) { this.uniqueID = nbttagcompound.a("UUID"); - this.ar = this.uniqueID.toString(); + this.au = this.uniqueID.toString(); } this.setPosition(this.locX, this.locY, this.locZ); this.setYawPitch(this.yaw, this.pitch); if (nbttagcompound.hasKeyOfType("CustomName", 8)) { - this.setCustomName(nbttagcompound.getString("CustomName")); + this.setCustomName(IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName"))); } this.setCustomNameVisible(nbttagcompound.getBoolean("CustomNameVisible")); - this.aG.a(nbttagcompound); this.setSilent(nbttagcompound.getBoolean("Silent")); this.setNoGravity(nbttagcompound.getBoolean("NoGravity")); - this.g(nbttagcompound.getBoolean("Glowing")); + this.h(nbttagcompound.getBoolean("Glowing")); if (nbttagcompound.hasKeyOfType("Tags", 9)) { - this.aH.clear(); + this.aJ.clear(); NBTTagList nbttaglist3 = nbttagcompound.getList("Tags", 8); int i = Math.min(nbttaglist3.size(), 1024); for (int j = 0; j < i; ++j) { - this.aH.add(nbttaglist3.getString(j)); + this.aJ.add(nbttaglist3.getString(j)); } } this.a(nbttagcompound); - if (this.aA()) { + if (this.aD()) { this.setPosition(this.locX, this.locY, this.locZ); } @@ -1776,7 +1823,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - protected boolean aA() { + protected boolean aD() { return true; } @@ -1791,7 +1838,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper */ public Chunk getCurrentChunk() { final Chunk chunk = currentChunk != null ? currentChunk.get() : null; - return chunk != null && chunk.isLoaded() ? chunk : null; + return chunk != null && chunk.isLoaded() ? chunk : (isAddedToChunk() ? world.getChunkIfLoaded(getChunkX(), getChunkZ()) : null); } /** * Returns the chunk at the location, using the entities local cache if avail @@ -1813,21 +1860,28 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public Chunk getChunkAtLocation() { return getCurrentChunkAt((int)Math.floor(locX) >> 4, (int)Math.floor(locZ) >> 4); } - public final MinecraftKey entityKey = EntityTypes.getKey(this); - public final String entityKeyString = entityKey != null ? entityKey.toString() : null; + + private MinecraftKey entityKey; + private String entityKeyString; @Override public MinecraftKey getMinecraftKey() { + if (entityKey == null) { + this.entityKey = EntityTypes.getName(this.getEntityType()); + this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; + } return entityKey; } @Override public String getMinecraftKeyString() { + getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 return entityKeyString; } @Nullable public final String getSaveID() { - return entityKeyString; + EntityTypes type = this.getEntityType(); + return type != null && type.isPersistable() ? getMinecraftKeyString() : null; // Paper end } @@ -1844,7 +1898,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper for (int j = 0; j < i; ++j) { double d0 = adouble1[j]; - nbttaglist.add(new NBTTagDouble(d0)); + nbttaglist.add((NBTBase) (new NBTTagDouble(d0))); } return nbttaglist; @@ -1858,20 +1912,25 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper for (int j = 0; j < i; ++j) { float f = afloat1[j]; - nbttaglist.add(new NBTTagFloat(f)); + nbttaglist.add((NBTBase) (new NBTTagFloat(f))); } return nbttaglist; } @Nullable - public EntityItem a(Item item, int i) { - return this.a(item, i, 0.0F); + public EntityItem a(IMaterial imaterial) { + return this.a(imaterial, 0); } @Nullable - public EntityItem a(Item item, int i, float f) { - return this.a(new ItemStack(item, i, 0), f); + public EntityItem a(IMaterial imaterial, int i) { + return this.a(new ItemStack(imaterial), (float) i); + } + + @Nullable + public EntityItem a_(ItemStack itemstack) { + return this.a(itemstack, 0.0F); } @Nullable public final EntityItem dropItem(ItemStack itemstack, float offset) { return this.a(itemstack, offset); } // Paper - OBFHELPER @@ -1888,7 +1947,14 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper // CraftBukkit end EntityItem entityitem = new EntityItem(this.world, this.locX, this.locY + (double) f, this.locZ, itemstack); - entityitem.q(); + entityitem.n(); + // CraftBukkit start + EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return null; + } + // CraftBukkit end this.world.addEntity(entityitem); return entityitem; } @@ -1902,24 +1968,43 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper if (this.noclip) { return false; } else { - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); + BlockPosition.b blockposition_b = BlockPosition.b.r(); + Throwable throwable = null; - for (int i = 0; i < 8; ++i) { - int j = MathHelper.floor(this.locY + (double) (((float) ((i >> 0) % 2) - 0.5F) * 0.1F) + (double) this.getHeadHeight()); - int k = MathHelper.floor(this.locX + (double) (((float) ((i >> 1) % 2) - 0.5F) * this.width * 0.8F)); - int l = MathHelper.floor(this.locZ + (double) (((float) ((i >> 2) % 2) - 0.5F) * this.width * 0.8F)); + try { + for (int i = 0; i < 8; ++i) { + int j = MathHelper.floor(this.locY + (double) (((float) ((i >> 0) % 2) - 0.5F) * 0.1F) + (double) this.getHeadHeight()); + int k = MathHelper.floor(this.locX + (double) (((float) ((i >> 1) % 2) - 0.5F) * this.width * 0.8F)); + int l = MathHelper.floor(this.locZ + (double) (((float) ((i >> 2) % 2) - 0.5F) * this.width * 0.8F)); - if (blockposition_pooledblockposition.getX() != k || blockposition_pooledblockposition.getY() != j || blockposition_pooledblockposition.getZ() != l) { - blockposition_pooledblockposition.f(k, j, l); - if (this.world.getType(blockposition_pooledblockposition).r()) { - blockposition_pooledblockposition.t(); - return true; + if (blockposition_b.getX() != k || blockposition_b.getY() != j || blockposition_b.getZ() != l) { + blockposition_b.f(k, j, l); + if (this.world.getType(blockposition_b).r()) { + boolean flag = true; + + return flag; + } } } - } - blockposition_pooledblockposition.t(); - return false; + return false; + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; + } finally { + if (blockposition_b != null) { + if (throwable != null) { + try { + blockposition_b.close(); + } catch (Throwable throwable2) { + throwable.addSuppressed(throwable2); + } + } else { + blockposition_b.close(); + } + } + + } } } @@ -1932,8 +2017,8 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return null; } - public void aE() { - Entity entity = this.bJ(); + public void aH() { + Entity entity = this.getVehicle(); if (this.isPassenger() && entity.dead) { this.stopRiding(); @@ -1941,7 +2026,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.motX = 0.0D; this.motY = 0.0D; this.motZ = 0.0D; - this.B_(); + this.tick(); if (this.isPassenger()) { entity.k(this); } @@ -1950,15 +2035,15 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public void k(Entity entity) { if (this.w(entity)) { - entity.setPosition(this.locX, this.locY + this.aG() + entity.aF(), this.locZ); + entity.setPosition(this.locX, this.locY + this.aJ() + entity.aI(), this.locZ); } } - public double aF() { + public double aI() { return 0.0D; } - public double aG() { + public double aJ() { return (double) this.length * 0.75D; } @@ -1967,8 +2052,8 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public boolean a(Entity entity, boolean flag) { - for (Entity entity1 = entity; entity1.au != null; entity1 = entity1.au) { - if (entity1.au == this) { + for (Entity entity1 = entity; entity1.ax != null; entity1 = entity1.ax) { + if (entity1.ax == this) { return false; } } @@ -1980,14 +2065,14 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.stopRiding(); } - this.au = entity; - this.au.o(this); + this.ax = entity; + this.ax.o(this); return true; } } protected boolean n(Entity entity) { - return this.j <= 0; + return this.k <= 0; } public void ejectPassengers() { @@ -1998,18 +2083,18 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public void stopRiding() { - if (this.au != null) { - Entity entity = this.au; + if (this.ax != null) { + Entity entity = this.ax; - this.au = null; - entity.p(this); + this.ax = null; + if (!entity.p(this)) this.ax = entity; // CraftBukkit } } protected void o(Entity entity) { if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 - if (entity.bJ() != this) { + if (entity.getVehicle() != this) { throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); } else { // CraftBukkit start @@ -2037,7 +2122,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return; } // Spigot end - if (!this.world.isClientSide && entity instanceof EntityHuman && !(this.bE() instanceof EntityHuman)) { + if (!this.world.isClientSide && entity instanceof EntityHuman && !(this.bO() instanceof EntityHuman)) { this.passengers.add(0, entity); } else { this.passengers.add(entity); @@ -2046,12 +2131,11 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - protected void p(Entity entity) { - if (entity.bJ() == this) { + protected boolean p(Entity entity) { // CraftBukkit + if (entity.getVehicle() == this) { throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); } else { // CraftBukkit start - entity.setVehicle(this); // Paper - Set the vehicle back for the event CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); Entity orig = craft == null ? null : craft.getHandle(); if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { @@ -2063,69 +2147,74 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle(); Entity n = craftn == null ? null : craftn.getHandle(); if (event.isCancelled() || n != orig) { - return; + return false; } } // CraftBukkit end - // Paper start - make EntityDismountEvent cancellable - if (!new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()).callEvent()) { - return; + // Spigot start + org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; } - entity.setVehicle(null); - // Paper end - + // Spigot end this.passengers.remove(entity); - entity.j = 60; + entity.k = 60; } + return true; // CraftBukkit } protected boolean q(Entity entity) { - return this.bF().size() < 1; + return this.bP().size() < 1; } - public float aI() { + public float aM() { return 0.0F; } - public Vec3D aJ() { - return this.f(this.pitch, this.yaw); + public Vec3D aN() { + return this.d(this.pitch, this.yaw); + } + + public Vec2F aO() { + return new Vec2F(this.pitch, this.yaw); } public void e(BlockPosition blockposition) { if (this.portalCooldown > 0) { - this.portalCooldown = this.aM(); + this.portalCooldown = this.aQ(); } else { - if (!this.world.isClientSide && !blockposition.equals(this.an)) { - this.an = new BlockPosition(blockposition); - ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = Blocks.PORTAL.c(this.world, this.an); + if (!this.world.isClientSide && !blockposition.equals(this.aq)) { + this.aq = new BlockPosition(blockposition); + ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = ((BlockPortal) Blocks.NETHER_PORTAL).c((GeneratorAccess) this.world, this.aq); double d0 = shapedetector_shapedetectorcollection.getFacing().k() == EnumDirection.EnumAxis.X ? (double) shapedetector_shapedetectorcollection.a().getZ() : (double) shapedetector_shapedetectorcollection.a().getX(); double d1 = shapedetector_shapedetectorcollection.getFacing().k() == EnumDirection.EnumAxis.X ? this.locZ : this.locX; d1 = Math.abs(MathHelper.c(d1 - (double) (shapedetector_shapedetectorcollection.getFacing().e().c() == EnumDirection.EnumAxisDirection.NEGATIVE ? 1 : 0), d0, d0 - (double) shapedetector_shapedetectorcollection.d())); double d2 = MathHelper.c(this.locY - 1.0D, (double) shapedetector_shapedetectorcollection.a().getY(), (double) (shapedetector_shapedetectorcollection.a().getY() - shapedetector_shapedetectorcollection.e())); - this.ao = new Vec3D(d1, d2, 0.0D); - this.ap = shapedetector_shapedetectorcollection.getFacing(); + this.ar = new Vec3D(d1, d2, 0.0D); + this.as = shapedetector_shapedetectorcollection.getFacing(); } - this.ak = true; + this.an = true; } } - public int aM() { + public int aQ() { return 300; } - public Iterable aO() { - return Entity.b; + public Iterable aS() { + return Entity.a; } public Iterable getArmorItems() { - return Entity.b; + return Entity.a; } - public Iterable aQ() { - return Iterables.concat(this.aO(), this.getArmorItems()); + public Iterable aU() { + return Iterables.concat(this.aS(), this.getArmorItems()); } public void setEquipment(EnumItemSlot enumitemslot, ItemStack itemstack) {} @@ -2137,11 +2226,15 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public boolean isPassenger() { - return this.bJ() != null; + return this.getVehicle() != null; } public boolean isVehicle() { - return !this.bF().isEmpty(); + return !this.bP().isEmpty(); + } + + public boolean aY() { + return true; } public boolean isSneaking() { @@ -2160,11 +2253,26 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.setFlag(3, flag); } - public boolean aW() { + public boolean isSwimming() { + return this.getFlag(4); + } + + public void setSwimming(boolean flag) { + // CraftBukkit start + if (this.isSwimming() != flag && this instanceof EntityLiving) { + if (CraftEventFactory.callToggleSwimEvent((EntityLiving) this, flag).isCancelled()) { + return; + } + } + // CraftBukkit end + this.setFlag(4, flag); + } + + public boolean bc() { return this.glowing || this.world.isClientSide && this.getFlag(6); } - public void g(boolean flag) { + public void h(boolean flag) { this.glowing = flag; if (!this.world.isClientSide) { this.setFlag(6, this.glowing); @@ -2176,19 +2284,19 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return this.getFlag(5); } - @Nullable public ScoreboardTeamBase getTeam() { return this.aY(); } // Paper - OBFHELPER + @Nullable public ScoreboardTeamBase getTeam() { return this.be(); } // Paper - OBFHELPER @Nullable - public ScoreboardTeamBase aY() { + public ScoreboardTeamBase be() { if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper - return this.world.getScoreboard().getPlayerTeam(this.bn()); + return this.world.getScoreboard().getPlayerTeam(this.getName()); } public boolean r(Entity entity) { - return this.a(entity.aY()); + return this.a(entity.be()); } public boolean a(ScoreboardTeamBase scoreboardteambase) { - return this.aY() != null ? this.aY().isAlly(scoreboardteambase) : false; + return this.be() != null ? this.be().isAlly(scoreboardteambase) : false; } public void setInvisible(boolean flag) { @@ -2196,22 +2304,26 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public boolean getFlag(int i) { - return (((Byte) this.datawatcher.get(Entity.Z)).byteValue() & 1 << i) != 0; + return (((Byte) this.datawatcher.get(Entity.ac)).byteValue() & 1 << i) != 0; } public void setFlag(int i, boolean flag) { - byte b0 = ((Byte) this.datawatcher.get(Entity.Z)).byteValue(); + byte b0 = ((Byte) this.datawatcher.get(Entity.ac)).byteValue(); if (flag) { - this.datawatcher.set(Entity.Z, Byte.valueOf((byte) (b0 | 1 << i))); + this.datawatcher.set(Entity.ac, Byte.valueOf((byte) (b0 | 1 << i))); } else { - this.datawatcher.set(Entity.Z, Byte.valueOf((byte) (b0 & ~(1 << i)))); + this.datawatcher.set(Entity.ac, Byte.valueOf((byte) (b0 & ~(1 << i)))); } } + public int bf() { + return 300; + } + public int getAirTicks() { - return ((Integer) this.datawatcher.get(Entity.aA)).intValue(); + return ((Integer) this.datawatcher.get(Entity.aD)).intValue(); } public void setAirTicks(int i) { @@ -2221,7 +2333,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper if (event.isCancelled()) { return; } - this.datawatcher.set(Entity.aA, Integer.valueOf(event.getAmount())); + this.datawatcher.set(Entity.aD, Integer.valueOf(event.getAmount())); // CraftBukkit end } @@ -2262,6 +2374,25 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } + public void j(boolean flag) { + if (flag) { + this.motY = Math.max(-0.9D, this.motY - 0.03D); + } else { + this.motY = Math.min(1.8D, this.motY + 0.1D); + } + + } + + public void k(boolean flag) { + if (flag) { + this.motY = Math.max(-0.3D, this.motY - 0.03D); + } else { + this.motY = Math.min(0.7D, this.motY + 0.06D); + } + + this.fallDistance = 0.0F; + } + public void b(EntityLiving entityliving) {} protected boolean i(double d0, double d1, double d2) { @@ -2270,33 +2401,33 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper double d4 = d1 - (double) blockposition.getY(); double d5 = d2 - (double) blockposition.getZ(); - if (!this.world.a(this.getBoundingBox())) { + if (this.world.getCubes((Entity) null, this.getBoundingBox())) { return false; } else { EnumDirection enumdirection = EnumDirection.UP; double d6 = Double.MAX_VALUE; - if (!this.world.t(blockposition.west()) && d3 < d6) { + if (!this.world.o(blockposition.west()) && d3 < d6) { d6 = d3; enumdirection = EnumDirection.WEST; } - if (!this.world.t(blockposition.east()) && 1.0D - d3 < d6) { + if (!this.world.o(blockposition.east()) && 1.0D - d3 < d6) { d6 = 1.0D - d3; enumdirection = EnumDirection.EAST; } - if (!this.world.t(blockposition.north()) && d5 < d6) { + if (!this.world.o(blockposition.north()) && d5 < d6) { d6 = d5; enumdirection = EnumDirection.NORTH; } - if (!this.world.t(blockposition.south()) && 1.0D - d5 < d6) { + if (!this.world.o(blockposition.south()) && 1.0D - d5 < d6) { d6 = 1.0D - d5; enumdirection = EnumDirection.SOUTH; } - if (!this.world.t(blockposition.up()) && 1.0D - d4 < d6) { + if (!this.world.o(blockposition.up()) && 1.0D - d4 < d6) { d6 = 1.0D - d4; enumdirection = EnumDirection.UP; } @@ -2322,27 +2453,32 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - public void ba() { - this.E = true; + public void bh() { + this.F = true; this.fallDistance = 0.0F; } - public String getName() { - if (this.hasCustomName()) { - return this.getCustomName(); + private static void c(IChatBaseComponent ichatbasecomponent) { + ichatbasecomponent.a((chatmodifier) -> { + chatmodifier.setChatClickable((ChatClickable) null); + }).a().forEach(Entity::c); + } + + public IChatBaseComponent getDisplayName() { + IChatBaseComponent ichatbasecomponent = this.getCustomName(); + + if (ichatbasecomponent != null) { + IChatBaseComponent ichatbasecomponent1 = ichatbasecomponent.e(); + + c(ichatbasecomponent1); + return ichatbasecomponent1; } else { - String s = EntityTypes.b(this); - - if (s == null) { - s = "generic"; - } - - return LocaleI18n.get("entity." + s + ".name"); + return new ChatMessage(this.g.d(), new Object[0]); } } @Nullable - public Entity[] bb() { + public Entity[] bi() { return null; } @@ -2356,9 +2492,9 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public void setHeadRotation(float f) {} - public void h(float f) {} + public void k(float f) {} - public boolean bd() { + public boolean bk() { return true; } @@ -2367,14 +2503,14 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public String toString() { - return String.format("%s[\'%s\'/%d, uuid=\'%s\', l=\'%s\', x=%.2f, y=%.2f, z=%.2f, cx=%d, cd=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getName(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.getWorldData().getName(), Double.valueOf(this.locX), Double.valueOf(this.locY), Double.valueOf(this.locZ), getChunkX(), getChunkZ(), this.ticksLived, this.valid, this.dead}); // Paper - add more information + return String.format(Locale.ROOT, "%s[\'%s\'/%d, uuid=\'%s\', l=\'%s\', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getDisplayName().getText(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.getWorldData().getName(), Double.valueOf(this.locX), Double.valueOf(this.locY), Double.valueOf(this.locZ), getChunkX(), getChunkZ(), this.ticksLived, this.valid, this.dead}); // Paper - add more information } public boolean isInvulnerable(DamageSource damagesource) { - return this.invulnerable && damagesource != DamageSource.OUT_OF_WORLD && !damagesource.u(); + return this.invulnerable && damagesource != DamageSource.OUT_OF_WORLD && !damagesource.v(); } - public boolean be() { + public boolean bl() { return this.invulnerable; } @@ -2386,22 +2522,22 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.setPositionRotation(entity.locX, entity.locY, entity.locZ, entity.yaw, entity.pitch); } - private void a(Entity entity) { + public void v(Entity entity) { NBTTagCompound nbttagcompound = entity.save(new NBTTagCompound()); nbttagcompound.remove("Dimension"); this.f(nbttagcompound); this.portalCooldown = entity.portalCooldown; - this.an = entity.an; - this.ao = entity.ao; - this.ap = entity.ap; + this.aq = entity.aq; + this.ar = entity.ar; + this.as = entity.as; } @Nullable - public Entity b(int i) { + public Entity d(int i) { if (!this.world.isClientSide && !this.dead) { this.world.methodProfiler.a("changeDimension"); - MinecraftServer minecraftserver = this.C_(); + MinecraftServer minecraftserver = this.bK(); // CraftBukkit start - Move logic into new function "teleportTo(Location,boolean)" // int j = this.dimension; // WorldServer worldserver = minecraftserver.getWorldServer(j); @@ -2447,7 +2583,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper // Need to make sure the profiler state is reset afterwards (but we still want to time the call) Entity entity = this.teleportTo(exit, true); - this.world.methodProfiler.b(); + this.world.methodProfiler.e(); return entity; } return null; @@ -2463,7 +2599,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.dimension = i; /* CraftBukkit start - TODO: Check if we need this if (j == 1 && i == 1) { - worldserver1 = minecraftserver.getWorldServer(0); + worldserver1 = minecraftserver.a(DimensionManager.OVERWORLD); this.dimension = 0; } // CraftBukkit end */ @@ -2507,13 +2643,13 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper // worldserver.entityJoinedWorld(this, false); // Handled in repositionEntity // CraftBukkit end this.world.methodProfiler.c("reloading"); - Entity entity = EntityTypes.a(this.getClass(), (World) worldserver1); + Entity entity = this.P().a((World) worldserver1); if (entity != null) { - entity.a(this); + entity.v(this); /* CraftBukkit start - We need to do this... if (j == 1 && i == 1) { - BlockPosition blockposition1 = worldserver1.q(worldserver1.getSpawn()); + BlockPosition blockposition1 = worldserver1.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver1.getSpawn()); entity.setPositionRotation(blockposition1, entity.yaw, entity.pitch); } else { @@ -2538,38 +2674,38 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } this.dead = true; - this.world.methodProfiler.b(); - worldserver.m(); - worldserver1.m(); - // this.world.methodProfiler.b(); // CraftBukkit: Moved up to keep balanced + this.world.methodProfiler.e(); + worldserver.q_(); + worldserver1.q_(); + // this.world.methodProfiler.e(); // CraftBukkit: Moved up to keep balanced return entity; } else { return null; } } - public boolean bf() { + public boolean bm() { return true; } - public float a(Explosion explosion, World world, BlockPosition blockposition, IBlockData iblockdata) { - return iblockdata.getBlock().a(this); + public float a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, float f) { + return f; } - public boolean a(Explosion explosion, World world, BlockPosition blockposition, IBlockData iblockdata, float f) { + public boolean a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, float f) { return true; } - public int bg() { + public int bn() { return 3; } public Vec3D getPortalOffset() { - return this.ao; + return this.ar; } public EnumDirection getPortalDirection() { - return this.ap; + return this.as; } public boolean isIgnoreBlockTrigger() { @@ -2577,63 +2713,43 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public void appendEntityCrashDetails(CrashReportSystemDetails crashreportsystemdetails) { - crashreportsystemdetails.a("Entity Type", new CrashReportCallable() { - public String a() throws Exception { - return EntityTypes.a(Entity.this) + " (" + Entity.this.getClass().getCanonicalName() + ")"; - } - - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Entity Type", () -> { + return EntityTypes.getName(this.P()) + " (" + this.getClass().getCanonicalName() + ")"; }); crashreportsystemdetails.a("Entity ID", (Object) Integer.valueOf(this.id)); - crashreportsystemdetails.a("Entity Name", new CrashReportCallable() { - public String a() throws Exception { - return Entity.this.getName(); - } - - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Entity Name", () -> { + return this.getDisplayName().getString(); }); - crashreportsystemdetails.a("Entity\'s Exact location", (Object) String.format("%.2f, %.2f, %.2f", new Object[] { Double.valueOf(this.locX), Double.valueOf(this.locY), Double.valueOf(this.locZ)})); + crashreportsystemdetails.a("Entity\'s Exact location", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", new Object[] { Double.valueOf(this.locX), Double.valueOf(this.locY), Double.valueOf(this.locZ)})); crashreportsystemdetails.a("Entity\'s Block location", (Object) CrashReportSystemDetails.a(MathHelper.floor(this.locX), MathHelper.floor(this.locY), MathHelper.floor(this.locZ))); - crashreportsystemdetails.a("Entity\'s Momentum", (Object) String.format("%.2f, %.2f, %.2f", new Object[] { Double.valueOf(this.motX), Double.valueOf(this.motY), Double.valueOf(this.motZ)})); - crashreportsystemdetails.a("Entity\'s Passengers", new CrashReportCallable() { - public String a() throws Exception { - return Entity.this.bF().toString(); - } - - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Entity\'s Momentum", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", new Object[] { Double.valueOf(this.motX), Double.valueOf(this.motY), Double.valueOf(this.motZ)})); + crashreportsystemdetails.a("Entity\'s Passengers", () -> { + return this.bP().toString(); }); - crashreportsystemdetails.a("Entity\'s Vehicle", new CrashReportCallable() { - public String a() throws Exception { - return Entity.this.bJ().toString(); - } - - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Entity\'s Vehicle", () -> { + return this.getVehicle().toString(); }); } public void setUUID(UUID uuid) { a(uuid); } // Paper - OBFHELPER public void a(UUID uuid) { this.uniqueID = uuid; - this.ar = this.uniqueID.toString(); + this.au = this.uniqueID.toString(); } public UUID getUniqueID() { return this.uniqueID; } - public String bn() { - return this.ar; + public String bu() { + return this.au; } - public boolean bo() { + public String getName() { + return this.au; + } + + public boolean bw() { return this.pushedByWater(); } @@ -2643,40 +2759,34 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public IChatBaseComponent getScoreboardDisplayName() { - ChatComponentText chatcomponenttext = new ChatComponentText(ScoreboardTeam.getPlayerDisplayName(this.aY(), this.getName())); - - chatcomponenttext.getChatModifier().setChatHoverable(this.bv()); - chatcomponenttext.getChatModifier().setInsertion(this.bn()); - return chatcomponenttext; + return ScoreboardTeam.a(this.be(), this.getDisplayName()).a((chatmodifier) -> { + chatmodifier.setChatHoverable(this.bC()).setInsertion(this.bu()); + }); } - public void setCustomName(String s) { - // CraftBukkit start - Add a sane limit for name length - if (s.length() > 256) { - s = s.substring(0, 256); - } - // CraftBukkit end - this.datawatcher.set(Entity.aB, s); + public void setCustomName(@Nullable IChatBaseComponent ichatbasecomponent) { + this.datawatcher.set(Entity.aE, Optional.ofNullable(ichatbasecomponent)); } - public String getCustomName() { - return (String) this.datawatcher.get(Entity.aB); + @Nullable + public IChatBaseComponent getCustomName() { + return (IChatBaseComponent) ((Optional) this.datawatcher.get(Entity.aE)).orElse((Object) null); } public boolean hasCustomName() { - return !((String) this.datawatcher.get(Entity.aB)).isEmpty(); + return ((Optional) this.datawatcher.get(Entity.aE)).isPresent(); } public void setCustomNameVisible(boolean flag) { - this.datawatcher.set(Entity.aC, Boolean.valueOf(flag)); + this.datawatcher.set(Entity.aF, Boolean.valueOf(flag)); } public boolean getCustomNameVisible() { - return ((Boolean) this.datawatcher.get(Entity.aC)).booleanValue(); + return ((Boolean) this.datawatcher.get(Entity.aF)).booleanValue(); } public void enderTeleportTo(double d0, double d1, double d2) { - this.aI = true; + this.aK = true; this.setPositionRotation(d0, d1, d2, this.yaw, this.pitch); this.world.entityJoinedWorld(this, false); } @@ -2684,23 +2794,23 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public void a(DataWatcherObject datawatcherobject) {} public EnumDirection getDirection() { - return EnumDirection.fromType2(MathHelper.floor((double) (this.yaw * 4.0F / 360.0F) + 0.5D) & 3); + return EnumDirection.fromAngle((double) this.yaw); } - public EnumDirection bu() { + public EnumDirection bB() { return this.getDirection(); } - protected ChatHoverable bv() { + protected ChatHoverable bC() { NBTTagCompound nbttagcompound = new NBTTagCompound(); - MinecraftKey minecraftkey = EntityTypes.a(this); + MinecraftKey minecraftkey = EntityTypes.getName(this.P()); - nbttagcompound.setString("id", this.bn()); + nbttagcompound.setString("id", this.bu()); if (minecraftkey != null) { nbttagcompound.setString("type", minecraftkey.toString()); } - nbttagcompound.setString("name", this.getName()); + nbttagcompound.setString("name", IChatBaseComponent.ChatSerializer.a(this.getDisplayName())); return new ChatHoverable(ChatHoverable.EnumHoverAction.SHOW_ENTITY, new ChatComponentText(nbttagcompound.toString())); } @@ -2739,12 +2849,12 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return this.length * 0.85F; } - public boolean bz() { - return this.aw; + public boolean bG() { + return this.az; } - public void k(boolean flag) { - this.aw = flag; + public void n(boolean flag) { + this.az = flag; } public boolean c(int i, ItemStack itemstack) { @@ -2753,15 +2863,11 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper public void sendMessage(IChatBaseComponent ichatbasecomponent) {} - public boolean a(int i, String s) { - return true; - } - public BlockPosition getChunkCoordinates() { - return new BlockPosition(this.locX, this.locY + 0.5D, this.locZ); + return new BlockPosition(this); } - public Vec3D d() { + public Vec3D bI() { return new Vec3D(this.locX, this.locY, this.locZ); } @@ -2769,39 +2875,16 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return this.world; } - public Entity f() { - return this; - } - - public boolean getSendCommandFeedback() { - return false; - } - - public void a(CommandObjectiveExecutor.EnumCommandResult commandobjectiveexecutor_enumcommandresult, int i) { - if (this.world != null && !this.world.isClientSide) { - this.aG.a(this.world.getMinecraftServer(), this, commandobjectiveexecutor_enumcommandresult, i); - } - - } - @Nullable - public MinecraftServer C_() { + public MinecraftServer bK() { return this.world.getMinecraftServer(); } - public CommandObjectiveExecutor bA() { - return this.aG; - } - - public void v(Entity entity) { - this.aG.a(entity.bA()); - } - public EnumInteractionResult a(EntityHuman entityhuman, Vec3D vec3d, EnumHand enumhand) { return EnumInteractionResult.PASS; } - public boolean bB() { + public boolean bL() { return false; } @@ -2850,28 +2933,28 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } } - public boolean bC() { + public boolean bM() { return false; } - public boolean bD() { - boolean flag = this.aI; + public boolean bN() { + boolean flag = this.aK; - this.aI = false; + this.aK = false; return flag; } @Nullable - public Entity bE() { + public Entity bO() { return null; } - public List bF() { + public List bP() { return (List) (this.passengers.isEmpty() ? Collections.emptyList() : Lists.newArrayList(this.passengers)); } public boolean w(Entity entity) { - Iterator iterator = this.bF().iterator(); + Iterator iterator = this.bP().iterator(); Entity entity1; @@ -2886,36 +2969,59 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return true; } - public Collection bG() { - HashSet hashset = Sets.newHashSet(); + public boolean a(Class oclass) { + Iterator iterator = this.bP().iterator(); - this.a(Entity.class, (Set) hashset); - return hashset; - } - - public Collection b(Class oclass) { - HashSet hashset = Sets.newHashSet(); - - this.a(oclass, (Set) hashset); - return hashset; - } - - private void a(Class oclass, Set set) { Entity entity; - for (Iterator iterator = this.bF().iterator(); iterator.hasNext(); entity.a(oclass, set)) { + do { + if (!iterator.hasNext()) { + return false; + } + entity = (Entity) iterator.next(); - if (oclass.isAssignableFrom(entity.getClass())) { - set.add((T) entity); // CraftBukkit - decompile error + } while (!oclass.isAssignableFrom(entity.getClass())); + + return true; + } + + public Collection bQ() { + HashSet hashset = Sets.newHashSet(); + Iterator iterator = this.bP().iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + + hashset.add(entity); + entity.a(false, hashset); + } + + return hashset; + } + + public boolean bR() { + HashSet hashset = Sets.newHashSet(); + + this.a(true, hashset); + return hashset.size() == 1; + } + + private void a(boolean flag, Set set) { + Entity entity; + + for (Iterator iterator = this.bP().iterator(); iterator.hasNext(); entity.a(flag, set)) { + entity = (Entity) iterator.next(); + if (!flag || EntityPlayer.class.isAssignableFrom(entity.getClass())) { + set.add(entity); } } } - public Entity getVehicle() { + public Entity getRootVehicle() { Entity entity; - for (entity = this; entity.isPassenger(); entity = entity.bJ()) { + for (entity = this; entity.isPassenger(); entity = entity.getVehicle()) { ; } @@ -2923,11 +3029,11 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper } public boolean x(Entity entity) { - return this.getVehicle() == entity.getVehicle(); + return this.getRootVehicle() == entity.getRootVehicle(); } public boolean y(Entity entity) { - Iterator iterator = this.bF().iterator(); + Iterator iterator = this.bP().iterator(); Entity entity1; @@ -2945,26 +3051,155 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper return true; } - public boolean bI() { - Entity entity = this.bE(); + public boolean bT() { + Entity entity = this.bO(); - return entity instanceof EntityHuman ? ((EntityHuman) entity).cZ() : !this.world.isClientSide; + return entity instanceof EntityHuman ? ((EntityHuman) entity).dn() : !this.world.isClientSide; } @Nullable - public Entity bJ() { - return this.au; + public Entity getVehicle() { + return this.ax; } public EnumPistonReaction getPushReaction() { return EnumPistonReaction.NORMAL; } - public SoundCategory bK() { + public SoundCategory bV() { return SoundCategory.NEUTRAL; } public int getMaxFireTicks() { return 1; } + + public CommandListenerWrapper getCommandListener() { + return new CommandListenerWrapper(this, new Vec3D(this.locX, this.locY, this.locZ), this.aO(), this.world instanceof WorldServer ? (WorldServer) this.world : null, this.y(), this.getDisplayName().getString(), this.getScoreboardDisplayName(), this.world.getMinecraftServer(), this); + } + + protected int y() { + return 0; + } + + public boolean k(int i) { + return this.y() >= i; + } + + public boolean a() { + return this.world.getGameRules().getBoolean("sendCommandFeedback"); + } + + public boolean b() { + return true; + } + + public boolean B_() { + return true; + } + + public void a(ArgumentAnchor.Anchor argumentanchor_anchor, Vec3D vec3d) { + Vec3D vec3d1 = argumentanchor_anchor.a(this); + double d0 = vec3d.x - vec3d1.x; + double d1 = vec3d.y - vec3d1.y; + double d2 = vec3d.z - vec3d1.z; + double d3 = (double) MathHelper.sqrt(d0 * d0 + d2 * d2); + + this.pitch = MathHelper.g((float) (-(MathHelper.c(d1, d3) * 57.2957763671875D))); + this.yaw = MathHelper.g((float) (MathHelper.c(d2, d0) * 57.2957763671875D) - 90.0F); + this.setHeadRotation(this.yaw); + this.lastPitch = this.pitch; + this.lastYaw = this.yaw; + } + + public boolean b(Tag tag) { + AxisAlignedBB axisalignedbb = this.getBoundingBox().shrink(0.001D); + int i = MathHelper.floor(axisalignedbb.a); + int j = MathHelper.f(axisalignedbb.d); + int k = MathHelper.floor(axisalignedbb.b); + int l = MathHelper.f(axisalignedbb.e); + int i1 = MathHelper.floor(axisalignedbb.c); + int j1 = MathHelper.f(axisalignedbb.f); + + if (!this.world.isAreaLoaded(i, k, i1, j, l, j1, true)) { + return false; + } else { + double d0 = 0.0D; + boolean flag = this.bw(); + boolean flag1 = false; + Vec3D vec3d = Vec3D.a; + int k1 = 0; + BlockPosition.b blockposition_b = BlockPosition.b.r(); + Throwable throwable = null; + + try { + for (int l1 = i; l1 < j; ++l1) { + for (int i2 = k; i2 < l; ++i2) { + for (int j2 = i1; j2 < j1; ++j2) { + blockposition_b.f(l1, i2, j2); + Fluid fluid = this.world.b((BlockPosition) blockposition_b); + + if (fluid.a(tag)) { + double d1 = (double) ((float) i2 + fluid.f()); + + if (d1 >= axisalignedbb.b) { + flag1 = true; + d0 = Math.max(d1 - axisalignedbb.b, d0); + if (flag) { + Vec3D vec3d1 = fluid.a((IWorldReader) this.world, (BlockPosition) blockposition_b); + + if (d0 < 0.4D) { + vec3d1 = vec3d1.a(d0); + } + + vec3d = vec3d.e(vec3d1); + ++k1; + } + } + } + } + } + } + } catch (Throwable throwable1) { + throwable = throwable1; + throw throwable1; + } finally { + if (blockposition_b != null) { + if (throwable != null) { + try { + blockposition_b.close(); + } catch (Throwable throwable2) { + throwable.addSuppressed(throwable2); + } + } else { + blockposition_b.close(); + } + } + + } + + if (vec3d.b() > 0.0D) { + if (k1 > 0) { + vec3d = vec3d.a(1.0D / (double) k1); + } + + if (!(this instanceof EntityHuman)) { + vec3d = vec3d.a(); + } + + double d2 = 0.014D; + + this.motX += vec3d.x * 0.014D; + this.motY += vec3d.y * 0.014D; + this.motZ += vec3d.z * 0.014D; + } + + this.W = d0; + return flag1; + } + } + + public double bY() { + return this.W; + } } diff --git a/sources/src/main/java/net/minecraft/server/EntityPlayer.java b/sources/src/main/java/net/minecraft/server/EntityPlayer.java index e22dbfdea..522c67f8e 100644 --- a/sources/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/sources/src/main/java/net/minecraft/server/EntityPlayer.java @@ -2,14 +2,13 @@ package net.minecraft.server; import com.google.common.collect.Lists; import com.mojang.authlib.GameProfile; - import io.netty.buffer.Unpooled; 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 javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -18,6 +17,7 @@ import org.apache.logging.log4j.Logger; import com.google.common.base.Preconditions; import org.bukkit.Bukkit; import org.bukkit.GameMode; +import org.bukkit.Location; import org.bukkit.WeatherType; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.entity.CraftPlayer; @@ -38,8 +38,9 @@ import org.bukkit.inventory.MainHand; */ public class EntityPlayer extends EntityHuman implements ICrafting { - private static final Logger bV = LogManager.getLogger(); - public String locale = null; // PAIL: private -> public // Paper - default to null + 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; public final MinecraftServer server; @@ -47,30 +48,30 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public double d; public double e; public final Deque removeQueue = new ArrayDeque<>(); // Paper - private final AdvancementDataPlayer bY; - private final ServerStatisticManager bZ; - private float ca = Float.MIN_VALUE; - private int cb = Integer.MIN_VALUE; - private int cc = Integer.MIN_VALUE; - private int cd = Integer.MIN_VALUE; - private int ce = Integer.MIN_VALUE; - private int cf = Integer.MIN_VALUE; + private final AdvancementDataPlayer cg; + private final ServerStatisticManager ch; + private float ci = Float.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 ch = -99999999; - private boolean ci = true; + private int cp = -99999999; + private boolean cq = true; public int lastSentExp = -99999999; public int invulnerableTicks = 60; - private EntityHuman.EnumChatVisibility cl; - private boolean cm = true; - private long cn = System.currentTimeMillis(); - private Entity co; + private EntityHuman.EnumChatVisibility ct; + private boolean cu = true; + private long cv = SystemUtils.b(); + private Entity cw; public boolean worldChangeInvuln; - private boolean cq; private void setHasSeenCredits(boolean has) { this.cq = has; } // Paper - OBFHELPER - private final RecipeBookServer cr = new RecipeBookServer(); - private Vec3D cs; - private int ct; - private boolean cu; - private Vec3D cv; + 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 int containerCounter; public boolean f; public int ping; @@ -100,35 +101,29 @@ public class EntityPlayer extends EntityHuman implements ICrafting { // CraftBukkit end public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, gameprofile); + super((World) worldserver, gameprofile); playerinteractmanager.player = this; this.playerInteractManager = playerinteractmanager; - // CraftBukkit start - BlockPosition blockposition = getSpawnPoint(minecraftserver, worldserver); - this.server = minecraftserver; - this.bZ = minecraftserver.getPlayerList().getStatisticManager(this); - this.bY = minecraftserver.getPlayerList().h(this); - this.P = 1.0F; - this.setPositionRotation(blockposition, 0.0F, 0.0F); - // CraftBukkit end - - while (!worldserver.getCubes(this, this.getBoundingBox()).isEmpty() && this.locY < 255.0D) { - this.setPosition(this.locX, this.locY + 1.0D, this.locZ); - } + this.cz = new RecipeBookServer(minecraftserver.getCraftingManager()); + this.ch = minecraftserver.getPlayerList().getStatisticManager(this); + this.cg = minecraftserver.getPlayerList().h(this); + this.Q = 1.0F; + this.a(worldserver); // CraftBukkit start this.displayName = this.getName(); this.canPickUpLoot = true; this.maxHealthCache = this.getMaxHealth(); - // CraftBukkit end } - public final BlockPosition getSpawnPoint(MinecraftServer minecraftserver, WorldServer worldserver) { + // Yes, this doesn't match Vanilla, but it's the best we can do for now. + // If this is an issue, PRs are welcome + public final BlockPosition getSpawnPoint(WorldServer worldserver) { BlockPosition blockposition = worldserver.getSpawn(); - if (worldserver.worldProvider.m() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) { - int i = Math.max(0, minecraftserver.a(worldserver)); + if (worldserver.worldProvider.g() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) { + int i = Math.max(0, this.server.a(worldserver)); int j = MathHelper.floor(worldserver.getWorldBorder().b((double) blockposition.getX(), (double) blockposition.getZ())); if (j < i) { @@ -139,19 +134,78 @@ public class EntityPlayer extends EntityHuman implements ICrafting { i = 1; } - blockposition = worldserver.q(blockposition.a(this.random.nextInt(i * 2 + 1) - i, 0, this.random.nextInt(i * 2 + 1) - i)); + int k = (i * 2 + 1) * (i * 2 + 1); + int l = this.s(k); + int i1 = (new Random()).nextInt(k); + + for (int j1 = 0; j1 < k; ++j1) { + int k1 = (i1 + l * j1) % k; + int l1 = k1 % (i * 2 + 1); + int i2 = k1 / (i * 2 + 1); + BlockPosition blockposition1 = worldserver.o().a(blockposition.getX() + l1 - i, blockposition.getZ() + i2 - i, false); + + if (blockposition1 != null) { + return blockposition1; + } + } } return blockposition; } // CraftBukkit end + private void a(WorldServer worldserver) { + BlockPosition blockposition = worldserver.getSpawn(); + + if (worldserver.worldProvider.g() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) { + int i = Math.max(0, this.server.a(worldserver)); + int j = MathHelper.floor(worldserver.getWorldBorder().b((double) blockposition.getX(), (double) blockposition.getZ())); + + if (j < i) { + i = j; + } + + if (j <= 1) { + i = 1; + } + + int k = (i * 2 + 1) * (i * 2 + 1); + int l = this.s(k); + int i1 = (new Random()).nextInt(k); + + for (int j1 = 0; j1 < k; ++j1) { + int k1 = (i1 + l * j1) % k; + int l1 = k1 % (i * 2 + 1); + int i2 = k1 / (i * 2 + 1); + BlockPosition blockposition1 = worldserver.o().a(blockposition.getX() + l1 - i, blockposition.getZ() + i2 - i, false); + + if (blockposition1 != null) { + this.setPositionRotation(blockposition1, 0.0F, 0.0F); + if (worldserver.getCubes(this, this.getBoundingBox())) { + break; + } + } + } + } else { + this.setPositionRotation(blockposition, 0.0F, 0.0F); + + while (!worldserver.getCubes(this, this.getBoundingBox()) && this.locY < 255.0D) { + this.setPosition(this.locX, this.locY + 1.0D, this.locZ); + } + } + + } + + private int s(int i) { + return i <= 16 ? i - 1 : 17; + } + public void a(NBTTagCompound nbttagcompound) { super.a(nbttagcompound); if (this.locY > 300) this.locY = 257; // Paper - bring down to a saner Y level if out of world if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { - if (this.C_().getForceGamemode()) { - this.playerInteractManager.setGameMode(this.C_().getGamemode()); + if (this.bK().getForceGamemode()) { + this.playerInteractManager.setGameMode(this.bK().getGamemode()); } else { this.playerInteractManager.setGameMode(EnumGamemode.getById(nbttagcompound.getInt("playerGameType"))); } @@ -160,50 +214,47 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (nbttagcompound.hasKeyOfType("enteredNetherPosition", 10)) { NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("enteredNetherPosition"); - this.cv = new Vec3D(nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("y"), nbttagcompound1.getDouble("z")); + this.cD = new Vec3D(nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("y"), nbttagcompound1.getDouble("z")); } - this.cq = nbttagcompound.getBoolean("seenCredits"); + this.cy = nbttagcompound.getBoolean("seenCredits"); if (nbttagcompound.hasKeyOfType("recipeBook", 10)) { - this.cr.a(nbttagcompound.getCompound("recipeBook")); + this.cz.a(nbttagcompound.getCompound("recipeBook")); } this.getBukkitEntity().readExtraData(nbttagcompound); // CraftBukkit } - public static void a(DataConverterManager dataconvertermanager) { - dataconvertermanager.a(DataConverterTypes.PLAYER, new DataInspector() { - public NBTTagCompound a(DataConverter dataconverter, NBTTagCompound nbttagcompound, int i) { - if (nbttagcompound.hasKeyOfType("RootVehicle", 10)) { - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); - - if (nbttagcompound1.hasKeyOfType("Entity", 10)) { - nbttagcompound1.set("Entity", dataconverter.a(DataConverterTypes.ENTITY, nbttagcompound1.getCompound("Entity"), i)); - } - } - - return nbttagcompound; - } - }); - } - public void b(NBTTagCompound nbttagcompound) { super.b(nbttagcompound); nbttagcompound.setInt("playerGameType", this.playerInteractManager.getGameMode().getId()); - nbttagcompound.setBoolean("seenCredits", this.cq); - if (this.cv != null) { + nbttagcompound.setBoolean("seenCredits", this.cy); + if (this.cD != null) { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - nbttagcompound1.setDouble("x", this.cv.x); - nbttagcompound1.setDouble("y", this.cv.y); - nbttagcompound1.setDouble("z", this.cv.z); + nbttagcompound1.setDouble("x", this.cD.x); + nbttagcompound1.setDouble("y", this.cD.y); + nbttagcompound1.setDouble("z", this.cD.z); nbttagcompound.set("enteredNetherPosition", nbttagcompound1); } - Entity entity = this.getVehicle(); - Entity entity1 = this.bJ(); + Entity entity = this.getRootVehicle(); + Entity entity1 = this.getVehicle(); - if (entity1 != null && entity != this && entity.b(EntityPlayer.class).size() == 1) { + // CraftBukkit start - handle non-persistent vehicles + boolean persistVehicle = true; + if (entity1 != null) { + Entity vehicle; + for (vehicle = entity1; vehicle != null; vehicle = vehicle.getVehicle()) { + if (!vehicle.persist) { + persistVehicle = false; + break; + } + } + } + + if (persistVehicle && entity1 != null && entity != this && entity.bR()) { + // CraftBukkit end NBTTagCompound nbttagcompound2 = new NBTTagCompound(); NBTTagCompound nbttagcompound3 = new NBTTagCompound(); @@ -213,7 +264,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { nbttagcompound.set("RootVehicle", nbttagcompound2); } - nbttagcompound.set("recipeBook", this.cr.c()); + nbttagcompound.set("recipeBook", this.cz.e()); this.getBukkitEntity().setExtraData(nbttagcompound); // CraftBukkit } @@ -242,6 +293,19 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } // CraftBukkit end + public void a(int i) { + float f = (float) this.getExpToLevel(); + float f1 = (f - 1.0F) / f; + + this.exp = MathHelper.a((float) i / f, 0.0F, f1); + this.lastSentExp = -1; + } + + public void b(int i) { + this.expLevel = i; + this.lastSentExp = -1; + } + public void levelDown(int i) { super.levelDown(i); this.lastSentExp = -1; @@ -270,11 +334,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { CriterionTriggers.d.a(this, iblockdata); } - protected ItemCooldown l() { + protected ItemCooldown g() { return new ItemCooldownPlayer(this); } - public void B_() { + public void tick() { // CraftBukkit start if (this.joining) { this.joining = false; @@ -332,22 +396,22 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } } - CriterionTriggers.v.a(this); - if (this.cs != null) { - CriterionTriggers.t.a(this, this.cs, this.ticksLived - this.ct); + CriterionTriggers.w.a(this); + if (this.cA != null) { + CriterionTriggers.u.a(this, this.cA, this.ticksLived - this.cB); } - this.bY.b(this); + this.cg.b(this); } public void playerTick() { try { - super.B_(); + super.tick(); for (int i = 0; i < this.inventory.getSize(); ++i) { ItemStack itemstack = this.inventory.getItem(i); - if (!itemstack.isEmpty() && itemstack.getItem().f()) { + if (itemstack.getItem().W_()) { Packet packet = ((ItemWorldMapBase) itemstack.getItem()).a(itemstack, this.world, (EntityHuman) this); if (packet != null) { @@ -356,26 +420,36 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } } - if (this.getHealth() != this.lastHealthSent || this.ch != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.ci) { + if (this.getHealth() != this.lastHealthSent || this.cp != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.cq) { this.playerConnection.sendPacket(new PacketPlayOutUpdateHealth(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit this.lastHealthSent = this.getHealth(); - this.ch = this.foodData.getFoodLevel(); - this.ci = this.foodData.getSaturationLevel() == 0.0F; + this.cp = this.foodData.getFoodLevel(); + this.cq = this.foodData.getSaturationLevel() == 0.0F; } - if (this.getHealth() + this.getAbsorptionHearts() != this.ca) { - this.ca = this.getHealth() + this.getAbsorptionHearts(); - this.a(IScoreboardCriteria.g, MathHelper.f(this.ca)); + if (this.getHealth() + this.getAbsorptionHearts() != this.ci) { + this.ci = this.getHealth() + this.getAbsorptionHearts(); + this.a(IScoreboardCriteria.g, MathHelper.f(this.ci)); } - if (this.foodData.getFoodLevel() != this.cb) { - this.cb = this.foodData.getFoodLevel(); - this.a(IScoreboardCriteria.h, MathHelper.f((float) this.cb)); + if (this.foodData.getFoodLevel() != this.cj) { + this.cj = this.foodData.getFoodLevel(); + this.a(IScoreboardCriteria.h, MathHelper.f((float) this.cj)); } - if (this.getAirTicks() != this.cc) { - this.cc = this.getAirTicks(); - this.a(IScoreboardCriteria.i, MathHelper.f((float) this.cc)); + if (this.getAirTicks() != this.ck) { + this.ck = this.getAirTicks(); + this.a(IScoreboardCriteria.i, MathHelper.f((float) this.ck)); + } + + if (this.getArmorStrength() != this.cl) { + this.cl = this.getArmorStrength(); + this.a(IScoreboardCriteria.j, MathHelper.f((float) this.cl)); + } + + if (this.expTotal != this.cn) { + this.cn = this.expTotal; + this.a(IScoreboardCriteria.k, MathHelper.f((float) this.cn)); } // CraftBukkit start - Force max health updates @@ -384,19 +458,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } // CraftBukkit end - if (this.getArmorStrength() != this.cd) { - this.cd = this.getArmorStrength(); - this.a(IScoreboardCriteria.j, MathHelper.f((float) this.cd)); - } - - if (this.expTotal != this.cf) { - this.cf = this.expTotal; - this.a(IScoreboardCriteria.k, MathHelper.f((float) this.cf)); - } - - if (this.expLevel != this.ce) { - this.ce = this.expLevel; - this.a(IScoreboardCriteria.l, MathHelper.f((float) this.ce)); + if (this.expLevel != this.cm) { + this.cm = this.expLevel; + this.a(IScoreboardCriteria.l, MathHelper.f((float) this.cm)); } if (this.expTotal != this.lastSentExp) { @@ -405,7 +469,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } if (this.ticksLived % 20 == 0) { - CriterionTriggers.o.a(this); + CriterionTriggers.p.a(this); } // CraftBukkit start - initialize oldLevel and fire PlayerLevelChangeEvent @@ -428,15 +492,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } private void a(IScoreboardCriteria iscoreboardcriteria, int i) { - Collection collection = this.world.getServer().getScoreboardManager().getScoreboardScores(iscoreboardcriteria, this.getName(), new java.util.ArrayList()); // CraftBukkit - Use our scores instead - Iterator iterator = collection.iterator(); - - while (iterator.hasNext()) { - ScoreboardScore scoreboardscore = (ScoreboardScore) iterator.next(); // CraftBukkit - Use our scores instead - + // CraftBukkit - Use our scores instead + this.world.getServer().getScoreboardManager().getScoreboardScores(iscoreboardcriteria, this.getName(), (scoreboardscore) -> { scoreboardscore.setScore(i); - } - + }); } public void die(DamageSource damagesource) { @@ -460,14 +519,14 @@ public class EntityPlayer extends EntityHuman implements ICrafting { IChatBaseComponent chatmessage = this.getCombatTracker().getDeathMessage(); - String deathmessage = chatmessage.toPlainText(); + String deathmessage = chatmessage.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? if (deathMessage.equals(deathmessage)) { - ScoreboardTeamBase scoreboardteambase = this.aY(); + ScoreboardTeamBase scoreboardteambase = this.be(); if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS) { if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OTHER_TEAMS) { @@ -494,29 +553,18 @@ public class EntityPlayer extends EntityHuman implements ICrafting { // CraftBukkit end // CraftBukkit - Get our scores instead - Collection collection = this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.d, this.getName(), new java.util.ArrayList()); - Iterator iterator = collection.iterator(); + this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.d, this.getName(), ScoreboardScore::incrementScore); - while (iterator.hasNext()) { - ScoreboardScore scoreboardscore = (ScoreboardScore) iterator.next(); // CraftBukkit - Use our scores instead - - scoreboardscore.incrementScore(); - } - - EntityLiving entityliving = this.ci(); + EntityLiving entityliving = this.cv(); if (entityliving != null) { - EntityTypes.MonsterEggInfo entitytypes_monsteregginfo = (EntityTypes.MonsterEggInfo) EntityTypes.eggInfo.get(EntityTypes.a((Entity) entityliving)); - - if (entitytypes_monsteregginfo != null) { - this.b(entitytypes_monsteregginfo.killedByEntityStatistic); - } - - entityliving.a(this, this.bb, damagesource); + this.b(StatisticList.ENTITY_KILLED_BY.b(entityliving.P())); + entityliving.a(this, this.be, damagesource); } - this.b(StatisticList.A); - this.a(StatisticList.h); + this.a(StatisticList.DEATHS); + this.a(StatisticList.CUSTOM.b(StatisticList.TIME_SINCE_DEATH)); + this.a(StatisticList.CUSTOM.b(StatisticList.n)); this.extinguish(); this.setFlag(0, false); this.getCombatTracker().g(); @@ -526,75 +574,44 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (entity != this) { super.a(entity, i, damagesource); this.addScore(i); + String s = this.getName(); + String s1 = entity.getName(); + // CraftBukkit - Get our scores instead - Collection collection = this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.f, this.getName(), new java.util.ArrayList()); - + this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.f, s, ScoreboardScore::incrementScore); if (entity instanceof EntityHuman) { - this.b(StatisticList.D); + this.a(StatisticList.PLAYER_KILLS); // CraftBukkit - Get our scores instead - this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.e, this.getName(), collection); - // collection.addAll(this.getScoreboard().getObjectivesForCriteria(IScoreboardCriteria.e)); - // CraftBukkit end + this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.e, s, ScoreboardScore::incrementScore); } else { - this.b(StatisticList.B); - } - - collection.addAll(this.E(entity)); - Iterator iterator = collection.iterator(); // CraftBukkit - - while (iterator.hasNext()) { - // CraftBukkit start - // ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next(); - - // this.getScoreboard().getPlayerScoreForObjective(this.getName(), scoreboardobjective).incrementScore(); - iterator.next().incrementScore(); - // CraftBukkit end + this.a(StatisticList.MOB_KILLS); } + this.a(s, s1, IScoreboardCriteria.m); + this.a(s1, s, IScoreboardCriteria.n); CriterionTriggers.b.a(this, entity, damagesource); } } - private Collection E(Entity entity) { // CraftBukkit - String s = entity instanceof EntityHuman ? entity.getName() : entity.bn(); - ScoreboardTeam scoreboardteam = this.getScoreboard().getPlayerTeam(this.getName()); + private void a(String s, String s1, IScoreboardCriteria[] aiscoreboardcriteria) { + ScoreboardTeam scoreboardteam = this.getScoreboard().getPlayerTeam(s1); if (scoreboardteam != null) { int i = scoreboardteam.getColor().b(); - if (i >= 0 && i < IScoreboardCriteria.n.length) { - Iterator iterator = this.getScoreboard().getObjectivesForCriteria(IScoreboardCriteria.n[i]).iterator(); - - while (iterator.hasNext()) { - ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next(); - ScoreboardScore scoreboardscore = this.getScoreboard().getPlayerScoreForObjective(s, scoreboardobjective); - - scoreboardscore.incrementScore(); - } - } - } - - ScoreboardTeam scoreboardteam1 = this.getScoreboard().getPlayerTeam(s); - - if (scoreboardteam1 != null) { - int j = scoreboardteam1.getColor().b(); - - if (j >= 0 && j < IScoreboardCriteria.m.length) { + if (i >= 0 && i < aiscoreboardcriteria.length) { // CraftBukkit - Get our scores instead - return this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.m[j], this.getName(), new java.util.ArrayList()); - // return this.getScoreboard().getObjectivesForCriteria(IScoreboardCriteria.m[j]); - // CraftBukkit end + this.world.getServer().getScoreboardManager().getScoreboardScores(aiscoreboardcriteria[i], s, ScoreboardScore::incrementScore); } } - return Lists.newArrayList(); } public boolean damageEntity(DamageSource damagesource, float f) { if (this.isInvulnerable(damagesource)) { return false; } else { - boolean flag = this.server.aa() && this.canPvP() && "fall".equals(damagesource.translationIndex); + boolean flag = this.server.S() && this.canPvP() && "fall".equals(damagesource.translationIndex); if (!flag && this.invulnerableTicks > 0 && damagesource != DamageSource.OUT_OF_WORLD) { return false; @@ -630,13 +647,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } @Nullable - public Entity b(int i) { + public Entity d(int i) { 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.cv = new Vec3D(this.locX, this.locY, this.locZ); + this.cD = new Vec3D(this.locX, this.locY, this.locZ); } else if (this.dimension != -1 && i != 0) { - this.cv = null; + this.cD = null; } if (this.dimension == 1 && i == 1) { @@ -645,8 +662,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { 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.cq ? 0.0F : 1.0F)); - this.cq = true; + this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(4, this.cy ? 0.0F : 1.0F)); + this.cy = true; } return this; @@ -662,7 +679,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.playerConnection.sendPacket(new PacketPlayOutWorldEvent(1032, BlockPosition.ZERO, 0, false)); this.lastSentExp = -1; this.lastHealthSent = -1.0F; - this.ch = -1; + this.cp = -1; return this; } } @@ -691,13 +708,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { EntityHuman.EnumBedResult entityhuman_enumbedresult = super.a(blockposition); if (entityhuman_enumbedresult == EntityHuman.EnumBedResult.OK) { - this.b(StatisticList.ab); + this.a(StatisticList.SLEEP_IN_BED); PacketPlayOutBed packetplayoutbed = new PacketPlayOutBed(this, blockposition); - this.x().getTracker().a((Entity) this, (Packet) packetplayoutbed); + this.getWorldServer().getTracker().a((Entity) this, (Packet) packetplayoutbed); this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch); this.playerConnection.sendPacket(packetplayoutbed); - CriterionTriggers.p.a(this); + CriterionTriggers.q.a(this); } return entityhuman_enumbedresult; @@ -706,7 +723,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void a(boolean flag, boolean flag1, boolean flag2) { if (!this.sleeping) return; // CraftBukkit - Can't leave bed if not in one! if (this.isSleeping()) { - this.x().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(this, 2)); + this.getWorldServer().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(this, 2)); } super.a(flag, flag1, flag2); @@ -717,12 +734,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public boolean a(Entity entity, boolean flag) { - Entity entity1 = this.bJ(); + Entity entity1 = this.getVehicle(); if (!super.a(entity, flag)) { return false; } else { - Entity entity2 = this.bJ(); + Entity entity2 = this.getVehicle(); if (entity2 != entity1 && this.playerConnection != null) { this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch); @@ -733,10 +750,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public void stopRiding() { - Entity entity = this.bJ(); + Entity entity = this.getVehicle(); super.stopRiding(); - Entity entity1 = this.bJ(); + Entity entity1 = this.getVehicle(); if (entity1 != entity && this.playerConnection != null) { this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch); @@ -745,16 +762,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (entity instanceof EntityPlayer) { WorldServer worldServer = (WorldServer) entity.getWorld(); worldServer.tracker.untrackEntity(this); - worldServer.tracker.entriesLock.lock(); // Akarin + worldServer.tracker.entriesLock.writeLock().lock(); // Akarin - ProtocolSupport will overwrite track method worldServer.tracker.track(this); - worldServer.tracker.entriesLock.unlock(); // Akarin + worldServer.tracker.entriesLock.writeLock().unlock(); // Akarin - ProtocolSupport will overwrite track method } // Paper end } public boolean isInvulnerable(DamageSource damagesource) { - return super.isInvulnerable(damagesource) || this.L(); + return super.isInvulnerable(damagesource) || this.H(); } protected void a(double d0, boolean flag, IBlockData iblockdata, BlockPosition blockposition) {} @@ -773,7 +790,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { BlockPosition blockposition = new BlockPosition(i, j, k); IBlockData iblockdata = this.world.getType(blockposition); - if (iblockdata.getMaterial() == Material.AIR) { + if (iblockdata.isAir()) { BlockPosition blockposition1 = blockposition.down(); IBlockData iblockdata1 = this.world.getType(blockposition1); Block block = iblockdata1.getBlock(); @@ -799,10 +816,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).b() != null && this.isSpectator()) { - this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).setChatModifier((new ChatModifier()).setColor(EnumChatFormat.RED)), true); + if (false && itileentitycontainer instanceof ILootable && ((ILootable) itileentitycontainer).Q_() != null && this.isSpectator()) { + this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).a(EnumChatFormat.RED), true); } else { - boolean cancelled = itileentitycontainer instanceof ILootable && ((ILootable) itileentitycontainer).b() != null && this.isSpectator(); + boolean cancelled = itileentitycontainer instanceof ILootable && ((ILootable) itileentitycontainer).Q_() != null && this.isSpectator(); Container container = CraftEventFactory.callInventoryOpenEvent(this, itileentitycontainer.createContainer(this.inventory, this), cancelled); if (container == null) { return; @@ -841,8 +858,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } // CraftBukkit end - if (iinventory instanceof ILootable && ((ILootable) iinventory).b() != null && this.isSpectator()) { - this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).setChatModifier((new ChatModifier()).setColor(EnumChatFormat.RED)), true); + if (iinventory instanceof ILootable && ((ILootable) iinventory).Q_() != null && this.isSpectator()) { + this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).a(EnumChatFormat.RED), true); } else { if (this.activeContainer != this.defaultContainer) { this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper @@ -853,7 +870,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (itileinventory.isLocked() && !this.a(itileinventory.getLock()) && !this.isSpectator()) { this.playerConnection.sendPacket(new PacketPlayOutChat(new ChatMessage("container.isLocked", new Object[] { iinventory.getScoreboardDisplayName()}), ChatMessageType.GAME_INFO)); - this.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ab, SoundCategory.BLOCKS, this.locX, this.locY, this.locZ, 1.0F, 1.0F)); + this.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_CHEST_LOCKED, SoundCategory.BLOCKS, this.locX, this.locY, this.locZ, 1.0F, 1.0F)); iinventory.closeContainer(this); // CraftBukkit return; } @@ -886,7 +903,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.activeContainer = container; // CraftBukkit this.activeContainer.windowId = this.containerCounter; this.activeContainer.addSlotListener(this); - InventoryMerchant inventorymerchant = ((ContainerMerchant) this.activeContainer).e(); + InventoryMerchant inventorymerchant = ((ContainerMerchant) this.activeContainer).d(); IChatBaseComponent ichatbasecomponent = imerchant.getScoreboardDisplayName(); this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.containerCounter, "minecraft:villager", ichatbasecomponent, inventorymerchant.getSize())); @@ -897,7 +914,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { packetdataserializer.writeInt(this.containerCounter); merchantrecipelist.a(packetdataserializer); - this.playerConnection.sendPacket(new PacketPlayOutCustomPayload("MC|TrList", packetdataserializer)); + this.playerConnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, packetdataserializer)); } } @@ -928,7 +945,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { PacketDataSerializer packetdataserializer = new PacketDataSerializer(Unpooled.buffer()); packetdataserializer.a((Enum) enumhand); - this.playerConnection.sendPacket(new PacketPlayOutCustomPayload("MC|BOpen", packetdataserializer)); + this.playerConnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.c, packetdataserializer)); } } @@ -983,7 +1000,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit // Paper end this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); - this.r(); + this.m(); } public void broadcastCarriedItem() { @@ -992,7 +1009,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } } - public void r() { + public void m() { this.activeContainer.b((EntityHuman) this); this.activeContainer = this.defaultContainer; } @@ -1000,49 +1017,33 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void a(float f, float f1, boolean flag, boolean flag1) { if (this.isPassenger()) { if (f >= -1.0F && f <= 1.0F) { - this.be = f; + this.bh = f; } if (f1 >= -1.0F && f1 <= 1.0F) { - this.bg = f1; + this.bj = f1; } - this.bd = flag; + this.bg = flag; this.setSneaking(flag1); } } - public void a(Statistic statistic, int i) { - if (statistic != null) { - this.bZ.b(this, statistic, i); - Iterator iterator = this.getScoreboard().getObjectivesForCriteria(statistic.f()).iterator(); - - while (iterator.hasNext()) { - ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next(); - - this.getScoreboard().getPlayerScoreForObjective(this.getName(), scoreboardobjective).addScore(i); - } - - } + public void a(Statistic statistic, int i) { + this.ch.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) { - if (statistic != null) { - this.bZ.setStatistic(this, statistic, 0); - Iterator iterator = this.getScoreboard().getObjectivesForCriteria(statistic.f()).iterator(); - - while (iterator.hasNext()) { - ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next(); - - this.getScoreboard().getPlayerScoreForObjective(this.getName(), scoreboardobjective).setScore(0); - } - - } + public void a(Statistic statistic) { + this.ch.setStatistic(this, statistic, 0); + this.world.getServer().getScoreboardManager().getScoreboardScores(statistic, this.getName(), ScoreboardScore::c); // CraftBukkit - Get our scores instead } - public void a(List list) { - this.cr.a(list, this); + public int a(Collection collection) { + return this.cz.a(collection, this); } public void a(MinecraftKey[] aminecraftkey) { @@ -1052,25 +1053,27 @@ public class EntityPlayer extends EntityHuman implements ICrafting { for (int j = 0; j < i; ++j) { MinecraftKey minecraftkey = aminecraftkey1[j]; + IRecipe irecipe = this.server.getCraftingManager().a(minecraftkey); - // CraftBukkit start - if (CraftingManager.a(minecraftkey) == null) { - Bukkit.getLogger().warning("Ignoring grant of non existent recipe " + minecraftkey); - continue; + if (irecipe != null) { + arraylist.add(irecipe); } - // CraftBukit end - arraylist.add(CraftingManager.a(minecraftkey)); } - this.a((List) arraylist); // CraftBukkit - decompile error + this.a((Collection) arraylist); } - public void b(List list) { - this.cr.b(list, this); + public int b(Collection collection) { + return this.cz.b(collection, this); } - public void s() { - this.cu = true; + public void giveExp(int i) { + super.giveExp(i); + this.lastSentExp = -1; + } + + public void n() { + this.cC = true; this.ejectPassengers(); if (this.sleeping) { this.a(true, false, false); @@ -1078,8 +1081,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } - public boolean t() { - return this.cu; + public boolean o() { + return this.cC; } public void triggerHealthUpdate() { @@ -1099,14 +1102,26 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.playerConnection.sendPacket(new PacketPlayOutChat(ichatbasecomponent, flag ? ChatMessageType.GAME_INFO : ChatMessageType.CHAT)); } - protected void v() { + protected void q() { if (!this.activeItem.isEmpty() && this.isHandRaised()) { this.playerConnection.sendPacket(new PacketPlayOutEntityStatus(this, (byte) 9)); - super.v(); + super.q(); } } + public void a(ArgumentAnchor.Anchor argumentanchor_anchor, Vec3D vec3d) { + super.a(argumentanchor_anchor, vec3d); + this.playerConnection.sendPacket(new PacketPlayOutLookAt(argumentanchor_anchor, vec3d.x, vec3d.y, vec3d.z)); + } + + public void a(ArgumentAnchor.Anchor argumentanchor_anchor, Entity entity, ArgumentAnchor.Anchor argumentanchor_anchor1) { + Vec3D vec3d = argumentanchor_anchor1.a(entity); + + super.a(argumentanchor_anchor, vec3d); + this.playerConnection.sendPacket(new PacketPlayOutLookAt(argumentanchor_anchor, entity, argumentanchor_anchor1)); + } + public void copyFrom(EntityPlayer entityplayer, boolean flag) { if (flag) { this.inventory.a(entityplayer.inventory); @@ -1116,9 +1131,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.expTotal = entityplayer.expTotal; this.exp = entityplayer.exp; this.setScore(entityplayer.getScore()); - this.an = entityplayer.an; - this.ao = entityplayer.ao; - this.ap = entityplayer.ap; + this.aq = entityplayer.aq; + this.ar = entityplayer.ar; + this.as = entityplayer.as; } else if (this.world.getGameRules().getBoolean("keepInventory") || entityplayer.isSpectator()) { this.inventory.a(entityplayer.inventory); this.expLevel = entityplayer.expLevel; @@ -1127,20 +1142,20 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.setScore(entityplayer.getScore()); } - this.bS = entityplayer.bS; + this.bZ = entityplayer.bZ; this.enderChest = entityplayer.enderChest; - this.getDataWatcher().set(EntityPlayer.br, entityplayer.getDataWatcher().get(EntityPlayer.br)); + this.getDataWatcher().set(EntityPlayer.bx, entityplayer.getDataWatcher().get(EntityPlayer.bx)); this.lastSentExp = -1; this.lastHealthSent = -1.0F; - this.ch = -1; - // this.cr.a((RecipeBook) entityplayer.cr); // CraftBukkit + this.cp = -1; + // this.cz.a((RecipeBook) entityplayer.cz); // CraftBukkit // Paper start - Optimize remove queue //this.removeQueue.addAll(entityplayer.removeQueue); if (this.removeQueue != entityplayer.removeQueue) { this.removeQueue.addAll(entityplayer.removeQueue); } - this.cq = entityplayer.cq; - this.cv = entityplayer.cv; + this.cy = entityplayer.cy; + this.cD = entityplayer.cD; this.setShoulderEntityLeft(entityplayer.getShoulderEntityLeft()); this.setShoulderEntityRight(entityplayer.getShoulderEntityRight()); } @@ -1149,27 +1164,27 @@ public class EntityPlayer extends EntityHuman implements ICrafting { super.a(mobeffect); this.playerConnection.sendPacket(new PacketPlayOutEntityEffect(this.getId(), mobeffect)); if (mobeffect.getMobEffect() == MobEffects.LEVITATION) { - this.ct = this.ticksLived; - this.cs = new Vec3D(this.locX, this.locY, this.locZ); + this.cB = this.ticksLived; + this.cA = new Vec3D(this.locX, this.locY, this.locZ); } - CriterionTriggers.z.a(this); + CriterionTriggers.A.a(this); } protected void a(MobEffect mobeffect, boolean flag) { super.a(mobeffect, flag); this.playerConnection.sendPacket(new PacketPlayOutEntityEffect(this.getId(), mobeffect)); - CriterionTriggers.z.a(this); + CriterionTriggers.A.a(this); } protected void b(MobEffect mobeffect) { super.b(mobeffect); this.playerConnection.sendPacket(new PacketPlayOutRemoveEntityEffect(this.getId(), mobeffect.getMobEffect())); if (mobeffect.getMobEffect() == MobEffects.LEVITATION) { - this.cs = null; + this.cA = null; } - CriterionTriggers.z.a(this); + CriterionTriggers.A.a(this); } public void enderTeleportTo(double d0, double d1, double d2) { @@ -1177,21 +1192,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public void a(Entity entity) { - this.x().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(entity, 4)); + this.getWorldServer().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(entity, 4)); } public void b(Entity entity) { - this.x().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(entity, 5)); + this.getWorldServer().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(entity, 5)); } public void updateAbilities() { if (this.playerConnection != null) { this.playerConnection.sendPacket(new PacketPlayOutAbilities(this.abilities)); - this.G(); + this.C(); } } - public WorldServer x() { + public WorldServer getWorldServer() { return (WorldServer) this.world; } @@ -1218,48 +1233,31 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } this.updateAbilities(); - this.cE(); + this.cR(); } public boolean isSpectator() { return this.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR; } - public boolean z() { + public boolean u() { return this.playerInteractManager.getGameMode() == EnumGamemode.CREATIVE; } public void sendMessage(IChatBaseComponent ichatbasecomponent) { - this.playerConnection.sendPacket(new PacketPlayOutChat(ichatbasecomponent)); + this.a(ichatbasecomponent, ChatMessageType.SYSTEM); } - public boolean a(int i, String s) { - /* CraftBukkit start - if ("seed".equals(s) && !this.server.aa()) { - return true; - } else if (!"tell".equals(s) && !"help".equals(s) && !"me".equals(s) && !"trigger".equals(s)) { - if (this.server.getPlayerList().isOp(this.getProfile())) { - OpListEntry oplistentry = (OpListEntry) this.server.getPlayerList().getOPs().get(this.getProfile()); - - return oplistentry != null ? oplistentry.a() >= i : this.server.q() >= i; - } else { - return false; + 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)); } - } else { - return true; - } - */ - if ("@".equals(s)) { - return getBukkitEntity().hasPermission("minecraft.command.selector"); - } - if ("".equals(s)) { - return getBukkitEntity().isOp(); - } - return getBukkitEntity().hasPermission("minecraft.command." + s); - // CraftBukkit end + + }); } - public String A() { + public String v() { String s = this.playerConnection.networkManager.getSocketAddress().toString(); s = s.substring(s.indexOf("/") + 1); @@ -1273,52 +1271,47 @@ 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); } - - // Paper start - add PlayerLocaleChangeEvent - // Since the field is initialized to null, this event should always fire the first time the packet is received - String oldLocale = this.locale; - this.locale = packetplayinsettings.a(); - if (!this.locale.equals(oldLocale)) { - new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), oldLocale, this.locale).callEvent(); - } - - // Compat with Bukkit - oldLocale = oldLocale != null ? oldLocale : "en_us"; - // Paper end - - if (!oldLocale.equals(packetplayinsettings.a())) { - PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packetplayinsettings.a()); + if (this.locale == null || !this.locale.equals(packetplayinsettings.b())) { // Paper - fix bug and check for null + PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packetplayinsettings.b()); this.server.server.getPluginManager().callEvent(event); } // CraftBukkit end - this.cl = packetplayinsettings.c(); - this.cm = packetplayinsettings.d(); - this.getDataWatcher().set(EntityPlayer.br, Byte.valueOf((byte) packetplayinsettings.e())); - this.getDataWatcher().set(EntityPlayer.bs, Byte.valueOf((byte) (packetplayinsettings.getMainHand() == EnumMainHand.LEFT ? 0 : 1))); + // Paper start - add PlayerLocaleChangeEvent + // Since the field is initialized to null, this event should always fire the first time the packet is received + String oldLocale = this.locale; + this.locale = packetplayinsettings.b(); + if (!this.locale.equals(oldLocale)) { + new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), oldLocale, this.locale).callEvent(); + } + // Paper end + this.ct = packetplayinsettings.d(); + this.cu = 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.cl; + return this.ct; } public void setResourcePack(String s, String s1) { this.playerConnection.sendPacket(new PacketPlayOutResourcePackSend(s, s1)); } - public BlockPosition getChunkCoordinates() { - return new BlockPosition(this.locX, this.locY + 0.5D, this.locZ); + protected int y() { + return this.server.a(this.getProfile()); } public void resetIdleTimer() { - this.cn = MinecraftServer.aw(); + this.cv = SystemUtils.b(); } public ServerStatisticManager getStatisticManager() { - return this.bZ; + return this.ch; } - public RecipeBookServer F() { - return this.cr; + public RecipeBookServer B() { + return this.cz; } public void c(Entity entity) { @@ -1334,33 +1327,33 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.removeQueue.remove(Integer.valueOf(entity.getId())); } - protected void G() { + protected void C() { if (this.isSpectator()) { - this.bY(); + this.cl(); this.setInvisible(true); } else { - super.G(); + super.C(); } - this.x().getTracker().a(this); + this.getWorldServer().getTracker().a(this); } public Entity getSpecatorTarget() { - return (Entity) (this.co == null ? this : this.co); + return (Entity) (this.cw == null ? this : this.cw); } public void setSpectatorTarget(Entity entity) { Entity entity1 = this.getSpecatorTarget(); - this.co = (Entity) (entity == null ? this : entity); - if (entity1 != this.co) { - this.playerConnection.sendPacket(new PacketPlayOutCamera(this.co)); - this.playerConnection.a(this.co.locX, this.co.locY, this.co.locZ, this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit + 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 } } - protected void I() { + protected void E() { if (this.portalCooldown > 0 && !this.worldChangeInvuln) { --this.portalCooldown; } @@ -1376,8 +1369,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } - public long J() { - return this.cn; + public long F() { + return this.cv; } @Nullable @@ -1387,23 +1380,23 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void a(EnumHand enumhand) { super.a(enumhand); - this.ds(); + this.dH(); } - public boolean L() { + public boolean H() { return this.worldChangeInvuln; } - public void M() { + public void I() { this.worldChangeInvuln = false; } - public void N() { + public void J() { if (!CraftEventFactory.callToggleGlideEvent(this, true).isCancelled()) // CraftBukkit this.setFlag(7, true); } - public void O() { + public void K() { // CraftBukkit start if (!CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { this.setFlag(7, true); @@ -1413,12 +1406,52 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public AdvancementDataPlayer getAdvancementData() { - return this.bY; + return this.cg; } @Nullable - public Vec3D Q() { - return this.cv; + public Vec3D M() { + return this.cD; + } + + // CraftBukkit start + public void a(WorldServer worldserver, double d0, double d1, double d2, float f, float f1) { + this.a(worldserver, d0, d1, d2, f, f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN); + } + + public void a(WorldServer worldserver, double d0, double d1, double d2, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { + // CraftBukkit end + this.setSpectatorTarget(this); + this.stopRiding(); + /* CraftBukkit start - replace with bukkit handling for multi-world + if (worldserver == this.world) { + this.playerConnection.a(d0, d1, d2, f, f1); + } else { + WorldServer worldserver1 = this.getWorldServer(); + + this.dimension = worldserver.worldProvider.getDimensionManager().getDimensionID(); + this.playerConnection.sendPacket(new PacketPlayOutRespawn(this.dimension, worldserver1.getDifficulty(), worldserver1.getWorldData().getType(), this.playerInteractManager.getGameMode())); + this.server.getPlayerList().f(this); + worldserver1.removeEntity(this); + this.dead = false; + this.setPositionRotation(d0, d1, d2, f, f1); + if (this.isAlive()) { + worldserver1.entityJoinedWorld(this, false); + worldserver.addEntity(this); + worldserver.entityJoinedWorld(this, false); + } + + this.spawnIn(worldserver); + this.server.getPlayerList().a(this, worldserver1); + this.playerConnection.a(d0, d1, d2, f, f1); + this.playerInteractManager.a(worldserver); + this.server.getPlayerList().b(this, worldserver); + this.server.getPlayerList().updateClient(this); + } + */ + this.getBukkitEntity().teleport(new Location(worldserver.getWorld(), d0, d1, d2, f, f1), cause); + // CraftBukkit end + } // CraftBukkit start - Add per-player time and weather. @@ -1540,7 +1573,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.exp = 0; this.deathTicks = 0; this.setArrowCount(0); - this.removeAllEffects(); + this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); this.updateEffects = true; this.activeContainer = this.defaultContainer; this.killer = null; diff --git a/sources/src/main/java/net/minecraft/server/EntityTracker.java b/sources/src/main/java/net/minecraft/server/EntityTracker.java index aeb5a8cd3..e7da005aa 100644 --- a/sources/src/main/java/net/minecraft/server/EntityTracker.java +++ b/sources/src/main/java/net/minecraft/server/EntityTracker.java @@ -2,25 +2,28 @@ package net.minecraft.server; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import com.googlecode.concurentlocks.ReentrantReadWriteUpdateLock; import java.util.ArrayList; import java.util.Iterator; import java.util.Set; -import java.util.concurrent.locks.ReentrantLock; + +import javax.annotation.concurrent.ThreadSafe; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * Akarin Changes Note - * 1) Add lock for entries set operations (safety issue) + * 1) Made collections and entry access thread-safe (safety issue) */ +@ThreadSafe // Akarin public class EntityTracker { private static final Logger a = LogManager.getLogger(); private final WorldServer world; private final Set c = Sets.newHashSet(); - public final ReentrantLock entriesLock = new ReentrantLock(); // Akarin - add lock + public final ReentrantReadWriteUpdateLock entriesLock = new ReentrantReadWriteUpdateLock(); // Akarin - add lock public final IntHashMap trackedEntities = new IntHashMap(); private int e; @@ -38,7 +41,7 @@ public class EntityTracker { this.addEntity(entity, 512, 2); EntityPlayer entityplayer = (EntityPlayer) entity; Iterator iterator = this.c.iterator(); - entriesLock.lock(); // Akarin + // entriesLock.writeLock().lock(); // Akarin - locked in EntityPlayer while (iterator.hasNext()) { EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); @@ -47,7 +50,7 @@ public class EntityTracker { entitytrackerentry.updatePlayer(entityplayer); } } - entriesLock.unlock(); // Akarin + // entriesLock.writeLock().unlock(); // Akarin - locked in EntityPlayer } else if (entity instanceof EntityFishingHook) { this.addEntity(entity, 64, 5, true); } else if (entity instanceof EntityArrow) { @@ -114,46 +117,37 @@ public class EntityTracker { this.addEntity(entity, i, j, false); } - public void addEntity(Entity entity, int i, final int j, boolean flag) { + public void addEntity(Entity entity, int originalRange, int j, boolean flag) { // Spigot org.spigotmc.AsyncCatcher.catchOp( "entity track"); // Spigot - i = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i); // Spigot + int i = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, originalRange); // Spigot try { + // entriesLock.writeLock().lock(); // Akarin - locked from track method if (this.trackedEntities.b(entity.getId())) { throw new IllegalStateException("Entity is already tracked!"); } EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(entity, i, this.e, j, flag); - entriesLock.lock(); // Akarin this.c.add(entitytrackerentry); - this.trackedEntities.a(entity.getId(), entitytrackerentry); entitytrackerentry.scanPlayers(this.world.players); - entriesLock.unlock(); // Akarin + // entriesLock.writeLock().unlock(); // Akarin - locked from track method } catch (Throwable throwable) { CrashReport crashreport = CrashReport.a(throwable, "Adding entity to track"); CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity To Track"); - crashreportsystemdetails.a("Tracking range", i + " blocks"); - final int finalI = i; // CraftBukkit - fix decompile error - crashreportsystemdetails.a("Update interval", new CrashReportCallable() { - public String a() throws Exception { - String s = "Once per " + finalI + " ticks"; // CraftBukkit + crashreportsystemdetails.a("Tracking range", (Object) (i + " blocks")); + crashreportsystemdetails.a("Update interval", () -> { + String s = "Once per " + i + " ticks"; - if (finalI == Integer.MAX_VALUE) { // CraftBukkit - s = "Maximum (" + s + ")"; - } - - return s; + if (i == Integer.MAX_VALUE) { + s = "Maximum (" + s + ")"; } - @Override - public Object call() throws Exception { - return this.a(); - } + return s; }); entity.appendEntityCrashDetails(crashreportsystemdetails); - this.trackedEntities.get(entity.getId()).b().appendEntityCrashDetails(crashreport.a("Entity That Is Already Tracked")); + ((EntityTrackerEntry) this.trackedEntities.get(entity.getId())).b().appendEntityCrashDetails(crashreport.a("Entity That Is Already Tracked")); try { throw new ReportedException(crashreport); @@ -166,34 +160,33 @@ public class EntityTracker { public void untrackEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp( "entity untrack"); // Spigot + entriesLock.writeLock().lock(); // Akarin if (entity instanceof EntityPlayer) { EntityPlayer entityplayer = (EntityPlayer) entity; Iterator iterator = this.c.iterator(); - entriesLock.lock(); // Akarin while (iterator.hasNext()) { EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); entitytrackerentry.a(entityplayer); } - entriesLock.unlock(); // Akarin } - EntityTrackerEntry entitytrackerentry1 = this.trackedEntities.d(entity.getId()); + EntityTrackerEntry entitytrackerentry1 = (EntityTrackerEntry) this.trackedEntities.d(entity.getId()); if (entitytrackerentry1 != null) { - entriesLock.lock(); // Akarin this.c.remove(entitytrackerentry1); entitytrackerentry1.a(); - entriesLock.unlock(); // Akarin } + + entriesLock.writeLock().unlock(); // Akarin } public void updatePlayers() { ArrayList arraylist = Lists.newArrayList(); Iterator iterator = this.c.iterator(); world.timings.tracker1.startTiming(); // Spigot - entriesLock.lock(); // Akarin + entriesLock.writeLock().lock(); // Akarin while (iterator.hasNext()) { EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); @@ -202,7 +195,7 @@ public class EntityTracker { Entity entity = entitytrackerentry.b(); if (entity instanceof EntityPlayer) { - arraylist.add(entity); + arraylist.add((EntityPlayer) entity); } } } @@ -221,14 +214,14 @@ public class EntityTracker { } } } - entriesLock.unlock(); // Akarin + entriesLock.writeLock().unlock(); // Akarin world.timings.tracker2.stopTiming(); // Spigot } public void a(EntityPlayer entityplayer) { Iterator iterator = this.c.iterator(); - entriesLock.lock(); // Akarin + entriesLock.writeLock().lock(); // Akarin while (iterator.hasNext()) { EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); @@ -239,11 +232,14 @@ public class EntityTracker { entitytrackerentry.updatePlayer(entityplayer); } } - entriesLock.unlock(); // Akarin + + entriesLock.writeLock().unlock(); // Akarin } public void a(Entity entity, Packet packet) { - EntityTrackerEntry entitytrackerentry = this.trackedEntities.get(entity.getId()); + entriesLock.readLock().lock(); // Akarin + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) this.trackedEntities.get(entity.getId()); + entriesLock.readLock().unlock(); // Akarin if (entitytrackerentry != null) { entitytrackerentry.broadcast(packet); @@ -252,7 +248,9 @@ public class EntityTracker { } public void sendPacketToEntity(Entity entity, Packet packet) { - EntityTrackerEntry entitytrackerentry = this.trackedEntities.get(entity.getId()); + entriesLock.readLock().lock(); // Akarin + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) this.trackedEntities.get(entity.getId()); + entriesLock.readLock().unlock(); // Akarin if (entitytrackerentry != null) { entitytrackerentry.broadcastIncludingSelf(packet); @@ -262,38 +260,39 @@ public class EntityTracker { public void untrackPlayer(EntityPlayer entityplayer) { Iterator iterator = this.c.iterator(); - entriesLock.lock(); // Akarin + entriesLock.writeLock().lock(); // Akarin while (iterator.hasNext()) { EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); entitytrackerentry.clear(entityplayer); } - entriesLock.unlock(); // Akarin + + entriesLock.writeLock().unlock(); // Akarin } public void a(EntityPlayer entityplayer, Chunk chunk) { ArrayList arraylist = Lists.newArrayList(); ArrayList arraylist1 = Lists.newArrayList(); Iterator iterator = this.c.iterator(); - entriesLock.lock(); // Akarin + entriesLock.writeLock().lock(); // Akarin while (iterator.hasNext()) { EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); Entity entity = entitytrackerentry.b(); - if (entity != entityplayer && entity.ab == chunk.locX && entity.ad == chunk.locZ) { + if (entity != entityplayer && entity.ae == chunk.locX && entity.ag == chunk.locZ) { entitytrackerentry.updatePlayer(entityplayer); if (entity instanceof EntityInsentient && ((EntityInsentient) entity).getLeashHolder() != null) { arraylist.add(entity); } - if (!entity.bF().isEmpty()) { + if (!entity.bP().isEmpty()) { arraylist1.add(entity); } } } - entriesLock.unlock(); // Akarin + entriesLock.writeLock().unlock(); // Akarin Entity entity1; @@ -320,13 +319,14 @@ public class EntityTracker { public void a(int i) { this.e = (i - 1) * 16; Iterator iterator = this.c.iterator(); - entriesLock.lock(); // Akarin + entriesLock.readLock().lock(); // Akarin while (iterator.hasNext()) { EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); entitytrackerentry.a(this.e); } - entriesLock.unlock(); // Akarin + + entriesLock.readLock().unlock(); // Akarin } } diff --git a/sources/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/sources/src/main/java/net/minecraft/server/EntityTrackerEntry.java deleted file mode 100644 index 6645c26ea..000000000 --- a/sources/src/main/java/net/minecraft/server/EntityTrackerEntry.java +++ /dev/null @@ -1,658 +0,0 @@ -package net.minecraft.server; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -// CraftBukkit start -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerVelocityEvent; -// CraftBukkit end - -/** - * Akarin Changes Note - * 1) Make trackedPlayerMap thread-safe (safety issue) - */ -public class EntityTrackerEntry { - - private static final Logger c = LogManager.getLogger(); - private final Entity tracker; - private final int e; - private int f; - private final int g; - private long xLoc; - private long yLoc; - private long zLoc; - private int yRot; - private int xRot; - private int headYaw; - private double n; - private double o; - private double p; - public int a; - private double q; - private double r; - private double s; - private boolean isMoving; - private final boolean u; - private int v; - private List w = Collections.emptyList(); - private boolean x; - private boolean y; - public boolean b; - // Paper start - // Replace trackedPlayers Set with a Map. The value is true until the player receives - // their first update (which is forced to have absolute coordinates), false afterward. - public java.util.Map trackedPlayerMap = new java.util.concurrent.ConcurrentHashMap(); // Akarin - make concurrent - public Set trackedPlayers = trackedPlayerMap.keySet(); - // Paper end - - public EntityTrackerEntry(Entity entity, int i, int j, int k, boolean flag) { - entity.tracker = this; // Paper - this.tracker = entity; - this.e = i; - this.f = j; - this.g = k; - this.u = flag; - this.xLoc = EntityTracker.a(entity.locX); - this.yLoc = EntityTracker.a(entity.locY); - this.zLoc = EntityTracker.a(entity.locZ); - this.yRot = MathHelper.d(entity.yaw * 256.0F / 360.0F); - this.xRot = MathHelper.d(entity.pitch * 256.0F / 360.0F); - this.headYaw = MathHelper.d(entity.getHeadRotation() * 256.0F / 360.0F); - this.y = entity.onGround; - } - - public boolean equals(Object object) { - return object instanceof EntityTrackerEntry ? ((EntityTrackerEntry) object).tracker.getId() == this.tracker.getId() : false; - } - - public int hashCode() { - return this.tracker.getId(); - } - - public void track(List list) { - this.b = false; - if (!this.isMoving || this.tracker.d(this.q, this.r, this.s) > 16.0D) { - this.q = this.tracker.locX; - this.r = this.tracker.locY; - this.s = this.tracker.locZ; - this.isMoving = true; - this.b = true; - this.scanPlayers(list); - } - - List list1 = this.tracker.bF(); - - if (!list1.equals(this.w)) { - this.w = list1; - this.broadcastIncludingSelf(new PacketPlayOutMount(this.tracker)); // CraftBukkit - } - - // PAIL : rename - if (this.tracker instanceof EntityItemFrame && this.a % 20 == 0) { // Paper - EntityItemFrame entityitemframe = (EntityItemFrame) this.tracker; - ItemStack itemstack = entityitemframe.getItem(); - - if (itemstack != null && itemstack.getItem() instanceof ItemWorldMap) { // Paper - moved back up - WorldMap worldmap = Items.FILLED_MAP.getSavedMap(itemstack, this.tracker.world); - Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit - - while (iterator.hasNext()) { - EntityHuman entityhuman = (EntityHuman) iterator.next(); - EntityPlayer entityplayer = (EntityPlayer) entityhuman; - - worldmap.a(entityplayer, itemstack); - Packet packet = Items.FILLED_MAP.a(itemstack, this.tracker.world, (EntityHuman) entityplayer); - - if (packet != null) { - entityplayer.playerConnection.sendPacket(packet); - } - } - } - - this.d(); - } - - if (this.a % this.g == 0 || this.tracker.impulse || this.tracker.getDataWatcher().a()) { - int i; - - if (this.tracker.isPassenger()) { - i = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); - int j = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); - boolean flag = Math.abs(i - this.yRot) >= 1 || Math.abs(j - this.xRot) >= 1; - - if (flag) { - this.broadcast(new PacketPlayOutEntity.PacketPlayOutEntityLook(this.tracker.getId(), (byte) i, (byte) j, this.tracker.onGround)); - this.yRot = i; - this.xRot = j; - } - - this.xLoc = EntityTracker.a(this.tracker.locX); - this.yLoc = EntityTracker.a(this.tracker.locY); - this.zLoc = EntityTracker.a(this.tracker.locZ); - this.d(); - this.x = true; - } else { - ++this.v; - long k = EntityTracker.a(this.tracker.locX); - long l = EntityTracker.a(this.tracker.locY); - long i1 = EntityTracker.a(this.tracker.locZ); - int j1 = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); - int k1 = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); - long l1 = k - this.xLoc; - long i2 = l - this.yLoc; - long j2 = i1 - this.zLoc; - Object object = null; - boolean flag1 = l1 * l1 + i2 * i2 + j2 * j2 >= 128L || this.a % 60 == 0; - boolean flag2 = Math.abs(j1 - this.yRot) >= 1 || Math.abs(k1 - this.xRot) >= 1; - - if (this.a > 0 || this.tracker instanceof EntityArrow) { // Paper - Moved up - // CraftBukkit start - Code moved from below - if (flag1) { - this.xLoc = k; - this.yLoc = l; - this.zLoc = i1; - } - - if (flag2) { - this.yRot = j1; - this.xRot = k1; - } - // CraftBukkit end - - if (l1 >= -32768L && l1 < 32768L && i2 >= -32768L && i2 < 32768L && j2 >= -32768L && j2 < 32768L && this.v <= 400 && !this.x && this.y == this.tracker.onGround) { - if ((!flag1 || !flag2) && !(this.tracker instanceof EntityArrow)) { - if (flag1) { - object = new PacketPlayOutEntity.PacketPlayOutRelEntityMove(this.tracker.getId(), l1, i2, j2, this.tracker.onGround); - } else if (flag2) { - object = new PacketPlayOutEntity.PacketPlayOutEntityLook(this.tracker.getId(), (byte) j1, (byte) k1, this.tracker.onGround); - } - } else { - object = new PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook(this.tracker.getId(), l1, i2, j2, (byte) j1, (byte) k1, this.tracker.onGround); - } - } else { - this.y = this.tracker.onGround; - this.v = 0; - // CraftBukkit start - Refresh list of who can see a player before sending teleport packet - if (this.tracker instanceof EntityPlayer) { - this.scanPlayers(new java.util.ArrayList(this.trackedPlayers)); - } - // CraftBukkit end - this.c(); - object = new PacketPlayOutEntityTeleport(this.tracker); - } - } - - boolean flag3 = this.u; - - if (this.tracker instanceof EntityLiving && ((EntityLiving) this.tracker).cP()) { - flag3 = true; - } - - if (flag3 && this.a > 0) { - double d0 = this.tracker.motX - this.n; - double d1 = this.tracker.motY - this.o; - double d2 = this.tracker.motZ - this.p; - double d3 = 0.02D; - double d4 = d0 * d0 + d1 * d1 + d2 * d2; - - if (d4 > 4.0E-4D || d4 > 0.0D && this.tracker.motX == 0.0D && this.tracker.motY == 0.0D && this.tracker.motZ == 0.0D) { - this.n = this.tracker.motX; - this.o = this.tracker.motY; - this.p = this.tracker.motZ; - this.broadcast(new PacketPlayOutEntityVelocity(this.tracker.getId(), this.n, this.o, this.p)); - } - } - - if (object != null) { - // Paper start - ensure fresh viewers get an absolute position on their first update, - // since we can't be certain what position they received in the spawn packet. - if (object instanceof PacketPlayOutEntityTeleport) { - this.broadcast((Packet) object); - } else { - PacketPlayOutEntityTeleport teleportPacket = null; - - for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { - if (viewer.getValue()) { - viewer.setValue(false); - if (teleportPacket == null) { - teleportPacket = new PacketPlayOutEntityTeleport(this.tracker); - } - viewer.getKey().playerConnection.sendPacket(teleportPacket); - } else { - viewer.getKey().playerConnection.sendPacket((Packet) object); - } - } - } - // Paper end - } - - this.d(); - /* CraftBukkit start - Code moved up - if (flag1) { - this.xLoc = k; - this.yLoc = l; - this.zLoc = i1; - } - - if (flag2) { - this.yRot = j1; - this.xRot = k1; - } - // CraftBukkit end */ - - this.x = false; - } - - i = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F); - if (Math.abs(i - this.headYaw) >= 1) { - this.broadcast(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) i)); - this.headYaw = i; - } - - this.tracker.impulse = false; - } - - ++this.a; - if (this.tracker.velocityChanged) { - // CraftBukkit start - Create PlayerVelocity event - boolean cancelled = false; - - if (this.tracker instanceof EntityPlayer) { - Player player = (Player) this.tracker.getBukkitEntity(); - org.bukkit.util.Vector velocity = player.getVelocity(); - - PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); - this.tracker.world.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { - cancelled = true; - } else if (!velocity.equals(event.getVelocity())) { - player.setVelocity(event.getVelocity()); - } - } - - if (!cancelled) { - this.broadcastIncludingSelf(new PacketPlayOutEntityVelocity(this.tracker)); - } - // CraftBukkit end - this.tracker.velocityChanged = false; - } - - } - - private void d() { - DataWatcher datawatcher = this.tracker.getDataWatcher(); - - if (datawatcher.a()) { - this.broadcastIncludingSelf(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false)); - } - - if (this.tracker instanceof EntityLiving) { - AttributeMapServer attributemapserver = (AttributeMapServer) ((EntityLiving) this.tracker).getAttributeMap(); - Set set = attributemapserver.getAttributes(); - - if (!set.isEmpty()) { - // CraftBukkit start - Send scaled max health - if (this.tracker instanceof EntityPlayer) { - ((EntityPlayer) this.tracker).getBukkitEntity().injectScaledMaxHealth(set, false); - } - // CraftBukkit end - this.broadcastIncludingSelf(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set)); - } - - set.clear(); - } - - } - - public void broadcast(Packet packet) { - Iterator iterator = this.trackedPlayers.iterator(); - - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - entityplayer.playerConnection.sendPacket(packet); - } - - } - - public void broadcastIncludingSelf(Packet packet) { - this.broadcast(packet); - if (this.tracker instanceof EntityPlayer) { - ((EntityPlayer) this.tracker).playerConnection.sendPacket(packet); - } - - } - - public void a() { - Iterator iterator = this.trackedPlayers.iterator(); - - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - this.tracker.c(entityplayer); - entityplayer.c(this.tracker); - } - - } - - public void a(EntityPlayer entityplayer) { - if (this.trackedPlayers.contains(entityplayer)) { - this.tracker.c(entityplayer); - entityplayer.c(this.tracker); - this.trackedPlayers.remove(entityplayer); - } - - } - - public void updatePlayer(EntityPlayer entityplayer) { - org.spigotmc.AsyncCatcher.catchOp( "player tracker update"); // Spigot - if (entityplayer != this.tracker) { - if (this.c(entityplayer)) { - if (!this.trackedPlayers.contains(entityplayer) && (this.e(entityplayer) || this.tracker.attachedToPlayer)) { - // CraftBukkit start - respect vanish API - if (this.tracker instanceof EntityPlayer) { - Player player = ((EntityPlayer) this.tracker).getBukkitEntity(); - if (!entityplayer.getBukkitEntity().canSee(player)) { - return; - } - } - - entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId())); - // CraftBukkit end - this.trackedPlayerMap.put(entityplayer, true); // Paper - Packet packet = this.e(); - - entityplayer.playerConnection.sendPacket(packet); - if (!this.tracker.getDataWatcher().d()) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(this.tracker.getId(), this.tracker.getDataWatcher(), true)); - } - - boolean flag = this.u; - - if (this.tracker instanceof EntityLiving) { - AttributeMapServer attributemapserver = (AttributeMapServer) ((EntityLiving) this.tracker).getAttributeMap(); - Collection collection = attributemapserver.c(); - - // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health - if (this.tracker.getId() == entityplayer.getId()) { - ((EntityPlayer) this.tracker).getBukkitEntity().injectScaledMaxHealth(collection, false); - } - // CraftBukkit end - - if (!collection.isEmpty()) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.tracker.getId(), collection)); - } - - if (((EntityLiving) this.tracker).cP()) { - flag = true; - } - } - - this.n = this.tracker.motX; - this.o = this.tracker.motY; - this.p = this.tracker.motZ; - if (flag && !(packet instanceof PacketPlayOutSpawnEntityLiving)) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityVelocity(this.tracker.getId(), this.tracker.motX, this.tracker.motY, this.tracker.motZ)); - } - - if (this.tracker instanceof EntityLiving) { - EnumItemSlot[] aenumitemslot = EnumItemSlot.values(); - int i = aenumitemslot.length; - - for (int j = 0; j < i; ++j) { - EnumItemSlot enumitemslot = aenumitemslot[j]; - ItemStack itemstack = ((EntityLiving) this.tracker).getEquipment(enumitemslot); - - if (!itemstack.isEmpty()) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEquipment(this.tracker.getId(), enumitemslot, itemstack)); - } - } - } - - if (this.tracker instanceof EntityHuman) { - EntityHuman entityhuman = (EntityHuman) this.tracker; - - if (entityhuman.isSleeping()) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutBed(entityhuman, new BlockPosition(this.tracker))); - } - } - - // CraftBukkit start - Fix for nonsensical head yaw - this.headYaw = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F); - this.broadcast(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) headYaw)); - // CraftBukkit end - - if (this.tracker instanceof EntityLiving) { - EntityLiving entityliving = (EntityLiving) this.tracker; - Iterator iterator = entityliving.getEffects().iterator(); - - while (iterator.hasNext()) { - MobEffect mobeffect = (MobEffect) iterator.next(); - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(this.tracker.getId(), mobeffect)); - } - } - - if (!this.tracker.bF().isEmpty()) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutMount(this.tracker)); - } - - if (this.tracker.isPassenger()) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutMount(this.tracker.bJ())); - } - - this.tracker.b(entityplayer); - entityplayer.d(this.tracker); - updatePassengers(entityplayer); // Paper - } - } else if (this.trackedPlayers.contains(entityplayer)) { - this.trackedPlayers.remove(entityplayer); - this.tracker.c(entityplayer); - entityplayer.c(this.tracker); - updatePassengers(entityplayer); // Paper - } - - } - } - - public boolean c(EntityPlayer entityplayer) { - // Paper start - if (tracker.isPassenger()) { - return isTrackedBy(tracker.getVehicle(), entityplayer); - } else if (hasPassengerInRange(tracker, entityplayer)) { - return true; - } - - return isInRangeOfPlayer(entityplayer); - } - private static boolean hasPassengerInRange(Entity entity, EntityPlayer entityplayer) { - if (!entity.isVehicle()) { - return false; - } - for (Entity passenger : entity.passengers) { - if (passenger.tracker != null && passenger.tracker.isInRangeOfPlayer(entityplayer)) { - return true; - } - if (passenger.isVehicle()) { - if (hasPassengerInRange(passenger, entityplayer)) { - return true; - } - } - } - return false; - } - private static boolean isTrackedBy(Entity entity, EntityPlayer entityplayer) { - return entity == entityplayer || entity.tracker != null && entity.tracker.trackedPlayers.contains(entityplayer); - } - private void updatePassengers(EntityPlayer player) { - if (tracker.isVehicle()) { - tracker.passengers.forEach((e) -> { - if (e.tracker != null) { - e.tracker.updatePlayer(player); - } - }); - player.playerConnection.sendPacket(new PacketPlayOutMount(this.tracker)); - } - } - private boolean isInRangeOfPlayer(EntityPlayer entityplayer) { - // Paper end - double d0 = entityplayer.locX - (double) this.xLoc / 4096.0D; - double d1 = entityplayer.locZ - (double) this.zLoc / 4096.0D; - int i = Math.min(this.e, this.f); - - return d0 >= (double) (-i) && d0 <= (double) i && d1 >= (double) (-i) && d1 <= (double) i && this.tracker.a(entityplayer); - } - - private boolean e(EntityPlayer entityplayer) { - return entityplayer.x().getPlayerChunkMap().a(entityplayer, this.tracker.ab, this.tracker.ad); - } - - public void scanPlayers(List list) { - for (int i = 0; i < list.size(); ++i) { - this.updatePlayer((EntityPlayer) list.get(i)); - } - - } - - private Packet e() { - if (this.tracker.dead) { - // CraftBukkit start - Remove useless error spam, just return - // EntityTrackerEntry.d.warn("Fetching addPacket for removed entity"); - return null; - // CraftBukkit end - } - - if (this.tracker instanceof EntityPlayer) { - return new PacketPlayOutNamedEntitySpawn((EntityHuman) this.tracker); - } else if (this.tracker instanceof IAnimal) { - this.headYaw = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F); - return new PacketPlayOutSpawnEntityLiving((EntityLiving) this.tracker); - } else if (this.tracker instanceof EntityPainting) { - return new PacketPlayOutSpawnEntityPainting((EntityPainting) this.tracker); - } else if (this.tracker instanceof EntityItem) { - return new PacketPlayOutSpawnEntity(this.tracker, 2, 1); - } else if (this.tracker instanceof EntityMinecartAbstract) { - EntityMinecartAbstract entityminecartabstract = (EntityMinecartAbstract) this.tracker; - - return new PacketPlayOutSpawnEntity(this.tracker, 10, entityminecartabstract.v().a()); - } else if (this.tracker instanceof EntityBoat) { - return new PacketPlayOutSpawnEntity(this.tracker, 1); - } else if (this.tracker instanceof EntityExperienceOrb) { - return new PacketPlayOutSpawnEntityExperienceOrb((EntityExperienceOrb) this.tracker); - } else if (this.tracker instanceof EntityFishingHook) { - EntityHuman entityhuman = ((EntityFishingHook) this.tracker).l(); - - return new PacketPlayOutSpawnEntity(this.tracker, 90, entityhuman == null ? this.tracker.getId() : entityhuman.getId()); - } else { - Entity entity; - - if (this.tracker instanceof EntitySpectralArrow) { - entity = ((EntitySpectralArrow) this.tracker).shooter; - return new PacketPlayOutSpawnEntity(this.tracker, 91, 1 + (entity == null ? this.tracker.getId() : entity.getId())); - } else if (this.tracker instanceof EntityTippedArrow) { - entity = ((EntityArrow) this.tracker).shooter; - return new PacketPlayOutSpawnEntity(this.tracker, 60, 1 + (entity == null ? this.tracker.getId() : entity.getId())); - } else if (this.tracker instanceof EntitySnowball) { - return new PacketPlayOutSpawnEntity(this.tracker, 61); - } else if (this.tracker instanceof EntityLlamaSpit) { - return new PacketPlayOutSpawnEntity(this.tracker, 68); - } else if (this.tracker instanceof EntityPotion) { - return new PacketPlayOutSpawnEntity(this.tracker, 73); - } else if (this.tracker instanceof EntityThrownExpBottle) { - return new PacketPlayOutSpawnEntity(this.tracker, 75); - } else if (this.tracker instanceof EntityEnderPearl) { - return new PacketPlayOutSpawnEntity(this.tracker, 65); - } else if (this.tracker instanceof EntityEnderSignal) { - return new PacketPlayOutSpawnEntity(this.tracker, 72); - } else if (this.tracker instanceof EntityFireworks) { - return new PacketPlayOutSpawnEntity(this.tracker, 76); - } else if (this.tracker instanceof EntityFireball) { - EntityFireball entityfireball = (EntityFireball) this.tracker; - PacketPlayOutSpawnEntity packetplayoutspawnentity = null; - byte b0 = 63; - - if (this.tracker instanceof EntitySmallFireball) { - b0 = 64; - } else if (this.tracker instanceof EntityDragonFireball) { - b0 = 93; - } else if (this.tracker instanceof EntityWitherSkull) { - b0 = 66; - } - - if (entityfireball.shooter != null) { - packetplayoutspawnentity = new PacketPlayOutSpawnEntity(this.tracker, b0, ((EntityFireball) this.tracker).shooter.getId()); - } else { - packetplayoutspawnentity = new PacketPlayOutSpawnEntity(this.tracker, b0, 0); - } - - packetplayoutspawnentity.a((int) (entityfireball.dirX * 8000.0D)); - packetplayoutspawnentity.b((int) (entityfireball.dirY * 8000.0D)); - packetplayoutspawnentity.c((int) (entityfireball.dirZ * 8000.0D)); - return packetplayoutspawnentity; - } else if (this.tracker instanceof EntityShulkerBullet) { - PacketPlayOutSpawnEntity packetplayoutspawnentity1 = new PacketPlayOutSpawnEntity(this.tracker, 67, 0); - - packetplayoutspawnentity1.a((int) (this.tracker.motX * 8000.0D)); - packetplayoutspawnentity1.b((int) (this.tracker.motY * 8000.0D)); - packetplayoutspawnentity1.c((int) (this.tracker.motZ * 8000.0D)); - return packetplayoutspawnentity1; - } else if (this.tracker instanceof EntityEgg) { - return new PacketPlayOutSpawnEntity(this.tracker, 62); - } else if (this.tracker instanceof EntityEvokerFangs) { - return new PacketPlayOutSpawnEntity(this.tracker, 79); - } else if (this.tracker instanceof EntityTNTPrimed) { - return new PacketPlayOutSpawnEntity(this.tracker, 50); - } else if (this.tracker instanceof EntityEnderCrystal) { - return new PacketPlayOutSpawnEntity(this.tracker, 51); - } else if (this.tracker instanceof EntityFallingBlock) { - EntityFallingBlock entityfallingblock = (EntityFallingBlock) this.tracker; - - return new PacketPlayOutSpawnEntity(this.tracker, 70, Block.getCombinedId(entityfallingblock.getBlock())); - } else if (this.tracker instanceof EntityArmorStand) { - return new PacketPlayOutSpawnEntity(this.tracker, 78); - } else if (this.tracker instanceof EntityItemFrame) { - EntityItemFrame entityitemframe = (EntityItemFrame) this.tracker; - - return new PacketPlayOutSpawnEntity(this.tracker, 71, entityitemframe.direction.get2DRotationValue(), entityitemframe.getBlockPosition()); - } else if (this.tracker instanceof EntityLeash) { - EntityLeash entityleash = (EntityLeash) this.tracker; - - return new PacketPlayOutSpawnEntity(this.tracker, 77, 0, entityleash.getBlockPosition()); - } else if (this.tracker instanceof EntityAreaEffectCloud) { - return new PacketPlayOutSpawnEntity(this.tracker, 3); - } else { - throw new IllegalArgumentException("Don\'t know how to add " + this.tracker.getClass() + "!"); - } - } - } - - public void clear(EntityPlayer entityplayer) { - org.spigotmc.AsyncCatcher.catchOp( "player tracker clear"); // Spigot - if (this.trackedPlayers.contains(entityplayer)) { - this.trackedPlayers.remove(entityplayer); - this.tracker.c(entityplayer); - entityplayer.c(this.tracker); - updatePassengers(entityplayer); // Paper - } - - } - - public Entity b() { - return this.tracker; - } - - public void a(int i) { - this.f = i; - } - - public void c() { - this.isMoving = false; - } -} diff --git a/sources/src/main/java/net/minecraft/server/EnumDirection.java b/sources/src/main/java/net/minecraft/server/EnumDirection.java deleted file mode 100644 index 141e1c302..000000000 --- a/sources/src/main/java/net/minecraft/server/EnumDirection.java +++ /dev/null @@ -1,317 +0,0 @@ -package net.minecraft.server; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterators; -import com.google.common.collect.Maps; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import javax.annotation.Nullable; - -/** - * Akarin Changes Note - * 1) Add OBFHELPER (panda redstone) - */ -public enum EnumDirection implements INamable { - - DOWN(0, 1, -1, "down", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.Y, new BaseBlockPosition(0, -1, 0)), UP(1, 0, -1, "up", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.Y, new BaseBlockPosition(0, 1, 0)), NORTH(2, 3, 2, "north", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.Z, new BaseBlockPosition(0, 0, -1)), SOUTH(3, 2, 0, "south", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.Z, new BaseBlockPosition(0, 0, 1)), WEST(4, 5, 1, "west", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.X, new BaseBlockPosition(-1, 0, 0)), EAST(5, 4, 3, "east", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.X, new BaseBlockPosition(1, 0, 0)); - - private final int g; - private final int h; - private final int i; - private final String j; - private final EnumDirection.EnumAxis k; - private final EnumDirection.EnumAxisDirection l; - private final BaseBlockPosition m; public BaseBlockPosition getDirectionPosition() { return m; } // Akarin - OBFHELPER - private static final EnumDirection[] n = new EnumDirection[6]; - private static final EnumDirection[] o = new EnumDirection[4]; - private static final Map p = Maps.newHashMap(); - - private EnumDirection(int i, int j, int k, String s, EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis, BaseBlockPosition baseblockposition) { - this.g = i; - this.i = k; - this.h = j; - this.j = s; - this.k = enumdirection_enumaxis; - this.l = enumdirection_enumaxisdirection; - this.m = baseblockposition; - } - - public int a() { - return this.g; - } - - public int get2DRotationValue() { - return this.i; - } - - public EnumDirection.EnumAxisDirection c() { - return this.l; - } - - public EnumDirection opposite() { - return fromType1(this.h); - } - - public EnumDirection e() { - switch (this) { - case NORTH: - return EnumDirection.EAST; - - case EAST: - return EnumDirection.SOUTH; - - case SOUTH: - return EnumDirection.WEST; - - case WEST: - return EnumDirection.NORTH; - - default: - throw new IllegalStateException("Unable to get Y-rotated facing of " + this); - } - } - - public EnumDirection f() { - switch (this) { - case NORTH: - return EnumDirection.WEST; - - case EAST: - return EnumDirection.NORTH; - - case SOUTH: - return EnumDirection.EAST; - - case WEST: - return EnumDirection.SOUTH; - - default: - throw new IllegalStateException("Unable to get CCW facing of " + this); - } - } - - public int getAdjacentX() { - return this.k == EnumDirection.EnumAxis.X ? this.l.a() : 0; - } - - public int getAdjacentY() { - return this.k == EnumDirection.EnumAxis.Y ? this.l.a() : 0; - } - - public int getAdjacentZ() { - return this.k == EnumDirection.EnumAxis.Z ? this.l.a() : 0; - } - - public String j() { - return this.j; - } - - public EnumDirection.EnumAxis getAxis() { return k(); } // Akarin - OBFHELPER - public EnumDirection.EnumAxis k() { - return this.k; - } - - public static EnumDirection fromType1(int i) { - return EnumDirection.n[MathHelper.a(i % EnumDirection.n.length)]; - } - - public static EnumDirection fromType2(int i) { - return EnumDirection.o[MathHelper.a(i % EnumDirection.o.length)]; - } - - public static EnumDirection fromAngle(double d0) { - return fromType2(MathHelper.floor(d0 / 90.0D + 0.5D) & 3); - } - - public float l() { - return (this.i & 3) * 90; - } - - public static EnumDirection a(Random random) { - return values()[random.nextInt(values().length)]; - } - - @Override - public String toString() { - return this.j; - } - - @Override - public String getName() { - return this.j; - } - - public static EnumDirection a(EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis) { - EnumDirection[] aenumdirection = values(); - int i = aenumdirection.length; - - for (int j = 0; j < i; ++j) { - EnumDirection enumdirection = aenumdirection[j]; - - if (enumdirection.c() == enumdirection_enumaxisdirection && enumdirection.k() == enumdirection_enumaxis) { - return enumdirection; - } - } - - throw new IllegalArgumentException("No such direction: " + enumdirection_enumaxisdirection + " " + enumdirection_enumaxis); - } - - public static EnumDirection a(BlockPosition blockposition, EntityLiving entityliving) { - if (Math.abs(entityliving.locX - (blockposition.getX() + 0.5F)) < 2.0D && Math.abs(entityliving.locZ - (blockposition.getZ() + 0.5F)) < 2.0D) { - double d0 = entityliving.locY + entityliving.getHeadHeight(); - - if (d0 - blockposition.getY() > 2.0D) { - return EnumDirection.UP; - } - - if (blockposition.getY() - d0 > 0.0D) { - return EnumDirection.DOWN; - } - } - - return entityliving.getDirection().opposite(); - } - - static { - EnumDirection[] aenumdirection = values(); - int i = aenumdirection.length; - - for (int j = 0; j < i; ++j) { - EnumDirection enumdirection = aenumdirection[j]; - - EnumDirection.n[enumdirection.g] = enumdirection; - if (enumdirection.k().c()) { - EnumDirection.o[enumdirection.i] = enumdirection; - } - - EnumDirection.p.put(enumdirection.j().toLowerCase(Locale.ROOT), enumdirection); - } - - } - - public static enum EnumDirectionLimit implements Predicate, Iterable { - - HORIZONTAL, VERTICAL; - - private EnumDirectionLimit() {} - - public EnumDirection[] a() { - switch (this) { - case HORIZONTAL: - return new EnumDirection[] { EnumDirection.NORTH, EnumDirection.EAST, EnumDirection.SOUTH, EnumDirection.WEST}; - - case VERTICAL: - return new EnumDirection[] { EnumDirection.UP, EnumDirection.DOWN}; - - default: - throw new Error("Someone\'s been tampering with the universe!"); - } - } - - public EnumDirection a(Random random) { - EnumDirection[] aenumdirection = this.a(); - - return aenumdirection[random.nextInt(aenumdirection.length)]; - } - - public boolean a(@Nullable EnumDirection enumdirection) { - return enumdirection != null && enumdirection.k().d() == this; - } - - @Override - public Iterator iterator() { - return Iterators.forArray(this.a()); - } - - @Override - public boolean apply(@Nullable EnumDirection object) { - return this.a(object); - } - } - - public static enum EnumAxisDirection { - - POSITIVE(1, "Towards positive"), NEGATIVE(-1, "Towards negative"); - - private final int c; - private final String d; - - private EnumAxisDirection(int i, String s) { - this.c = i; - this.d = s; - } - - public int a() { - return this.c; - } - - @Override - public String toString() { - return this.d; - } - } - - public static enum EnumAxis implements Predicate, INamable { - - X("x", EnumDirection.EnumDirectionLimit.HORIZONTAL), Y("y", EnumDirection.EnumDirectionLimit.VERTICAL), Z("z", EnumDirection.EnumDirectionLimit.HORIZONTAL); - - private static final Map d = Maps.newHashMap(); - private final String e; - private final EnumDirection.EnumDirectionLimit f; - - private EnumAxis(String s, EnumDirection.EnumDirectionLimit enumdirection_enumdirectionlimit) { - this.e = s; - this.f = enumdirection_enumdirectionlimit; - } - - public String a() { - return this.e; - } - - public boolean b() { - return this.f == EnumDirection.EnumDirectionLimit.VERTICAL; - } - - public boolean isHorizontal() { return c(); } // Akarin - OBFHELPER - public boolean c() { - return this.f == EnumDirection.EnumDirectionLimit.HORIZONTAL; - } - - @Override - public String toString() { - return this.e; - } - - public boolean a(@Nullable EnumDirection enumdirection) { - return enumdirection != null && enumdirection.k() == this; - } - - public EnumDirection.EnumDirectionLimit d() { - return this.f; - } - - @Override - public String getName() { - return this.e; - } - - @Override - public boolean apply(@Nullable EnumDirection object) { - return this.a(object); - } - - static { - EnumDirection.EnumAxis[] aenumdirection_enumaxis = values(); - int i = aenumdirection_enumaxis.length; - - for (int j = 0; j < i; ++j) { - EnumDirection.EnumAxis enumdirection_enumaxis = aenumdirection_enumaxis[j]; - - EnumDirection.EnumAxis.d.put(enumdirection_enumaxis.a().toLowerCase(Locale.ROOT), enumdirection_enumaxis); - } - - } - } -} diff --git a/sources/src/main/java/net/minecraft/server/FileIOThread.java b/sources/src/main/java/net/minecraft/server/FileIOThread.java new file mode 100644 index 000000000..366b2951d --- /dev/null +++ b/sources/src/main/java/net/minecraft/server/FileIOThread.java @@ -0,0 +1,82 @@ +package net.minecraft.server; + +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** + * Akarin Changes Note + * 1) Multi-threaded chunk saving (performance) + */ +public class FileIOThread implements Runnable { + + private static final Logger a = LogManager.getLogger(); + private static final FileIOThread b = new FileIOThread(); + private final List c = /*Collections.synchronizedList(Lists.newArrayList())*/ null; // Akarin - I don't think any plugin rely on this + private volatile long d; + private volatile long e; + private volatile boolean f; + + private FileIOThread() { + // Thread thread = new Thread(this, "File IO Thread"); // Akarin + + // thread.setUncaughtExceptionHandler(new ThreadNamedUncaughtExceptionHandler(FileIOThread.a)); // Akarin + // thread.setPriority(1); // Akarin + // thread.start(); // Akarin + } + + public static FileIOThread a() { + return FileIOThread.b; + } + + public void run() { + while (true) { + this.c(); + } + } + + private void c() { + for (int i = 0; i < this.c.size(); ++i) { + IAsyncChunkSaver iasyncchunksaver = (IAsyncChunkSaver) this.c.get(i); + boolean flag = iasyncchunksaver.a(); + + if (!flag) { + this.c.remove(i--); + ++this.e; + } + + if (com.destroystokyo.paper.PaperConfig.enableFileIOThreadSleep) { // Paper + try { + Thread.sleep(this.f ? 0L : 1L); // Paper + } catch (InterruptedException interruptedexception) { + interruptedexception.printStackTrace(); + }} // Paper + } + + if (this.c.isEmpty()) { + try { + Thread.sleep(25L); + } catch (InterruptedException interruptedexception1) { + interruptedexception1.printStackTrace(); + } + } + + } + + public void a(IAsyncChunkSaver iasyncchunksaver) { + if (!this.c.contains(iasyncchunksaver)) { + ++this.d; + this.c.add(iasyncchunksaver); + } + } + + public void b() throws InterruptedException { + this.f = true; + + while (this.d != this.e) { + Thread.sleep(10L); + } + + this.f = false; + } +} diff --git a/sources/src/main/java/net/minecraft/server/ItemEnderEye.java b/sources/src/main/java/net/minecraft/server/ItemEnderEye.java index 57bab9f03..0a382120a 100644 --- a/sources/src/main/java/net/minecraft/server/ItemEnderEye.java +++ b/sources/src/main/java/net/minecraft/server/ItemEnderEye.java @@ -8,37 +8,40 @@ import io.akarin.server.core.AkarinGlobalConfig; */ public class ItemEnderEye extends Item { - public ItemEnderEye() { - this.b(CreativeModeTab.f); + public ItemEnderEye(Item.Info item_info) { + super(item_info); } - @Override - public EnumInteractionResult a(EntityHuman entityhuman, World world, BlockPosition blockposition, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) { + public EnumInteractionResult a(ItemActionContext itemactioncontext) { + World world = itemactioncontext.getWorld(); + BlockPosition blockposition = itemactioncontext.getClickPosition(); IBlockData iblockdata = world.getType(blockposition); - ItemStack itemstack = entityhuman.b(enumhand); - if (entityhuman.a(blockposition.shift(enumdirection), enumdirection, itemstack) && iblockdata.getBlock() == Blocks.END_PORTAL_FRAME && !iblockdata.get(BlockEnderPortalFrame.EYE).booleanValue()) { + if (iblockdata.getBlock() == Blocks.END_PORTAL_FRAME && !((Boolean) iblockdata.get(BlockEnderPortalFrame.EYE)).booleanValue()) { if (world.isClientSide) { return EnumInteractionResult.SUCCESS; } else { - world.setTypeAndData(blockposition, iblockdata.set(BlockEnderPortalFrame.EYE, Boolean.valueOf(true)), 2); + IBlockData iblockdata1 = (IBlockData) iblockdata.set(BlockEnderPortalFrame.EYE, Boolean.valueOf(true)); + + Block.a(iblockdata, iblockdata1, (GeneratorAccess) world, blockposition); + world.setTypeAndData(blockposition, iblockdata1, 2); world.updateAdjacentComparators(blockposition, Blocks.END_PORTAL_FRAME); - itemstack.subtract(1); + itemactioncontext.getItemStack().subtract(1); for (int i = 0; i < 16; ++i) { - double d0 = blockposition.getX() + (5.0F + ItemEnderEye.j.nextFloat() * 6.0F) / 16.0F; - double d1 = blockposition.getY() + 0.8125F; - double d2 = blockposition.getZ() + (5.0F + ItemEnderEye.j.nextFloat() * 6.0F) / 16.0F; + double d0 = (double) ((float) blockposition.getX() + (5.0F + ItemEnderEye.k.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 d3 = 0.0D; double d4 = 0.0D; double d5 = 0.0D; - world.addParticle(EnumParticle.SMOKE_NORMAL, d0, d1, d2, 0.0D, 0.0D, 0.0D, new int[0]); + world.addParticle(Particles.M, d0, d1, d2, 0.0D, 0.0D, 0.0D); } - world.a((EntityHuman) null, blockposition, SoundEffects.bp, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.a((EntityHuman) null, blockposition, SoundEffects.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.BLOCKS, 1.0F, 1.0F); if (AkarinGlobalConfig.disableEndPortalCreate) return EnumInteractionResult.SUCCESS; // Akarin - ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = BlockEnderPortalFrame.e().a(world, blockposition); + ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = BlockEnderPortalFrame.d().a(world, blockposition); if (shapedetector_shapedetectorcollection != null) { BlockPosition blockposition1 = shapedetector_shapedetectorcollection.a().a(-3, 0, -3); @@ -55,11 +58,10 @@ public class ItemEnderEye extends Item { return EnumInteractionResult.SUCCESS; } } else { - return EnumInteractionResult.FAIL; + return EnumInteractionResult.PASS; } } - @Override public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { ItemStack itemstack = entityhuman.b(enumhand); MovingObjectPosition movingobjectposition = this.a(world, entityhuman, false); @@ -69,24 +71,24 @@ public class ItemEnderEye extends Item { } else { entityhuman.c(enumhand); if (!world.isClientSide) { - BlockPosition blockposition = ((WorldServer) world).getChunkProviderServer().a(world, "Stronghold", new BlockPosition(entityhuman), false); + BlockPosition blockposition = ((WorldServer) world).getChunkProviderServer().a(world, "Stronghold", new BlockPosition(entityhuman), 100); if (blockposition != null) { - EntityEnderSignal entityendersignal = new EntityEnderSignal(world, entityhuman.locX, entityhuman.locY + entityhuman.length / 2.0F, entityhuman.locZ); + EntityEnderSignal entityendersignal = new EntityEnderSignal(world, entityhuman.locX, entityhuman.locY + (double) (entityhuman.length / 2.0F), entityhuman.locZ); entityendersignal.a(blockposition); world.addEntity(entityendersignal); if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.l.a((EntityPlayer) entityhuman, blockposition); + CriterionTriggers.m.a((EntityPlayer) entityhuman, blockposition); } - world.a((EntityHuman) null, entityhuman.locX, entityhuman.locY, entityhuman.locZ, SoundEffects.bc, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderEye.j.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.k.nextFloat() * 0.4F + 0.8F)); world.a((EntityHuman) null, 1003, new BlockPosition(entityhuman), 0); if (!entityhuman.abilities.canInstantlyBuild) { itemstack.subtract(1); } - entityhuman.b(StatisticList.b(this)); + entityhuman.b(StatisticList.ITEM_USED.b(this)); return new InteractionResultWrapper(EnumInteractionResult.SUCCESS, itemstack); } } diff --git a/sources/src/main/java/net/minecraft/server/MinecraftServer.java b/sources/src/main/java/net/minecraft/server/MinecraftServer.java index d2f7ecd79..3b09dc145 100644 --- a/sources/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/sources/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1,37 +1,49 @@ package net.minecraft.server; +import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.gson.JsonElement; import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfileRepository; import com.mojang.authlib.minecraft.MinecraftSessionService; import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +import com.mojang.datafixers.DataFixer; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; -import io.netty.handler.codec.base64.Base64; -import java.awt.GraphicsEnvironment; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.Proxy; import java.net.URLEncoder; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Queue; import java.util.Random; +import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import javax.annotation.Nullable; import javax.imageio.ImageIO; import org.apache.commons.lang3.Validate; @@ -47,63 +59,76 @@ import co.aikar.timings.MinecraftTimings; // Paper * Akarin Changes Note * 1) Make worlds list thread-safe (slack service) */ -public abstract class MinecraftServer implements ICommandListener, Runnable, IAsyncTaskHandler, IMojangStatistics { +public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStatistics, ICommandListener, Runnable { private static MinecraftServer SERVER; // Paper public static final Logger LOGGER = LogManager.getLogger(); public static final File a = new File("usercache.json"); public Convertable convertable; - private final MojangStatisticsGenerator m = new MojangStatisticsGenerator("server", this, aw()); + private final MojangStatisticsGenerator j = new MojangStatisticsGenerator("server", this, SystemUtils.b()); public File universe; - private final List o = Lists.newArrayList(); - public final ICommandHandler b; + private final List l = Lists.newArrayList(); public final MethodProfiler methodProfiler = new MethodProfiler(); - private ServerConnection p; // Spigot - private final ServerPing q = new ServerPing(); - private final Random r = new Random(); - public final DataConverterManager dataConverterManager; + private ServerConnection m; // Spigot + private final ServerPing n = new ServerPing(); + private final Random o = new Random(); + public final DataFixer dataConverterManager; private String serverIp; - private int u = -1; + private int r = -1; public WorldServer[] worldServer; - private PlayerList v; + private PlayerList s; private boolean isRunning = true; private boolean isRestarting = false; // Paper - flag to signify we're attempting to restart private boolean isStopped; private int ticks; - protected final Proxy e; - public String f; - public int g; + protected final Proxy d; + private IChatBaseComponent w; + private int x; private boolean onlineMode; - private boolean A; + private boolean z; private boolean spawnAnimals; private boolean spawnNPCs; private boolean pvpMode; private boolean allowFlight; private String motd; + private int F; private int G; - private int H; - public final long[] h = new long[100]; - public long[][] i; - private KeyPair I; + public final long[] e = new long[100]; + public long[][] f; + private KeyPair H; + private String I; private String J; - private String K; private boolean demoMode; - private boolean N; + private boolean M; + private String N = ""; private String O = ""; - private String P = ""; - private boolean Q; - private long R; - private String S; + private boolean P; + private long Q; + private IChatBaseComponent R; + private boolean S; private boolean T; - private boolean U; - private final YggdrasilAuthenticationService V; - private final MinecraftSessionService W; - private final GameProfileRepository X; - private final UserCache Y; - private long Z; - protected final Queue> j = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Spigot, PAIL: Rename // Paper - Make size() constant-time + private final YggdrasilAuthenticationService U; + private final MinecraftSessionService V; + private final GameProfileRepository W; + private final UserCache X; + private long Y; + protected final Queue> g = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Spigot, PAIL: Rename // Paper - Make size() constant-time private Thread serverThread; - private long ab = aw(); + private long aa = SystemUtils.b(); + private final IReloadableResourceManager ac; + private final ResourcePackRepository resourcePackRepository; + private ResourcePackSourceFolder resourcePackFolder; + public CommandDispatcher commandDispatcher; + private final CraftingManager ag; + private final TagRegistry ah; + private final ScoreboardServer ai; + private final BossBattleCustomData aj; + private final LootTableRegistry ak; + private final AdvancementDataWorld al; + private final CustomFunctionData am; + private boolean an; + private boolean forceUpgrade; + private float ap; // CraftBukkit start public List worlds = Lists.newCopyOnWriteArrayList(); // new ArrayList(); // Akarin @@ -113,28 +138,44 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs public org.bukkit.command.RemoteConsoleCommandSender remoteConsole; //public ConsoleReader reader; // Paper public static int currentTick = 0; // Paper - Further improve tick loop + public boolean serverAutoSave = false; // Paper public final Thread primaryThread; public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; - public boolean serverAutoSave = false; // Paper + public File bukkitDataPackFolder; + public CommandDispatcher vanillaCommandDispatcher; // CraftBukkit end // Spigot start public final SlackActivityAccountant slackActivityAccountant = new SlackActivityAccountant(); // Spigot end - public MinecraftServer(OptionSet options, Proxy proxy, DataConverterManager dataconvertermanager, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache) { + public MinecraftServer(OptionSet options, Proxy proxy, DataFixer datafixer, CommandDispatcher commanddispatcher, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache) { SERVER = this; // Paper - better singleton - io.netty.util.ResourceLeakDetector.setEnabled( false ); // Spigot - disable - this.e = proxy; - this.V = yggdrasilauthenticationservice; - this.W = minecraftsessionservice; - this.X = gameprofilerepository; - this.Y = usercache; + this.commandDispatcher = commanddispatcher; // CraftBukkit + this.ac = new ResourceManager(EnumResourcePackType.SERVER_DATA); + this.resourcePackRepository = new ResourcePackRepository(ResourcePackLoader::new); + this.ag = new CraftingManager(); + this.ah = new TagRegistry(); + this.ai = new ScoreboardServer(this); + this.aj = new BossBattleCustomData(this); + this.ak = new LootTableRegistry(); + this.al = new AdvancementDataWorld(); + this.am = new CustomFunctionData(this); + this.d = proxy; + this.commandDispatcher = this.vanillaCommandDispatcher = commanddispatcher; // CraftBukkit + this.U = yggdrasilauthenticationservice; + this.V = minecraftsessionservice; + this.W = gameprofilerepository; + this.X = usercache; // this.universe = file; // CraftBukkit - // this.p = new ServerConnection(this); // Spigot - this.b = this.i(); - // this.convertable = new WorldLoaderServer(file); // CraftBukkit - moved to DedicatedServer.init - this.dataConverterManager = dataconvertermanager; + // this.m = new ServerConnection(this); // CraftBukkit // Spigot + // this.convertable = file == null ? null : new WorldLoaderServer(file.toPath(), file.toPath().resolve("../backups"), datafixer); // CraftBukkit - moved to DedicatedServer.init + this.dataConverterManager = datafixer; + this.ac.a((IResourcePackListener) this.ah); + this.ac.a((IResourcePackListener) this.ag); + this.ac.a((IResourcePackListener) this.ak); + this.ac.a((IResourcePackListener) this.am); + this.ac.a((IResourcePackListener) this.al); // CraftBukkit start this.options = options; // Paper start - Handled by TerminalConsoleAppender @@ -170,61 +211,91 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs public abstract PropertyManager getPropertyManager(); // CraftBukkit end - protected CommandDispatcher i() { - return new CommandDispatcher(this); - } - public abstract boolean init() throws IOException; - protected void a(String s) { + public void convertWorld(String s) { if (this.getConvertable().isConvertable(s)) { MinecraftServer.LOGGER.info("Converting map!"); - this.b("menu.convertingLevel"); + this.b((IChatBaseComponent) (new ChatMessage("menu.convertingLevel", new Object[0]))); this.getConvertable().convert(s, new IProgressUpdate() { - private long b = System.currentTimeMillis(); + private long b = SystemUtils.b(); - @Override - public void a(String s) {} + public void a(IChatBaseComponent ichatbasecomponent) {} - @Override public void a(int i) { - if (System.currentTimeMillis() - this.b >= 1000L) { - this.b = System.currentTimeMillis(); + if (SystemUtils.b() - this.b >= 1000L) { + this.b = SystemUtils.b(); MinecraftServer.LOGGER.info("Converting... {}%", Integer.valueOf(i)); } } - @Override - public void c(String s) {} + public void c(IChatBaseComponent ichatbasecomponent) {} }); } + if (this.forceUpgrade) { + MinecraftServer.LOGGER.info("Forcing world upgrade! {}", s); // CraftBukkit + WorldData worlddata = this.getConvertable().c(s); // CraftBukkit + + if (worlddata != null) { + WorldUpgrader worldupgrader = new WorldUpgrader(s, this.getConvertable(), worlddata); // CraftBukkit + IChatBaseComponent ichatbasecomponent = null; + + while (!worldupgrader.b()) { + IChatBaseComponent ichatbasecomponent1 = worldupgrader.m(); + + if (ichatbasecomponent != ichatbasecomponent1) { + ichatbasecomponent = ichatbasecomponent1; + MinecraftServer.LOGGER.info(worldupgrader.m().getString()); + } + + int i = worldupgrader.j(); + + if (i > 0) { + int j = worldupgrader.k() + worldupgrader.l(); + + MinecraftServer.LOGGER.info("{}% completed ({} / {} chunks)...", Integer.valueOf(MathHelper.d((float) j / (float) i * 100.0F)), Integer.valueOf(j), Integer.valueOf(i)); + } + + if (this.isStopped()) { + worldupgrader.a(); + } else { + try { + Thread.sleep(1000L); + } catch (InterruptedException interruptedexception) { + ; + } + } + } + } + } + } - protected synchronized void b(String s) { - this.S = s; + protected synchronized void b(IChatBaseComponent ichatbasecomponent) { + this.R = ichatbasecomponent; } - public void a(String s, String s1, long i, WorldType worldtype, String s2) { - this.a(s); - this.b("menu.loadingLevel"); + public void a(String s, String s1, long i, WorldType worldtype, JsonElement jsonelement) { + // this.convertWorld(s); // CraftBukkit - moved down + this.b((IChatBaseComponent) (new ChatMessage("menu.loadingLevel", new Object[0]))); this.worldServer = new WorldServer[3]; /* CraftBukkit start - Remove ticktime arrays and worldsettings - this.i = new long[this.worldServer.length][100]; - IDataManager idatamanager = this.convertable.a(s, true); + this.f = new long[this.worldServer.length][100]; + IDataManager idatamanager = this.convertable.a(s, this); - this.a(this.S(), idatamanager); + this.a(this.getWorld(), idatamanager); WorldData worlddata = idatamanager.getWorldData(); WorldSettings worldsettings; if (worlddata == null) { - if (this.V()) { + if (this.N()) { worldsettings = DemoWorldServer.a; } else { worldsettings = new WorldSettings(i, this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype); - worldsettings.setGeneratorSettings(s2); - if (this.N) { + worldsettings.setGeneratorSettings(jsonelement); + if (this.M) { worldsettings.a(); } } @@ -234,11 +305,14 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs worlddata.a(s1); worldsettings = new WorldSettings(worlddata); } + + this.a(idatamanager.getDirectory(), worlddata); */ int worldCount = 3; for (int j = 0; j < worldCount; ++j) { WorldServer world; + WorldData worlddata; byte dimension = 0; if (j == 1) { @@ -259,19 +333,21 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs String worldType = org.bukkit.World.Environment.getEnvironment(dimension).toString().toLowerCase(); String name = (dimension == 0) ? s : s + "_" + worldType; + this.convertWorld(name); // Run conversion now org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); WorldSettings worldsettings = new WorldSettings(i, this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype); - worldsettings.setGeneratorSettings(s2); + worldsettings.setGeneratorSettings(jsonelement); if (j == 0) { - IDataManager idatamanager = new ServerNBTManager(server.getWorldContainer(), s1, true, this.dataConverterManager); - WorldData worlddata = idatamanager.getWorldData(); + IDataManager idatamanager = new ServerNBTManager(server.getWorldContainer(), s1, this, this.dataConverterManager); + worlddata = idatamanager.getWorldData(); if (worlddata == null) { worlddata = new WorldData(worldsettings, s1); } worlddata.checkName(s1); // 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) - if (this.V()) { + this.a(idatamanager.getDirectory(), worlddata); + if (this.N()) { world = (WorldServer) (new DemoWorldServer(this, idatamanager, worlddata, dimension, this.methodProfiler)).b(); } else { world = (WorldServer) (new WorldServer(this, idatamanager, worlddata, dimension, this.methodProfiler, org.bukkit.World.Environment.getEnvironment(dimension), gen)).b(); @@ -315,9 +391,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } } - IDataManager idatamanager = new ServerNBTManager(server.getWorldContainer(), name, true, this.dataConverterManager); + IDataManager idatamanager = new ServerNBTManager(server.getWorldContainer(), name, this, this.dataConverterManager); // world =, b0 to dimension, s1 to name, added Environment and gen - WorldData worlddata = idatamanager.getWorldData(); + worlddata = idatamanager.getWorldData(); if (worlddata == null) { worlddata = new WorldData(worldsettings, name); } @@ -328,71 +404,137 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(world.getWorld())); world.addIWorldAccess(new WorldManager(this, world)); - if (!this.R()) { + if (!this.J()) { world.getWorldData().setGameType(this.getGamemode()); } worlds.add(world); getPlayerList().setPlayerFileData(worlds.toArray(new WorldServer[worlds.size()])); + + if (worlddata.P() != null) { + this.aR().a(worlddata.P()); + } } + this.s.setPlayerFileData(this.worldServer); // CraftBukkit end - this.v.setPlayerFileData(this.worldServer); + this.a(this.getDifficulty()); - this.l(); + this.g_(); // Paper start - Handle collideRule team for player collision toggle - final Scoreboard scoreboard = this.getWorld().getScoreboard(); + final Scoreboard scoreboard = this.getScoreboard(); final java.util.Collection toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(ScoreboardTeam::getName).collect(java.util.stream.Collectors.toList()); for (String teamName : toRemove) { scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves } if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { - this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + this.getWorld().random.nextInt(), 16); + this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + worlds.get(0).random.nextInt(), 16); ScoreboardTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); collideTeam.setCanSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all } // Paper end } - protected void l() { + protected void a(File file, WorldData worlddata) { + this.resourcePackRepository.a((ResourcePackSource) (new ResourcePackSourceVanilla())); + this.resourcePackFolder = new ResourcePackSourceFolder(new File(file, "datapacks")); + // CraftBukkit start + bukkitDataPackFolder = new File(new File(file, "datapacks"), "bukkit"); + if (!bukkitDataPackFolder.exists()) { + bukkitDataPackFolder.mkdirs(); + } + File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); + if (!mcMeta.exists()) { + try { + com.google.common.io.Files.write("{\n" + + " \"pack\": {\n" + + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" + + " \"pack_format\": 1\n" + + " }\n" + + "}", mcMeta, com.google.common.base.Charsets.UTF_8); + } catch (IOException ex) { + throw new RuntimeException("Could not initialize Bukkit datapack", ex); + } + } + // CraftBukkit end + this.resourcePackRepository.a((ResourcePackSource) this.resourcePackFolder); + this.resourcePackRepository.a(); + ArrayList arraylist = Lists.newArrayList(); + Iterator iterator = worlddata.O().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + ResourcePackLoader resourcepackloader = this.resourcePackRepository.a(s); + + if (resourcepackloader != null) { + arraylist.add(resourcepackloader); + } else { + MinecraftServer.LOGGER.warn("Missing data pack {}", s); + } + } + + this.resourcePackRepository.a((Collection) arraylist); + this.a(worlddata); + } + + protected void g_() { boolean flag = true; boolean flag1 = true; boolean flag2 = true; boolean flag3 = true; - int i = 0; + boolean flag4 = true; - this.b("menu.generatingTerrain"); - boolean flag4 = false; + this.b((IChatBaseComponent) (new ChatMessage("menu.generatingTerrain", new Object[0]))); + boolean flag5 = false; // CraftBukkit start - fire WorldLoadEvent and handle whether or not to keep the spawn in memory + Stopwatch stopwatch = Stopwatch.createStarted(); for (int m = 0; m < worlds.size(); m++) { WorldServer worldserver = this.worlds.get(m); MinecraftServer.LOGGER.info("Preparing start region for level " + m + " (Seed: " + worldserver.getSeed() + ")"); - if (!worldserver.getWorld().getKeepSpawnInMemory()) { continue; } BlockPosition blockposition = worldserver.getSpawn(); - long j = aw(); - i = 0; + ArrayList arraylist = Lists.newArrayList(); + Set set = Sets.newConcurrentHashSet(); // Paper start short radius = worldserver.paperConfig.keepLoadedRange; - for (int k = -radius; k <= radius && this.isRunning(); k += 16) { - for (int l = -radius; l <= radius && this.isRunning(); l += 16) { - // Paper end - long i1 = aw(); - - if (i1 - j > 1000L) { - this.a_("Preparing spawn area", i * 100 / 625); - j = i1; - } - - ++i; - worldserver.getChunkProviderServer().getChunkAt(blockposition.getX() + k >> 4, blockposition.getZ() + l >> 4); + for (int i = -radius; i <= radius && this.isRunning(); i += 16) { + for (int j = -radius; j <= radius && this.isRunning(); j += 16) { + // Paper end + arraylist.add(new ChunkCoordIntPair(blockposition.getX() + i >> 4, blockposition.getZ() + j >> 4)); } + } // Paper + if (this.isRunning()) { // Paper + int expected = arraylist.size(); // Paper + + + CompletableFuture completablefuture = worldserver.getChunkProviderServer().a((Iterable) arraylist, (chunk) -> { + set.add(chunk.getPos()); + if (set.size() < expected && set.size() % 25 == 0) this.a(new ChatMessage("menu.preparingSpawn", new Object[0]), set.size() * 100 / expected); // Paper + }); + + while (!completablefuture.isDone()) { + try { + completablefuture.get(1L, TimeUnit.SECONDS); + } catch (InterruptedException interruptedexception) { + throw new RuntimeException(interruptedexception); + } catch (ExecutionException executionexception) { + if (executionexception.getCause() instanceof RuntimeException) { + throw (RuntimeException) executionexception.getCause(); + } + + throw new RuntimeException(executionexception.getCause()); + } catch (TimeoutException timeoutexception) { + this.a(new ChatMessage("menu.preparingSpawn", new Object[0]), set.size() * 100 / expected); // Paper + } + } + + this.a(new ChatMessage("menu.preparingSpawn", new Object[0]), set.size() * 100 / expected); // Paper } } @@ -400,7 +542,8 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(world.getWorld())); } // CraftBukkit end - this.t(); + this.m(); + MinecraftServer.LOGGER.info("Time elapsed: {} ms", Long.valueOf(stopwatch.elapsed(TimeUnit.MILLISECONDS))); } protected void a(String s, IDataManager idatamanager) { @@ -424,21 +567,19 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs public abstract boolean isHardcore(); - public abstract int q(); + public abstract int k(); - public abstract boolean r(); + public abstract boolean l(); - public abstract boolean s(); - - protected void a_(String s, int i) { - this.f = s; - this.g = i; - MinecraftServer.LOGGER.info("{}: {}%", s, Integer.valueOf(i)); + protected void a(IChatBaseComponent ichatbasecomponent, int i) { + this.w = ichatbasecomponent; + this.x = i; + MinecraftServer.LOGGER.info("{}: {}%", ichatbasecomponent.getString(), Integer.valueOf(i)); } - protected void t() { - this.f = null; - this.g = 0; + protected void m() { + this.w = null; + this.x = 0; this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); // CraftBukkit } @@ -458,7 +599,6 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs try { worldserver.save(true, (IProgressUpdate) null); - worldserver.saveLevel(); // CraftBukkit } catch (ExceptionWorldConflict exceptionworldconflict) { MinecraftServer.LOGGER.warn(exceptionworldconflict.getMessage()); } @@ -486,14 +626,14 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs this.server.disablePlugins(); } // CraftBukkit end - if (this.an() != null) { - this.an().b(); + if (this.getServerConnection() != null) { + this.getServerConnection().b(); } - if (this.v != null) { + if (this.s != null) { MinecraftServer.LOGGER.info("Saving players"); - this.v.savePlayers(); - this.v.u(isRestarting); + this.s.savePlayers(); + this.s.u(isRestarting);; try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets } @@ -505,8 +645,10 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs int j; WorldServer worldserver; - for (j = 0; j < i; ++j) { - worldserver = aworldserver[j]; + // CraftBukkit start + for (j = 0; j < worlds.size(); ++j) { + worldserver = worlds.get(j); + // CraftBukkit end if (worldserver != null) { worldserver.savingDisabled = false; } @@ -516,24 +658,24 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs aworldserver = this.worldServer; i = aworldserver.length; - /* CraftBukkit start - Handled in saveChunks - for (j = 0; j < i; ++j) { - worldserver = aworldserver[j]; + // CraftBukkit start + for (j = 0; j < worlds.size(); ++j) { + worldserver = worlds.get(j); + // CraftBukkit end if (worldserver != null) { - worldserver.saveLevel(); + worldserver.close(); } } - // CraftBukkit end */ } - if (this.m.d()) { - this.m.e(); + if (this.j.d()) { + this.j.e(); } // Spigot start if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) { LOGGER.info("Saving usercache.json"); - this.Y.c(false); // Paper + this.getUserCache().c(false); // Paper } // Spigot end } @@ -542,7 +684,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs return this.serverIp; } - public void c(String s) { + public void b(String s) { this.serverIp = s; } @@ -611,16 +753,13 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } // Paper End - @Override public void run() { try { if (this.init()) { - this.ab = aw(); - long i = 0L; - - this.q.setMOTD(new ChatComponentText(this.motd)); - this.q.setServerInfo(new ServerPing.ServerData("1.12.2", 340)); - this.a(this.q); + this.aa = SystemUtils.b(); + this.n.setMOTD(new ChatComponentText(this.motd)); + this.n.setServerInfo(new ServerPing.ServerData("1.13", 393)); + this.a(this.n); // Spigot start Arrays.fill( recentTps, 20 ); @@ -663,8 +802,10 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } lastTick = curTime; - this.C(); - this.Q = true; + MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit + this.v(); + this.aa += 50L; + this.P = true; } // Spigot end } else { @@ -678,7 +819,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs MinecraftServer.LOGGER.error( "\tCause of unexpected exception was", throwable.getCause() ); } // Spigot End - CrashReport crashreport = null; + CrashReport crashreport; if (throwable instanceof ReportedException) { crashreport = this.b(((ReportedException) throwable).a()); @@ -686,7 +827,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs crashreport = this.b(new CrashReport("Exception in server tick loop", throwable)); } - File file = new File(new File(this.A(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt"); + File file = new File(new File(this.t(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt"); if (crashreport.a(file)) { MinecraftServer.LOGGER.error("This crash report has been saved to: {}", file.getAbsolutePath()); @@ -709,7 +850,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } catch (Exception ignored) { } // CraftBukkit end - this.B(); + this.u(); } } @@ -717,10 +858,10 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } public void a(ServerPing serverping) { - File file = this.d("server-icon.png"); + File file = this.c("server-icon.png"); if (!file.exists()) { - file = this.getConvertable().b(this.S(), "icon.png"); + file = this.getConvertable().b(this.getWorld(), "icon.png"); } if (file.isFile()) { @@ -732,9 +873,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide", new Object[0]); Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high", new Object[0]); ImageIO.write(bufferedimage, "PNG", new ByteBufOutputStream(bytebuf)); - ByteBuf bytebuf1 = Base64.encode(bytebuf); + ByteBuffer bytebuffer = Base64.getEncoder().encode(bytebuf.nioBuffer()); - serverping.setFavicon("data:image/png;base64," + bytebuf1.toString(StandardCharsets.UTF_8)); + serverping.setFavicon("data:image/png;base64," + StandardCharsets.UTF_8.decode(bytebuffer)); } catch (Exception exception) { MinecraftServer.LOGGER.error("Couldn\'t load server icon", exception); } finally { @@ -744,40 +885,39 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } - public File A() { + public File t() { return new File("."); } protected void a(CrashReport crashreport) {} - public void B() {} + public void u() {} - protected void C() throws ExceptionWorldConflict { // CraftBukkit - added throws + protected void v() { co.aikar.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Paper this.slackActivityAccountant.tickStarted(); // Spigot - long i = System.nanoTime(); long startTime = i; // Paper + long i = SystemUtils.c(); long startTime = i; // Paper ++this.ticks; - if (this.T) { - this.T = false; - this.methodProfiler.a = true; - this.methodProfiler.a(); + if (this.S) { + this.S = false; + this.methodProfiler.a(this.ticks); } this.methodProfiler.a("root"); - this.D(); - if (i - this.Z >= 5000000000L) { - this.Z = i; - this.q.setPlayerSample(new ServerPing.ServerPingPlayerSample(this.I(), this.H())); - GameProfile[] agameprofile = new GameProfile[Math.min(this.H(), org.spigotmc.SpigotConfig.playerSample)]; // Paper - int j = MathHelper.nextInt(this.r, 0, this.H() - agameprofile.length); + this.w(); + if (i - this.Y >= 5000000000L) { + this.Y = i; + this.n.setPlayerSample(new ServerPing.ServerPingPlayerSample(this.B(), this.A())); + GameProfile[] agameprofile = new GameProfile[Math.min(this.A(), org.spigotmc.SpigotConfig.playerSample)]; // Paper + int j = MathHelper.nextInt(this.o, 0, this.A() - agameprofile.length); for (int k = 0; k < agameprofile.length; ++k) { - agameprofile[k] = this.v.v().get(j + k).getProfile(); + agameprofile[k] = ((EntityPlayer) this.s.v().get(j + k)).getProfile(); } Collections.shuffle(Arrays.asList(agameprofile)); - this.q.b().a(agameprofile); + this.n.b().a(agameprofile); } this.methodProfiler.a("save"); @@ -788,7 +928,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs playerSaveInterval = autosavePeriod; } if (playerSaveInterval > 0) { // CraftBukkit // Paper - this.v.savePlayers(playerSaveInterval); + this.s.savePlayers(playerSaveInterval); // Spigot Start } // Paper - Incremental Auto Saving @@ -802,50 +942,49 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs server.playerCommandState = false; // this.saveChunks(true); // Spigot End - this.methodProfiler.b(); + this.methodProfiler.e(); //} // Paper - Incremental Auto Saving - this.methodProfiler.a("tallying"); - // Spigot start - long tickNanos; - this.h[this.ticks % 100] = tickNanos = System.nanoTime() - i; - // Spigot end - this.methodProfiler.b(); this.methodProfiler.a("snooper"); - if (getSnooperEnabled() && !this.m.d() && this.ticks > 100) { // Spigot - this.m.a(); + if (getSnooperEnabled() && !this.j.d() && this.ticks > 100) { // Spigot + this.j.a(); } if (getSnooperEnabled() && this.ticks % 6000 == 0) { // Spigot - this.m.b(); + this.j.b(); } - this.methodProfiler.b(); - this.methodProfiler.b(); + this.methodProfiler.e(); + this.methodProfiler.a("tallying"); + long l = this.e[this.ticks % 100] = SystemUtils.c() - i; + this.ap = this.ap * 0.8F + (float) l / 1000000.0F * 0.19999999F; + this.methodProfiler.e(); + this.methodProfiler.e(); org.spigotmc.WatchdogThread.tick(); // Spigot PaperLightingQueue.processQueue(startTime); // Paper - this.slackActivityAccountant.tickEnded(tickNanos); // Spigot + this.slackActivityAccountant.tickEnded(l); // Spigot co.aikar.timings.TimingsManager.FULL_SERVER_TICK.stopTiming(); // Paper } - public void D() { + public void w() { MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Paper this.server.getScheduler().mainThreadHeartbeat(this.ticks); // CraftBukkit MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Paper MinecraftTimings.minecraftSchedulerTimer.startTiming(); // Paper this.methodProfiler.a("jobs"); - Queue queue = this.j; - // Spigot start - FutureTask entry; - int count = this.j.size(); - while (count-- > 0 && (entry = this.j.poll()) != null) { - SystemUtils.a(entry, MinecraftServer.LOGGER); - } - // Spigot end + FutureTask futuretask; + + while ((futuretask = (FutureTask) this.g.poll()) != null) { + SystemUtils.a(futuretask, MinecraftServer.LOGGER); + } MinecraftTimings.minecraftSchedulerTimer.stopTiming(); // Paper + this.methodProfiler.c("commandFunctions"); + MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot + this.getFunctionData().Y_(); + MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot this.methodProfiler.c("levels"); // CraftBukkit start @@ -864,7 +1003,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs // Send time updates to everyone, it will get the right time from the world the player is in. if (this.ticks % 20 == 0) { for (int i = 0; i < this.getPlayerList().players.size(); ++i) { - EntityPlayer entityplayer = this.getPlayerList().players.get(i); + EntityPlayer entityplayer = (EntityPlayer) this.getPlayerList().players.get(i); entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateTime(entityplayer.world.getTime(), entityplayer.getPlayerTime(), entityplayer.world.getGameRules().getBoolean("doDaylightCycle"))); // Add support for per player time } } @@ -873,11 +1012,10 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs int i; for (i = 0; i < this.worlds.size(); ++i) { // CraftBukkit - long j = System.nanoTime(); + long j = SystemUtils.c(); - // if (i == 0 || this.getAllowNether()) { + if (true || i == 0 || this.getAllowNether()) { // CraftBukkit WorldServer worldserver = this.worlds.get(i); - TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; this.methodProfiler.a(() -> { return worldserver.getWorldData().getName(); @@ -885,8 +1023,8 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs /* Drop global time updates if (this.ticks % 20 == 0) { this.methodProfiler.a("timeSync"); - this.v.a((Packet) (new PacketPlayOutUpdateTime(worldserver.getTime(), worldserver.getDayTime(), worldserver.getGameRules().getBoolean("doDaylightCycle"))), worldserver.worldProvider.getDimensionManager().getDimensionID()); - this.methodProfiler.b(); + this.s.a((Packet) (new PacketPlayOutUpdateTime(worldserver.getTime(), worldserver.getDayTime(), worldserver.getGameRules().getBoolean("doDaylightCycle"))), worldserver.worldProvider.getDimensionManager().getDimensionID()); + this.methodProfiler.e(); } // CraftBukkit end */ @@ -926,38 +1064,33 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs throw new ReportedException(crashreport); } - this.methodProfiler.b(); + this.methodProfiler.e(); this.methodProfiler.a("tracker"); worldserver.getTracker().updatePlayers(); - this.methodProfiler.b(); - this.methodProfiler.b(); + this.methodProfiler.e(); + this.methodProfiler.e(); worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions - // } // CraftBukkit + } - // this.i[i][this.ticks % 100] = System.nanoTime() - j; // CraftBukkit + // this.f[i][this.ticks % 100] = SystemUtils.c() - j; // CraftBukkit } this.methodProfiler.c("connection"); MinecraftTimings.connectionTimer.startTiming(); // Spigot - this.an().c(); + this.getServerConnection().c(); MinecraftTimings.connectionTimer.stopTiming(); // Spigot this.methodProfiler.c("players"); MinecraftTimings.playerListTimer.startTiming(); // Spigot - this.v.tick(); + this.s.tick(); MinecraftTimings.playerListTimer.stopTiming(); // Spigot - this.methodProfiler.c("commandFunctions"); - MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot - this.aL().e(); - MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot this.methodProfiler.c("tickables"); - MinecraftTimings.tickablesTimer.startTiming(); // Spigot - for (i = 0; i < this.o.size(); ++i) { - this.o.get(i).e(); + for (i = 0; i < this.l.size(); ++i) { + ((ITickable) this.l.get(i)).Y_(); } MinecraftTimings.tickablesTimer.stopTiming(); // Spigot - this.methodProfiler.b(); + this.methodProfiler.e(); } public boolean getAllowNether() { @@ -965,7 +1098,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } public void a(ITickable itickable) { - this.o.add(itickable); + this.l.add(itickable); } public static void main(final OptionSet options) { // CraftBukkit - replaces main(String[] astring) @@ -979,16 +1112,17 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs String s2 = null; boolean flag1 = false; boolean flag2 = false; + boolean flag3 = false; int i = -1; for (int j = 0; j < astring.length; ++j) { String s3 = astring[j]; String s4 = j == astring.length - 1 ? null : astring[j + 1]; - boolean flag3 = false; + boolean flag4 = false; if (!"nogui".equals(s3) && !"--nogui".equals(s3)) { if ("--port".equals(s3) && s4 != null) { - flag3 = true; + flag4 = true; try { i = Integer.parseInt(s4); @@ -996,24 +1130,26 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs ; } } else if ("--singleplayer".equals(s3) && s4 != null) { - flag3 = true; + flag4 = true; s = s4; } else if ("--universe".equals(s3) && s4 != null) { - flag3 = true; + flag4 = true; s1 = s4; } else if ("--world".equals(s3) && s4 != null) { - flag3 = true; + flag4 = true; s2 = s4; } else if ("--demo".equals(s3)) { flag1 = true; } else if ("--bonusChest".equals(s3)) { flag2 = true; + } else if ("--forceUpgrade".equals(s3)) { + flag3 = true; } } else { flag = false; } - if (flag3) { + if (flag4) { ++j; } } @@ -1028,7 +1164,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs /* CraftBukkit start if (s != null) { - dedicatedserver.i(s); + dedicatedserver.h(s); } if (s2 != null) { @@ -1040,23 +1176,30 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } if (flag1) { - dedicatedserver.b(true); - } - - if (flag2) { dedicatedserver.c(true); } - if (flag && !GraphicsEnvironment.isHeadless()) { - dedicatedserver.aR(); + if (flag2) { + dedicatedserver.d(true); } - dedicatedserver.F(); - Runtime.getRuntime().addShutdownHook(new Thread("Server Shutdown Thread") { + if (flag && !GraphicsEnvironment.isHeadless()) { + dedicatedserver.aY(); + } + + if (flag3) { + dedicatedserver.setForceUpgrade(true); + } + + dedicatedserver.y(); + Thread thread = new Thread("Server Shutdown Thread") { public void run() { dedicatedserver.stop(); } - }); + }; + + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(MinecraftServer.LOGGER)); + Runtime.getRuntime().addShutdownHook(thread); */ if (options.has("port")) { @@ -1074,6 +1217,10 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs dedicatedserver.setWorld((String) options.valueOf("world")); } + if (options.has("forceUpgrade")) { + dedicatedserver.setForceUpgrade(true); + } + dedicatedserver.primaryThread.start(); // CraftBukkit end } catch (Exception exception) { @@ -1082,15 +1229,22 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } - public void F() { + protected void setForceUpgrade(boolean flag) { + this.forceUpgrade = flag; + } + + public void y() { /* CraftBukkit start - prevent abuse this.serverThread = new Thread(this, "Server thread"); + this.serverThread.setUncaughtExceptionHandler((thread, throwable) -> { + MinecraftServer.LOGGER.error(throwable); + }); this.serverThread.start(); // CraftBukkit end */ } - public File d(String s) { - return new File(this.A(), s); + public File c(String s) { + return new File(this.t(), s); } public void info(String s) { @@ -1112,37 +1266,37 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs // CraftBukkit end } + public WorldServer a(DimensionManager dimensionmanager) { + return dimensionmanager == DimensionManager.NETHER ? this.worlds.get(1) : (dimensionmanager == DimensionManager.THE_END ? this.worlds.get(2) : this.worlds.get(0)); // CraftBukkit + } + public String getVersion() { - return "1.12.2"; + return "1.13"; } - public int getPlayerCount() { return H(); } // Paper - OBFHELPER - public int H() { - return this.v.getPlayerCount(); + public int getPlayerCount() { return A(); } // Paper - OBFHELPER + public int A() { + return this.s.getPlayerCount(); } - public int getMaxPlayers() { return I(); } // Paper - OBFHELPER - public int I() { - return this.v.getMaxPlayers(); + public int getMaxPlayers() { return B(); } // Paper - OBFHELPER + public int B() { + return this.s.getMaxPlayers(); } public String[] getPlayers() { - return this.v.f(); - } - - public GameProfile[] K() { - return this.v.g(); + return this.s.f(); } public boolean isDebugging() { return this.getPropertyManager().getBoolean("debug", false); // CraftBukkit - don't hardcode } - public void g(String s) { + public void f(String s) { MinecraftServer.LOGGER.error(s); } - public void h(String s) { + public void g(String s) { if (this.isDebugging()) { MinecraftServer.LOGGER.info(s); } @@ -1154,139 +1308,79 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } public CrashReport b(CrashReport crashreport) { - crashreport.g().a("Profiler Position", new CrashReportCallable() { - public String a() throws Exception { - return MinecraftServer.this.methodProfiler.a ? MinecraftServer.this.methodProfiler.c() : "N/A (disabled)"; - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreport.g().a("Profiler Position", () -> { + return this.methodProfiler.a() ? this.methodProfiler.f() : "N/A (disabled)"; }); - if (this.v != null) { - crashreport.g().a("Player Count", new CrashReportCallable() { - public String a() { - return MinecraftServer.this.v.getPlayerCount() + " / " + MinecraftServer.this.v.getMaxPlayers() + "; " + MinecraftServer.this.v.v(); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + if (this.s != null) { + crashreport.g().a("Player Count", () -> { + return this.s.getPlayerCount() + " / " + this.s.getMaxPlayers() + "; " + this.s.v(); }); } + crashreport.g().a("Data Packs", () -> { + StringBuilder stringbuilder = new StringBuilder(); + Iterator iterator = this.resourcePackRepository.d().iterator(); + + while (iterator.hasNext()) { + ResourcePackLoader resourcepackloader = (ResourcePackLoader) iterator.next(); + + if (stringbuilder.length() > 0) { + stringbuilder.append(", "); + } + + stringbuilder.append(resourcepackloader.e()); + if (!resourcepackloader.c().a()) { + stringbuilder.append(" (incompatible)"); + } + } + + return stringbuilder.toString(); + }); return crashreport; } - public List tabCompleteCommand(ICommandListener icommandlistener, String s, @Nullable BlockPosition blockposition, boolean flag) { - /* CraftBukkit start - Allow tab-completion of Bukkit commands - ArrayList arraylist = Lists.newArrayList(); - boolean flag1 = s.startsWith("/"); - - if (flag1) { - s = s.substring(1); - } - - if (!flag1 && !flag) { - String[] astring = s.split(" ", -1); - String s1 = astring[astring.length - 1]; - String[] astring1 = this.v.f(); - int i = astring1.length; - - for (int j = 0; j < i; ++j) { - String s2 = astring1[j]; - - if (CommandAbstract.a(s1, s2)) { - arraylist.add(s2); - } - } - - return arraylist; - } else { - boolean flag2 = !s.contains(" "); - List list = this.b.a(icommandlistener, s, blockposition); - - if (!list.isEmpty()) { - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - String s3 = (String) iterator.next(); - - if (flag2 && !flag) { - arraylist.add("/" + s3); - } else { - arraylist.add(s3); - } - } - } - - return arraylist; - } - */ - return server.tabComplete(icommandlistener, s, blockposition, flag); - // CraftBukkit end - } - - public boolean M() { + public boolean F() { return true; // CraftBukkit } - @Override - public String getName() { - return "Server"; - } - - @Override public void sendMessage(IChatBaseComponent ichatbasecomponent) { - // Paper - Log message with colors - MinecraftServer.LOGGER.info(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(ichatbasecomponent, net.minecraft.server.EnumChatFormat.WHITE)); + MinecraftServer.LOGGER.info(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(ichatbasecomponent, net.minecraft.server.EnumChatFormat.WHITE));// Paper - Log message with colors } - @Override - public boolean a(int i, String s) { - return true; + public KeyPair G() { + return this.H; } - public ICommandHandler getCommandHandler() { - return this.b; - } - - public KeyPair O() { - return this.I; - } - - public int P() { - return this.u; + public int H() { + return this.r; } public void setPort(int i) { - this.u = i; + this.r = i; } - public String Q() { + public String I() { + return this.I; + } + + public void h(String s) { + this.I = s; + } + + public boolean J() { + return this.I != null; + } + + public String getWorld() { return this.J; } - public void i(String s) { + public void setWorld(String s) { this.J = s; } - public boolean R() { - return this.J != null; - } - - public String S() { - return this.K; - } - - public void setWorld(String s) { - this.K = s; - } - public void a(KeyPair keypair) { - this.I = keypair; + this.H = keypair; } public void a(EnumDifficulty enumdifficulty) { @@ -1302,7 +1396,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs if (worldserver.getWorldData().isHardcore()) { worldserver.getWorldData().setDifficulty(EnumDifficulty.HARD); worldserver.setSpawnFlags(true, true); - } else if (this.R()) { + } else if (this.J()) { worldserver.getWorldData().setDifficulty(enumdifficulty); worldserver.setSpawnFlags(worldserver.getDifficulty() != EnumDifficulty.PEACEFUL, true); } else { @@ -1318,16 +1412,16 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs return true; } - public boolean V() { + public boolean N() { return this.demoMode; } - public void b(boolean flag) { + public void c(boolean flag) { this.demoMode = flag; } - public void c(boolean flag) { - this.N = flag; + public void d(boolean flag) { + this.M = flag; } public Convertable getConvertable() { @@ -1335,32 +1429,31 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } public String getResourcePack() { - return this.O; + return this.N; } public String getResourcePackHash() { - return this.P; + return this.O; } public void setResourcePack(String s, String s1) { - this.O = s; - this.P = s1; + this.N = s; + this.O = s1; } - @Override public void a(MojangStatisticsGenerator mojangstatisticsgenerator) { mojangstatisticsgenerator.a("whitelist_enabled", Boolean.valueOf(false)); mojangstatisticsgenerator.a("whitelist_count", Integer.valueOf(0)); - if (this.v != null) { - mojangstatisticsgenerator.a("players_current", Integer.valueOf(this.H())); - mojangstatisticsgenerator.a("players_max", Integer.valueOf(this.I())); - mojangstatisticsgenerator.a("players_seen", Integer.valueOf(this.v.getSeenPlayers().length)); + if (this.s != null) { + mojangstatisticsgenerator.a("players_current", Integer.valueOf(this.A())); + mojangstatisticsgenerator.a("players_max", Integer.valueOf(this.B())); + mojangstatisticsgenerator.a("players_seen", Integer.valueOf(this.s.getSeenPlayers().length)); } mojangstatisticsgenerator.a("uses_auth", Boolean.valueOf(this.onlineMode)); - mojangstatisticsgenerator.a("gui_state", this.ap() ? "enabled" : "disabled"); - mojangstatisticsgenerator.a("run_time", Long.valueOf((aw() - mojangstatisticsgenerator.g()) / 60L * 1000L)); - mojangstatisticsgenerator.a("avg_tick_ms", Integer.valueOf((int) (MathHelper.a(this.h) * 1.0E-6D))); + mojangstatisticsgenerator.a("gui_state", this.ai() ? "enabled" : "disabled"); + mojangstatisticsgenerator.a("run_time", Long.valueOf((SystemUtils.b() - mojangstatisticsgenerator.g()) / 60L * 1000L)); + mojangstatisticsgenerator.a("avg_tick_ms", Integer.valueOf((int) (MathHelper.a(this.e) * 1.0E-6D))); int i = 0; if (this.worldServer != null) { @@ -1377,8 +1470,8 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs mojangstatisticsgenerator.a("world[" + i + "][hardcore]", Boolean.valueOf(worlddata.isHardcore())); mojangstatisticsgenerator.a("world[" + i + "][generator_name]", worlddata.getType().name()); mojangstatisticsgenerator.a("world[" + i + "][generator_version]", Integer.valueOf(worlddata.getType().getVersion())); - mojangstatisticsgenerator.a("world[" + i + "][height]", Integer.valueOf(this.G)); - mojangstatisticsgenerator.a("world[" + i + "][chunks_loaded]", Integer.valueOf(worldserver.getChunkProviderServer().g())); + mojangstatisticsgenerator.a("world[" + i + "][height]", Integer.valueOf(this.F)); + mojangstatisticsgenerator.a("world[" + i + "][chunks_loaded]", Integer.valueOf(worldserver.getChunkProviderServer().h())); ++i; } } @@ -1387,20 +1480,11 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs mojangstatisticsgenerator.a("worlds", Integer.valueOf(i)); } - @Override - public void b(MojangStatisticsGenerator mojangstatisticsgenerator) { - mojangstatisticsgenerator.b("singleplayer", Boolean.valueOf(this.R())); - mojangstatisticsgenerator.b("server_brand", this.getServerModName()); - mojangstatisticsgenerator.b("gui_supported", GraphicsEnvironment.isHeadless() ? "headless" : "supported"); - mojangstatisticsgenerator.b("dedicated", Boolean.valueOf(this.aa())); - } - - @Override public boolean getSnooperEnabled() { return true; } - public abstract boolean aa(); + public abstract boolean S(); public boolean getOnlineMode() { return server.getOnlineMode(); // CraftBukkit @@ -1410,12 +1494,12 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs this.onlineMode = flag; } - public boolean ac() { - return this.A; + public boolean U() { + return this.z; } - public void e(boolean flag) { - this.A = flag; + public void f(boolean flag) { + this.z = flag; } public boolean getSpawnAnimals() { @@ -1430,7 +1514,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs return this.spawnNPCs; } - public abstract boolean af(); + public abstract boolean X(); public void setSpawnNPCs(boolean flag) { this.spawnNPCs = flag; @@ -1463,11 +1547,11 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } public int getMaxBuildHeight() { - return this.G; + return this.F; } public void c(int i) { - this.G = i; + this.F = i; } public boolean isStopped() { @@ -1475,13 +1559,15 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } public PlayerList getPlayerList() { - return this.v; + return this.s; } public void a(PlayerList playerlist) { - this.v = playerlist; + this.s = playerlist; } + public abstract boolean af(); + public void setGamemode(EnumGamemode enumgamemode) { // CraftBukkit start for (int i = 0; i < this.worlds.size(); ++i) { @@ -1490,33 +1576,22 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } - // Spigot Start - public ServerConnection getServerConnection() - { - return this.p; - } - // Spigot End - public ServerConnection an() { - return this.p == null ? this.p = new ServerConnection(this) : this.p; // Spigot + public ServerConnection getServerConnection() { + return this.m == null ? this.m = new ServerConnection(this) : this.m; // Spigot } - public boolean ap() { + public boolean ai() { return false; } - public abstract String a(EnumGamemode enumgamemode, boolean flag); + public abstract boolean a(EnumGamemode enumgamemode, boolean flag, int i); - public int aq() { + public int aj() { return this.ticks; } - public void ar() { - this.T = true; - } - - @Override - public World getWorld() { - return this.worlds.get(0); // CraftBukkit + public void ak() { + this.S = true; } public int getSpawnProtection() { @@ -1528,83 +1603,43 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } public void setForceGamemode(boolean flag) { - this.U = flag; + this.T = flag; } public boolean getForceGamemode() { - return this.U; - } - - public Proxy av() { - return this.e; - } - - public static long aw() { - return System.currentTimeMillis(); + return this.T; } public int getIdleTimeout() { - return this.H; + return this.G; } public void setIdleTimeout(int i) { - this.H = i; + this.G = i; } - public MinecraftSessionService getSessionService() { return az(); } // Paper - OBFHELPER - public MinecraftSessionService az() { - return this.W; + public MinecraftSessionService getSessionService() { return ar(); } // Paper - OBFHELPER + public MinecraftSessionService ar() { + return this.V; } public GameProfileRepository getGameProfileRepository() { - return this.X; + return this.W; } public UserCache getUserCache() { - return this.Y; + return this.X; } public ServerPing getServerPing() { - return this.q; + return this.n; } - public void aD() { - this.Z = 0L; + public void av() { + this.Y = 0L; } - @Nullable - public Entity a(UUID uuid) { - WorldServer[] aworldserver = this.worldServer; - int i = aworldserver.length; - - // CraftBukkit start - for (int j = 0; j < worlds.size(); ++j) { - WorldServer worldserver = worlds.get(j); - // CraftBukkit end - - if (worldserver != null) { - Entity entity = worldserver.getEntity(uuid); - - if (entity != null) { - return entity; - } - } - } - - return null; - } - - @Override - public boolean getSendCommandFeedback() { - return worlds.get(0).getGameRules().getBoolean("sendCommandFeedback"); - } - - @Override - public MinecraftServer C_() { - return this; - } - - public int aE() { + public int aw() { return 29999984; } @@ -1612,12 +1647,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs Validate.notNull(callable); if (!this.isMainThread()) { // CraftBukkit && !this.isStopped()) { ListenableFutureTask listenablefuturetask = ListenableFutureTask.create(callable); - Queue queue = this.j; - // Spigot start - this.j.add(listenablefuturetask); + this.g.add(listenablefuturetask); return listenablefuturetask; - // Spigot end } else { try { return Futures.immediateFuture(callable.call()); @@ -1627,53 +1659,175 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs } } - @Override public ListenableFuture postToMainThread(Runnable runnable) { Validate.notNull(runnable); return this.a(Executors.callable(runnable)); } - @Override public boolean isMainThread() { return Thread.currentThread() == this.serverThread; } - public int aG() { + public int ay() { return 256; } - public long aH() { - return this.ab; + public long az() { + return this.aa; } - public final Thread getServerThread() { return this.aI(); } // Paper - OBFHELPER - public Thread aI() { + public final Thread getServerThread() { return this.aA(); } // Paper - OBFHELPER + public Thread aA() { return this.serverThread; } + public DataFixer aB() { + return this.dataConverterManager; + } + public int a(@Nullable WorldServer worldserver) { return worldserver != null ? worldserver.getGameRules().c("spawnRadius") : 10; } public AdvancementDataWorld getAdvancementData() { - return this.worlds.get(0).z(); // CraftBukkit + return this.al; } - public CustomFunctionData aL() { - return this.worlds.get(0).A(); // CraftBukkit + public CustomFunctionData getFunctionData() { + return this.am; } public void reload() { - if (this.isMainThread()) { - this.getPlayerList().savePlayers(); - this.worlds.get(0).getLootTableRegistry().reload(); // CraftBukkit - this.getAdvancementData().reload(); - this.aL().f(); - this.getPlayerList().reload(); - } else { + if (!this.isMainThread()) { this.postToMainThread(this::reload); + } else { + this.getPlayerList().savePlayers(); + this.resourcePackRepository.a(); + this.a(this.worlds.get(0).getWorldData()); // CraftBukkit + this.getPlayerList().reload(); + } + } + + private void a(WorldData worlddata) { + ArrayList arraylist = Lists.newArrayList(this.resourcePackRepository.d()); + Iterator iterator = this.resourcePackRepository.b().iterator(); + + while (iterator.hasNext()) { + ResourcePackLoader resourcepackloader = (ResourcePackLoader) iterator.next(); + + if (!worlddata.N().contains(resourcepackloader.e()) && !arraylist.contains(resourcepackloader)) { + MinecraftServer.LOGGER.info("Found new data pack {}, loading it automatically", resourcepackloader.e()); + resourcepackloader.h().a(arraylist, resourcepackloader, (resourcepackloader1) -> { // CraftBukkit - decompile error + return resourcepackloader1; // CraftBukkit - decompile error + }, false); + } } + this.resourcePackRepository.a((Collection) arraylist); + ArrayList arraylist1 = Lists.newArrayList(); + + this.resourcePackRepository.d().forEach((resourcepackloader) -> { + arraylist1.add(resourcepackloader.d()); // CraftBukkit - decompile error + }); + this.ac.a((List) arraylist1); + worlddata.O().clear(); + worlddata.N().clear(); + this.resourcePackRepository.d().forEach((resourcepackloader) -> { + worlddata.O().add(resourcepackloader.e()); + }); + this.resourcePackRepository.b().forEach((resourcepackloader) -> { + if (!this.resourcePackRepository.d().contains(resourcepackloader)) { + worlddata.N().add(resourcepackloader.e()); + } + + }); + } + + public void a(CommandListenerWrapper commandlistenerwrapper) { + if (this.aS()) { + PlayerList playerlist = commandlistenerwrapper.getServer().getPlayerList(); + WhiteList whitelist = playerlist.getWhitelist(); + + if (whitelist.isEnabled()) { + ArrayList arraylist = Lists.newArrayList(playerlist.v()); + Iterator iterator = arraylist.iterator(); + + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + + if (!whitelist.isWhitelisted(entityplayer.getProfile())) { + entityplayer.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.not_whitelisted", new Object[0])); + } + } + + } + } + } + + public IReloadableResourceManager getResourceManager() { + return this.ac; + } + + public ResourcePackRepository getResourcePackRepository() { + return this.resourcePackRepository; + } + + public CommandDispatcher getCommandDispatcher() { + return this.commandDispatcher; + } + + public CommandListenerWrapper getServerCommandListener() { + return new CommandListenerWrapper(this, this.worlds.isEmpty() ? Vec3D.a : new Vec3D(this.worlds.get(0).getSpawn()), Vec2F.a, this.worlds.isEmpty() ? null : this.worlds.get(0), 4, "Server", new ChatComponentText("Server"), this, (Entity) null); // CraftBukkit + } + + public boolean a() { + return true; + } + + public boolean b() { + return true; + } + + public CraftingManager getCraftingManager() { + return this.ag; + } + + public TagRegistry getTagRegistry() { + return this.ah; + } + + public ScoreboardServer getScoreboard() { + return this.ai; + } + + public LootTableRegistry aP() { + return this.ak; + } + + public GameRules aQ() { + return this.worlds.get(0).getGameRules(); // CraftBukkit + } + + public BossBattleCustomData aR() { + return this.aj; + } + + public boolean aS() { + return this.an; + } + + public void l(boolean flag) { + this.an = flag; + } + + public int a(GameProfile gameprofile) { + if (this.getPlayerList().isOp(gameprofile)) { + OpListEntry oplistentry = (OpListEntry) this.getPlayerList().getOPs().get(gameprofile); + + return oplistentry != null ? oplistentry.a() : (this.J() ? (this.I().equals(gameprofile.getName()) ? 4 : (this.getPlayerList().x() ? 4 : 0)) : this.k()); + } else { + return 0; + } } // CraftBukkit start diff --git a/sources/src/main/java/net/minecraft/server/NetworkManager.java b/sources/src/main/java/net/minecraft/server/NetworkManager.java index 047c67c29..30520ad98 100644 --- a/sources/src/main/java/net/minecraft/server/NetworkManager.java +++ b/sources/src/main/java/net/minecraft/server/NetworkManager.java @@ -1,30 +1,27 @@ package net.minecraft.server; +import com.google.common.collect.Queues; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.googlecode.concurentlocks.ReentrantReadWriteUpdateLock; -import io.akarin.api.internal.utils.CheckedConcurrentLinkedQueue; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.DefaultEventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalEventLoopGroup; import io.netty.channel.local.LocalServerChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.timeout.TimeoutException; import io.netty.util.AttributeKey; 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 javax.annotation.Nullable; import javax.crypto.SecretKey; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.Validate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -33,10 +30,7 @@ import org.apache.logging.log4j.MarkerManager; /** * Akarin Changes Note - * 1) Add volatile to fields (nsc) - * 2) Expose private members (nsc) - * 3) Changes lock type to updatable lock (compatibility) - * 4) Removes unneed array creation (performance) + * 1) Changes lock type to updatable lock (compatibility) */ public class NetworkManager extends SimpleChannelInboundHandler> { @@ -44,50 +38,35 @@ public class NetworkManager extends SimpleChannelInboundHandler> { public static final Marker a = MarkerManager.getMarker("NETWORK"); public static final Marker b = MarkerManager.getMarker("NETWORK_PACKETS", NetworkManager.a); public static final AttributeKey c = AttributeKey.valueOf("protocol"); - public static final LazyInitVar d = new LazyInitVar() { - protected NioEventLoopGroup a() { - return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build()); - } - - @Override - protected Object init() { - return this.a(); - } - }; - public static final LazyInitVar e = new LazyInitVar() { - protected EpollEventLoopGroup a() { - return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).build()); - } - - @Override - protected Object init() { - return this.a(); - } - }; - public static final LazyInitVar f = new LazyInitVar() { - protected LocalEventLoopGroup a() { - return new LocalEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build()); - } - - @Override - protected Object init() { - return this.a(); - } - }; + public static final LazyInitVar d = new LazyInitVar(() -> { + return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build()); + }); + public static final LazyInitVar e = new LazyInitVar(() -> { + return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).build()); + }); + public static final LazyInitVar f = new LazyInitVar(() -> { + return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build()); + }); private final EnumProtocolDirection h; - private final Queue i = new CheckedConcurrentLinkedQueue(); private final Queue getPacketQueue() { return this.i; } // Paper - Anti-Xray - OBFHELPER // Akarin + private final Queue i = Queues.newConcurrentLinkedQueue(); private final ReentrantReadWriteUpdateLock j = new ReentrantReadWriteUpdateLock(); // Akarin - use update lock public Channel channel; // Spigot Start // PAIL public SocketAddress l; public java.util.UUID spoofedUUID; public com.mojang.authlib.properties.Property[] spoofedProfile; - public volatile boolean preparing = true; // Akarin - add volatile + public boolean preparing = true; // Spigot End private PacketListener m; private IChatBaseComponent n; private boolean o; private boolean p; + private int q; + private int r; + private float s; + private float t; + private int u; + private boolean v; // Paper start - NetworkClient implementation public int protocolVersion; public java.net.InetSocketAddress virtualHost; @@ -98,7 +77,6 @@ public class NetworkManager extends SimpleChannelInboundHandler> { this.h = enumprotocoldirection; } - @Override public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception { super.channelActive(channelhandlercontext); this.channel = channelhandlercontext.channel(); @@ -121,37 +99,58 @@ public class NetworkManager extends SimpleChannelInboundHandler> { NetworkManager.g.debug("Enabled auto read"); } - @Override public void channelInactive(ChannelHandlerContext channelhandlercontext) throws Exception { this.close(new ChatMessage("disconnect.endOfStream", new Object[0])); } - @Override - public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) throws Exception { - ChatMessage chatmessage; - - if (throwable instanceof TimeoutException) { - chatmessage = new ChatMessage("disconnect.timeout", new Object[0]); + public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { + if (throwable instanceof SkipEncodeException) { + NetworkManager.g.debug("Skipping packet due to errors", throwable.getCause()); } else { - chatmessage = new ChatMessage("disconnect.genericReason", new Object[] { "Internal Exception: " + throwable}); - } + boolean flag = !this.v; - NetworkManager.g.debug(chatmessage.toPlainText(), throwable); - this.close(chatmessage); + this.v = true; + if (this.channel.isOpen()) { + if (throwable instanceof TimeoutException) { + NetworkManager.g.debug("Timeout", throwable); + this.close(new ChatMessage("disconnect.timeout", new Object[0])); + } else { + ChatMessage chatmessage = new ChatMessage("disconnect.genericReason", new Object[] { "Internal Exception: " + throwable}); + + if (flag) { + NetworkManager.g.debug("Failed to sent packet", throwable); + this.sendPacket(new PacketPlayOutKickDisconnect(chatmessage), (future) -> { + this.close(chatmessage); // CraftBukkit - decompile error + }); + this.stopReading(); + } else { + NetworkManager.g.debug("Double fault", throwable); + this.close(chatmessage); + } + } + + } + } if (MinecraftServer.getServer().isDebugging()) throwable.printStackTrace(); // Spigot } protected void a(ChannelHandlerContext channelhandlercontext, Packet packet) throws Exception { if (this.channel.isOpen()) { try { - ((Packet) packet).a(this.m); // CraftBukkit - decompile error + a(packet, this.m); } catch (CancelledPacketHandleException cancelledpackethandleexception) { ; } + + ++this.q; } } + private static void a(Packet packet, PacketListener packetlistener) { + packet.a((T) packetlistener); // CraftBukkit - decompile error + } + public void setPacketListener(PacketListener packetlistener) { Validate.notNull(packetlistener, "packetListener", new Object[0]); NetworkManager.g.debug("Set listener of {} to {}", this, packetlistener); @@ -159,14 +158,18 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } public void sendPacket(Packet packet) { - if (this.isConnected() && this.trySendQueue() && !(packet instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) packet).isReady())) { // Paper - Async-Anti-Xray - Add chunk packets which are not ready or all packets if the queue contains chunk packets which are not ready to the queue and send the packets later in the right order - //this.m(); // Paper - Async-Anti-Xray - Move to if statement (this.trySendQueue()) - this.a(packet, (GenericFutureListener[]) null); + this.sendPacket(packet, (GenericFutureListener) null); + } + + public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { + if (this.isConnected()) { + this.o(); + this.b(packet, genericfuturelistener); } else { this.j.writeLock().lock(); try { - this.i.add(new NetworkManager.QueuedPacket(packet)); // Akarin - remove fake listener creation + this.i.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); } finally { this.j.writeLock().unlock(); } @@ -174,27 +177,11 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } - public void sendPacket(Packet packet, GenericFutureListener> genericfuturelistener, GenericFutureListener>... agenericfuturelistener) { - if (this.isConnected() && this.trySendQueue() && !(packet instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) packet).isReady())) { // Paper - Async-Anti-Xray - Add chunk packets which are not ready or all packets if the queue contains chunk packets which are not ready to the queue and send the packets later in the right order - //this.m(); // Paper - Async-Anti-Xray - Move to if statement (this.trySendQueue()) - this.a(packet, ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener)); - } else { - this.j.writeLock().lock(); - - try { - this.i.add(new NetworkManager.QueuedPacket(packet, ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener))); - } finally { - this.j.writeLock().unlock(); - } - } - - } - - private void dispatchPacket(final Packet packet, @Nullable final GenericFutureListener>[] genericFutureListeners) { this.a(packet, genericFutureListeners); } // Paper - Anti-Xray - OBFHELPER - private void a(final Packet packet, @Nullable final GenericFutureListener>[] agenericfuturelistener) { - final EnumProtocol enumprotocol = EnumProtocol.a(packet); - final EnumProtocol enumprotocol1 = this.channel.attr(NetworkManager.c).get(); + private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { + EnumProtocol enumprotocol = EnumProtocol.a(packet); + EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); + ++this.r; if (enumprotocol1 != enumprotocol) { NetworkManager.g.debug("Disabled auto read"); this.channel.config().setAutoRead(false); @@ -207,75 +194,63 @@ public class NetworkManager extends SimpleChannelInboundHandler> { ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - if (agenericfuturelistener != null) { - channelfuture.addListeners(agenericfuturelistener); + if (genericfuturelistener != null) { + channelfuture.addListener(genericfuturelistener); } channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); } else { - this.channel.eventLoop().execute(new Runnable() { - @Override - public void run() { - if (enumprotocol != enumprotocol1) { - NetworkManager.this.setProtocol(enumprotocol); - } - - ChannelFuture channelfuture = NetworkManager.this.channel.writeAndFlush(packet); - - if (agenericfuturelistener != null) { - channelfuture.addListeners(agenericfuturelistener); - } - - channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + this.channel.eventLoop().execute(() -> { + if (enumprotocol != enumprotocol1) { + this.setProtocol(enumprotocol); } + + ChannelFuture channelfuture = this.channel.writeAndFlush(packet); + + if (genericfuturelistener != null) { + channelfuture.addListener(genericfuturelistener); + } + + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); }); } } - // 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 trySendQueue() { return this.m(); } // OBFHELPER - private boolean m() { // void -> boolean + private void o() { if (this.channel != null && this.channel.isOpen()) { - 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) + this.j.updateLock().lock(); // Akarin try { while (!this.i.isEmpty()) { - NetworkManager.QueuedPacket networkmanager_queuedpacket = this.getPacketQueue().peek(); // poll -> peek + NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.i.poll(); - 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.getGenericFutureListeners()); // dispatch the packet - } - } + this.b(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); } } finally { - this.j.writeLock().unlock(); // readLock -> writeLock (because of race condition between peek and poll) + this.j.updateLock().unlock(); // Akarin } } - - return true; // Return true if all packets were dispatched } - // Paper end public void a() { - this.m(); + this.o(); if (this.m instanceof ITickable) { - ((ITickable) this.m).e(); + ((ITickable) this.m).Y_(); } if (this.channel != null) { if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version } + if (this.u++ % 20 == 0) { + this.t = this.t * 0.75F + (float) this.r * 0.25F; + this.s = this.s * 0.75F + (float) this.q * 0.25F; + this.r = 0; + this.q = 0; + } + } public SocketAddress getSocketAddress() { @@ -315,6 +290,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { return this.m; } + @Nullable public IChatBaseComponent j() { return this.n; } @@ -365,19 +341,19 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } } - @Override protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet object) throws Exception { // CraftBukkit - fix decompile error - this.a(channelhandlercontext, object); + this.a(channelhandlercontext, (Packet) object); } - public static class QueuedPacket { // Akarin - default -> public + static class QueuedPacket { - private final Packet a; public final Packet getPacket() { return this.a; } // Paper - Anti-Xray - OBFHELPER // Akarin - private -> public - private final GenericFutureListener>[] b; public final GenericFutureListener>[] getGenericFutureListeners() { return this.b; } // Paper - Anti-Xray - OBFHELPER // Akarin - private -> public + private final Packet a; + @Nullable + private final GenericFutureListener> b; - public QueuedPacket(Packet packet, GenericFutureListener>... agenericfuturelistener) { + public QueuedPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { this.a = packet; - this.b = agenericfuturelistener; + this.b = genericfuturelistener; } } diff --git a/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java index de69eba45..beac0e955 100644 --- a/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +++ b/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java @@ -8,10 +8,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map.Entry; -// Paper start -import com.destroystokyo.paper.antixray.PacketPlayOutMapChunkInfo; // Anti-Xray -// Paper end - /** * Akarin Changes Note * 1) WrappedByteBuf -> ByteBuf (compatibility) @@ -24,30 +20,17 @@ public class PacketPlayOutMapChunk implements Packet { private ByteBuf d; // Akarin - byte[] -> ByteBuf private List e; private boolean f; - private volatile boolean ready = false; // Paper - Async-Anti-Xray - Ready flag for the network manager - // Paper start - Async-Anti-Xray - Set the ready flag to true - public PacketPlayOutMapChunk() { - this.ready = true; - } - // Paper end + public PacketPlayOutMapChunk() {} public PacketPlayOutMapChunk(Chunk chunk, int i) { - PacketPlayOutMapChunkInfo packetPlayOutMapChunkInfo = chunk.world.chunkPacketBlockController.getPacketPlayOutMapChunkInfo(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.m(); + boolean flag = chunk.getWorld().worldProvider.g(); this.d = allocateBuffer(this.a(chunk, flag, i)); // Akarin - - // Paper start - Anti-Xray - Add chunk packet info - if (packetPlayOutMapChunkInfo != null) { - packetPlayOutMapChunkInfo.setData(this.d); - } - // Paper end - - this.c = this.writeChunk(new PacketDataSerializer(this.d), chunk, flag, i, packetPlayOutMapChunkInfo); // Paper - Anti-Xray - Add chunk packet info // Akarin + this.c = this.a(new PacketDataSerializer(this.d), chunk, flag, i); // Akarin this.e = Lists.newArrayList(); Iterator iterator = chunk.getTileEntities().entrySet().iterator(); @@ -57,26 +40,15 @@ public class PacketPlayOutMapChunk implements Packet { TileEntity tileentity = (TileEntity) entry.getValue(); int j = blockposition.getY() >> 4; - if (this.e() || (i & 1 << j) != 0) { - NBTTagCompound nbttagcompound = tileentity.d(); + if (this.f() || (i & 1 << j) != 0) { + NBTTagCompound nbttagcompound = tileentity.aa_(); this.e.add(nbttagcompound); } } - chunk.world.chunkPacketBlockController.modifyBlocks(this, packetPlayOutMapChunkInfo); // 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(); @@ -106,7 +78,7 @@ public class PacketPlayOutMapChunk implements Packet { packetdataserializer.writeBoolean(this.f); packetdataserializer.d(this.c); packetdataserializer.d(this.d.array().length); // Akarin - packetdataserializer.writeBytes(this.d.array()); + packetdataserializer.writeBytes(this.d); packetdataserializer.d(this.e.size()); Iterator iterator = this.e.iterator(); @@ -122,33 +94,27 @@ public class PacketPlayOutMapChunk implements Packet { packetlistenerplayout.a(this); } - private ByteBuf allocateBuffer(int expectedCapacity) { return g(expectedCapacity); } // Akarin - OBFHELPER - private ByteBuf g(int expectedCapacity) { // Akarin - added argument + private ByteBuf allocateBuffer(int expectedCapacity) { return h(expectedCapacity); } // Akarin - OBFHELPER + private ByteBuf h(int expectedCapacity) { // Akarin - added argument ByteBuf bytebuf = Unpooled.buffer(expectedCapacity); // Akarin bytebuf.writerIndex(0); return bytebuf; } - // Paper start - Anti-Xray - Support default method - public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, boolean writeSkyLightArray, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, writeSkyLightArray, chunkSectionSelector); } // OBFHELPER 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, PacketPlayOutMapChunkInfo packetPlayOutMapChunkInfo) { return this.a(packetDataSerializer, chunk, writeSkyLightArray, chunkSectionSelector, packetPlayOutMapChunkInfo); } // Paper - Anti-Xray - OBFHELPER - public int a(PacketDataSerializer packetdataserializer, Chunk chunk, boolean flag, int i, PacketPlayOutMapChunkInfo packetPlayOutMapChunkInfo) { // Paper - Anti-Xray - Add chunk packet info int j = 0; ChunkSection[] achunksection = chunk.getSections(); int k = 0; - for (int l = achunksection.length; k < l; ++k) { + int l; + + for (l = achunksection.length; k < l; ++k) { ChunkSection chunksection = achunksection[k]; - if (chunksection != Chunk.a && (!this.e() || !chunksection.a()) && (i & 1 << k) != 0) { + if (chunksection != Chunk.a && (!this.f() || !chunksection.a()) && (i & 1 << k) != 0) { j |= 1 << k; - chunksection.getBlocks().writeBlocks(packetdataserializer, packetPlayOutMapChunkInfo, k); // Paper - Anti-Xray - Add chunk packet info + chunksection.getBlocks().b(packetdataserializer); packetdataserializer.writeBytes(chunksection.getEmittedLightArray().asBytes()); if (flag) { packetdataserializer.writeBytes(chunksection.getSkyLightArray().asBytes()); @@ -156,8 +122,12 @@ public class PacketPlayOutMapChunk implements Packet { } } - if (this.e()) { - packetdataserializer.writeBytes(chunk.getBiomeIndex()); + if (this.f()) { + BiomeBase[] abiomebase = chunk.getBiomeIndex(); + + for (l = 0; l < abiomebase.length; ++l) { + packetdataserializer.writeInt(BiomeBase.REGISTRY_ID.a((BiomeBase) abiomebase[l])); + } } return j; @@ -171,7 +141,7 @@ public class PacketPlayOutMapChunk implements Packet { for (int l = achunksection.length; k < l; ++k) { ChunkSection chunksection = achunksection[k]; - if (chunksection != Chunk.a && (!this.e() || !chunksection.a()) && (i & 1 << k) != 0) { + if (chunksection != Chunk.a && (!this.f() || !chunksection.a()) && (i & 1 << k) != 0) { j += chunksection.getBlocks().a(); j += chunksection.getEmittedLightArray().asBytes().length; if (flag) { @@ -180,14 +150,14 @@ public class PacketPlayOutMapChunk implements Packet { } } - if (this.e()) { - j += chunk.getBiomeIndex().length; + if (this.f()) { + j += chunk.getBiomeIndex().length * 4; } return j; } - public boolean e() { + public boolean f() { return this.f; } } diff --git a/sources/src/main/java/net/minecraft/server/PlayerChunk.java b/sources/src/main/java/net/minecraft/server/PlayerChunk.java deleted file mode 100644 index aa5e8722f..000000000 --- a/sources/src/main/java/net/minecraft/server/PlayerChunk.java +++ /dev/null @@ -1,314 +0,0 @@ -package net.minecraft.server; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - -import java.util.Iterator; -import java.util.List; -import javax.annotation.Nullable; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -// CraftBukkit Start -import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor; -// CraftBukkit end - -/** - * Akarin Changes Note - * 1) Check whether players empty (performance, MC-120780) - */ -public class PlayerChunk { - - private static final Logger a = LogManager.getLogger(); - private final PlayerChunkMap playerChunkMap; - public final List c = Lists.newArrayList(); // CraftBukkit - public - private final ChunkCoordIntPair location; - private final short[] dirtyBlocks = new short[64]; - @Nullable - public Chunk chunk; // CraftBukkit - public - private int dirtyCount; - private int h; - private long i; - private boolean done; - - // CraftBukkit start - add fields - boolean chunkExists; // Paper - private boolean loadInProgress = false; - private Runnable loadedRunnable = new Runnable() { - @Override - public void run() { - loadInProgress = false; - PlayerChunk.this.chunk = PlayerChunk.this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(location.x, location.z); - markChunkUsed(); // Paper - delay chunk unloads - } - }; - // Paper start - delay chunk unloads - public final void markChunkUsed() { - if (chunk != null && chunk.scheduledForUnload != null) { - chunk.scheduledForUnload = null; - } - } - // Paper end - // CraftBukkit end - - public PlayerChunk(PlayerChunkMap playerchunkmap, int i, int j) { - this.playerChunkMap = playerchunkmap; - this.location = new ChunkCoordIntPair(i, j); - // CraftBukkit start - loadInProgress = true; - this.chunk = playerchunkmap.getWorld().getChunkProviderServer().getChunkAt(i, j, loadedRunnable, false); - this.chunkExists = this.chunk != null || ChunkIOExecutor.hasQueuedChunkLoad(playerChunkMap.getWorld(), i, j); // Paper - markChunkUsed(); // Paper - delay chunk unloads - // CraftBukkit end - } - - public ChunkCoordIntPair a() { - return this.location; - } - - public void a(final EntityPlayer entityplayer) { // CraftBukkit - added final to argument - if (this.c.contains(entityplayer)) { - PlayerChunk.a.debug("Failed to add player. {} already is in chunk {}, {}", entityplayer, Integer.valueOf(this.location.x), Integer.valueOf(this.location.z)); - } else { - if (this.c.isEmpty()) { - this.i = this.playerChunkMap.getWorld().getTime(); - } - - this.c.add(entityplayer); - // CraftBukkit start - use async chunk io - // if (this.done) { - // this.sendChunk(entityplayer); - // } - if (this.done) { - this.sendChunk(entityplayer); - } - // CraftBukkit end - - } - } - - public void b(EntityPlayer entityplayer) { - if (this.c.contains(entityplayer)) { - // CraftBukkit start - If we haven't loaded yet don't load the chunk just so we can clean it up - if (!this.done) { - this.c.remove(entityplayer); - - if (this.c.isEmpty()) { - ChunkIOExecutor.dropQueuedChunkLoad(this.playerChunkMap.getWorld(), this.location.x, this.location.z, this.loadedRunnable); - this.playerChunkMap.b(this); - } - - return; - } - // CraftBukkit end - if (this.done) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutUnloadChunk(this.location.x, this.location.z)); - } - - this.c.remove(entityplayer); - if (this.c.isEmpty()) { - this.playerChunkMap.b(this); - } - - } - } - - public boolean a(boolean flag) { - if (this.chunk != null) { - return true; - } else { - /* CraftBukkit start - if (flag) { - this.chunk = this.playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(this.location.x, this.location.z); - } else { - this.chunk = this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(this.location.x, this.location.z); - } - */ - if (!loadInProgress) { - loadInProgress = true; - this.chunk = playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(this.location.x, this.location.z, loadedRunnable, flag); - markChunkUsed(); // Paper - delay chunk unloads - } - // CraftBukkit end - - return this.chunk != null; - } - } - - public boolean b() { - if (this.done) { - return true; - } else if (this.chunk == null) { - return false; - } else if (!this.chunk.isReady()) { - return false; - } else if (!this.chunk.world.chunkPacketBlockController.onChunkPacketCreate(this.chunk, '\uffff', false)) { // Paper - Anti-Xray - Load nearby chunks if necessary - return false; // Paper - Anti-Xray - Wait and try again later - } else { - this.dirtyCount = 0; - this.h = 0; - this.done = true; - if (c.isEmpty()) return true; // Akarin - Fixes MC-120780 - PacketPlayOutMapChunk packetplayoutmapchunk = new PacketPlayOutMapChunk(this.chunk, '\uffff'); - Iterator iterator = this.c.iterator(); - - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - entityplayer.playerConnection.sendPacket(packetplayoutmapchunk); - this.playerChunkMap.getWorld().getTracker().a(entityplayer, this.chunk); - } - - return true; - } - } - - public void sendChunk(EntityPlayer entityplayer) { - if (this.done) { - this.chunk.world.chunkPacketBlockController.onChunkPacketCreate(this.chunk, '\uffff', true); // Paper - Anti-Xray - Load nearby chunks if necessary - entityplayer.playerConnection.sendPacket(new PacketPlayOutMapChunk(this.chunk, '\uffff')); - this.playerChunkMap.getWorld().getTracker().a(entityplayer, this.chunk); - } - } - - public void c() { - long i = this.playerChunkMap.getWorld().getTime(); - - if (this.chunk != null) { - this.chunk.c(this.chunk.x() + i - this.i); - } - - this.i = i; - } - - public void a(int i, int j, int k) { - if (this.done) { - if (this.dirtyCount == 0) { - this.playerChunkMap.a(this); - } - - this.h |= 1 << (j >> 4); - if (this.dirtyCount < 64) { - short short0 = (short) (i << 12 | k << 8 | j); - - for (int l = 0; l < this.dirtyCount; ++l) { - if (this.dirtyBlocks[l] == short0) { - return; - } - } - - this.dirtyBlocks[this.dirtyCount++] = short0; - } - - } - } - - public void a(Packet packet) { - if (this.done) { - for (int i = 0; i < this.c.size(); ++i) { - this.c.get(i).playerConnection.sendPacket(packet); - } - - } - } - - public void d() { - if (this.done && this.chunk != null) { - if (this.dirtyCount != 0) { - int i; - int j; - int k; - - if (this.dirtyCount == 1) { - i = (this.dirtyBlocks[0] >> 12 & 15) + this.location.x * 16; - j = this.dirtyBlocks[0] & 255; - k = (this.dirtyBlocks[0] >> 8 & 15) + this.location.z * 16; - BlockPosition blockposition = new BlockPosition(i, j, k); - - this.a((new PacketPlayOutBlockChange(this.playerChunkMap.getWorld(), blockposition))); - if (this.playerChunkMap.getWorld().getType(blockposition).getBlock().isTileEntity()) { - this.a(this.playerChunkMap.getWorld().getTileEntity(blockposition)); - } - } else if (this.dirtyCount == 64) { - // Paper - Anti-Xray - Loading chunks here could cause a ConcurrentModificationException #1104 - //this.chunk.world.chunkPacketBlockController.onChunkPacketCreate(this.chunk, this.h, true); // Paper - Anti-Xray - Load nearby chunks if necessary - this.a((new PacketPlayOutMapChunk(this.chunk, this.h))); - } else { - this.a((new PacketPlayOutMultiBlockChange(this.dirtyCount, this.dirtyBlocks, this.chunk))); - - for (i = 0; i < this.dirtyCount; ++i) { - j = (this.dirtyBlocks[i] >> 12 & 15) + this.location.x * 16; - k = this.dirtyBlocks[i] & 255; - int l = (this.dirtyBlocks[i] >> 8 & 15) + this.location.z * 16; - BlockPosition blockposition1 = new BlockPosition(j, k, l); - - if (this.playerChunkMap.getWorld().getType(blockposition1).getBlock().isTileEntity()) { - this.a(this.playerChunkMap.getWorld().getTileEntity(blockposition1)); - } - } - } - - this.dirtyCount = 0; - this.h = 0; - } - } - } - - private void a(@Nullable TileEntity tileentity) { - if (tileentity != null) { - PacketPlayOutTileEntityData packetplayouttileentitydata = tileentity.getUpdatePacket(); - - if (packetplayouttileentitydata != null) { - this.a(packetplayouttileentitydata); - } - } - - } - - public boolean d(EntityPlayer entityplayer) { - return this.c.contains(entityplayer); - } - - public boolean a(Predicate predicate) { - return Iterables.tryFind(this.c, predicate).isPresent(); - } - - public boolean a(double d0, Predicate predicate) { - int i = 0; - - for (int j = this.c.size(); i < j; ++i) { - EntityPlayer entityplayer = this.c.get(i); - - if (predicate.apply(entityplayer) && this.location.a(entityplayer) < d0 * d0) { - return true; - } - } - - return false; - } - - public boolean e() { - return this.done; - } - - @Nullable - public Chunk f() { - return this.chunk; - } - - public double g() { - double d0 = Double.MAX_VALUE; - Iterator iterator = this.c.iterator(); - - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - double d1 = this.location.a(entityplayer); - - if (d1 < d0) { - d0 = d1; - } - } - - return d0; - } -} diff --git a/sources/src/main/java/net/minecraft/server/PlayerChunkMap.java b/sources/src/main/java/net/minecraft/server/PlayerChunkMap.java new file mode 100644 index 000000000..cd24abaeb --- /dev/null +++ b/sources/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -0,0 +1,573 @@ +package net.minecraft.server; + +import co.aikar.timings.Timing; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Predicate; +import javax.annotation.Nullable; +import javax.annotation.concurrent.ThreadSafe; + +// CraftBukkit start +import java.util.LinkedList; +// CraftBukkit end + +/** + * Akarin Changes Note + * 1) Make whole class thread-safe (safety issue) + */ +@ThreadSafe // Akarin - idk why we need do so!! +public class PlayerChunkMap { + + private static final Predicate a = (entityplayer) -> { + return entityplayer != null && !entityplayer.isSpectator(); + }; + private static final Predicate b = (entityplayer) -> { + return entityplayer != null && (!entityplayer.isSpectator() || entityplayer.getWorldServer().getGameRules().getBoolean("spectatorsGenerateChunks")); + }; + private final WorldServer world; + private final List managedPlayers = Lists.newArrayList(); + private final ReentrantReadWriteLock managedPlayersLock = new ReentrantReadWriteLock(); // Akarin - add lock + private final Long2ObjectMap e = new Long2ObjectOpenHashMap(4096); + private final Set f = Sets.newHashSet(); + private final List g = Lists.newLinkedList(); + private final List h = Lists.newLinkedList(); + private final List i = Lists.newCopyOnWriteArrayList(); // Akarin - bad plugin will access this + private AtomicInteger j = new AtomicInteger(); public int getViewDistance() { return j.get(); } // Paper OBFHELPER // Akarin - atmoic + private long k; + private AtomicBoolean l = new AtomicBoolean(true); // Akarin - atmoic + private AtomicBoolean m = new AtomicBoolean(true); // Akarin - atmoic + private boolean wasNotEmpty; // CraftBukkit - add field + + public PlayerChunkMap(WorldServer worldserver) { + this.world = worldserver; + this.a(worldserver.spigotConfig.viewDistance); // Spigot + } + + public WorldServer getWorld() { + return this.world; + } + + public Iterator b() { + final Iterator iterator = this.i.iterator(); + + return new AbstractIterator() { + protected Chunk a() { + while (true) { + if (iterator.hasNext()) { + PlayerChunk playerchunk = (PlayerChunk) iterator.next(); + Chunk chunk = playerchunk.f(); + + if (chunk == null) { + continue; + } + + if (!chunk.v()) { + return chunk; + } + + if (!playerchunk.a(128.0D, PlayerChunkMap.a)) { + continue; + } + + return chunk; + } + + return (Chunk) this.endOfData(); + } + } + + protected Object computeNext() { + return this.a(); + } + }; + } + + public synchronized void flush() { // Akarin - synchronized + long i = this.world.getTime(); + int j; + PlayerChunk playerchunk; + + if (i - this.k > 8000L) { + try (Timing ignored = world.timings.doChunkMapUpdate.startTiming()) { // Paper + this.k = i; + + for (j = 0; j < this.i.size(); ++j) { + playerchunk = (PlayerChunk) this.i.get(j); + playerchunk.d(); + playerchunk.c(); + } + } // Paper timing + } + + if (!this.f.isEmpty()) { + try (Timing ignored = world.timings.doChunkMapToUpdate.startTiming()) { // Paper + Iterator iterator = this.f.iterator(); + + while (iterator.hasNext()) { + playerchunk = (PlayerChunk) iterator.next(); + playerchunk.d(); + } + + this.f.clear(); + } // Paper timing + } + + if (this.l.get() && i % 4L == 0L) { // Akarin + this.l.getAndSet(false); // Akarin + try (Timing ignored = world.timings.doChunkMapSortMissing.startTiming()) { // Paper + // CraftBukkit start + Collections.sort(this.h, (playerchunkx, playerchunk1x) -> { + return ComparisonChain.start().compare(playerchunkx.g(), playerchunk1x.g()).result(); + }); + } // Paper timing + } + + if (this.m.get() && i % 4L == 2L) { // Akarin + this.m.getAndSet(false); // Akarin + try (Timing ignored = world.timings.doChunkMapSortSendToPlayers.startTiming()) { // Paper + Collections.sort(this.g, (playerchunkx, playerchunk1x) -> { + return ComparisonChain.start().compare(playerchunkx.g(), playerchunk1x.g()).result(); + }); + } // Paper timing + // CraftBukkit end + } + + if (!this.h.isEmpty()) { + try (Timing ignored = world.timings.doChunkMapPlayersNeedingChunks.startTiming()) { // Paper + // Spigot start + org.spigotmc.SlackActivityAccountant activityAccountant = this.world.getMinecraftServer().slackActivityAccountant; + activityAccountant.startActivity(0.5); + int chunkGensAllowed = world.paperConfig.maxChunkGensPerTick; // Paper + // Spigot end + + Iterator iterator1 = this.h.iterator(); + + while (iterator1.hasNext()) { + PlayerChunk playerchunk1 = (PlayerChunk) iterator1.next(); + + if (playerchunk1.f() == null) { + boolean flag = playerchunk1.a(PlayerChunkMap.b); + // Paper start + if (flag && !playerchunk1.chunkExists && chunkGensAllowed-- <= 0) { + continue; + } + // Paper end + + if (playerchunk1.a(flag)) { + iterator1.remove(); + if (playerchunk1.b()) { + this.g.remove(playerchunk1); + } + + if (activityAccountant.activityTimeIsExhausted()) { // Spigot + break; + } + } + // CraftBukkit start - SPIGOT-2891: remove once chunk has been provided + } else { + iterator1.remove(); + } + // CraftBukkit end + } + + activityAccountant.endActivity(); // Spigot + } // Paper timing + } + + if (!this.g.isEmpty()) { + j = world.paperConfig.maxChunkSendsPerTick; // Paper + try (Timing ignored = world.timings.doChunkMapPendingSendToPlayers.startTiming()) { // Paper + Iterator iterator2 = this.g.iterator(); + + while (iterator2.hasNext()) { + PlayerChunk playerchunk2 = (PlayerChunk) iterator2.next(); + + if (playerchunk2.b()) { + iterator2.remove(); + --j; + if (j < 0) { + break; + } + } + } + } // Paper timing + } + + managedPlayersLock.readLock().lock(); // Akarin + if (this.managedPlayers.isEmpty()) { + try (Timing ignored = world.timings.doChunkMapUnloadChunks.startTiming()) { // Paper + WorldProvider worldprovider = this.world.worldProvider; + + if (!worldprovider.p() && !this.world.savingDisabled) { // Paper - respect saving disabled setting + this.world.getChunkProviderServer().b(); + } + } // Paper timing + } + managedPlayersLock.readLock().unlock(); // Akarin + + } + + public synchronized boolean a(int i, int j) { // Akarin - synchronized + long k = d(i, j); + + return this.e.get(k) != null; + } + + @Nullable + public synchronized PlayerChunk getChunk(int i, int j) { // Akarin - synchronized + return (PlayerChunk) this.e.get(d(i, j)); + } + + private PlayerChunk c(int i, int j) { + long k = d(i, j); + PlayerChunk playerchunk = (PlayerChunk) this.e.get(k); + + if (playerchunk == null) { + playerchunk = new PlayerChunk(this, i, j); + this.e.put(k, playerchunk); + this.i.add(playerchunk); + if (playerchunk.f() == null) { + this.h.add(playerchunk); + } + + if (!playerchunk.b()) { + this.g.add(playerchunk); + } + } + + return playerchunk; + } + + // CraftBukkit start - add method + public final boolean isChunkInUse(int x, int z) { + PlayerChunk pi = getChunk(x, z); + if (pi != null) { + return (pi.c.size() > 0); + } + return false; + } + // CraftBukkit end + + public void flagDirty(BlockPosition blockposition) { + int i = blockposition.getX() >> 4; + int j = blockposition.getZ() >> 4; + PlayerChunk playerchunk = this.getChunk(i, j); + + if (playerchunk != null) { + playerchunk.a(blockposition.getX() & 15, blockposition.getY(), blockposition.getZ() & 15); + } + + } + + public void addPlayer(EntityPlayer entityplayer) { + int i = (int) entityplayer.locX >> 4; + int j = (int) entityplayer.locZ >> 4; + + entityplayer.d = entityplayer.locX; + entityplayer.e = entityplayer.locZ; + + + // CraftBukkit start - Load nearby chunks first + List chunkList = new LinkedList(); + + // Paper start - Player view distance API + int viewDistance = entityplayer.getViewDistance(); + for (int k = i - viewDistance; k <= i + viewDistance; ++k) { + for (int l = j - viewDistance; l <= j + viewDistance; ++l) { + // Paper end + chunkList.add(new ChunkCoordIntPair(k, l)); + } + } + + Collections.sort(chunkList, new ChunkCoordComparator(entityplayer)); + synchronized (this) { // Akarin - synchronized + for (ChunkCoordIntPair pair : chunkList) { + this.c(pair.x, pair.z).a(entityplayer); + } + } // Akarin + // CraftBukkit end + + managedPlayersLock.writeLock().lock(); // Akarin + this.managedPlayers.add(entityplayer); + managedPlayersLock.writeLock().unlock(); // Akarin + this.e(); + } + + public void removePlayer(EntityPlayer entityplayer) { + int i = (int) entityplayer.d >> 4; + int j = (int) entityplayer.e >> 4; + + // Paper start - Player view distance API + int viewDistance = entityplayer.getViewDistance(); + for (int k = i - viewDistance; k <= i + viewDistance; ++k) { + for (int l = j - viewDistance; l <= j + viewDistance; ++l) { + // Paper end + PlayerChunk playerchunk = this.getChunk(k, l); + + if (playerchunk != null) { + playerchunk.b(entityplayer); + } + } + } + + managedPlayersLock.writeLock().lock(); // Akarin + this.managedPlayers.remove(entityplayer); + managedPlayersLock.writeLock().unlock(); // Akarin + this.e(); + } + + private boolean a(int i, int j, int k, int l, int i1) { + int j1 = i - k; + int k1 = j - l; + + return j1 >= -i1 && j1 <= i1 ? k1 >= -i1 && k1 <= i1 : false; + } + + public void movePlayer(EntityPlayer entityplayer) { + int i = (int) entityplayer.locX >> 4; + int j = (int) entityplayer.locZ >> 4; + double d0 = entityplayer.d - entityplayer.locX; + double d1 = entityplayer.e - entityplayer.locZ; + double d2 = d0 * d0 + d1 * d1; + + if (d2 >= 64.0D) { + int k = (int) entityplayer.d >> 4; + int l = (int) entityplayer.e >> 4; + final int viewDistance = entityplayer.getViewDistance(); // Paper - Player view distance API + int i1 = Math.max(getViewDistance(), viewDistance); // Paper - Player view distance API + + int j1 = i - k; + int k1 = j - l; + + List chunksToLoad = new LinkedList(); // CraftBukkit + + if (j1 != 0 || k1 != 0) { + for (int l1 = i - i1; l1 <= i + i1; ++l1) { + for (int i2 = j - i1; i2 <= j + i1; ++i2) { + if (!this.a(l1, i2, k, l, viewDistance)) { // Paper - Player view distance API + // this.c(l1, i2).a(entityplayer); + chunksToLoad.add(new ChunkCoordIntPair(l1, i2)); // CraftBukkit + } + + if (!this.a(l1 - j1, i2 - k1, i, j, i1)) { + PlayerChunk playerchunk = this.getChunk(l1 - j1, i2 - k1); + + if (playerchunk != null) { + playerchunk.b(entityplayer); + } + } + } + } + + entityplayer.d = entityplayer.locX; + entityplayer.e = entityplayer.locZ; + this.e(); + + // CraftBukkit start - send nearest chunks first + Collections.sort(chunksToLoad, new ChunkCoordComparator(entityplayer)); + synchronized (this) { // Akarin - synchronized + for (ChunkCoordIntPair pair : chunksToLoad) { + this.c(pair.x, pair.z).a(entityplayer); + } + } // Akarin + // CraftBukkit end + } + } + } + + public boolean a(EntityPlayer entityplayer, int i, int j) { + PlayerChunk playerchunk = this.getChunk(i, j); + + return playerchunk != null && playerchunk.d(entityplayer) && playerchunk.e(); + } + + public final void setViewDistanceForAll(int viewDistance) { this.a(viewDistance); } // Paper - OBFHELPER + // Paper start - Separate into two methods + public void a(int i) { + i = MathHelper.clamp(i, 3, 32); + if (i != this.j.get()) { // Akarin + int j = i - this.j.get(); // Akarin + managedPlayersLock.readLock().lock(); // Akarin + ArrayList arraylist = Lists.newArrayList(this.managedPlayers); + managedPlayersLock.readLock().unlock(); // Akarin + Iterator iterator = arraylist.iterator(); + + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + this.setViewDistance(entityplayer, i, false); // Paper - Split, don't mark sort pending, we'll handle it after + } + + this.j.getAndSet(i); // Akarin + this.e(); + } + } + + public void setViewDistance(EntityPlayer entityplayer, int i) { + this.setViewDistance(entityplayer, i, true); // Mark sort pending by default so we don't have to remember to do so all the time + } + + // Copied from above with minor changes + public void setViewDistance(EntityPlayer entityplayer, int i, boolean markSort) { + i = MathHelper.clamp(i, 3, 32); + int oldViewDistance = entityplayer.getViewDistance(); + if (i != oldViewDistance) { + int j = i - oldViewDistance; + + int k = (int) entityplayer.locX >> 4; + int l = (int) entityplayer.locZ >> 4; + int i1; + int j1; + + if (j > 0) { + synchronized (this) { // Akarin - synchronized + for (i1 = k - i; i1 <= k + i; ++i1) { + for (j1 = l - i; j1 <= l + i; ++j1) { + PlayerChunk playerchunk = this.c(i1, j1); + + if (!playerchunk.d(entityplayer)) { + playerchunk.a(entityplayer); + } + } + } + } // Akarin + } else { + synchronized (this) { // Akarin - synchronized + for (i1 = k - oldViewDistance; i1 <= k + oldViewDistance; ++i1) { + for (j1 = l - oldViewDistance; j1 <= l + oldViewDistance; ++j1) { + if (!this.a(i1, j1, k, l, i)) { + this.c(i1, j1).b(entityplayer); + } + } + } + } // Akarin + if (markSort) { + this.e(); + } + } + } + } + // Paper end + + private void e() { + this.l.getAndSet(true); // Akarin + this.m.getAndSet(true); // Akarin + } + + public static int getFurthestViewableBlock(int i) { + return i * 16 - 16; + } + + private static long d(int i, int j) { + return (long) i + 2147483647L | (long) j + 2147483647L << 32; + } + + public synchronized void a(PlayerChunk playerchunk) { // Akarin - synchronized + org.spigotmc.AsyncCatcher.catchOp("Async Player Chunk Add"); // Paper + this.f.add(playerchunk); + } + + public synchronized void b(PlayerChunk playerchunk) { // Akarin - synchronized + org.spigotmc.AsyncCatcher.catchOp("Async Player Chunk Remove"); // Paper + ChunkCoordIntPair chunkcoordintpair = playerchunk.a(); + long i = d(chunkcoordintpair.x, chunkcoordintpair.z); + + playerchunk.c(); + this.e.remove(i); + this.i.remove(playerchunk); + this.f.remove(playerchunk); + this.g.remove(playerchunk); + this.h.remove(playerchunk); + Chunk chunk = playerchunk.f(); + + if (chunk != null) { + // Paper start - delay chunk unloads + if (world.paperConfig.delayChunkUnloadsBy <= 0) { + this.getWorld().getChunkProviderServer().unload(chunk); + } else { + chunk.scheduledForUnload = System.currentTimeMillis(); + } + // Paper end + } + + } + + // CraftBukkit start - Sorter to load nearby chunks first + private static class ChunkCoordComparator implements java.util.Comparator { + private int x; + private int z; + + public ChunkCoordComparator (EntityPlayer entityplayer) { + x = (int) entityplayer.locX >> 4; + z = (int) entityplayer.locZ >> 4; + } + + public int compare(ChunkCoordIntPair a, ChunkCoordIntPair b) { + if (a.equals(b)) { + return 0; + } + + // Subtract current position to set center point + int ax = a.x - this.x; + int az = a.z - this.z; + int bx = b.x - this.x; + int bz = b.z - this.z; + + int result = ((ax - bx) * (ax + bx)) + ((az - bz) * (az + bz)); + if (result != 0) { + return result; + } + + if (ax < 0) { + if (bx < 0) { + return bz - az; + } else { + return -1; + } + } else { + if (bx < 0) { + return 1; + } else { + return az - bz; + } + } + } + } + // CraftBukkit end + + // Paper start - Player view distance API + public void updateViewDistance(EntityPlayer player, int distanceIn) { + final int oldViewDistance = player.getViewDistance(); + + // This represents the view distance that we will set on the player + // It can exist as a negative value + int playerViewDistance = MathHelper.clamp(distanceIn, 3, 32); + + // This value is the one we actually use to update the chunk map + // We don't ever want this to be a negative + int toSet = playerViewDistance; + + if (distanceIn < 0) { + playerViewDistance = -1; + toSet = world.getPlayerChunkMap().getViewDistance(); + } + + if (toSet != oldViewDistance) { + // Order matters + this.setViewDistance(player, toSet); + player.setViewDistance(playerViewDistance); + } + } + // Paper end +} diff --git a/sources/src/main/java/net/minecraft/server/PlayerConnection.java b/sources/src/main/java/net/minecraft/server/PlayerConnection.java index f892a865e..276f4cf9f 100644 --- a/sources/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/sources/src/main/java/net/minecraft/server/PlayerConnection.java @@ -2,21 +2,20 @@ package net.minecraft.server; import com.google.common.primitives.Doubles; import com.google.common.primitives.Floats; +import com.mojang.brigadier.ParseResults; +import com.mojang.brigadier.suggestion.Suggestions; import io.akarin.api.internal.Akari; import io.akarin.server.core.AkarinGlobalConfig; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; -import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.Set; +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.Location; @@ -25,6 +24,7 @@ import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.craftbukkit.inventory.CraftInventoryView; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.util.CraftChatMessage; +import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.LazyPlayerSet; import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.entity.Player; @@ -56,7 +56,6 @@ 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 @@ -67,6 +66,7 @@ import co.aikar.timings.MinecraftTimings; // Paper * 2) Expose private members (slack service) * 3) Removed keep-alive codes (slack service) * 4) Accessible keep-alive limit (feature, compatibility) + * 5) Automatic pass async command (experience) */ public class PlayerConnection implements PacketListenerPlayIn, ITickable { @@ -75,12 +75,13 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { private final MinecraftServer minecraftServer; public EntityPlayer player; private int e; - private volatile long f = getCurrentMillis(); public void setLastPing(long lastPing) { this.f = lastPing;}; public long getLastPing() { return this.f;}; // Paper - OBFHELPER - set ping to delay initial // Akarin - private -> public - volatile + private volatile long f = SystemUtils.b(); public void setLastPing(long lastPing) { this.f = lastPing;}; public long getLastPing() { return this.f;}; // Paper - OBFHELPER - set ping to delay initial // Akarin - private -> public - volatile private volatile boolean g; public void setPendingPing(boolean isPending) { this.g = isPending;}; public boolean isPendingPing() { return this.g;}; // Paper - OBFHELPER // Akarin - private -> public - volatile private volatile long h; public void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; public long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER // Akarin - private -> public - volatile // CraftBukkit start - multithreaded fields private volatile int chatThrottle; private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); + private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits // CraftBukkit end private int j; private final IntHashMap k = new IntHashMap(); @@ -106,7 +107,6 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { private int E; private int receivedMovePackets; private int processedMovePackets; - private AutoRecipe H = new AutoRecipe(); 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 public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { @@ -142,10 +142,9 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { public CraftPlayer getPlayer() { return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); } - private final static HashSet invalidItems = new HashSet(java.util.Arrays.asList(8, 9, 10, 11, 26, 34, 36, 43, 51, 55, 59, 62, 63, 64, 68, 71, 74, 75, 83, 90, 92, 93, 94, 104, 105, 115, 117, 118, 119, 125, 127, 132, 140, 141, 142, 144)); // TODO: Check after every update. // CraftBukkit end - public void e() { + public void Y_() { this.syncPosition(); this.player.playerTick(); this.player.setLocation(this.l, this.m, this.n, this.player.yaw, this.player.pitch); @@ -153,7 +152,8 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.processedMovePackets = this.receivedMovePackets; if (this.B) { if (++this.C > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getName()); + PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); + this.disconnect(new ChatMessage("multiplayer.disconnect.flying", new Object[0])); this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message return; } @@ -162,17 +162,17 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.C = 0; } - this.r = this.player.getVehicle(); - if (this.r != this.player && this.r.bE() == this.player) { + this.r = this.player.getRootVehicle(); + if (this.r != this.player && this.r.bO() == this.player) { this.s = this.r.locX; this.t = this.r.locY; this.u = this.r.locZ; this.v = this.r.locX; this.w = this.r.locY; this.x = this.r.locZ; - if (this.D && this.player.getVehicle().bE() == this.player) { + if (this.D && this.player.getRootVehicle().bO() == this.player) { if (++this.E > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName()); + PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message return; } @@ -190,13 +190,13 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { /* // Akarin // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings // This should effectively place the keepalive handling back to "as it was" before 1.12.2 - long currentTime = this.getCurrentMillis(); + long currentTime = SystemUtils.b(); long elapsedTime = currentTime - this.getLastPing(); + if (this.isPendingPing()) { - // We're pending a ping from the client if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info - this.disconnect(new ChatMessage("disconnect.timeout")); + this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); } } else { if (elapsedTime >= 15000L) { // 15 seconds @@ -204,14 +204,16 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.setLastPing(currentTime); this.setKeepAliveID(currentTime); this.sendPacket(new PacketPlayOutKeepAlive(this.getKeepAliveID())); + } } // Paper end */ // Akarin - this.minecraftServer.methodProfiler.b(); + this.minecraftServer.methodProfiler.e(); // CraftBukkit start for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable /* Use thread-safe field access instead if (this.chatThrottle > 0) { --this.chatThrottle; @@ -223,7 +225,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { --this.j; } - if (this.player.J() > 0L && this.minecraftServer.getIdleTimeout() > 0 && MinecraftServer.aw() - this.player.J() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { + if (this.player.F() > 0L && this.minecraftServer.getIdleTimeout() > 0 && SystemUtils.b() - this.player.F() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 this.disconnect(new ChatMessage("multiplayer.disconnect.idling", new Object[0])); } @@ -270,26 +272,24 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // Send the possibly modified leave message s = event.getReason(); // CraftBukkit end - final ChatComponentText chatcomponenttext = new ChatComponentText(s); + final ChatComponentText ichatbasecomponent = new ChatComponentText(s); - this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(chatcomponenttext), new GenericFutureListener() { - public void operationComplete(Future future) throws Exception { // CraftBukkit - decompile error - PlayerConnection.this.networkManager.close(chatcomponenttext); - } - }, new GenericFutureListener[0]); - this.a(chatcomponenttext); // CraftBukkit - fire quit instantly - this.networkManager.stopReading(); - // CraftBukkit - Don't wait - this.minecraftServer.postToMainThread(new Runnable() { - public void run() { - PlayerConnection.this.networkManager.handleDisconnection(); - } + this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { + this.networkManager.close(ichatbasecomponent); }); + this.a(ichatbasecomponent); // CraftBukkit - fire quit instantly + this.networkManager.stopReading(); + MinecraftServer minecraftserver = this.minecraftServer; + NetworkManager networkmanager = this.networkManager; + + this.networkManager.getClass(); + // CraftBukkit - Don't wait + minecraftserver.postToMainThread(networkmanager::handleDisconnection); } public void a(PacketPlayInSteerVehicle packetplayinsteervehicle) { - PlayerConnectionUtils.ensureMainThread(packetplayinsteervehicle, this, this.player.x()); - this.player.a(packetplayinsteervehicle.a(), packetplayinsteervehicle.b(), packetplayinsteervehicle.c(), packetplayinsteervehicle.d()); + PlayerConnectionUtils.ensureMainThread(packetplayinsteervehicle, this, this.player.getWorldServer()); + this.player.a(packetplayinsteervehicle.b(), packetplayinsteervehicle.c(), packetplayinsteervehicle.d(), packetplayinsteervehicle.e()); } private static boolean b(PacketPlayInFlying packetplayinflying) { @@ -301,14 +301,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInVehicleMove packetplayinvehiclemove) { - PlayerConnectionUtils.ensureMainThread(packetplayinvehiclemove, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinvehiclemove, this, this.player.getWorldServer()); if (b(packetplayinvehiclemove)) { this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_vehicle_movement", new Object[0])); } else { - Entity entity = this.player.getVehicle(); + Entity entity = this.player.getRootVehicle(); - if (entity != this.player && entity.bE() == this.player && entity == this.r) { - WorldServer worldserver = this.player.x(); + if (entity != this.player && entity.bO() == this.player && entity == this.r) { + WorldServer worldserver = this.player.getWorldServer(); double d0 = entity.locX; double d1 = entity.locY; double d2 = entity.locZ; @@ -341,7 +341,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } else { allowedPlayerTicks = 20; } - float speed; + double speed; if (player.abilities.isFlying) { speed = player.abilities.flySpeed * 20f; } else { @@ -349,14 +349,14 @@ 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.R() || !this.minecraftServer.Q().equals(entity.getName()))) { // Spigot + 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()))) { // CraftBukkit end - PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName(), this.player.getName(), Double.valueOf(d6), Double.valueOf(d7), Double.valueOf(d8)); + 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)); return; } - boolean flag = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)).isEmpty(); + boolean flag = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); d6 = d3 - this.v; d7 = d4 - this.w - 1.0E-6D; @@ -380,7 +380,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } entity.setLocation(d3, d4, d5, f, f1); - boolean flag2 = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)).isEmpty(); + boolean flag2 = worldserver.getCubes(entity, entity.getBoundingBox().shrink(0.0625D)); if (flag && (flag1 || !flag2)) { entity.setLocation(d0, d1, d2, f, f1); @@ -458,7 +458,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.minecraftServer.getPlayerList().d(this.player); this.player.checkMovement(this.player.locX - d0, this.player.locY - d1, this.player.locZ - d2); - this.D = d11 >= -0.03125D && !this.minecraftServer.getAllowFlight() && !worldserver.c(entity.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D)); + this.D = d11 >= -0.03125D && !this.minecraftServer.getAllowFlight() && !worldserver.a(entity.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D)); this.v = entity.locX; this.w = entity.locY; this.x = entity.locZ; @@ -468,14 +468,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInTeleportAccept packetplayinteleportaccept) { - PlayerConnectionUtils.ensureMainThread(packetplayinteleportaccept, this, this.player.x()); - if (packetplayinteleportaccept.a() == this.teleportAwait && this.teleportPos != null) { // CraftBukkit + 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); - if (this.player.L()) { + if (this.player.H()) { this.o = this.teleportPos.x; this.p = this.teleportPos.y; this.q = this.teleportPos.z; - this.player.M(); + this.player.I(); } this.teleportPos = null; @@ -484,20 +484,26 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInRecipeDisplayed packetplayinrecipedisplayed) { - PlayerConnectionUtils.ensureMainThread(packetplayinrecipedisplayed, this, this.player.x()); - if (packetplayinrecipedisplayed.a() == PacketPlayInRecipeDisplayed.Status.SHOWN) { - this.player.F().f(packetplayinrecipedisplayed.b()); - } else if (packetplayinrecipedisplayed.a() == PacketPlayInRecipeDisplayed.Status.SETTINGS) { - this.player.F().a(packetplayinrecipedisplayed.c()); - this.player.F().b(packetplayinrecipedisplayed.d()); + PlayerConnectionUtils.ensureMainThread(packetplayinrecipedisplayed, this, this.player.getWorldServer()); + if (packetplayinrecipedisplayed.b() == PacketPlayInRecipeDisplayed.Status.SHOWN) { + IRecipe irecipe = this.minecraftServer.getCraftingManager().a(packetplayinrecipedisplayed.c()); + + if (irecipe != null) { + this.player.B().e(irecipe); + } + } else if (packetplayinrecipedisplayed.b() == PacketPlayInRecipeDisplayed.Status.SETTINGS) { + this.player.B().a(packetplayinrecipedisplayed.d()); + this.player.B().b(packetplayinrecipedisplayed.e()); + this.player.B().c(packetplayinrecipedisplayed.f()); + this.player.B().d(packetplayinrecipedisplayed.g()); } } public void a(PacketPlayInAdvancements packetplayinadvancements) { - PlayerConnectionUtils.ensureMainThread(packetplayinadvancements, this, this.player.x()); - if (packetplayinadvancements.b() == PacketPlayInAdvancements.Status.OPENED_TAB) { - MinecraftKey minecraftkey = packetplayinadvancements.c(); + PlayerConnectionUtils.ensureMainThread(packetplayinadvancements, this, this.player.getWorldServer()); + if (packetplayinadvancements.c() == PacketPlayInAdvancements.Status.OPENED_TAB) { + MinecraftKey minecraftkey = packetplayinadvancements.d(); Advancement advancement = this.minecraftServer.getAdvancementData().a(minecraftkey); if (advancement != null) { @@ -507,8 +513,324 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } + public void a(PacketPlayInTabComplete packetplayintabcomplete) { + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable + this.disconnect(new ChatMessage("disconnect.spam", new Object[0])); + minecraftServer.postToMainThread(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper + return; + } + // Paper start + com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; + java.util.List completions = new java.util.ArrayList<>(); + String buffer = packetplayintabcomplete.c(); + event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, + buffer, true, null); + event.callEvent(); + completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); + if (event.isCancelled() || event.isHandled()) { + + // Still fire sync event with the provided completions, if someone is listening + if (!event.isCancelled() && org.bukkit.event.server.TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { + java.util.List finalCompletions = completions; + Waitable> syncCompletions = new Waitable>() { + @Override + protected java.util.List evaluate() { + org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(PlayerConnection.this.getPlayer(), buffer, finalCompletions, true, null); + return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); + } + }; + server.getServer().processQueue.add(syncCompletions); + try { + completions = syncCompletions.get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } + } + java.util.List otherSuggestions = completions; + minecraftServer.postToMainThread(() -> sendSuggestions(packetplayintabcomplete, otherSuggestions)); + return; + } + minecraftServer.postToMainThread(() -> sendSuggestions(packetplayintabcomplete, null)); + } + public void sendSuggestions(PacketPlayInTabComplete packetplayintabcomplete, java.util.List otherSuggestions) { + + ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(packetplayintabcomplete.c(), this.player.getCommandListener()); + //noinspection unchecked + java.util.concurrent.CompletableFuture completionSuggestions = this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults); + completionSuggestions.thenAccept((Suggestions suggestions) -> { + if (otherSuggestions != null && !otherSuggestions.isEmpty()) { + com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), packetplayintabcomplete.b()); + otherSuggestions.forEach(builder::suggest); + suggestions.getList().addAll(builder.build().getList()); + } + // Paper end + if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer + this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); // CraftBukkit - decompile error + }); + } + + public void a(PacketPlayInSetCommandBlock packetplayinsetcommandblock) { + PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandblock, this, this.player.getWorldServer()); + if (!this.minecraftServer.getEnableCommandBlock()) { + this.player.sendMessage(new ChatMessage("advMode.notEnabled", new Object[0])); + } else if (!this.player.isCreativeAndOp()) { + this.player.sendMessage(new ChatMessage("advMode.notAllowed", new Object[0])); + } else { + CommandBlockListenerAbstract commandblocklistenerabstract = null; + TileEntityCommand tileentitycommand = null; + BlockPosition blockposition = packetplayinsetcommandblock.b(); + TileEntity tileentity = this.player.world.getTileEntity(blockposition); + + if (tileentity instanceof TileEntityCommand) { + tileentitycommand = (TileEntityCommand) tileentity; + commandblocklistenerabstract = tileentitycommand.getCommandBlock(); + } + + String s = packetplayinsetcommandblock.c(); + boolean flag = packetplayinsetcommandblock.d(); + + if (commandblocklistenerabstract != null) { + EnumDirection enumdirection = (EnumDirection) this.player.world.getType(blockposition).get(BlockCommand.a); + IBlockData iblockdata; + + switch (packetplayinsetcommandblock.g()) { + case SEQUENCE: + iblockdata = Blocks.CHAIN_COMMAND_BLOCK.getBlockData(); + this.player.world.setTypeAndData(blockposition, (IBlockData) ((IBlockData) iblockdata.set(BlockCommand.a, enumdirection)).set(BlockCommand.b, Boolean.valueOf(packetplayinsetcommandblock.e())), 2); + break; + + case AUTO: + iblockdata = Blocks.REPEATING_COMMAND_BLOCK.getBlockData(); + this.player.world.setTypeAndData(blockposition, (IBlockData) ((IBlockData) iblockdata.set(BlockCommand.a, enumdirection)).set(BlockCommand.b, Boolean.valueOf(packetplayinsetcommandblock.e())), 2); + break; + + case REDSTONE: + default: + iblockdata = Blocks.COMMAND_BLOCK.getBlockData(); + this.player.world.setTypeAndData(blockposition, (IBlockData) ((IBlockData) iblockdata.set(BlockCommand.a, enumdirection)).set(BlockCommand.b, Boolean.valueOf(packetplayinsetcommandblock.e())), 2); + } + + tileentity.z(); + this.player.world.setTileEntity(blockposition, tileentity); + commandblocklistenerabstract.setCommand(s); + commandblocklistenerabstract.a(flag); + if (!flag) { + commandblocklistenerabstract.c((IChatBaseComponent) null); + } + + tileentitycommand.b(packetplayinsetcommandblock.f()); + commandblocklistenerabstract.e(); + if (!UtilColor.b(s)) { + this.player.sendMessage(new ChatMessage("advMode.setCommand.success", new Object[] { s})); + } + } + + } + } + + public void a(PacketPlayInSetCommandMinecart packetplayinsetcommandminecart) { + PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandminecart, this, this.player.getWorldServer()); + if (!this.minecraftServer.getEnableCommandBlock()) { + this.player.sendMessage(new ChatMessage("advMode.notEnabled", new Object[0])); + } else if (!this.player.isCreativeAndOp()) { + this.player.sendMessage(new ChatMessage("advMode.notAllowed", new Object[0])); + } else { + CommandBlockListenerAbstract commandblocklistenerabstract = packetplayinsetcommandminecart.a(this.player.world); + + if (commandblocklistenerabstract != null) { + commandblocklistenerabstract.setCommand(packetplayinsetcommandminecart.b()); + commandblocklistenerabstract.a(packetplayinsetcommandminecart.c()); + if (!packetplayinsetcommandminecart.c()) { + commandblocklistenerabstract.c((IChatBaseComponent) null); + } + + commandblocklistenerabstract.e(); + this.player.sendMessage(new ChatMessage("advMode.setCommand.success", new Object[] { packetplayinsetcommandminecart.b()})); + } + + } + } + + public void a(PacketPlayInPickItem packetplayinpickitem) { + PlayerConnectionUtils.ensureMainThread(packetplayinpickitem, this, this.player.getWorldServer()); + this.player.inventory.d(packetplayinpickitem.b()); + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, this.player.inventory.itemInHandIndex, this.player.inventory.getItem(this.player.inventory.itemInHandIndex))); + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, packetplayinpickitem.b(), this.player.inventory.getItem(packetplayinpickitem.b()))); + this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); + } + + public void a(PacketPlayInItemName packetplayinitemname) { + PlayerConnectionUtils.ensureMainThread(packetplayinitemname, this, this.player.getWorldServer()); + if (this.player.activeContainer instanceof ContainerAnvil) { + ContainerAnvil containeranvil = (ContainerAnvil) this.player.activeContainer; + String s = SharedConstants.a(packetplayinitemname.b()); + + if (s.length() <= 35) { + containeranvil.a(s); + } + } + + } + + public void a(PacketPlayInBeacon packetplayinbeacon) { + PlayerConnectionUtils.ensureMainThread(packetplayinbeacon, this, this.player.getWorldServer()); + if (this.player.activeContainer instanceof ContainerBeacon) { + ContainerBeacon containerbeacon = (ContainerBeacon) this.player.activeContainer; + Slot slot = containerbeacon.getSlot(0); + + if (slot.hasItem()) { + slot.a(1); + IInventory iinventory = containerbeacon.d(); + + iinventory.setProperty(1, packetplayinbeacon.b()); + iinventory.setProperty(2, packetplayinbeacon.c()); + iinventory.update(); + } + } + + } + + public void a(PacketPlayInStruct packetplayinstruct) { + PlayerConnectionUtils.ensureMainThread(packetplayinstruct, this, this.player.getWorldServer()); + if (this.player.isCreativeAndOp()) { + BlockPosition blockposition = packetplayinstruct.b(); + IBlockData iblockdata = this.player.world.getType(blockposition); + TileEntity tileentity = this.player.world.getTileEntity(blockposition); + + if (tileentity instanceof TileEntityStructure) { + TileEntityStructure tileentitystructure = (TileEntityStructure) tileentity; + + tileentitystructure.setUsageMode(packetplayinstruct.d()); + tileentitystructure.setStructureName(packetplayinstruct.e()); + tileentitystructure.b(packetplayinstruct.f()); + tileentitystructure.c(packetplayinstruct.g()); + tileentitystructure.b(packetplayinstruct.h()); + tileentitystructure.b(packetplayinstruct.i()); + tileentitystructure.b(packetplayinstruct.j()); + tileentitystructure.a(packetplayinstruct.k()); + tileentitystructure.e(packetplayinstruct.l()); + tileentitystructure.f(packetplayinstruct.m()); + tileentitystructure.a(packetplayinstruct.n()); + tileentitystructure.a(packetplayinstruct.o()); + if (tileentitystructure.d()) { + String s = tileentitystructure.getStructureName(); + + if (packetplayinstruct.c() == TileEntityStructure.UpdateType.SAVE_AREA) { + if (tileentitystructure.q()) { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.save_success", new Object[] { s})), false); + } else { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.save_failure", new Object[] { s})), false); + } + } else if (packetplayinstruct.c() == TileEntityStructure.UpdateType.LOAD_AREA) { + if (!tileentitystructure.D()) { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.load_not_found", new Object[] { s})), false); + } else if (tileentitystructure.r()) { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.load_success", new Object[] { s})), false); + } else { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.load_prepare", new Object[] { s})), false); + } + } else if (packetplayinstruct.c() == TileEntityStructure.UpdateType.SCAN_AREA) { + if (tileentitystructure.p()) { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.size_success", new Object[] { s})), false); + } else { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.size_failure", new Object[0])), false); + } + } + } else { + this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.invalid_structure_name", new Object[] { packetplayinstruct.e()})), false); + } + + tileentitystructure.update(); + this.player.world.notify(blockposition, iblockdata, iblockdata, 3); + } + + } + } + + public void a(PacketPlayInTrSel packetplayintrsel) { + PlayerConnectionUtils.ensureMainThread(packetplayintrsel, this, this.player.getWorldServer()); + int i = packetplayintrsel.b(); + Container container = this.player.activeContainer; + + if (container instanceof ContainerMerchant) { + ((ContainerMerchant) container).d(i); + } + + } + + public void a(PacketPlayInBEdit packetplayinbedit) { + // CraftBukkit start + PlayerConnectionUtils.ensureMainThread(packetplayinbedit, this, this.player.getWorldServer()); + if (this.lastBookTick + 20 > MinecraftServer.currentTick) { + this.disconnect("Book edited too quickly!"); + return; + } + this.lastBookTick = MinecraftServer.currentTick; + // CraftBukkit end + ItemStack itemstack = packetplayinbedit.b(); + + if (!itemstack.isEmpty()) { + if (ItemBookAndQuill.b(itemstack.getTag())) { + ItemStack itemstack1 = this.player.getItemInMainHand(); + + if (!itemstack1.isEmpty()) { + if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack1.getItem() == Items.WRITABLE_BOOK) { + if (packetplayinbedit.c()) { + ItemStack itemstack2 = new ItemStack(Items.WRITTEN_BOOK); + + itemstack2.a("author", (NBTBase) (new NBTTagString(this.player.getDisplayName().getString()))); + itemstack2.a("title", (NBTBase) (new NBTTagString(itemstack.getTag().getString("title")))); + NBTTagList nbttaglist = itemstack.getTag().getList("pages", 8); + + for (int i = 0; i < nbttaglist.size(); ++i) { + String s = nbttaglist.getString(i); + ChatComponentText chatcomponenttext = new ChatComponentText(s); + + s = IChatBaseComponent.ChatSerializer.a((IChatBaseComponent) chatcomponenttext); + nbttaglist.set(i, (NBTBase) (new NBTTagString(s))); + } + + itemstack2.a("pages", (NBTBase) nbttaglist); + CraftEventFactory.handleEditBookEvent(player, itemstack2); // CraftBukkit + } else { + itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); + CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit + } + } + + } + } + } + } + + public void a(PacketPlayInEntityNBTQuery packetplayinentitynbtquery) { + PlayerConnectionUtils.ensureMainThread(packetplayinentitynbtquery, this, this.player.getWorldServer()); + if (this.player.k(2)) { + Entity entity = this.player.getWorldServer().getEntity(packetplayinentitynbtquery.c()); + + if (entity != null) { + NBTTagCompound nbttagcompound = entity.save(new NBTTagCompound()); + + this.player.playerConnection.sendPacket(new PacketPlayOutNBTQuery(packetplayinentitynbtquery.b(), nbttagcompound)); + } + + } + } + + public void a(PacketPlayInTileNBTQuery packetplayintilenbtquery) { + PlayerConnectionUtils.ensureMainThread(packetplayintilenbtquery, this, this.player.getWorldServer()); + if (this.player.k(2)) { + TileEntity tileentity = this.player.getWorldServer().getTileEntity(packetplayintilenbtquery.c()); + NBTTagCompound nbttagcompound = tileentity != null ? tileentity.save(new NBTTagCompound()) : null; + + this.player.playerConnection.sendPacket(new PacketPlayOutNBTQuery(packetplayintilenbtquery.b(), nbttagcompound)); + } + } + public void a(PacketPlayInFlying packetplayinflying) { - PlayerConnectionUtils.ensureMainThread(packetplayinflying, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinflying, this, this.player.getWorldServer()); if (b(packetplayinflying)) { this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_player_movement", new Object[0])); } else { @@ -569,7 +891,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.lastTick = (int) (System.currentTimeMillis() / 50); if (i > Math.max(this.allowedPlayerTicks, 5)) { - PlayerConnection.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName(), Integer.valueOf(i)); + PlayerConnection.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getDisplayName().getString(), Integer.valueOf(i)); i = 1; } @@ -578,30 +900,30 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } else { allowedPlayerTicks = 20; } - float speed; + double speed; if (player.abilities.isFlying) { speed = player.abilities.flySpeed * 20f; } else { speed = player.abilities.walkSpeed * 10f; } - if (!this.player.L() && (!this.player.x().getGameRules().getBoolean("disableElytraMovementCheck") || !this.player.cP())) { - float f2 = this.player.cP() ? 300.0F : 100.0F; + 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.R() || !this.minecraftServer.Q().equals(this.player.getName()))) { // Spigot + 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()))) { // CraftBukkit end - PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName(), Double.valueOf(d7), Double.valueOf(d8), Double.valueOf(d9)); + 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); return; } } - boolean flag = worldserver.getCubes(this.player, this.player.getBoundingBox().shrink(0.0625D)).isEmpty(); + boolean flag = worldserver.getCubes(this.player, this.player.getBoundingBox().shrink(0.0625D)); d7 = d4 - this.o; d8 = d5 - this.p; d9 = d6 - this.q; - if (this.player.onGround && !packetplayinflying.a() && d8 > 0.0D) { + if (this.player.onGround && !packetplayinflying.b() && d8 > 0.0D) { // Paper start - Add player jump event Player player = this.getPlayer(); Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. @@ -633,7 +955,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } this.player.move(EnumMoveType.PLAYER, d7, d8, d9); - this.player.onGround = packetplayinflying.a(); + this.player.onGround = packetplayinflying.b(); double d12 = d8; d7 = d4 - this.player.locX; @@ -646,15 +968,15 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { d11 = d7 * d7 + d8 * d8 + d9 * d9; boolean flag1 = false; - if (!this.player.L() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot + if (!this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot flag1 = true; - PlayerConnection.LOGGER.warn("{} moved wrongly!", this.player.getName()); + PlayerConnection.LOGGER.warn("{} moved wrongly!", this.player.getDisplayName().getString()); } this.player.setLocation(d4, d5, d6, f, f1); this.player.checkMovement(this.player.locX - d0, this.player.locY - d1, this.player.locZ - d2); if (!this.player.noclip && !this.player.isSleeping()) { - boolean flag2 = worldserver.getCubes(this.player, this.player.getBoundingBox().shrink(0.0625D)).isEmpty(); + boolean flag2 = worldserver.getCubes(this.player, this.player.getBoundingBox().shrink(0.0625D)); if (flag && (flag1 || !flag2)) { this.a(d0, d1, d2, f, f1); @@ -727,10 +1049,10 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.B = d12 >= -0.03125D; this.B &= !this.minecraftServer.getAllowFlight() && !this.player.abilities.canFly; - this.B &= !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.cP() && !worldserver.c(this.player.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D)); - this.player.onGround = packetplayinflying.a(); + this.B &= !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.dc() && !worldserver.a(this.player.getBoundingBox().g(0.0625D).b(0.0D, -0.55D, 0.0D)); + this.player.onGround = packetplayinflying.b(); this.minecraftServer.getPlayerList().d(this.player); - this.player.a(this.player.locY - d3, packetplayinflying.a()); + this.player.a(this.player.locY - d3, packetplayinflying.b()); this.o = this.player.locX; this.p = this.player.locY; this.q = this.player.locZ; @@ -815,17 +1137,12 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { double d3 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X) ? this.player.locX : 0.0D; double d4 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Y) ? this.player.locY : 0.0D; double d5 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Z) ? this.player.locZ : 0.0D; + float f2 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Y_ROT) ? this.player.yaw : 0.0F; + float f3 = set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X_ROT) ? this.player.pitch : 0.0F; - this.teleportPos = new Vec3D(d0 + d3, d1 + d4, d2 + d5); - float f2 = f; - float f3 = f1; - - if (set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.Y_ROT)) { - f2 = f + this.player.yaw; - } - - if (set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X_ROT)) { - f3 = f1 + this.player.pitch; + this.teleportPos = new Vec3D(d0, d1, d2); + if (++this.teleportAwait == Integer.MAX_VALUE) { + this.teleportAwait = 0; } // CraftBukkit start - update last location @@ -836,37 +1153,42 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.lastPitch = f3; // CraftBukkit end - if (++this.teleportAwait == Integer.MAX_VALUE) { - this.teleportAwait = 0; - } - this.A = this.e; - this.player.setLocation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, f2, f3); - this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0, d1, d2, f, f1, set, this.teleportAwait)); + 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)); } public void a(PacketPlayInBlockDig packetplayinblockdig) { - PlayerConnectionUtils.ensureMainThread(packetplayinblockdig, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinblockdig, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); - BlockPosition blockposition = packetplayinblockdig.a(); + BlockPosition blockposition = packetplayinblockdig.b(); this.player.resetIdleTimer(); - switch (packetplayinblockdig.c()) { + switch (packetplayinblockdig.d()) { case SWAP_HELD_ITEMS: if (!this.player.isSpectator()) { ItemStack itemstack = this.player.b(EnumHand.OFF_HAND); - // CraftBukkit start - PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getPlayer(), CraftItemStack.asBukkitCopy(itemstack), CraftItemStack.asBukkitCopy(this.player.b(EnumHand.MAIN_HAND))); + // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394) + CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack); + CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.b(EnumHand.MAIN_HAND)); + PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getPlayer(), mainHand.clone(), offHand.clone()); this.server.getPluginManager().callEvent(swapItemsEvent); if (swapItemsEvent.isCancelled()) { return; } - itemstack = CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem()); - this.player.a(EnumHand.OFF_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getOffHandItem())); + if (swapItemsEvent.getOffHandItem().equals(offHand)) { + this.player.a(EnumHand.OFF_HAND, this.player.b(EnumHand.MAIN_HAND)); + } else { + this.player.a(EnumHand.OFF_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getOffHandItem())); + } + if (swapItemsEvent.getMainHandItem().equals(mainHand)) { + this.player.a(EnumHand.MAIN_HAND, itemstack); + } else { + this.player.a(EnumHand.MAIN_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem())); + } // CraftBukkit end - this.player.a(EnumHand.MAIN_HAND, itemstack); } return; @@ -919,12 +1241,12 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } else if (blockposition.getY() >= this.minecraftServer.getMaxBuildHeight()) { return; } else { - if (packetplayinblockdig.c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (packetplayinblockdig.d() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { if (!this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) { - this.player.playerInteractManager.a(blockposition, packetplayinblockdig.b()); + this.player.playerInteractManager.a(blockposition, packetplayinblockdig.c()); } else { // CraftBukkit start - fire PlayerInteractEvent - CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, packetplayinblockdig.b(), this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, packetplayinblockdig.c(), this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); // Update any tile entity data for this block TileEntity tileentity = worldserver.getTileEntity(blockposition); @@ -934,13 +1256,13 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // CraftBukkit end } } else { - if (packetplayinblockdig.c() == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) { + if (packetplayinblockdig.d() == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) { this.player.playerInteractManager.a(blockposition); - } else if (packetplayinblockdig.c() == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + } else if (packetplayinblockdig.d() == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { this.player.playerInteractManager.e(); } - if (worldserver.getType(blockposition).getMaterial() != Material.AIR) { + if (!worldserver.getType(blockposition).isAir()) { this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); } } @@ -975,21 +1297,20 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // Spigot end public void a(PacketPlayInUseItem packetplayinuseitem) { - PlayerConnectionUtils.ensureMainThread(packetplayinuseitem, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinuseitem, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit if (!checkLimit(packetplayinuseitem.timestamp)) return; // Spigot - check limit WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); - EnumHand enumhand = packetplayinuseitem.c(); + EnumHand enumhand = packetplayinuseitem.d(); ItemStack itemstack = this.player.b(enumhand); - BlockPosition blockposition = packetplayinuseitem.a(); - EnumDirection enumdirection = packetplayinuseitem.b(); + BlockPosition blockposition = packetplayinuseitem.b(); + EnumDirection enumdirection = packetplayinuseitem.c(); this.player.resetIdleTimer(); if (blockposition.getY() >= this.minecraftServer.getMaxBuildHeight() - 1 && (enumdirection == EnumDirection.UP || blockposition.getY() >= this.minecraftServer.getMaxBuildHeight())) { - ChatMessage chatmessage = new ChatMessage("build.tooHigh", new Object[] { Integer.valueOf(this.minecraftServer.getMaxBuildHeight())}); + IChatBaseComponent ichatbasecomponent = (new ChatMessage("build.tooHigh", new Object[] { Integer.valueOf(this.minecraftServer.getMaxBuildHeight())})).a(EnumChatFormat.RED); - chatmessage.getChatModifier().setColor(EnumChatFormat.RED); - this.player.playerConnection.sendPacket(new PacketPlayOutChat(chatmessage, ChatMessageType.GAME_INFO)); + this.player.playerConnection.sendPacket(new PacketPlayOutChat(ichatbasecomponent, ChatMessageType.GAME_INFO)); } else if (this.teleportPos == null && this.player.d((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && !this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) { // CraftBukkit start - Check if we can actually do something over this large a distance Location eyeLoc = this.getPlayer().getEyeLocation(); @@ -998,7 +1319,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { return; } // CraftBukkit end - this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, blockposition, enumdirection, packetplayinuseitem.d(), packetplayinuseitem.e(), packetplayinuseitem.f()); + this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, blockposition, enumdirection, packetplayinuseitem.e(), packetplayinuseitem.f(), packetplayinuseitem.g()); } this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); @@ -1006,11 +1327,11 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInBlockPlace packetplayinblockplace) { - PlayerConnectionUtils.ensureMainThread(packetplayinblockplace, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinblockplace, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit if (!checkLimit(packetplayinblockplace.timestamp)) return; // Spigot - check limit WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); - EnumHand enumhand = packetplayinblockplace.a(); + EnumHand enumhand = packetplayinblockplace.b(); ItemStack itemstack = this.player.b(enumhand); this.player.resetIdleTimer(); @@ -1032,7 +1353,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { float f8 = f3 * f5; double d3 = player.playerInteractManager.getGameMode()== EnumGamemode.CREATIVE ? 5.0D : 4.5D; Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); - MovingObjectPosition movingobjectposition = this.player.world.rayTrace(vec3d, vec3d1, false); + MovingObjectPosition movingobjectposition = this.player.world.rayTrace(vec3d, vec3d1); boolean cancelled; if (movingobjectposition == null || movingobjectposition.type != MovingObjectPosition.EnumMovingObjectType.BLOCK) { @@ -1058,7 +1379,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInSpectate packetplayinspectate) { - PlayerConnectionUtils.ensureMainThread(packetplayinspectate, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinspectate, this, this.player.getWorldServer()); if (this.player.isSpectator()) { Entity entity = null; WorldServer[] aworldserver = this.minecraftServer.worldServer; @@ -1076,38 +1397,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } if (entity != null) { - this.player.setSpectatorTarget(this.player); - this.player.stopRiding(); - - /* CraftBukkit start - replace with bukkit handling for multi-world - if (entity.world == this.player.world) { - this.player.enderTeleportTo(entity.locX, entity.locY, entity.locZ); - } else { - WorldServer worldserver1 = this.player.x(); - WorldServer worldserver2 = (WorldServer) entity.world; - - this.player.dimension = entity.dimension; - this.sendPacket(new PacketPlayOutRespawn(this.player.dimension, worldserver1.getDifficulty(), worldserver1.getWorldData().getType(), this.player.playerInteractManager.getGameMode())); - this.minecraftServer.getPlayerList().f(this.player); - worldserver1.removeEntity(this.player); - this.player.dead = false; - this.player.setPositionRotation(entity.locX, entity.locY, entity.locZ, entity.yaw, entity.pitch); - if (this.player.isAlive()) { - worldserver1.entityJoinedWorld(this.player, false); - worldserver2.addEntity(this.player); - worldserver2.entityJoinedWorld(this.player, false); - } - - this.player.spawnIn(worldserver2); - this.minecraftServer.getPlayerList().a(this.player, worldserver1); - this.player.enderTeleportTo(entity.locX, entity.locY, entity.locZ); - this.player.playerInteractManager.a(worldserver2); - this.minecraftServer.getPlayerList().b(this.player, worldserver2); - this.minecraftServer.getPlayerList().updateClient(this.player); - } - */ - this.player.getBukkitEntity().teleport(entity.getBukkitEntity(), PlayerTeleportEvent.TeleportCause.SPECTATE); - // CraftBukkit end + this.player.a((WorldServer) entity.world, entity.locX, entity.locY, entity.locZ, entity.yaw, entity.pitch, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit } } @@ -1115,22 +1405,17 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // CraftBukkit start public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { - PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.x()); - // Paper start - //this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); - final PlayerResourcePackStatusEvent.Status status = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; - this.getPlayer().setResourcePackStatus(status); - this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), status)); - // Paper end + PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.getWorldServer()); + this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); } // CraftBukkit end public void a(PacketPlayInBoatMove packetplayinboatmove) { - PlayerConnectionUtils.ensureMainThread(packetplayinboatmove, this, this.player.x()); - Entity entity = this.player.bJ(); + PlayerConnectionUtils.ensureMainThread(packetplayinboatmove, this, this.player.getWorldServer()); + Entity entity = this.player.getVehicle(); if (entity instanceof EntityBoat) { - ((EntityBoat) entity).a(packetplayinboatmove.a(), packetplayinboatmove.b()); + ((EntityBoat) entity).a(packetplayinboatmove.b(), packetplayinboatmove.c()); } } @@ -1143,39 +1428,40 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.processedDisconnect = true; } // CraftBukkit end - PlayerConnection.LOGGER.info("{} lost connection: {}", this.player.getName(), ichatbasecomponent.toPlainText()); + PlayerConnection.LOGGER.info("{} lost connection: {}", this.player.getDisplayName().getString(), ichatbasecomponent.getString()); // CraftBukkit start - Replace vanilla quit message handling with our own. /* - this.minecraftServer.aD(); - ChatMessage chatmessage = new ChatMessage("multiplayer.player.left", new Object[] { this.player.getScoreboardDisplayName()}); - - chatmessage.getChatModifier().setColor(EnumChatFormat.YELLOW); - this.minecraftServer.getPlayerList().sendMessage(chatmessage); + this.minecraftServer.av(); + this.minecraftServer.getPlayerList().sendMessage((new ChatMessage("multiplayer.player.left", new Object[] { this.player.getScoreboardDisplayName()})).a(EnumChatFormat.YELLOW)); */ - this.player.s(); + this.player.n(); String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); if ((quitMessage != null) && (quitMessage.length() > 0)) { this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); } // CraftBukkit end - if (this.minecraftServer.R() && this.player.getName().equals(this.minecraftServer.Q())) { + if (this.minecraftServer.J() && this.player.getDisplayName().getString().equals(this.minecraftServer.I())) { PlayerConnection.LOGGER.info("Stopping singleplayer server as player logged out"); this.minecraftServer.safeShutdown(); } } - public void sendPacket(final Packet packet) { + public void sendPacket(Packet packet) { + this.a(packet, (GenericFutureListener) null); + } + + public void a(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { if (packet instanceof PacketPlayOutChat) { PacketPlayOutChat packetplayoutchat = (PacketPlayOutChat) packet; EntityHuman.EnumChatVisibility entityhuman_enumchatvisibility = this.player.getChatFlags(); - if (entityhuman_enumchatvisibility == EntityHuman.EnumChatVisibility.HIDDEN && packetplayoutchat.c() != ChatMessageType.GAME_INFO) { + if (entityhuman_enumchatvisibility == EntityHuman.EnumChatVisibility.HIDDEN && packetplayoutchat.d() != ChatMessageType.GAME_INFO) { return; } - if (entityhuman_enumchatvisibility == EntityHuman.EnumChatVisibility.SYSTEM && !packetplayoutchat.b()) { + if (entityhuman_enumchatvisibility == EntityHuman.EnumChatVisibility.SYSTEM && !packetplayoutchat.c()) { return; } } @@ -1190,29 +1476,23 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // CraftBukkit end try { - this.networkManager.sendPacket(packet); + this.networkManager.sendPacket(packet, genericfuturelistener); } catch (Throwable throwable) { CrashReport crashreport = CrashReport.a(throwable, "Sending packet"); CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Packet being sent"); - crashreportsystemdetails.a("Packet class", new CrashReportCallable() { - public String a() throws Exception { - return packet.getClass().getCanonicalName(); - } - - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Packet class", () -> { + return packet.getClass().getCanonicalName(); }); throw new ReportedException(crashreport); } } public void a(PacketPlayInHeldItemSlot packetplayinhelditemslot) { - PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit - if (packetplayinhelditemslot.a() >= 0 && packetplayinhelditemslot.a() < PlayerInventory.getHotbarSize()) { - PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.a()); + if (packetplayinhelditemslot.b() >= 0 && packetplayinhelditemslot.b() < PlayerInventory.getHotbarSize()) { + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.b()); this.server.getPluginManager().callEvent(event); if (event.isCancelled()) { this.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); @@ -1220,10 +1500,10 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { return; } // CraftBukkit end - this.player.inventory.itemInHandIndex = packetplayinhelditemslot.a(); + this.player.inventory.itemInHandIndex = packetplayinhelditemslot.b(); this.player.resetIdleTimer(); } else { - PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName()); + PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit //Spigot "Nope" -> Descriptive reason } } @@ -1235,19 +1515,16 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { return; } - boolean isSync = packetplayinchat.a().startsWith("/"); - if (packetplayinchat.a().startsWith("/")) { - PlayerConnectionUtils.ensureMainThread(packetplayinchat, this, this.player.x()); + boolean isSync = packetplayinchat.b().startsWith("/"); + if (packetplayinchat.b().startsWith("/")) { + PlayerConnectionUtils.ensureMainThread(packetplayinchat, this, this.player.getWorldServer()); } // CraftBukkit end if (this.player.dead || this.player.getChatFlags() == EntityHuman.EnumChatVisibility.HIDDEN) { // CraftBukkit - dead men tell no tales - ChatMessage chatmessage = new ChatMessage("chat.cannotSend", new Object[0]); - - chatmessage.getChatModifier().setColor(EnumChatFormat.RED); - this.sendPacket(new PacketPlayOutChat(chatmessage)); + this.sendPacket(new PacketPlayOutChat((new ChatMessage("chat.cannotSend", new Object[0])).a(EnumChatFormat.RED))); } else { this.player.resetIdleTimer(); - String s = packetplayinchat.a(); + String s = packetplayinchat.b(); s = StringUtils.normalizeSpace(s); @@ -1312,9 +1589,9 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.chat(s, true); // CraftBukkit end - the below is for reference. :) } else { - ChatMessage chatmessage1 = new ChatMessage("chat.type.text", new Object[] { this.player.getScoreboardDisplayName(), s}); + ChatMessage chatmessage = new ChatMessage("chat.type.text", new Object[] { this.player.getScoreboardDisplayName(), s}); - this.minecraftServer.getPlayerList().sendMessage(chatmessage1, false); + this.minecraftServer.getPlayerList().sendMessage(chatmessage, false); } // Spigot start - spam exclusions @@ -1445,7 +1722,8 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // Paper Start - (Meh) Support for vanilla world scoreboard name coloring String displayName = event.getPlayer().getDisplayName(); if (this.player.getWorld().paperConfig.useVanillaScoreboardColoring) { - displayName = ScoreboardTeam.getPlayerDisplayName(this.player.getTeam(), player.getDisplayName()); + // Explicitly add a RESET here, vanilla uses components for this now... + displayName = CraftChatMessage.fromComponent(ScoreboardTeam.a(this.player.getTeam(),((CraftPlayer) player).getHandle().getDisplayName())) + org.bukkit.ChatColor.RESET; } s = String.format(event.getFormat(), displayName, event.getMessage()); @@ -1467,7 +1745,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { private void handleCommand(String s) { MinecraftTimings.playerCommandTimer.startTiming(); // Paper - // CraftBukkit start - whole method + // CraftBukkit start - whole method if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot this.LOGGER.info(this.player.getName() + " issued server command: " + s); @@ -1483,22 +1761,21 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { try { if (this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { - MinecraftTimings.playerCommandTimer.stopTiming(); // Paper return; } } catch (org.bukkit.command.CommandException ex) { player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - MinecraftTimings.playerCommandTimer.stopTiming(); // Paper return; + } finally { + MinecraftTimings.playerCommandTimer.stopTiming(); // Paper } - MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - // this.minecraftServer.getCommandHandler().a(this.player, s); + // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); // CraftBukkit end } public void a(PacketPlayInArmAnimation packetplayinarmanimation) { - PlayerConnectionUtils.ensureMainThread(packetplayinarmanimation, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinarmanimation, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit this.player.resetIdleTimer(); // CraftBukkit start - Raytrace to look for 'rogue armswings' @@ -1517,7 +1794,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { float f8 = f3 * f5; double d3 = player.playerInteractManager.getGameMode()== EnumGamemode.CREATIVE ? 5.0D : 4.5D; Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); - MovingObjectPosition movingobjectposition = this.player.world.rayTrace(vec3d, vec3d1, false); + MovingObjectPosition movingobjectposition = this.player.world.rayTrace(vec3d, vec3d1); if (movingobjectposition == null || movingobjectposition.type != MovingObjectPosition.EnumMovingObjectType.BLOCK) { CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); @@ -1529,17 +1806,17 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { if (event.isCancelled()) return; // CraftBukkit end - this.player.a(packetplayinarmanimation.a()); + this.player.a(packetplayinarmanimation.b()); } public void a(PacketPlayInEntityAction packetplayinentityaction) { - PlayerConnectionUtils.ensureMainThread(packetplayinentityaction, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinentityaction, this, this.player.getWorldServer()); // CraftBukkit start if (this.player.dead) return; - switch (packetplayinentityaction.b()) { + switch (packetplayinentityaction.c()) { case START_SNEAKING: case STOP_SNEAKING: - PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getPlayer(), packetplayinentityaction.b() == PacketPlayInEntityAction.EnumPlayerAction.START_SNEAKING); + PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getPlayer(), packetplayinentityaction.c() == PacketPlayInEntityAction.EnumPlayerAction.START_SNEAKING); this.server.getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -1548,7 +1825,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { break; case START_SPRINTING: case STOP_SPRINTING: - PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getPlayer(), packetplayinentityaction.b() == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING); + PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getPlayer(), packetplayinentityaction.c() == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING); this.server.getPluginManager().callEvent(e2); if (e2.isCancelled()) { @@ -1560,7 +1837,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.player.resetIdleTimer(); IJumpable ijumpable; - switch (packetplayinentityaction.b()) { + switch (packetplayinentityaction.c()) { case START_SNEAKING: this.player.setSneaking(true); @@ -1592,38 +1869,38 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { break; case START_RIDING_JUMP: - if (this.player.bJ() instanceof IJumpable) { - ijumpable = (IJumpable) this.player.bJ(); - int i = packetplayinentityaction.c(); + if (this.player.getVehicle() instanceof IJumpable) { + ijumpable = (IJumpable) this.player.getVehicle(); + int i = packetplayinentityaction.d(); - if (ijumpable.a() && i > 0) { - ijumpable.b_(i); + if (ijumpable.G_() && i > 0) { + ijumpable.b(i); } } break; case STOP_RIDING_JUMP: - if (this.player.bJ() instanceof IJumpable) { - ijumpable = (IJumpable) this.player.bJ(); - ijumpable.r_(); + if (this.player.getVehicle() instanceof IJumpable) { + ijumpable = (IJumpable) this.player.getVehicle(); + ijumpable.I_(); } break; case OPEN_INVENTORY: - if (this.player.bJ() instanceof EntityHorseAbstract) { - ((EntityHorseAbstract) this.player.bJ()).c((EntityHuman) this.player); + if (this.player.getVehicle() instanceof EntityHorseAbstract) { + ((EntityHorseAbstract) this.player.getVehicle()).c((EntityHuman) this.player); } break; case START_FALL_FLYING: - if (!this.player.onGround && this.player.motY < 0.0D && !this.player.cP() && !this.player.isInWater()) { + if (!this.player.onGround && this.player.motY < 0.0D && !this.player.dc() && !this.player.isInWater()) { ItemStack itemstack = this.player.getEquipment(EnumItemSlot.CHEST); - if (itemstack.getItem() == Items.cS && ItemElytra.d(itemstack)) { - this.player.N(); + if (itemstack.getItem() == Items.ELYTRA && ItemElytra.e(itemstack)) { + this.player.J(); } } else { - this.player.O(); + this.player.K(); } break; @@ -1634,7 +1911,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInUseEntity packetplayinuseentity) { - PlayerConnectionUtils.ensureMainThread(packetplayinuseentity, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinuseentity, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); Entity entity = packetplayinuseentity.a((World) worldserver); @@ -1658,23 +1935,28 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { if (this.player.h(entity) < d0) { EnumHand enumhand; - ItemStack itemInHand = this.player.b(packetplayinuseentity.b() == null ? EnumHand.MAIN_HAND : packetplayinuseentity.b()); // CraftBukkit + ItemStack itemInHand = this.player.b(packetplayinuseentity.c() == null ? EnumHand.MAIN_HAND : packetplayinuseentity.c()); // CraftBukkit - if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT - || packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) { + if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT + || packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) { // CraftBukkit start boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient; Item origItem = this.player.inventory.getItemInHand() == null ? null : this.player.inventory.getItemInHand().getItem(); PlayerInteractEntityEvent event; - if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT) { - event = new PlayerInteractEntityEvent((Player) this.getPlayer(), entity.getBukkitEntity(), (packetplayinuseentity.b() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); + if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT) { + event = new PlayerInteractEntityEvent((Player) this.getPlayer(), entity.getBukkitEntity(), (packetplayinuseentity.c() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); } else { - Vec3D target = packetplayinuseentity.c(); - event = new PlayerInteractAtEntityEvent((Player) this.getPlayer(), entity.getBukkitEntity(), new org.bukkit.util.Vector(target.x, target.y, target.z), (packetplayinuseentity.b() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); + Vec3D target = packetplayinuseentity.d(); + event = new PlayerInteractAtEntityEvent((Player) this.getPlayer(), entity.getBukkitEntity(), new org.bukkit.util.Vector(target.x, target.y, target.z), (packetplayinuseentity.c() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); } this.server.getPluginManager().callEvent(event); - if (triggerLeashUpdate && (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != Items.LEAD)) { + // Fish bucket - SPIGOT-4048 + if ((entity instanceof EntityFish && origItem != null && origItem.getItem() == Items.WATER_BUCKET) && (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem)) { + this.sendPacket(new PacketPlayOutSpawnEntityLiving((EntityFish) entity)); + } + + if (triggerLeashUpdate && (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem)) { // Refresh the current leash state this.sendPacket(new PacketPlayOutAttachEntity(entity, ((EntityInsentient) entity).getLeashHolder())); } @@ -1691,26 +1973,26 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // CraftBukkit end } - if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT) { - enumhand = packetplayinuseentity.b(); + if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT) { + enumhand = packetplayinuseentity.c(); this.player.a(entity, enumhand); // CraftBukkit start if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { this.player.updateInventory(this.player.activeContainer); } // CraftBukkit end - } else if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) { - enumhand = packetplayinuseentity.b(); - entity.a(this.player, packetplayinuseentity.c(), enumhand); + } else if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) { + enumhand = packetplayinuseentity.c(); + entity.a(this.player, packetplayinuseentity.d(), enumhand); // CraftBukkit start if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { this.player.updateInventory(this.player.activeContainer); } // CraftBukkit end - } else if (packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + } else if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { if (entity instanceof EntityItem || entity instanceof EntityExperienceOrb || entity instanceof EntityArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked", new Object[0])); - this.minecraftServer.warning("Player " + this.player.getName() + " tried to attack an invalid entity"); + this.minecraftServer.warning("Player " + this.player.getDisplayName().getString() + " tried to attack an invalid entity"); return; } @@ -1729,8 +2011,8 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( this.getPlayer(), packetplayinuseentity.getEntityId(), - packetplayinuseentity.a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, - packetplayinuseentity.b() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND + packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, + packetplayinuseentity.c() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND )); } // Paper end @@ -1738,9 +2020,9 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInClientCommand packetplayinclientcommand) { - PlayerConnectionUtils.ensureMainThread(packetplayinclientcommand, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinclientcommand, this, this.player.getWorldServer()); this.player.resetIdleTimer(); - PacketPlayInClientCommand.EnumClientCommand packetplayinclientcommand_enumclientcommand = packetplayinclientcommand.a(); + PacketPlayInClientCommand.EnumClientCommand packetplayinclientcommand_enumclientcommand = packetplayinclientcommand.b(); switch (packetplayinclientcommand_enumclientcommand) { case PERFORM_RESPAWN: @@ -1748,7 +2030,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { 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 - CriterionTriggers.u.a(this.player, DimensionManager.THE_END, DimensionManager.OVERWORLD); + CriterionTriggers.v.a(this.player, DimensionManager.THE_END, DimensionManager.OVERWORLD); } else { if (this.player.getHealth() > 0.0F) { return; @@ -1757,7 +2039,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, false); if (this.minecraftServer.isHardcore()) { this.player.a(EnumGamemode.SPECTATOR); - this.player.x().getGameRules().set("spectatorsGenerateChunks", "false"); + this.player.getWorldServer().getGameRules().set("spectatorsGenerateChunks", "false", this.minecraftServer); } } break; @@ -1769,19 +2051,19 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInCloseWindow packetplayinclosewindow) { - PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit CraftEventFactory.handleInventoryCloseEvent(this.player, org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLAYER); // CraftBukkit // Paper - this.player.r(); + this.player.m(); } public void a(PacketPlayInWindowClick packetplayinwindowclick) { - PlayerConnectionUtils.ensureMainThread(packetplayinwindowclick, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinwindowclick, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit this.player.resetIdleTimer(); - if (this.player.activeContainer.windowId == packetplayinwindowclick.a() && this.player.activeContainer.c(this.player) && this.player.activeContainer.canUse(this.player)) { // CraftBukkit + if (this.player.activeContainer.windowId == packetplayinwindowclick.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer.canUse(this.player)) { // CraftBukkit boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if if (false/*this.player.isSpectator()*/) { // CraftBukkit NonNullList nonnulllist = NonNullList.a(); @@ -1793,12 +2075,12 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.player.a(this.player.activeContainer, nonnulllist); } else { // CraftBukkit start - Call InventoryClickEvent - if (packetplayinwindowclick.b() < -1 && packetplayinwindowclick.b() != -999) { + if (packetplayinwindowclick.c() < -1 && packetplayinwindowclick.c() != -999) { return; } InventoryView inventory = this.player.activeContainer.getBukkitView(); - SlotType type = CraftInventoryView.getSlotType(inventory, packetplayinwindowclick.b()); + SlotType type = CraftInventoryView.getSlotType(inventory, packetplayinwindowclick.c()); InventoryClickEvent event; ClickType click = ClickType.UNKNOWN; @@ -1806,36 +2088,36 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { ItemStack itemstack = ItemStack.a; - switch (packetplayinwindowclick.f()) { + switch (packetplayinwindowclick.g()) { case PICKUP: - if (packetplayinwindowclick.c() == 0) { + if (packetplayinwindowclick.d() == 0) { click = ClickType.LEFT; - } else if (packetplayinwindowclick.c() == 1) { + } else if (packetplayinwindowclick.d() == 1) { click = ClickType.RIGHT; } - if (packetplayinwindowclick.c() == 0 || packetplayinwindowclick.c() == 1) { + if (packetplayinwindowclick.d() == 0 || packetplayinwindowclick.d() == 1) { action = InventoryAction.NOTHING; // Don't want to repeat ourselves - if (packetplayinwindowclick.b() == -999) { + if (packetplayinwindowclick.c() == -999) { if (!player.inventory.getCarried().isEmpty()) { - action = packetplayinwindowclick.c() == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR; + action = packetplayinwindowclick.d() == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR; } - } else if (packetplayinwindowclick.b() < 0) { + } else if (packetplayinwindowclick.c() < 0) { action = InventoryAction.NOTHING; } else { - Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); + Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.c()); if (slot != null) { ItemStack clickedItem = slot.getItem(); ItemStack cursor = player.inventory.getCarried(); if (clickedItem.isEmpty()) { if (!cursor.isEmpty()) { - action = packetplayinwindowclick.c() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE; + action = packetplayinwindowclick.d() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE; } } else if (slot.isAllowed(player)) { if (cursor.isEmpty()) { - action = packetplayinwindowclick.c() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF; + action = packetplayinwindowclick.d() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF; } else if (slot.isAllowed(cursor)) { if (clickedItem.doMaterialsMatch(cursor) && ItemStack.equals(clickedItem, cursor)) { - int toPlace = packetplayinwindowclick.c() == 0 ? cursor.getCount() : 1; + int toPlace = packetplayinwindowclick.d() == 0 ? cursor.getCount() : 1; toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); toPlace = Math.min(toPlace, slot.inventory.getMaxStackSize() - clickedItem.getCount()); if (toPlace == 1) { @@ -1850,7 +2132,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } else if (cursor.getCount() <= slot.getMaxStackSize()) { action = InventoryAction.SWAP_WITH_CURSOR; } - } else if (cursor.getItem() == clickedItem.getItem() && (!cursor.usesData() || cursor.getData() == clickedItem.getData()) && ItemStack.equals(cursor, clickedItem)) { + } else if (cursor.getItem() == clickedItem.getItem() && ItemStack.equals(cursor, clickedItem)) { if (clickedItem.getCount() >= 0) { if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) { // As of 1.5, this is result slots only @@ -1865,16 +2147,16 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { break; // TODO check on updates case QUICK_MOVE: - if (packetplayinwindowclick.c() == 0) { + if (packetplayinwindowclick.d() == 0) { click = ClickType.SHIFT_LEFT; - } else if (packetplayinwindowclick.c() == 1) { + } else if (packetplayinwindowclick.d() == 1) { click = ClickType.SHIFT_RIGHT; } - if (packetplayinwindowclick.c() == 0 || packetplayinwindowclick.c() == 1) { - if (packetplayinwindowclick.b() < 0) { + if (packetplayinwindowclick.d() == 0 || packetplayinwindowclick.d() == 1) { + if (packetplayinwindowclick.c() < 0) { action = InventoryAction.NOTHING; } else { - Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); + Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.c()); if (slot != null && slot.isAllowed(this.player) && slot.hasItem()) { action = InventoryAction.MOVE_TO_OTHER_INVENTORY; } else { @@ -1884,11 +2166,11 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } break; case SWAP: - if (packetplayinwindowclick.c() >= 0 && packetplayinwindowclick.c() < 9) { + if (packetplayinwindowclick.d() >= 0 && packetplayinwindowclick.d() < 9) { click = ClickType.NUMBER_KEY; - Slot clickedSlot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); + Slot clickedSlot = this.player.activeContainer.getSlot(packetplayinwindowclick.c()); if (clickedSlot.isAllowed(player)) { - ItemStack hotbar = this.player.inventory.getItem(packetplayinwindowclick.c()); + ItemStack hotbar = this.player.inventory.getItem(packetplayinwindowclick.d()); boolean canCleanSwap = hotbar.isEmpty() || (clickedSlot.inventory == player.inventory && clickedSlot.isAllowed(hotbar)); // the slot will accept the hotbar item if (clickedSlot.hasItem()) { if (canCleanSwap) { @@ -1907,12 +2189,12 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } break; case CLONE: - if (packetplayinwindowclick.c() == 2) { + if (packetplayinwindowclick.d() == 2) { click = ClickType.MIDDLE; - if (packetplayinwindowclick.b() < 0) { // Paper - GH-404 + if (packetplayinwindowclick.c() < 0) { // Paper - GH-404 action = InventoryAction.NOTHING; } else { - Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); + Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.c()); if (slot != null && slot.hasItem() && player.abilities.canInstantlyBuild && player.inventory.getCarried().isEmpty()) { action = InventoryAction.CLONE_STACK; } else { @@ -1925,18 +2207,18 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } break; case THROW: - if (packetplayinwindowclick.b() >= 0) { - if (packetplayinwindowclick.c() == 0) { + if (packetplayinwindowclick.c() >= 0) { + if (packetplayinwindowclick.d() == 0) { click = ClickType.DROP; - Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); + Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.c()); if (slot != null && slot.hasItem() && slot.isAllowed(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.getItemOf(Blocks.AIR)) { action = InventoryAction.DROP_ONE_SLOT; } else { action = InventoryAction.NOTHING; } - } else if (packetplayinwindowclick.c() == 1) { + } else if (packetplayinwindowclick.d() == 1) { click = ClickType.CONTROL_DROP; - Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.b()); + Slot slot = this.player.activeContainer.getSlot(packetplayinwindowclick.c()); if (slot != null && slot.hasItem() && slot.isAllowed(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.getItemOf(Blocks.AIR)) { action = InventoryAction.DROP_ALL_SLOT; } else { @@ -1946,23 +2228,23 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } else { // Sane default (because this happens when they are holding nothing. Don't ask why.) click = ClickType.LEFT; - if (packetplayinwindowclick.c() == 1) { + if (packetplayinwindowclick.d() == 1) { click = ClickType.RIGHT; } action = InventoryAction.NOTHING; } break; case QUICK_CRAFT: - itemstack = this.player.activeContainer.a(packetplayinwindowclick.b(), packetplayinwindowclick.c(), packetplayinwindowclick.f(), this.player); + itemstack = this.player.activeContainer.a(packetplayinwindowclick.c(), packetplayinwindowclick.d(), packetplayinwindowclick.g(), this.player); break; case PICKUP_ALL: click = ClickType.DOUBLE_CLICK; action = InventoryAction.NOTHING; - if (packetplayinwindowclick.b() >= 0 && !this.player.inventory.getCarried().isEmpty()) { + if (packetplayinwindowclick.c() >= 0 && !this.player.inventory.getCarried().isEmpty()) { ItemStack cursor = this.player.inventory.getCarried(); action = InventoryAction.NOTHING; // Quick check for if we have any of the item - if (inventory.getTopInventory().contains(org.bukkit.Material.getMaterial(Item.getId(cursor.getItem()))) || inventory.getBottomInventory().contains(org.bukkit.Material.getMaterial(Item.getId(cursor.getItem())))) { + if (inventory.getTopInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem())) || inventory.getBottomInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem()))) { action = InventoryAction.COLLECT_TO_CURSOR; } } @@ -1971,21 +2253,21 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { break; } - if (packetplayinwindowclick.f() != InventoryClickType.QUICK_CRAFT) { + if (packetplayinwindowclick.g() != InventoryClickType.QUICK_CRAFT) { if (click == ClickType.NUMBER_KEY) { - event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.b(), click, action, packetplayinwindowclick.c()); + event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.c(), click, action, packetplayinwindowclick.d()); } else { - event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.b(), click, action); + event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.c(), click, action); } org.bukkit.inventory.Inventory top = inventory.getTopInventory(); - if (packetplayinwindowclick.b() == 0 && top instanceof CraftingInventory) { + if (packetplayinwindowclick.c() == 0 && top instanceof CraftingInventory) { org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe(); if (recipe != null) { if (click == ClickType.NUMBER_KEY) { - event = new CraftItemEvent(recipe, inventory, type, packetplayinwindowclick.b(), click, action, packetplayinwindowclick.c()); + event = new CraftItemEvent(recipe, inventory, type, packetplayinwindowclick.c(), click, action, packetplayinwindowclick.d()); } else { - event = new CraftItemEvent(recipe, inventory, type, packetplayinwindowclick.b(), click, action); + event = new CraftItemEvent(recipe, inventory, type, packetplayinwindowclick.c(), click, action); } } } @@ -2000,7 +2282,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { switch (event.getResult()) { case ALLOW: case DEFAULT: - itemstack = this.player.activeContainer.a(packetplayinwindowclick.b(), packetplayinwindowclick.c(), packetplayinwindowclick.f(), this.player); + itemstack = this.player.activeContainer.a(packetplayinwindowclick.c(), packetplayinwindowclick.d(), packetplayinwindowclick.g(), this.player); break; case DENY: /* Needs enum constructor in InventoryAction @@ -2033,12 +2315,12 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { case PLACE_ONE: case SWAP_WITH_CURSOR: this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, this.player.inventory.getCarried())); - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.activeContainer.windowId, packetplayinwindowclick.b(), this.player.activeContainer.getSlot(packetplayinwindowclick.b()).getItem())); + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.activeContainer.windowId, packetplayinwindowclick.c(), this.player.activeContainer.getSlot(packetplayinwindowclick.c()).getItem())); break; // Modified clicked only case DROP_ALL_SLOT: case DROP_ONE_SLOT: - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.activeContainer.windowId, packetplayinwindowclick.b(), this.player.activeContainer.getSlot(packetplayinwindowclick.b()).getItem())); + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.activeContainer.windowId, packetplayinwindowclick.c(), this.player.activeContainer.getSlot(packetplayinwindowclick.c()).getItem())); break; // Modified cursor only case DROP_ALL_CURSOR: @@ -2060,23 +2342,22 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } } // CraftBukkit end - if (ItemStack.matches(packetplayinwindowclick.e(), itemstack)) { - this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.a(), packetplayinwindowclick.d(), true)); + if (ItemStack.matches(packetplayinwindowclick.f(), itemstack)) { + this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.b(), packetplayinwindowclick.e(), true)); this.player.f = true; this.player.activeContainer.b(); this.player.broadcastCarriedItem(); this.player.f = false; } else { - this.k.a(this.player.activeContainer.windowId, Short.valueOf(packetplayinwindowclick.d())); - this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.a(), packetplayinwindowclick.d(), false)); + this.k.a(this.player.activeContainer.windowId, Short.valueOf(packetplayinwindowclick.e())); + this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.b(), packetplayinwindowclick.e(), false)); this.player.activeContainer.a(this.player, false); NonNullList nonnulllist1 = NonNullList.a(); for (int j = 0; j < this.player.activeContainer.slots.size(); ++j) { ItemStack itemstack1 = ((Slot) this.player.activeContainer.slots.get(j)).getItem(); - ItemStack itemstack2 = itemstack1.isEmpty() ? ItemStack.a : itemstack1; - nonnulllist1.add(itemstack2); + nonnulllist1.add(itemstack1.isEmpty() ? ItemStack.a : itemstack1); } this.player.a(this.player.activeContainer, nonnulllist1); @@ -2087,52 +2368,55 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInAutoRecipe packetplayinautorecipe) { - PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); this.player.resetIdleTimer(); - if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.a() && this.player.activeContainer.c(this.player)) { - this.H.a(this.player, packetplayinautorecipe.b(), packetplayinautorecipe.c()); + if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player)) { + IRecipe irecipe = this.minecraftServer.getCraftingManager().a(packetplayinautorecipe.c()); + + if (this.player.activeContainer instanceof ContainerFurnace) { + (new AutoRecipeFurnace()).a(this.player, irecipe, packetplayinautorecipe.d()); + } else { + (new AutoRecipe()).a(this.player, irecipe, packetplayinautorecipe.d()); + } + } } public void a(PacketPlayInEnchantItem packetplayinenchantitem) { - PlayerConnectionUtils.ensureMainThread(packetplayinenchantitem, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinenchantitem, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit this.player.resetIdleTimer(); - if (this.player.activeContainer.windowId == packetplayinenchantitem.a() && this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { - this.player.activeContainer.a(this.player, packetplayinenchantitem.b()); + if (this.player.activeContainer.windowId == packetplayinenchantitem.b() && this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { + this.player.activeContainer.a(this.player, packetplayinenchantitem.c()); this.player.activeContainer.b(); } } public void a(PacketPlayInSetCreativeSlot packetplayinsetcreativeslot) { - PlayerConnectionUtils.ensureMainThread(packetplayinsetcreativeslot, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinsetcreativeslot, this, this.player.getWorldServer()); if (this.player.playerInteractManager.isCreative()) { - boolean flag = packetplayinsetcreativeslot.a() < 0; + boolean flag = packetplayinsetcreativeslot.b() < 0; ItemStack itemstack = packetplayinsetcreativeslot.getItemStack(); + NBTTagCompound nbttagcompound = itemstack.b("BlockEntityTag"); - if (!itemstack.isEmpty() && itemstack.hasTag() && itemstack.getTag().hasKeyOfType("BlockEntityTag", 10)) { - NBTTagCompound nbttagcompound = itemstack.getTag().getCompound("BlockEntityTag"); + if (!itemstack.isEmpty() && nbttagcompound != null && nbttagcompound.hasKey("x") && nbttagcompound.hasKey("y") && nbttagcompound.hasKey("z")) { + BlockPosition blockposition = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); + TileEntity tileentity = this.player.world.getTileEntity(blockposition); - if (nbttagcompound.hasKey("x") && nbttagcompound.hasKey("y") && nbttagcompound.hasKey("z")) { - BlockPosition blockposition = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - TileEntity tileentity = this.player.world.getTileEntity(blockposition); + if (tileentity != null) { + NBTTagCompound nbttagcompound1 = tileentity.save(new NBTTagCompound()); - if (tileentity != null) { - NBTTagCompound nbttagcompound1 = tileentity.save(new NBTTagCompound()); - - nbttagcompound1.remove("x"); - nbttagcompound1.remove("y"); - nbttagcompound1.remove("z"); - itemstack.a("BlockEntityTag", (NBTBase) nbttagcompound1); - } + nbttagcompound1.remove("x"); + nbttagcompound1.remove("y"); + nbttagcompound1.remove("z"); + itemstack.a("BlockEntityTag", (NBTBase) nbttagcompound1); } } - boolean flag1 = packetplayinsetcreativeslot.a() >= 1 && packetplayinsetcreativeslot.a() <= 45; - // CraftBukkit - Add invalidItems check - boolean flag2 = itemstack.isEmpty() || itemstack.getData() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty() && (!invalidItems.contains(Item.getId(itemstack.getItem())) || !org.spigotmc.SpigotConfig.filterCreativeItems); // Spigot - if (flag || (flag1 && !ItemStack.matches(this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem(), packetplayinsetcreativeslot.getItemStack()))) { // Insist on valid slot + boolean flag1 = packetplayinsetcreativeslot.b() >= 1 && packetplayinsetcreativeslot.b() <= 45; + boolean flag2 = itemstack.isEmpty() || itemstack.getDamage() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); + if (flag || (flag1 && !ItemStack.matches(this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.b()).getItem(), packetplayinsetcreativeslot.getItemStack()))) { // Insist on valid slot // CraftBukkit start - Call click event InventoryView inventory = this.player.defaultContainer.getBukkitView(); org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packetplayinsetcreativeslot.getItemStack()); @@ -2140,14 +2424,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { SlotType type = SlotType.QUICKBAR; if (flag) { type = SlotType.OUTSIDE; - } else if (packetplayinsetcreativeslot.a() < 36) { - if (packetplayinsetcreativeslot.a() >= 5 && packetplayinsetcreativeslot.a() < 9) { + } else if (packetplayinsetcreativeslot.b() < 36) { + if (packetplayinsetcreativeslot.b() >= 5 && packetplayinsetcreativeslot.b() < 9) { type = SlotType.ARMOR; } else { type = SlotType.CONTAINER; } } - InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packetplayinsetcreativeslot.a(), item); + InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packetplayinsetcreativeslot.b(), item); server.getPluginManager().callEvent(event); itemstack = CraftItemStack.asNMSCopy(event.getCursor()); @@ -2161,8 +2445,8 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { break; case DENY: // Reset the slot - if (packetplayinsetcreativeslot.a() >= 0) { - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.defaultContainer.windowId, packetplayinsetcreativeslot.a(), this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.a()).getItem())); + if (packetplayinsetcreativeslot.b() >= 0) { + this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.player.defaultContainer.windowId, packetplayinsetcreativeslot.b(), this.player.defaultContainer.getSlot(packetplayinsetcreativeslot.b()).getItem())); this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a)); } return; @@ -2172,9 +2456,9 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { if (flag1 && flag2) { if (itemstack.isEmpty()) { - this.player.defaultContainer.setItem(packetplayinsetcreativeslot.a(), ItemStack.a); + this.player.defaultContainer.setItem(packetplayinsetcreativeslot.b(), ItemStack.a); } else { - this.player.defaultContainer.setItem(packetplayinsetcreativeslot.a(), itemstack); + this.player.defaultContainer.setItem(packetplayinsetcreativeslot.b(), itemstack); } this.player.defaultContainer.a(this.player, true); @@ -2183,7 +2467,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { EntityItem entityitem = this.player.drop(itemstack, true); if (entityitem != null) { - entityitem.j(); + entityitem.f(); } } } @@ -2191,22 +2475,22 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInTransaction packetplayintransaction) { - PlayerConnectionUtils.ensureMainThread(packetplayintransaction, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayintransaction, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit Short oshort = (Short) this.k.get(this.player.activeContainer.windowId); - if (oshort != null && packetplayintransaction.b() == oshort.shortValue() && this.player.activeContainer.windowId == packetplayintransaction.a() && !this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { + if (oshort != null && packetplayintransaction.c() == oshort.shortValue() && this.player.activeContainer.windowId == packetplayintransaction.b() && !this.player.activeContainer.c(this.player) && !this.player.isSpectator()) { this.player.activeContainer.a(this.player, true); } } public void a(PacketPlayInUpdateSign packetplayinupdatesign) { - PlayerConnectionUtils.ensureMainThread(packetplayinupdatesign, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinupdatesign, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit this.player.resetIdleTimer(); WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension); - BlockPosition blockposition = packetplayinupdatesign.a(); + BlockPosition blockposition = packetplayinupdatesign.b(); if (worldserver.isLoaded(blockposition)) { IBlockData iblockdata = worldserver.getType(blockposition); @@ -2218,19 +2502,19 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { TileEntitySign tileentitysign = (TileEntitySign) tileentity; - if (!tileentitysign.a() || tileentitysign.e() != this.player) { - this.minecraftServer.warning("Player " + this.player.getName() + " just tried to change non-editable sign"); + if (!tileentitysign.d() || tileentitysign.e() != this.player) { + this.minecraftServer.warning("Player " + this.player.getDisplayName().getString() + " just tried to change non-editable sign"); this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit return; } - String[] astring = packetplayinupdatesign.b(); + String[] astring = packetplayinupdatesign.c(); // CraftBukkit start Player player = this.server.getPlayer(this.player); - int x = packetplayinupdatesign.a().getX(); - int y = packetplayinupdatesign.a().getY(); - int z = packetplayinupdatesign.a().getZ(); + int x = packetplayinupdatesign.b().getX(); + int y = packetplayinupdatesign.b().getY(); + int z = packetplayinupdatesign.b().getZ(); String[] lines = new String[4]; for (int i = 0; i < astring.length; ++i) { @@ -2252,16 +2536,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInKeepAlive packetplayinkeepalive) { - //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.x()); // CraftBukkit // Paper - This shouldn't be on the main thread - if (this.g && packetplayinkeepalive.a() == this.h) { - int i = (int) (this.d() - this.f); + //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread + if (this.g && packetplayinkeepalive.b() == this.h) { + int i = (int) (SystemUtils.b() - this.f); this.player.ping = (this.player.ping * 3 + i) / 4; this.g = false; - } else if (!this.player.getName().equals(this.minecraftServer.Q())) { + } else if (!this.player.getDisplayName().getString().equals(this.minecraftServer.I())) { // Paper start - This needs to be handled on the main thread for plugins - PlayerConnection.LOGGER.warn("{} sent an invalid keepalive! pending keepalive: {} got id: {} expected id: {}", - this.player.getName(), this.isPendingPing(), packetplayinkeepalive.a(), this.getKeepAliveID()); minecraftServer.postToMainThread(() -> { this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); }); @@ -2270,13 +2552,8 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } - private long getCurrentMillis() { return d(); } // Paper - OBFHELPER - private long d() { - return System.nanoTime() / 1000000L; - } - public void a(PacketPlayInAbilities packetplayinabilities) { - PlayerConnectionUtils.ensureMainThread(packetplayinabilities, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinabilities, this, this.player.getWorldServer()); // CraftBukkit start if (this.player.abilities.canFly && this.player.abilities.isFlying != packetplayinabilities.isFlying()) { PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.server.getPlayer(this.player), packetplayinabilities.isFlying()); @@ -2290,439 +2567,52 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // CraftBukkit end } - // Paper start - async tab completion - public void a(PacketPlayInTabComplete packet) { - // CraftBukkit start - if (chatSpamField.addAndGet(this, 10) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { - minecraftServer.postToMainThread(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); - return; - } - // CraftBukkit end - - com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; - java.util.List completions = new ArrayList<>(); - BlockPosition blockpos = packet.b(); - String buffer = packet.a(); - boolean isCommand = buffer.startsWith("/") || packet.c(); - event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, - buffer, isCommand, blockpos != null ? MCUtil.toLocation(player.world, blockpos) : null); - event.callEvent(); - completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); - if (event.isCancelled() || event.isHandled()) { - // Still fire sync event with the provided completions, if someone is listening - if (!event.isCancelled() && org.bukkit.event.server.TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { - java.util.List finalCompletions = completions; - Waitable> syncCompletions = new Waitable>() { - @Override - protected java.util.List evaluate() { - org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(PlayerConnection.this.getPlayer(), buffer, finalCompletions, isCommand, blockpos != null ? MCUtil.toLocation(player.world, blockpos) : null); - return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); - } - }; - server.getServer().processQueue.add(syncCompletions); - try { - completions = syncCompletions.get(); - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } - } - - this.player.playerConnection.sendPacket(new PacketPlayOutTabComplete(completions.toArray(new String[completions.size()]))); - return; - } - minecraftServer.postToMainThread(() -> { - java.util.List syncCompletions = this.minecraftServer.tabCompleteCommand(this.player, buffer, blockpos, isCommand); - this.player.playerConnection.sendPacket(new PacketPlayOutTabComplete(syncCompletions.toArray(new String[syncCompletions.size()]))); - }); - // Paper end - } - public void a(PacketPlayInSettings packetplayinsettings) { - PlayerConnectionUtils.ensureMainThread(packetplayinsettings, this, this.player.x()); + PlayerConnectionUtils.ensureMainThread(packetplayinsettings, this, this.player.getWorldServer()); this.player.a(packetplayinsettings); } + // CraftBukkit start + private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register"); + private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister"); + public void a(PacketPlayInCustomPayload packetplayincustompayload) { - PlayerConnectionUtils.ensureMainThread(packetplayincustompayload, this, this.player.x()); - String s = packetplayincustompayload.a(); - PacketDataSerializer packetdataserializer; - ItemStack itemstack; - ItemStack itemstack1; - - if ("MC|BEdit".equals(s)) { - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { - this.disconnect("Book edited too quickly!"); - return; - } - this.lastBookTick = MinecraftServer.currentTick; - // CraftBukkit end - packetdataserializer = packetplayincustompayload.b(); - + PlayerConnectionUtils.ensureMainThread(packetplayincustompayload, this, this.player.getWorldServer()); + if (packetplayincustompayload.tag.equals(CUSTOM_REGISTER)) { try { - itemstack = packetdataserializer.k(); - if (itemstack.isEmpty()) { - return; + String channels = packetplayincustompayload.data.toString(com.google.common.base.Charsets.UTF_8); + for (String channel : channels.split("\0")) { + getPlayer().addChannel(channel); } - - if (!ItemBookAndQuill.b(itemstack.getTag())) { - throw new IOException("Invalid book tag!"); + } catch (Exception ex) { + PlayerConnection.LOGGER.error("Couldn\'t register custom payload", ex); + this.disconnect("Invalid payload REGISTER!"); + } + } else if (packetplayincustompayload.tag.equals(CUSTOM_UNREGISTER)) { + try { + String channels = packetplayincustompayload.data.toString(com.google.common.base.Charsets.UTF_8); + for (String channel : channels.split("\0")) { + getPlayer().removeChannel(channel); } - - itemstack1 = this.player.getItemInMainHand(); - if (itemstack1.isEmpty()) { - return; - } - - if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack.getItem() == itemstack1.getItem()) { - itemstack1 = new ItemStack(Items.WRITABLE_BOOK); // CraftBukkit - itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); - CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit - } - } catch (Exception exception) { - IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBookEdit", "Invalid book data!", exception); // Paper + } catch (Exception ex) { + PlayerConnection.LOGGER.error("Couldn\'t unregister custom payload", ex); + this.disconnect("Invalid payload UNREGISTER!"); } } else { - String s1; - - if ("MC|BSign".equals(s)) { - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { - this.disconnect("Book edited too quickly!"); - return; - } - this.lastBookTick = MinecraftServer.currentTick; - // CraftBukkit end - packetdataserializer = packetplayincustompayload.b(); - - try { - itemstack = packetdataserializer.k(); - if (itemstack.isEmpty()) { - return; - } - - if (!ItemWrittenBook.b(itemstack.getTag())) { - throw new IOException("Invalid book tag!"); - } - - itemstack1 = this.player.getItemInMainHand(); - if (itemstack1.isEmpty()) { - return; - } - - if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack1.getItem() == Items.WRITABLE_BOOK) { - ItemStack itemstack2 = new ItemStack(Items.WRITTEN_BOOK); - - itemstack2.a("author", (NBTBase) (new NBTTagString(this.player.getName()))); - itemstack2.a("title", (NBTBase) (new NBTTagString(itemstack.getTag().getString("title")))); - NBTTagList nbttaglist = itemstack.getTag().getList("pages", 8); - - for (int i = 0; i < nbttaglist.size(); ++i) { - s1 = nbttaglist.getString(i); - ChatComponentText chatcomponenttext = new ChatComponentText(s1); - - s1 = IChatBaseComponent.ChatSerializer.a((IChatBaseComponent) chatcomponenttext); - nbttaglist.a(i, new NBTTagString(s1)); - } - - itemstack2.a("pages", (NBTBase) nbttaglist); - CraftEventFactory.handleEditBookEvent(player, itemstack2); // CraftBukkit - } - } catch (Exception exception1) { - IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBookSign", "Invalid book data!", exception1); // Paper - } - } else if ("MC|TrSel".equals(s)) { - try { - int j = packetplayincustompayload.b().readInt(); - Container container = this.player.activeContainer; - - if (container instanceof ContainerMerchant) { - ((ContainerMerchant) container).d(j); - } - } catch (Exception exception2) { - IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidTrade", "Invalid trade data!", exception2); // Paper - } - } else { - TileEntity tileentity; - - if ("MC|AdvCmd".equals(s)) { - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled", new Object[0])); - return; - } - - if (!this.player.isCreativeAndOp()) { - this.player.sendMessage(new ChatMessage("advMode.notAllowed", new Object[0])); - return; - } - - packetdataserializer = packetplayincustompayload.b(); - - try { - byte b0 = packetdataserializer.readByte(); - CommandBlockListenerAbstract commandblocklistenerabstract = null; - - if (b0 == 0) { - tileentity = this.player.world.getTileEntity(new BlockPosition(packetdataserializer.readInt(), packetdataserializer.readInt(), packetdataserializer.readInt())); - if (tileentity instanceof TileEntityCommand) { - commandblocklistenerabstract = ((TileEntityCommand) tileentity).getCommandBlock(); - } - } else if (b0 == 1) { - Entity entity = this.player.world.getEntity(packetdataserializer.readInt()); - - if (entity instanceof EntityMinecartCommandBlock) { - commandblocklistenerabstract = ((EntityMinecartCommandBlock) entity).getCommandBlock(); - } - } - - String s2 = packetdataserializer.e(packetdataserializer.readableBytes()); - boolean flag = packetdataserializer.readBoolean(); - - if (commandblocklistenerabstract != null) { - commandblocklistenerabstract.setCommand(s2); - commandblocklistenerabstract.a(flag); - if (!flag) { - commandblocklistenerabstract.b((IChatBaseComponent) null); - } - - commandblocklistenerabstract.i(); - this.player.sendMessage(new ChatMessage("advMode.setCommand.success", new Object[] { s2})); - } - } catch (Exception exception3) { - PlayerConnection.LOGGER.error("Couldn\'t set command block", exception3); - this.disconnect("Invalid command data!"); // CraftBukkit - } - } else if ("MC|AutoCmd".equals(s)) { - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled", new Object[0])); - return; - } - - if (!this.player.isCreativeAndOp()) { - this.player.sendMessage(new ChatMessage("advMode.notAllowed", new Object[0])); - return; - } - - packetdataserializer = packetplayincustompayload.b(); - - try { - CommandBlockListenerAbstract commandblocklistenerabstract1 = null; - TileEntityCommand tileentitycommand = null; - BlockPosition blockposition = new BlockPosition(packetdataserializer.readInt(), packetdataserializer.readInt(), packetdataserializer.readInt()); - TileEntity tileentity1 = this.player.world.getTileEntity(blockposition); - - if (tileentity1 instanceof TileEntityCommand) { - tileentitycommand = (TileEntityCommand) tileentity1; - commandblocklistenerabstract1 = tileentitycommand.getCommandBlock(); - } - - String s3 = packetdataserializer.e(packetdataserializer.readableBytes()); - boolean flag1 = packetdataserializer.readBoolean(); - TileEntityCommand.Type tileentitycommand_type = TileEntityCommand.Type.valueOf(packetdataserializer.e(16)); - boolean flag2 = packetdataserializer.readBoolean(); - boolean flag3 = packetdataserializer.readBoolean(); - - if (commandblocklistenerabstract1 != null) { - EnumDirection enumdirection = (EnumDirection) this.player.world.getType(blockposition).get(BlockCommand.a); - IBlockData iblockdata; - - switch (tileentitycommand_type) { - case SEQUENCE: - iblockdata = Blocks.dd.getBlockData(); - this.player.world.setTypeAndData(blockposition, iblockdata.set(BlockCommand.a, enumdirection).set(BlockCommand.b, Boolean.valueOf(flag2)), 2); - break; - - case AUTO: - iblockdata = Blocks.dc.getBlockData(); - this.player.world.setTypeAndData(blockposition, iblockdata.set(BlockCommand.a, enumdirection).set(BlockCommand.b, Boolean.valueOf(flag2)), 2); - break; - - case REDSTONE: - iblockdata = Blocks.COMMAND_BLOCK.getBlockData(); - this.player.world.setTypeAndData(blockposition, iblockdata.set(BlockCommand.a, enumdirection).set(BlockCommand.b, Boolean.valueOf(flag2)), 2); - } - - tileentity1.A(); - this.player.world.setTileEntity(blockposition, tileentity1); - commandblocklistenerabstract1.setCommand(s3); - commandblocklistenerabstract1.a(flag1); - if (!flag1) { - commandblocklistenerabstract1.b((IChatBaseComponent) null); - } - - tileentitycommand.b(flag3); - commandblocklistenerabstract1.i(); - if (!UtilColor.b(s3)) { - this.player.sendMessage(new ChatMessage("advMode.setCommand.success", new Object[] { s3})); - } - } - } catch (Exception exception4) { - PlayerConnection.LOGGER.error("Couldn\'t set command block", exception4); - this.disconnect("Invalid command data!"); // CraftBukkit - } - } else { - int k; - - if ("MC|Beacon".equals(s)) { - if (this.player.activeContainer instanceof ContainerBeacon) { - try { - packetdataserializer = packetplayincustompayload.b(); - k = packetdataserializer.readInt(); - int l = packetdataserializer.readInt(); - ContainerBeacon containerbeacon = (ContainerBeacon) this.player.activeContainer; - Slot slot = containerbeacon.getSlot(0); - - if (slot.hasItem()) { - slot.a(1); - IInventory iinventory = containerbeacon.e(); - - iinventory.setProperty(1, k); - iinventory.setProperty(2, l); - iinventory.update(); - } - } catch (Exception exception5) { - IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidBeacon", "Invalid beacon data!", exception5); // Paper - } - } - } else if ("MC|ItemName".equals(s)) { - if (this.player.activeContainer instanceof ContainerAnvil) { - ContainerAnvil containeranvil = (ContainerAnvil) this.player.activeContainer; - - if (packetplayincustompayload.b() != null && packetplayincustompayload.b().readableBytes() >= 1) { - String s4 = SharedConstants.a(packetplayincustompayload.b().e(32767)); - - if (s4.length() <= 35) { - containeranvil.a(s4); - } - } else { - containeranvil.a(""); - } - } - } else if ("MC|Struct".equals(s)) { - if (!this.player.isCreativeAndOp()) { - return; - } - - packetdataserializer = packetplayincustompayload.b(); - - try { - BlockPosition blockposition1 = new BlockPosition(packetdataserializer.readInt(), packetdataserializer.readInt(), packetdataserializer.readInt()); - IBlockData iblockdata1 = this.player.world.getType(blockposition1); - - tileentity = this.player.world.getTileEntity(blockposition1); - if (tileentity instanceof TileEntityStructure) { - TileEntityStructure tileentitystructure = (TileEntityStructure) tileentity; - byte b1 = packetdataserializer.readByte(); - - s1 = packetdataserializer.e(32); - tileentitystructure.a(TileEntityStructure.UsageMode.valueOf(s1)); - tileentitystructure.a(packetdataserializer.e(64)); - int i1 = MathHelper.clamp(packetdataserializer.readInt(), -32, 32); - int j1 = MathHelper.clamp(packetdataserializer.readInt(), -32, 32); - int k1 = MathHelper.clamp(packetdataserializer.readInt(), -32, 32); - - tileentitystructure.b(new BlockPosition(i1, j1, k1)); - int l1 = MathHelper.clamp(packetdataserializer.readInt(), 0, 32); - int i2 = MathHelper.clamp(packetdataserializer.readInt(), 0, 32); - int j2 = MathHelper.clamp(packetdataserializer.readInt(), 0, 32); - - tileentitystructure.c(new BlockPosition(l1, i2, j2)); - String s5 = packetdataserializer.e(32); - - tileentitystructure.b(EnumBlockMirror.valueOf(s5)); - String s6 = packetdataserializer.e(32); - - tileentitystructure.b(EnumBlockRotation.valueOf(s6)); - tileentitystructure.b(packetdataserializer.e(128)); - tileentitystructure.a(packetdataserializer.readBoolean()); - tileentitystructure.e(packetdataserializer.readBoolean()); - tileentitystructure.f(packetdataserializer.readBoolean()); - tileentitystructure.a(MathHelper.a(packetdataserializer.readFloat(), 0.0F, 1.0F)); - tileentitystructure.a(packetdataserializer.h()); - String s7 = tileentitystructure.a(); - - if (b1 == 2) { - if (tileentitystructure.q()) { - this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.save_success", new Object[] { s7})), false); - } else { - this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.save_failure", new Object[] { s7})), false); - } - } else if (b1 == 3) { - if (!tileentitystructure.E()) { - this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.load_not_found", new Object[] { s7})), false); - } else if (tileentitystructure.r()) { - this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.load_success", new Object[] { s7})), false); - } else { - this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.load_prepare", new Object[] { s7})), false); - } - } else if (b1 == 4) { - if (tileentitystructure.p()) { - this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.size_success", new Object[] { s7})), false); - } else { - this.player.a((IChatBaseComponent) (new ChatMessage("structure_block.size_failure", new Object[0])), false); - } - } - - tileentitystructure.update(); - this.player.world.notify(blockposition1, iblockdata1, iblockdata1, 3); - } - } catch (Exception exception6) { - PlayerConnection.LOGGER.error("Couldn\'t set structure block", exception6); - this.disconnect("Invalid structure data!"); // CraftBukkit - } - } else if ("MC|PickItem".equals(s)) { - packetdataserializer = packetplayincustompayload.b(); - - try { - k = packetdataserializer.g(); - this.player.inventory.d(k); - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, this.player.inventory.itemInHandIndex, this.player.inventory.getItem(this.player.inventory.itemInHandIndex))); - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, k, this.player.inventory.getItem(k))); - this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); - } catch (Exception exception7) { - IllegalPacketEvent.process(player.getBukkitEntity(), "InvalidPickItem", "Invalid PickItem", exception7); // Paper - } - } - // CraftBukkit start - else if (packetplayincustompayload.a().equals("REGISTER")) { - try { - String channels = packetplayincustompayload.b().toString(com.google.common.base.Charsets.UTF_8); - for (String channel : channels.split("\0")) { - getPlayer().addChannel(channel); - } - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t register custom payload", ex); - this.disconnect("Invalid payload REGISTER!"); - } - } else if (packetplayincustompayload.a().equals("UNREGISTER")) { - try { - String channels = packetplayincustompayload.b().toString(com.google.common.base.Charsets.UTF_8); - for (String channel : channels.split("\0")) { - getPlayer().removeChannel(channel); - } - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t unregister custom payload", ex); - this.disconnect("Invalid payload UNREGISTER!"); - } - } else { - try { - byte[] data = new byte[packetplayincustompayload.b().readableBytes()]; - packetplayincustompayload.b().readBytes(data); - server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.a(), data); - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); - this.disconnect("Invalid custom payload!"); - } - } - // CraftBukkit end - } + try { + byte[] data = new byte[packetplayincustompayload.data.readableBytes()]; + packetplayincustompayload.data.readBytes(data); + server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); + } catch (Exception ex) { + PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); + this.disconnect("Invalid custom payload!"); } } } - // CraftBukkit start - Add "isDisconnected" method public final boolean isDisconnected() { return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper } + // CraftBukkit end } diff --git a/sources/src/main/java/net/minecraft/server/PlayerList.java b/sources/src/main/java/net/minecraft/server/PlayerList.java deleted file mode 100644 index 0ec255217..000000000 --- a/sources/src/main/java/net/minecraft/server/PlayerList.java +++ /dev/null @@ -1,1541 +0,0 @@ -package net.minecraft.server; - -import co.aikar.timings.MinecraftTimings; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.mojang.authlib.GameProfile; - -import io.akarin.api.internal.Akari; -import io.akarin.server.core.AkarinGlobalConfig; -import io.netty.buffer.Unpooled; -import java.io.File; -import java.net.SocketAddress; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import javax.annotation.Nullable; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -// CraftBukkit start -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; - -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.TravelAgent; -import org.bukkit.craftbukkit.util.CraftChatMessage; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerPortalEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.util.Vector; -import org.spigotmc.event.player.PlayerSpawnLocationEvent; -// CraftBukkit end - -/** - * Akarin Changes Note - * 1) Changes (dis)connect messages (feature) - */ -public abstract class PlayerList { - - public static final File a = new File("banned-players.json"); - public static final File b = new File("banned-ips.json"); - public static final File c = new File("ops.json"); - public static final File d = new File("whitelist.json"); - private static final Logger f = LogManager.getLogger(); - private static final SimpleDateFormat g = new SimpleDateFormat("yyyy-MM-dd \'at\' HH:mm:ss z"); - private final MinecraftServer server; - public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety - private final Map j = Maps.newHashMap(); - private final GameProfileBanList k; - private final IpBanList l; - private final OpList operators; - private final WhiteList whitelist; - // CraftBukkit start - // private final Map o; - // private final Map p; - // CraftBukkit end - public IPlayerFileData playerFileData; - private boolean hasWhitelist; - protected int maxPlayers; - private int s; - private EnumGamemode t; - private boolean u; - private int v; - - // CraftBukkit start - private CraftServer cserver; - private final Map playersByName = new org.spigotmc.CaseInsensitiveMap(); - @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule - - public PlayerList(MinecraftServer minecraftserver) { - this.cserver = minecraftserver.server = new CraftServer(minecraftserver, this); - minecraftserver.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper - // CraftBukkit end - - this.k = new GameProfileBanList(PlayerList.a); - this.l = new IpBanList(PlayerList.b); - this.operators = new OpList(PlayerList.c); - this.whitelist = new WhiteList(PlayerList.d); - // CraftBukkit start - // this.o = Maps.newHashMap(); - // this.p = Maps.newHashMap(); - // CraftBukkit end - this.server = minecraftserver; - this.k.a(false); - this.l.a(false); - this.maxPlayers = 8; - } - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { - GameProfile gameprofile = entityplayer.getProfile(); - UserCache usercache = this.server.getUserCache(); - GameProfile gameprofile1 = usercache.a(gameprofile.getId()); - String s = gameprofile1 == null ? gameprofile.getName() : gameprofile1.getName(); - - usercache.a(gameprofile); - NBTTagCompound nbttagcompound = this.a(entityplayer); - // CraftBukkit start - Better rename detection - if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) { - NBTTagCompound bukkit = nbttagcompound.getCompound("bukkit"); - s = bukkit.hasKeyOfType("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; - } - // CraftBukkit end - - // Paper start - support PlayerInitialSpawnEvent - Location originalLoc = new Location(entityplayer.world.getWorld(), entityplayer.locX, entityplayer.locY, entityplayer.locZ, entityplayer.yaw, entityplayer.pitch); - com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent event = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(entityplayer.getBukkitEntity(), originalLoc); - this.server.server.getPluginManager().callEvent(event); - - Location newLoc = event.getSpawnLocation(); - entityplayer.world = ((CraftWorld) newLoc.getWorld()).getHandle(); - entityplayer.locX = newLoc.getX(); - entityplayer.locY = newLoc.getY(); - entityplayer.locZ = newLoc.getZ(); - entityplayer.yaw = newLoc.getYaw(); - entityplayer.pitch = newLoc.getPitch(); - entityplayer.dimension = ((CraftWorld) newLoc.getWorld()).getHandle().dimension; - // Paper end - - entityplayer.spawnIn(this.server.getWorldServer(entityplayer.dimension)); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); - String s1 = "local"; - - if (networkmanager.getSocketAddress() != null) { - s1 = networkmanager.getSocketAddress().toString(); - } - - // Spigot start - spawn location event - Player bukkitPlayer = entityplayer.getBukkitEntity(); - PlayerSpawnLocationEvent ev = new PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); - Bukkit.getPluginManager().callEvent(ev); - - Location loc = ev.getSpawnLocation(); - WorldServer world = ((CraftWorld) loc.getWorld()).getHandle(); - - entityplayer.spawnIn(world); - entityplayer.setPosition(loc.getX(), loc.getY(), loc.getZ()); - entityplayer.setYawPitch(loc.getYaw(), loc.getPitch()); - // Spigot end - - // CraftBukkit - Moved message to after join - // PlayerList.f.info("{}[{}] logged in with entity id {} at ({}, {}, {})", entityplayer.getName(), s1, Integer.valueOf(entityplayer.getId()), Double.valueOf(entityplayer.locX), Double.valueOf(entityplayer.locY), Double.valueOf(entityplayer.locZ)); - WorldServer worldserver = this.server.getWorldServer(entityplayer.dimension); - WorldData worlddata = worldserver.getWorldData(); - - this.a(entityplayer, (EntityPlayer) null, worldserver); - PlayerConnection playerconnection = new PlayerConnection(this.server, networkmanager, entityplayer); - - playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), worlddata.isHardcore(), worldserver.worldProvider.getDimensionManager().getDimensionID(), worldserver.getDifficulty(), this.getMaxPlayers(), worlddata.getType(), worldserver.getGameRules().getBoolean("reducedDebugInfo"))); - entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit - playerconnection.sendPacket(new PacketPlayOutCustomPayload("MC|Brand", (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); - playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); - playerconnection.sendPacket(new PacketPlayOutAbilities(entityplayer.abilities)); - playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); - playerconnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, (byte) (worldserver.getGameRules().getBoolean("reducedDebugInfo") ? 22 : 23))); // Paper - fix this rule not being initialized on the client - this.f(entityplayer); - entityplayer.getStatisticManager().c(); - entityplayer.F().a(entityplayer); - this.sendScoreboard((ScoreboardServer) worldserver.getScoreboard(), entityplayer); - this.server.aD(); - // CraftBukkit start - login message is handled in the event - // ChatMessage chatmessage; - - String joinMessage; - if (entityplayer.getName().equalsIgnoreCase(s)) { - // chatmessage = new ChatMessage("multiplayer.player.joined", new Object[] { entityplayer.getScoreboardDisplayName()}); - joinMessage = LocaleI18n.a(AkarinGlobalConfig.messageJoin, entityplayer.getName()); // Akarin - } else { - // chatmessage = new ChatMessage("multiplayer.player.joined.renamed", new Object[] { entityplayer.getScoreboardDisplayName(), s}); - joinMessage = LocaleI18n.a(AkarinGlobalConfig.messageJoinRenamed, entityplayer.getName(), s); // Akarin - } - - // chatmessage.getChatModifier().setColor(EnumChatFormat.YELLOW); - // this.sendMessage(chatmessage); - this.onPlayerJoin(entityplayer, joinMessage); - // CraftBukkit end - worldserver = server.getWorldServer(entityplayer.dimension); // CraftBukkit - Update in case join event changed it - playerconnection.a(entityplayer.locX, entityplayer.locY, entityplayer.locZ, entityplayer.yaw, entityplayer.pitch); - this.b(entityplayer, worldserver); - if (!this.server.getResourcePack().isEmpty()) { - entityplayer.setResourcePack(this.server.getResourcePack(), this.server.getResourcePackHash()); - } - - Iterator iterator = entityplayer.getEffects().iterator(); - - while (iterator.hasNext()) { - MobEffect mobeffect = (MobEffect) iterator.next(); - - playerconnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobeffect)); - } - - if (nbttagcompound != null && nbttagcompound.hasKeyOfType("RootVehicle", 10)) { - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); - Entity entity = ChunkRegionLoader.a(nbttagcompound1.getCompound("Entity"), worldserver, true); - - if (entity != null) { - UUID uuid = nbttagcompound1.a("Attach"); - Iterator iterator1; - Entity entity1; - - if (entity.getUniqueID().equals(uuid)) { - entityplayer.a(entity, true); - } else { - iterator1 = entity.bG().iterator(); - - while (iterator1.hasNext()) { - entity1 = (Entity) iterator1.next(); - if (entity1.getUniqueID().equals(uuid)) { - entityplayer.a(entity1, true); - break; - } - } - } - - if (!entityplayer.isPassenger()) { - PlayerList.f.warn("Couldn\'t reattach entity to player"); - worldserver.removeEntity(entity); - iterator1 = entity.bG().iterator(); - - while (iterator1.hasNext()) { - entity1 = (Entity) iterator1.next(); - worldserver.removeEntity(entity1); - } - } - } - } - - entityplayer.syncInventory(); - // Paper start - Add to collideRule team if needed - final Scoreboard scoreboard = this.getServer().getWorld().getScoreboard(); - if (this.collideRuleTeamName != null && scoreboard.getTeam(collideRuleTeamName) != null && entityplayer.getTeam() == null) { - scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeamName); - } - // Paper end - // CraftBukkit - Moved from above, added world - PlayerList.f.info(entityplayer.getName() + "[" + s1 + "] logged in with entity id " + entityplayer.getId() + " at ([" + entityplayer.world.worldData.getName() + "]" + entityplayer.locX + ", " + entityplayer.locY + ", " + entityplayer.locZ + ")"); - } - - public void sendScoreboard(ScoreboardServer scoreboardserver, EntityPlayer entityplayer) { - HashSet hashset = Sets.newHashSet(); - Iterator iterator = scoreboardserver.getTeams().iterator(); - - while (iterator.hasNext()) { - ScoreboardTeam scoreboardteam = (ScoreboardTeam) iterator.next(); - - entityplayer.playerConnection.sendPacket(new PacketPlayOutScoreboardTeam(scoreboardteam, 0)); - } - - for (int i = 0; i < 19; ++i) { - ScoreboardObjective scoreboardobjective = scoreboardserver.getObjectiveForSlot(i); - - if (scoreboardobjective != null && !hashset.contains(scoreboardobjective)) { - List list = scoreboardserver.getScoreboardScorePacketsForObjective(scoreboardobjective); - Iterator iterator1 = list.iterator(); - - while (iterator1.hasNext()) { - Packet packet = (Packet) iterator1.next(); - - entityplayer.playerConnection.sendPacket(packet); - } - - hashset.add(scoreboardobjective); - } - } - - } - - public void setPlayerFileData(WorldServer[] aworldserver) { - if (playerFileData != null) return; // CraftBukkit - this.playerFileData = aworldserver[0].getDataManager().getPlayerFileData(); - aworldserver[0].getWorldBorder().a(new IWorldBorderListener() { - @Override - public void a(WorldBorder worldborder, double d0) { - PlayerList.this.sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_SIZE), worldborder.world); - } - - @Override - public void a(WorldBorder worldborder, double d0, double d1, long i) { - PlayerList.this.sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.LERP_SIZE), worldborder.world); - } - - @Override - public void a(WorldBorder worldborder, double d0, double d1) { - PlayerList.this.sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_CENTER), worldborder.world); - } - - @Override - public void a(WorldBorder worldborder, int i) { - PlayerList.this.sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_WARNING_TIME), worldborder.world); - } - - @Override - public void b(WorldBorder worldborder, int i) { - PlayerList.this.sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_WARNING_BLOCKS), worldborder.world); - } - - @Override - public void b(WorldBorder worldborder, double d0) {} - - @Override - public void c(WorldBorder worldborder, double d0) {} - }); - } - - public void a(EntityPlayer entityplayer, @Nullable WorldServer worldserver) { - WorldServer worldserver1 = entityplayer.x(); - - if (worldserver != null) { - worldserver.getPlayerChunkMap().removePlayer(entityplayer); - } - - worldserver1.getPlayerChunkMap().addPlayer(entityplayer); - worldserver1.getChunkProviderServer().getChunkAt((int) entityplayer.locX >> 4, (int) entityplayer.locZ >> 4); - if (worldserver != null) { - CriterionTriggers.u.a(entityplayer, worldserver.worldProvider.getDimensionManager(), worldserver1.worldProvider.getDimensionManager()); - if (worldserver.worldProvider.getDimensionManager() == DimensionManager.NETHER && entityplayer.world.worldProvider.getDimensionManager() == DimensionManager.OVERWORLD && entityplayer.Q() != null) { - CriterionTriggers.B.a(entityplayer, entityplayer.Q()); - } - } - - } - - public int d() { - return PlayerChunkMap.getFurthestViewableBlock(this.s()); - } - - @Nullable - public NBTTagCompound a(EntityPlayer entityplayer) { - NBTTagCompound nbttagcompound = this.server.worlds.get(0).getWorldData().h(); // CraftBukkit - NBTTagCompound nbttagcompound1; - - if (entityplayer.getName().equals(this.server.Q()) && nbttagcompound != null) { - nbttagcompound1 = nbttagcompound; - entityplayer.f(nbttagcompound); - PlayerList.f.debug("loading single player"); - } else { - nbttagcompound1 = this.playerFileData.load(entityplayer); - } - - return nbttagcompound1; - } - - protected void savePlayerFile(EntityPlayer entityplayer) { - entityplayer.lastSave = MinecraftServer.currentTick; // Paper - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = entityplayer.getStatisticManager(); // CraftBukkit - - if (serverstatisticmanager != null) { - serverstatisticmanager.b(); - } - - AdvancementDataPlayer advancementdataplayer = entityplayer.getAdvancementData(); // CraftBukkit - - if (advancementdataplayer != null) { - advancementdataplayer.c(); - } - - } - - public void onPlayerJoin(EntityPlayer entityplayer, String joinMessage) { // CraftBukkit added param - this.players.add(entityplayer); - this.playersByName.put(entityplayer.getName(), entityplayer); // Spigot - this.j.put(entityplayer.getUniqueID(), entityplayer); - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer})); // CraftBukkit - replaced with loop below - WorldServer worldserver = this.server.getWorldServer(entityplayer.dimension); - - // CraftBukkit start - PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(entityplayer), joinMessage); - cserver.getPluginManager().callEvent(playerJoinEvent); - - if (!entityplayer.playerConnection.networkManager.isConnected()) { - return; - } - - joinMessage = playerJoinEvent.getJoinMessage(); - - if (joinMessage != null && joinMessage.length() > 0) { - for (IChatBaseComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { - server.getPlayerList().sendAll(new PacketPlayOutChat(line)); - } - } - - ChunkIOExecutor.adjustPoolSize(getPlayerCount()); - // CraftBukkit end - - // CraftBukkit start - sendAll above replaced with this loop - PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, entityplayer); - - for (int i = 0; i < this.players.size(); ++i) { - EntityPlayer entityplayer1 = this.players.get(i); - - if (entityplayer1.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { - entityplayer1.playerConnection.sendPacket(packet); - } - - if (!entityplayer.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) { - continue; - } - - entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer1})); - } - entityplayer.sentListPacket = true; - // CraftBukkit end - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(entityplayer.getId(), entityplayer.datawatcher, true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn - - // CraftBukkit start - Only add if the player wasn't moved in the event - if (entityplayer.world == worldserver && !worldserver.players.contains(entityplayer)) { - worldserver.addEntity(entityplayer); - this.a(entityplayer, (WorldServer) null); - } - // CraftBukkit end - } - - public void d(EntityPlayer entityplayer) { - entityplayer.x().getPlayerChunkMap().movePlayer(entityplayer); - } - - public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string - WorldServer worldserver = entityplayer.x(); - - entityplayer.b(StatisticList.f); - - // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it - org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(entityplayer, org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), LocaleI18n.a(AkarinGlobalConfig.messagePlayerQuit, entityplayer.getName())); // Akarin - use I18n to replace name - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - - - entityplayer.playerTick();// SPIGOT-924 - // CraftBukkit end - - // Paper start - Remove from collideRule team if needed - if (this.collideRuleTeamName != null) { - final Scoreboard scoreBoard = this.server.getWorld().getScoreboard(); - final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName); - if (entityplayer.getTeam() == team && team != null) { - scoreBoard.removePlayerFromTeam(entityplayer.getName(), team); - } - } - // Paper end - - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getVehicle(); - - if (entity.b(EntityPlayer.class).size() == 1) { - PlayerList.f.debug("Removing player mount"); - entityplayer.stopRiding(); - worldserver.removeEntity(entity); - Iterator iterator = entity.bG().iterator(); - - while (iterator.hasNext()) { - Entity entity1 = (Entity) iterator.next(); - - worldserver.removeEntity(entity1); - } - - worldserver.getChunkAt(entityplayer.ab, entityplayer.ad).markDirty(); - } - } - - worldserver.kill(entityplayer); - worldserver.getPlayerChunkMap().removePlayer(entityplayer); - entityplayer.getAdvancementData().a(); - this.players.remove(entityplayer); - this.playersByName.remove(entityplayer.getName()); // Spigot - UUID uuid = entityplayer.getUniqueID(); - EntityPlayer entityplayer1 = this.j.get(uuid); - - if (entityplayer1 == entityplayer) { - this.j.remove(uuid); - // CraftBukkit start - // this.o.remove(uuid); - // this.p.remove(uuid); - // CraftBukkit end - } - - // CraftBukkit start - // this.sendAll(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[] { entityplayer})); - PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityplayer); - for (int i = 0; i < players.size(); i++) { - EntityPlayer entityplayer2 = this.players.get(i); - - if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { - entityplayer2.playerConnection.sendPacket(packet); - } else { - entityplayer2.getBukkitEntity().removeDisconnectingPlayer(entityplayer.getBukkitEntity()); - } - } - // This removes the scoreboard (and player reference) for the specific player in the manager - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - - ChunkIOExecutor.adjustPoolSize(this.getPlayerCount()); // CraftBukkit - - return playerQuitEvent.getQuitMessage(); // CraftBukkit - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer - public EntityPlayer attemptLogin(LoginListener loginlistener, GameProfile gameprofile, String hostname) { - // Moved from processLogin - UUID uuid = EntityHuman.a(gameprofile); - ArrayList arraylist = Lists.newArrayList(); - - EntityPlayer entityplayer; - - for (int i = 0; i < this.players.size(); ++i) { - entityplayer = this.players.get(i); - if (entityplayer.getUniqueID().equals(uuid)) { - arraylist.add(entityplayer); - } - } - - Iterator iterator = arraylist.iterator(); - - while (iterator.hasNext()) { - entityplayer = (EntityPlayer) iterator.next(); - savePlayerFile(entityplayer); // CraftBukkit - Force the player's inventory to be saved - entityplayer.playerConnection.disconnect(AkarinGlobalConfig.messageDupLogin); // Akarin - } - - // Instead of kicking then returning, we need to store the kick reason - // in the event, check with plugins to see if it's ok, and THEN kick - // depending on the outcome. - SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress(); - - EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), gameprofile, new PlayerInteractManager(server.getWorldServer(0))); - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - String s; - - if (getProfileBans().isBanned(gameprofile) && !getProfileBans().get(gameprofile).hasExpired()) { - GameProfileBanEntry gameprofilebanentry = this.k.get(gameprofile); - - s = LocaleI18n.a(AkarinGlobalConfig.messageBan, - gameprofilebanentry.getReason().equals(Akari.EMPTY_STRING) ? Akari.EMPTY_STRING : AkarinGlobalConfig.messageBanReason + gameprofilebanentry.getReason(), - gameprofilebanentry.getExpires() == null ? Akari.EMPTY_STRING : AkarinGlobalConfig.messageBanExpires + PlayerList.g.format(gameprofilebanentry.getExpires())); // Akarin - modify message - - // return s; - if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s); // Spigot - } else if (!this.isWhitelisted(gameprofile, event)) { // Paper - // return "You are not white-listed on this server!"; - //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted - } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { - IpBanEntry ipbanentry = this.l.get(socketaddress); - - s = LocaleI18n.a(AkarinGlobalConfig.messageBan, - ipbanentry.getReason().equals(Akari.EMPTY_STRING) ? Akari.EMPTY_STRING : AkarinGlobalConfig.messageBanReason + ipbanentry.getReason(), - ipbanentry.getExpires() == null ? Akari.EMPTY_STRING : AkarinGlobalConfig.messageBanExpires + PlayerList.g.format(ipbanentry.getExpires())); // Akarin - modify message - - // return s; - event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s); - } else { - // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? "The server is full!" : null; - if (this.players.size() >= this.maxPlayers && !this.f(gameprofile)) { - event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot - } - } - - cserver.getPluginManager().callEvent(event); - if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { - loginlistener.disconnect(event.getKickMessage()); - return null; - } - return entity; - } - - public EntityPlayer processLogin(GameProfile gameprofile, EntityPlayer player) { // CraftBukkit - added EntityPlayer - /* CraftBukkit startMoved up - UUID uuid = EntityHuman.a(gameprofile); - ArrayList arraylist = Lists.newArrayList(); - - for (int i = 0; i < this.players.size(); ++i) { - EntityPlayer entityplayer = (EntityPlayer) this.players.get(i); - - if (entityplayer.getUniqueID().equals(uuid)) { - arraylist.add(entityplayer); - } - } - - EntityPlayer entityplayer1 = (EntityPlayer) this.j.get(gameprofile.getId()); - - if (entityplayer1 != null && !arraylist.contains(entityplayer1)) { - arraylist.add(entityplayer1); - } - - Iterator iterator = arraylist.iterator(); - - while (iterator.hasNext()) { - EntityPlayer entityplayer2 = (EntityPlayer) iterator.next(); - - entityplayer2.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0])); - } - - Object object; - - if (this.server.V()) { - object = new DemoPlayerInteractManager(this.server.getWorldServer(0)); - } else { - object = new PlayerInteractManager(this.server.getWorldServer(0)); - } - - return new EntityPlayer(this.server, this.server.getWorldServer(0), gameprofile, (PlayerInteractManager) object); - */ - return player; - // CraftBukkit end - } - - // CraftBukkit start - public EntityPlayer moveToWorld(EntityPlayer entityplayer, int i, boolean flag) { - return this.moveToWorld(entityplayer, i, flag, null, true); - } - - public EntityPlayer moveToWorld(EntityPlayer entityplayer, int i, boolean flag, Location location, boolean avoidSuffocation) { - entityplayer.stopRiding(); // CraftBukkit - entityplayer.x().getTracker().untrackPlayer(entityplayer); - // entityplayer.x().getTracker().untrackEntity(entityplayer); // CraftBukkit - entityplayer.x().getPlayerChunkMap().removePlayer(entityplayer); - this.players.remove(entityplayer); - this.playersByName.remove(entityplayer.getName()); // Spigot - this.server.getWorldServer(entityplayer.dimension).removeEntity(entityplayer); - BlockPosition blockposition = entityplayer.getBed(); - boolean flag1 = entityplayer.isRespawnForced(); - - /* CraftBukkit start - entityplayer.dimension = i; - Object object; - - if (this.server.V()) { - object = new DemoPlayerInteractManager(this.server.getWorldServer(entityplayer.dimension)); - } else { - object = new PlayerInteractManager(this.server.getWorldServer(entityplayer.dimension)); - } - - EntityPlayer entityplayer1 = new EntityPlayer(this.server, this.server.getWorldServer(entityplayer.dimension), entityplayer.getProfile(), (PlayerInteractManager) object); - // */ - EntityPlayer entityplayer1 = entityplayer; - org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld(); - entityplayer.viewingCredits = false; - // CraftBukkit end - - entityplayer1.playerConnection = entityplayer.playerConnection; - entityplayer1.copyFrom(entityplayer, flag); - entityplayer1.h(entityplayer.getId()); - entityplayer1.v(entityplayer); - entityplayer1.a(entityplayer.getMainHand()); - Iterator iterator = entityplayer.getScoreboardTags().iterator(); - - while (iterator.hasNext()) { - String s = (String) iterator.next(); - - entityplayer1.addScoreboardTag(s); - } - - // WorldServer worldserver = this.server.getWorldServer(entityplayer.dimension); // CraftBukkit - handled later - - // this.a(entityplayer1, entityplayer, worldserver); // CraftBukkit - removed - BlockPosition blockposition1; - - // CraftBukkit start - fire PlayerRespawnEvent - if (location == null) { - boolean isBedSpawn = false; - CraftWorld cworld = (CraftWorld) this.server.server.getWorld(entityplayer.spawnWorld); - if (cworld != null && blockposition != null) { - blockposition1 = EntityHuman.getBed(cworld.getHandle(), blockposition, flag1); - if (blockposition1 != null) { - isBedSpawn = true; - location = new Location(cworld, blockposition1.getX() + 0.5F, blockposition1.getY() + 0.1F, blockposition1.getZ() + 0.5F); - } else { - entityplayer1.setRespawnPosition(null, true); - entityplayer1.playerConnection.sendPacket(new PacketPlayOutGameStateChange(0, 0.0F)); - } - } - - if (location == null) { - cworld = (CraftWorld) this.server.server.getWorlds().get(0); - blockposition = entityplayer1.getSpawnPoint(this.server, cworld.getHandle()); - location = new Location(cworld, blockposition.getX() + 0.5F, blockposition.getY() + 0.1F, blockposition.getZ() + 0.5F); - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); - PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn); - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { - return entityplayer; - } - // Spigot End - - location = respawnEvent.getRespawnLocation(); - entityplayer.reset(); - } else { - location.setWorld(server.getWorldServer(i).getWorld()); - } - WorldServer worldserver = ((CraftWorld) location.getWorld()).getHandle(); - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - // CraftBukkit end - - worldserver.getChunkProviderServer().getChunkAt((int) entityplayer1.locX >> 4, (int) entityplayer1.locZ >> 4); - - while (avoidSuffocation && !worldserver.getCubes(entityplayer1, entityplayer1.getBoundingBox()).isEmpty() && entityplayer1.locY < 256.0D) { - entityplayer1.setPosition(entityplayer1.locX, entityplayer1.locY + 1.0D, entityplayer1.locZ); - } - // CraftBukkit start - byte actualDimension = (byte) (worldserver.getWorld().getEnvironment().getId()); - // Force the client to refresh their chunk cache - if (fromWorld.getEnvironment() == worldserver.getWorld().getEnvironment()) { - entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn((byte) (actualDimension >= 0 ? -1 : 0), worldserver.getDifficulty(), worldserver.getWorldData().getType(), entityplayer.playerInteractManager.getGameMode())); - } - - entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(actualDimension, worldserver.getDifficulty(), worldserver.getWorldData().getType(), entityplayer1.playerInteractManager.getGameMode())); - entityplayer1.spawnIn(worldserver); - entityplayer1.dead = false; - entityplayer1.playerConnection.teleport(new Location(worldserver.getWorld(), entityplayer1.locX, entityplayer1.locY, entityplayer1.locZ, entityplayer1.yaw, entityplayer1.pitch)); - entityplayer1.setSneaking(false); - blockposition1 = worldserver.getSpawn(); - // entityplayer1.playerConnection.a(entityplayer1.locX, entityplayer1.locY, entityplayer1.locZ, entityplayer1.yaw, entityplayer1.pitch); - entityplayer1.playerConnection.sendPacket(new PacketPlayOutSpawnPosition(blockposition1)); - entityplayer1.playerConnection.sendPacket(new PacketPlayOutExperience(entityplayer1.exp, entityplayer1.expTotal, entityplayer1.expLevel)); - this.b(entityplayer1, worldserver); - this.f(entityplayer1); - if (!entityplayer.playerConnection.isDisconnected()) { - worldserver.getPlayerChunkMap().addPlayer(entityplayer1); - worldserver.addEntity(entityplayer1); - this.players.add(entityplayer1); - this.playersByName.put(entityplayer1.getName(), entityplayer1); // Spigot - this.j.put(entityplayer1.getUniqueID(), entityplayer1); - } - // entityplayer1.syncInventory(); - entityplayer1.setHealth(entityplayer1.getHealth()); - // Added from changeDimension - updateClient(entityplayer); // Update health, etc... - entityplayer.updateAbilities(); - for (Object o1 : entityplayer.getEffects()) { - MobEffect mobEffect = (MobEffect) o1; - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobEffect)); - } - - // Fire advancement trigger - CriterionTriggers.u.a(entityplayer, ((CraftWorld) fromWorld).getHandle().worldProvider.getDimensionManager(), worldserver.worldProvider.getDimensionManager()); - if (((CraftWorld) fromWorld).getHandle().worldProvider.getDimensionManager() == DimensionManager.NETHER && worldserver.worldProvider.getDimensionManager() == DimensionManager.OVERWORLD && entityplayer.Q() != null) { - CriterionTriggers.B.a(entityplayer, entityplayer.Q()); - } - - // Don't fire on respawn - if (fromWorld != location.getWorld()) { - PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(entityplayer.getBukkitEntity(), fromWorld); - server.server.getPluginManager().callEvent(event); - } - - // Save player file again if they were disconnected - if (entityplayer.playerConnection.isDisconnected()) { - this.savePlayerFile(entityplayer); - } - // CraftBukkit end - return entityplayer1; - } - - // CraftBukkit start - Replaced the standard handling of portals with a more customised method. - public void changeDimension(EntityPlayer entityplayer, int i, TeleportCause cause) { - WorldServer exitWorld = null; - if (entityplayer.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 : this.server.worlds) { - if (world.dimension == i) { - exitWorld = world; - } - } - } - - Location enter = entityplayer.getBukkitEntity().getLocation(); - Location exit = null; - boolean useTravelAgent = false; // don't use agent for custom worlds or return from THE_END - if (exitWorld != null) { - if ((cause == TeleportCause.END_PORTAL) && (i == 0)) { - // THE_END -> NORMAL; use bed if available, otherwise default spawn - exit = entityplayer.getBukkitEntity().getBedSpawnLocation(); - if (exit == null || ((CraftWorld) exit.getWorld()).getHandle().dimension != 0) { - BlockPosition randomSpawn = entityplayer.getSpawnPoint(server, exitWorld); - exit = new Location(exitWorld.getWorld(), randomSpawn.getX(), randomSpawn.getY(), randomSpawn.getZ()); - } else { - exit = exit.add(0.5F, 0.1F, 0.5F); // SPIGOT-3879 - } - } else { - // NORMAL <-> NETHER or NORMAL -> THE_END - exit = this.calculateTarget(enter, exitWorld); - useTravelAgent = true; - } - } - - TravelAgent agent = exit != null ? (TravelAgent) ((CraftWorld) exit.getWorld()).getHandle().getTravelAgent() : org.bukkit.craftbukkit.CraftTravelAgent.DEFAULT; // return arbitrary TA to compensate for implementation dependent plugins - PlayerPortalEvent event = new PlayerPortalEvent(entityplayer.getBukkitEntity(), enter, exit, agent, cause); - event.useTravelAgent(useTravelAgent); - Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled() || event.getTo() == null) { - return; - } - - exit = event.useTravelAgent() ? event.getPortalTravelAgent().findOrCreate(event.getTo()) : event.getTo(); - if (exit == null) { - return; - } - exitWorld = ((CraftWorld) exit.getWorld()).getHandle(); - - org.bukkit.event.player.PlayerTeleportEvent tpEvent = new org.bukkit.event.player.PlayerTeleportEvent(entityplayer.getBukkitEntity(), enter, exit, cause); - Bukkit.getServer().getPluginManager().callEvent(tpEvent); - if (tpEvent.isCancelled() || tpEvent.getTo() == null) { - return; - } - - Vector velocity = entityplayer.getBukkitEntity().getVelocity(); - exitWorld.getTravelAgent().adjustExit(entityplayer, exit, velocity); - - entityplayer.worldChangeInvuln = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds - this.moveToWorld(entityplayer, exitWorld.dimension, true, exit, true); // SPIGOT-3864 - if (entityplayer.motX != velocity.getX() || entityplayer.motY != velocity.getY() || entityplayer.motZ != velocity.getZ()) { - entityplayer.getBukkitEntity().setVelocity(velocity); - } - } - - public void f(EntityPlayer entityplayer) { - GameProfile gameprofile = entityplayer.getProfile(); - int i = this.isOp(gameprofile) ? this.operators.a(gameprofile) : 0; - - i = this.server.R() && this.server.worldServer[0].getWorldData().u() ? 4 : i; - i = this.u ? 4 : i; - this.b(entityplayer, i); - } - - public void a(EntityPlayer entityplayer, int i) { - int j = entityplayer.dimension; - WorldServer worldserver = this.server.getWorldServer(entityplayer.dimension); - - entityplayer.dimension = i; - WorldServer worldserver1 = this.server.getWorldServer(entityplayer.dimension); - - entityplayer.playerConnection.sendPacket(new PacketPlayOutRespawn(entityplayer.dimension, entityplayer.world.getDifficulty(), entityplayer.world.getWorldData().getType(), entityplayer.playerInteractManager.getGameMode())); - this.f(entityplayer); - worldserver.removeEntity(entityplayer); - entityplayer.dead = false; - this.changeWorld(entityplayer, j, worldserver, worldserver1); - this.a(entityplayer, worldserver); - entityplayer.playerConnection.a(entityplayer.locX, entityplayer.locY, entityplayer.locZ, entityplayer.yaw, entityplayer.pitch); - entityplayer.playerInteractManager.a(worldserver1); - entityplayer.playerConnection.sendPacket(new PacketPlayOutAbilities(entityplayer.abilities)); - this.b(entityplayer, worldserver1); - this.updateClient(entityplayer); - Iterator iterator = entityplayer.getEffects().iterator(); - - while (iterator.hasNext()) { - MobEffect mobeffect = (MobEffect) iterator.next(); - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobeffect)); - } - - } - - public void changeWorld(Entity entity, int i, WorldServer worldserver, WorldServer worldserver1) { - // CraftBukkit start - Split into modular functions - Location exit = calculateTarget(entity.getBukkitEntity().getLocation(), worldserver1); - repositionEntity(entity, exit, true); - } - - // Copy of original changeWorld(Entity, int, WorldServer, WorldServer) method with only location calculation logic - public Location calculateTarget(Location enter, World target) { - WorldServer worldserver = ((CraftWorld) enter.getWorld()).getHandle(); - WorldServer worldserver1 = target.getWorld().getHandle(); - int i = worldserver.dimension; - - double y = enter.getY(); - float yaw = enter.getYaw(); - float pitch = enter.getPitch(); - double d0 = enter.getX(); - double d1 = enter.getZ(); - double d2 = 8.0D; - /* - double d0 = entity.locX; - double d1 = entity.locZ; - double d2 = 8.0D; - float f = entity.yaw; - */ - - worldserver.methodProfiler.a("moving"); - if (worldserver1.dimension == -1) { - d0 = MathHelper.a(d0 / d2, worldserver1.getWorldBorder().b()+ 16.0D, worldserver1.getWorldBorder().d() - 16.0D); - d1 = MathHelper.a(d1 / d2, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D); - /* - entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch); - if (entity.isAlive()) { - worldserver.entityJoinedWorld(entity, false); - } - */ - } else if (worldserver1.dimension == 0) { - d0 = MathHelper.a(d0 * d2, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D); - d1 = MathHelper.a(d1 * d2, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D); - /* - entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch); - if (entity.isAlive()) { - worldserver.entityJoinedWorld(entity, false); - } - */ - } else { - BlockPosition blockposition; - - if (i == 1) { - // use default NORMAL world spawn instead of target - worldserver1 = this.server.worlds.get(0); - blockposition = worldserver1.getSpawn(); - } else { - blockposition = worldserver1.getDimensionSpawn(); - } - - d0 = blockposition.getX(); - y = blockposition.getY(); - d1 = blockposition.getZ(); - /* - entity.setPositionRotation(d0, entity.locY, d1, 90.0F, 0.0F); - if (entity.isAlive()) { - worldserver.entityJoinedWorld(entity, false); - } - */ - } - - worldserver.methodProfiler.b(); - if (i != 1) { - worldserver.methodProfiler.a("placing"); - d0 = MathHelper.clamp((int) d0, -29999872, 29999872); - d1 = MathHelper.clamp((int) d1, -29999872, 29999872); - /* - if (entity.isAlive()) { - entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch); - worldserver1.getTravelAgent().a(entity, f); - worldserver1.addEntity(entity); - worldserver1.entityJoinedWorld(entity, false); - } - */ - - worldserver.methodProfiler.b(); - } - - // entity.spawnIn(worldserver1); - return new Location(worldserver1.getWorld(), d0, y, d1, yaw, pitch); - } - - // copy of original a(Entity, int, WorldServer, WorldServer) method with only entity repositioning logic - public void repositionEntity(Entity entity, Location exit, boolean portal) { - WorldServer worldserver = (WorldServer) entity.world; - WorldServer worldserver1 = ((CraftWorld) exit.getWorld()).getHandle(); - int i = worldserver.dimension; - - /* - double d0 = entity.locX; - double d1 = entity.locZ; - double d2 = 8.0D; - float f = entity.yaw; - */ - - worldserver.methodProfiler.a("moving"); - entity.setPositionRotation(exit.getX(), exit.getY(), exit.getZ(), exit.getYaw(), exit.getPitch()); - if (entity.isAlive()) { - worldserver.entityJoinedWorld(entity, false); - } - /* - if (entity.dimension == -1) { - 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); - entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch); - if (entity.isAlive()) { - worldserver.entityJoinedWorld(entity, false); - } - } else if (entity.dimension == 0) { - 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); - entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch); - if (entity.isAlive()) { - worldserver.entityJoinedWorld(entity, false); - } - } else { - BlockPosition blockposition; - - if (i == 1) { - // use default NORMAL world spawn instead of target - worldserver1 = this.server.worlds.get(0); - blockposition = worldserver1.getSpawn(); - } else { - blockposition = worldserver1.getDimensionSpawn(); - } - - d0 = (double) blockposition.getX(); - entity.locY = (double) blockposition.getY(); - d1 = (double) blockposition.getZ(); - entity.setPositionRotation(d0, entity.locY, d1, 90.0F, 0.0F); - if (entity.isAlive()) { - worldserver.entityJoinedWorld(entity, false); - } - } - */ - - worldserver.methodProfiler.b(); - if (i != 1) { - worldserver.methodProfiler.a("placing"); - /* - d0 = (double) MathHelper.clamp((int) d0, -29999872, 29999872); - d1 = (double) MathHelper.clamp((int) d1, -29999872, 29999872); - */ - if (entity.isAlive()) { - // entity.setPositionRotation(d0, entity.locY, d1, entity.yaw, entity.pitch); - // worldserver1.getTravelAgent().a(entity, f); - if (portal) { - Vector velocity = entity.getBukkitEntity().getVelocity(); - worldserver1.getTravelAgent().adjustExit(entity, exit, velocity); - entity.setPositionRotation(exit.getX(), exit.getY(), exit.getZ(), exit.getYaw(), exit.getPitch()); - if (entity.motX != velocity.getX() || entity.motY != velocity.getY() || entity.motZ != velocity.getZ()) { - entity.getBukkitEntity().setVelocity(velocity); - } - } - // worldserver1.addEntity(entity); - worldserver1.entityJoinedWorld(entity, false); - } - - worldserver.methodProfiler.b(); - } - - entity.spawnIn(worldserver1); - // CraftBukkit end - } - - public void tick() { - if (++this.v > 600) { - // CraftBukkit start - for (int i = 0; i < this.players.size(); ++i) { - final EntityPlayer target = this.players.get(i); - - target.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_LATENCY, Iterables.filter(this.players, new Predicate() { - @Override - public boolean apply(EntityPlayer input) { - return target.getBukkitEntity().canSee(input.getBukkitEntity()); - } - }))); - } - // CraftBukkit end - this.v = 0; - } - - } - - public void sendAll(Packet packet) { - for (int i = 0; i < this.players.size(); ++i) { - this.players.get(i).playerConnection.sendPacket(packet); - } - - } - - // CraftBukkit start - add a world/entity limited version - public void sendAll(Packet packet, EntityHuman entityhuman) { - for (int i = 0; i < this.players.size(); ++i) { - EntityPlayer entityplayer = this.players.get(i); - if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { - continue; - } - this.players.get(i).playerConnection.sendPacket(packet); - } - } - - public void sendAll(Packet packet, World world) { - for (int i = 0; i < world.players.size(); ++i) { - ((EntityPlayer) world.players.get(i)).playerConnection.sendPacket(packet); - } - - } - // CraftBukkit end - - public void a(Packet packet, int i) { - for (int j = 0; j < this.players.size(); ++j) { - EntityPlayer entityplayer = this.players.get(j); - - if (entityplayer.dimension == i) { - entityplayer.playerConnection.sendPacket(packet); - } - } - - } - - public void a(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) { - ScoreboardTeamBase scoreboardteambase = entityhuman.aY(); - - if (scoreboardteambase != null) { - Collection collection = scoreboardteambase.getPlayerNameSet(); - Iterator iterator = collection.iterator(); - - while (iterator.hasNext()) { - String s = (String) iterator.next(); - EntityPlayer entityplayer = this.getPlayer(s); - - if (entityplayer != null && entityplayer != entityhuman) { - entityplayer.sendMessage(ichatbasecomponent); - } - } - - } - } - - public void b(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) { - ScoreboardTeamBase scoreboardteambase = entityhuman.aY(); - - if (scoreboardteambase == null) { - this.sendMessage(ichatbasecomponent); - } else { - for (int i = 0; i < this.players.size(); ++i) { - EntityPlayer entityplayer = this.players.get(i); - - if (entityplayer.aY() != scoreboardteambase) { - entityplayer.sendMessage(ichatbasecomponent); - } - } - - } - } - - public String b(boolean flag) { - String s = ""; - ArrayList arraylist = Lists.newArrayList(this.players); - - for (int i = 0; i < arraylist.size(); ++i) { - if (i > 0) { - s = s + ", "; - } - - s = s + ((EntityPlayer) arraylist.get(i)).getName(); - if (flag) { - s = s + " (" + ((EntityPlayer) arraylist.get(i)).bn() + ")"; - } - } - - return s; - } - - public String[] f() { - String[] astring = new String[this.players.size()]; - - for (int i = 0; i < this.players.size(); ++i) { - astring[i] = this.players.get(i).getName(); - } - - return astring; - } - - public GameProfile[] g() { - GameProfile[] agameprofile = new GameProfile[this.players.size()]; - - for (int i = 0; i < this.players.size(); ++i) { - agameprofile[i] = this.players.get(i).getProfile(); - } - - return agameprofile; - } - - public GameProfileBanList getProfileBans() { - return this.k; - } - - public IpBanList getIPBans() { - return this.l; - } - - public void addOp(GameProfile gameprofile) { - int i = this.server.q(); - - this.operators.add(new OpListEntry(gameprofile, this.server.q(), this.operators.b(gameprofile))); - this.b(this.a(gameprofile.getId()), i); - // CraftBukkit start - Player player = server.server.getPlayer(gameprofile.getId()); - if (player != null) { - player.recalculatePermissions(); - } - // CraftBukkit end - } - - public void removeOp(GameProfile gameprofile) { - this.operators.remove(gameprofile); - this.b(this.a(gameprofile.getId()), 0); - // CraftBukkit start - Player player = server.server.getPlayer(gameprofile.getId()); - if (player != null) { - player.recalculatePermissions(); - } - // CraftBukkit end - } - - private void b(EntityPlayer entityplayer, int i) { - if (entityplayer != null && entityplayer.playerConnection != null) { - byte b0; - - if (i <= 0) { - b0 = 24; - } else if (i >= 4) { - b0 = 28; - } else { - b0 = (byte) (24 + i); - } - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, b0)); - } - - } - - // Paper start - public boolean isWhitelisted(GameProfile gameprofile) { - return isWhitelisted(gameprofile, null); - } - public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { - boolean isOp = this.operators.d(gameprofile); - boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); - final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; - event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); - event.callEvent(); - if (!event.isWhitelisted()) { - if (loginEvent != null) { - loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage()); - } - return false; - } - return true; - } - // Paper end - - public boolean isOp(GameProfile gameprofile) { - return this.operators.d(gameprofile) || this.server.R() && this.server.worlds.get(0).getWorldData().u() && this.server.Q().equalsIgnoreCase(gameprofile.getName()) || this.u; // CraftBukkit - } - - @Nullable - public EntityPlayer getPlayer(String s) { - return this.playersByName.get(s); // Spigot - } - - public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i, Packet packet) { - for (int j = 0; j < this.players.size(); ++j) { - EntityPlayer entityplayer = this.players.get(j); - - // CraftBukkit start - Test if player receiving packet can see the source of the packet - if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { - continue; - } - // CraftBukkit end - - if (entityplayer != entityhuman && entityplayer.dimension == i) { - double d4 = d0 - entityplayer.locX; - double d5 = d1 - entityplayer.locY; - double d6 = d2 - entityplayer.locZ; - - if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) { - entityplayer.playerConnection.sendPacket(packet); - } - } - } - - } - - // Paper start - public void savePlayers() { - savePlayers(null); - } - - public void savePlayers(Integer interval) { - MCUtil.ensureMain("Save Players", () -> { // Paper - ensure main - long now = MinecraftServer.currentTick; - MinecraftTimings.savePlayers.startTiming(); // Paper - int numSaved = 0; // Paper - for (int i = 0; i < this.players.size(); ++i) { - EntityPlayer entityplayer = this.players.get(i); - if (interval == null || now - entityplayer.lastSave >= interval) { - this.savePlayerFile(entityplayer); - if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } // Paper - } - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main - } - // Paper end - - public void addWhitelist(GameProfile gameprofile) { - this.whitelist.add(new WhiteListEntry(gameprofile)); - } - - public void removeWhitelist(GameProfile gameprofile) { - this.whitelist.remove(gameprofile); - } - - public WhiteList getWhitelist() { - return this.whitelist; - } - - public String[] getWhitelisted() { - return this.whitelist.getEntries(); - } - - public OpList getOPs() { - return this.operators; - } - - public String[] n() { - return this.operators.getEntries(); - } - - public void reloadWhitelist() {} - - public void b(EntityPlayer entityplayer, WorldServer worldserver) { - WorldBorder worldborder = entityplayer.world.getWorldBorder(); // CraftBukkit - - entityplayer.playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE)); - entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateTime(worldserver.getTime(), worldserver.getDayTime(), worldserver.getGameRules().getBoolean("doDaylightCycle"))); - BlockPosition blockposition = worldserver.getSpawn(); - - entityplayer.playerConnection.sendPacket(new PacketPlayOutSpawnPosition(blockposition)); - if (worldserver.isRaining()) { - // CraftBukkit start - handle player weather - // entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(1, 0.0F)); - // entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(7, worldserver.j(1.0F))); - // entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(8, worldserver.h(1.0F))); - entityplayer.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false); - entityplayer.updateWeather(-worldserver.o, worldserver.o, -worldserver.q, worldserver.q); - // CraftBukkit end - } - - } - - public void updateClient(EntityPlayer entityplayer) { - entityplayer.updateInventory(entityplayer.defaultContainer); - // entityplayer.triggerHealthUpdate(); - entityplayer.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange - entityplayer.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); - } - - public int getPlayerCount() { - return this.players.size(); - } - - public int getMaxPlayers() { - return this.maxPlayers; - } - - public String[] getSeenPlayers() { - return this.server.worlds.get(0).getDataManager().getPlayerFileData().getSeenPlayers(); // CraftBukkit - } - - public boolean getHasWhitelist() { - return this.hasWhitelist; - } - - public void setHasWhitelist(boolean flag) { - this.hasWhitelist = flag; - } - - public List b(String s) { - ArrayList arraylist = Lists.newArrayList(); - Iterator iterator = this.players.iterator(); - - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - if (entityplayer.A().equals(s)) { - arraylist.add(entityplayer); - } - } - - return arraylist; - } - - public int s() { - return this.s; - } - - public MinecraftServer getServer() { - return this.server; - } - - public NBTTagCompound t() { - return null; - } - - private void a(EntityPlayer entityplayer, EntityPlayer entityplayer1, World world) { - if (entityplayer1 != null) { - entityplayer.playerInteractManager.setGameMode(entityplayer1.playerInteractManager.getGameMode()); - } else if (this.t != null) { - entityplayer.playerInteractManager.setGameMode(this.t); - } - - entityplayer.playerInteractManager.b(world.getWorldData().getGameType()); - } - - // Paper start - Extract method to allow for restarting flag - public void u() { - u(false); - } - - public void u(boolean isRestarting) { - // CraftBukkit start - disconnect safely - for (EntityPlayer player : this.players) { - player.playerConnection.disconnect(!isRestarting ? this.server.server.getShutdownMessage() : org.spigotmc.SpigotConfig.restartMessage); // CraftBukkit - add custom shutdown message // Paper - add isRestarting flag - } - // CraftBukkit end - // Paper start - Remove collideRule team if it exists - if (this.collideRuleTeamName != null) { - final Scoreboard scoreboard = this.getServer().getWorld().getScoreboard(); - final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName); - if (team != null) scoreboard.removeTeam(team); - } - // Paper end - } - // Paper end - - // CraftBukkit start - public void sendMessage(IChatBaseComponent[] iChatBaseComponents) { - for (IChatBaseComponent component : iChatBaseComponents) { - sendMessage(component, true); - } - } - // CraftBukkit end - - public void sendMessage(IChatBaseComponent ichatbasecomponent, boolean flag) { - this.server.sendMessage(ichatbasecomponent); - ChatMessageType chatmessagetype = flag ? ChatMessageType.SYSTEM : ChatMessageType.CHAT; - - // CraftBukkit start - we run this through our processor first so we can get web links etc - this.sendAll(new PacketPlayOutChat(CraftChatMessage.fixComponent(ichatbasecomponent), chatmessagetype)); - // CraftBukkit end - } - - public void sendMessage(IChatBaseComponent ichatbasecomponent) { - this.sendMessage(ichatbasecomponent, true); - } - - public ServerStatisticManager getStatisticManager(EntityPlayer entityhuman) { - UUID uuid = entityhuman.getUniqueID(); - ServerStatisticManager serverstatisticmanager = uuid == null ? null : (ServerStatisticManager) entityhuman.getStatisticManager(); - // CraftBukkit end - - if (serverstatisticmanager == null) { - File file = new File(this.server.getWorldServer(0).getDataManager().getDirectory(), "stats"); - File file1 = new File(file, uuid + ".json"); - - if (!file1.exists()) { - File file2 = new File(file, entityhuman.getName() + ".json"); - - if (file2.exists() && file2.isFile()) { - file2.renameTo(file1); - } - } - - serverstatisticmanager = new ServerStatisticManager(this.server, file1); - serverstatisticmanager.a(); - // this.o.put(uuid, serverstatisticmanager); // CraftBukkit - } - - return serverstatisticmanager; - } - - public AdvancementDataPlayer h(EntityPlayer entityplayer) { - UUID uuid = entityplayer.getUniqueID(); - AdvancementDataPlayer advancementdataplayer = entityplayer.getAdvancementData(); // CraftBukkit - - if (advancementdataplayer == null) { - File file = new File(this.server.getWorldServer(0).getDataManager().getDirectory(), "advancements"); - File file1 = new File(file, uuid + ".json"); - - advancementdataplayer = new AdvancementDataPlayer(this.server, file1, entityplayer); - // this.p.put(uuid, advancementdataplayer); // CraftBukkit - } - - advancementdataplayer.a(entityplayer); - return advancementdataplayer; - } - - public void a(int i) { - this.s = i; - if (this.server.worldServer != null) { - WorldServer[] aworldserver = this.server.worldServer; - int j = aworldserver.length; - - // CraftBukkit start - for (int k = 0; k < server.worlds.size(); ++k) { - WorldServer worldserver = server.worlds.get(0); - // CraftBukkit end - - if (worldserver != null) { - worldserver.getPlayerChunkMap().a(i); - worldserver.getTracker().a(i); - } - } - - } - } - - public List v() { - return this.players; - } - - public EntityPlayer a(UUID uuid) { - return this.j.get(uuid); - } - - public boolean f(GameProfile gameprofile) { - return false; - } - - public void reload() { - // CraftBukkit start - /*Iterator iterator = this.p.values().iterator(); - - while (iterator.hasNext()) { - AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) iterator.next(); - - advancementdataplayer.b(); - }*/ - - for (EntityPlayer player : players) { - player.getAdvancementData().b(); - player.getAdvancementData().b(player); // CraftBukkit - trigger immediate flush of advancements - } - // CraftBukkit end - - } -} diff --git a/sources/src/main/java/net/minecraft/server/RegionFileCache.java b/sources/src/main/java/net/minecraft/server/RegionFileCache.java deleted file mode 100644 index 0c061fdd0..000000000 --- a/sources/src/main/java/net/minecraft/server/RegionFileCache.java +++ /dev/null @@ -1,127 +0,0 @@ -package net.minecraft.server; - -import com.destroystokyo.paper.exception.ServerInternalException; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; -import com.destroystokyo.paper.PaperConfig; // Paper -import java.util.LinkedHashMap; // Paper - -/** - * Akarin Changes Note - * 1) Removes unneed synchronization (performance) - */ -public class RegionFileCache { - - public static final Map a = new LinkedHashMap(PaperConfig.regionFileCacheSize, 0.75f, true); // Spigot - private -> public, Paper - HashMap -> LinkedHashMap - - public static synchronized RegionFile a(File file, int i, int j) { - File file1 = new File(file, "region"); - File file2 = new File(file1, "r." + (i >> 5) + "." + (j >> 5) + ".mca"); - RegionFile regionfile = (RegionFile) RegionFileCache.a.get(file2); - - if (regionfile != null) { - return regionfile; - } else { - if (!file1.exists()) { - file1.mkdirs(); - } - - if (RegionFileCache.a.size() >= PaperConfig.regionFileCacheSize) { // Paper - trimCache(); // Paper - } - - RegionFile regionfile1 = new RegionFile(file2); - - RegionFileCache.a.put(file2, regionfile1); - return regionfile1; - } - } - - public static synchronized RegionFile b(File file, int i, int j) { - File file1 = new File(file, "region"); - File file2 = new File(file1, "r." + (i >> 5) + "." + (j >> 5) + ".mca"); - RegionFile regionfile = (RegionFile) RegionFileCache.a.get(file2); - - if (regionfile != null) { - return regionfile; - } else if (file1.exists() && file2.exists()) { - if (RegionFileCache.a.size() >= 256) { - a(); - } - - RegionFile regionfile1 = new RegionFile(file2); - - RegionFileCache.a.put(file2, regionfile1); - return regionfile1; - } else { - return null; - } - } - - // Paper Start - private static synchronized void trimCache() { - Iterator> itr = RegionFileCache.a.entrySet().iterator(); - int count = RegionFileCache.a.size() - PaperConfig.regionFileCacheSize; - while (count-- >= 0 && itr.hasNext()) { - try { - itr.next().getValue().c(); - } catch (IOException ioexception) { - ioexception.printStackTrace(); - ServerInternalException.reportInternalException(ioexception); - } - itr.remove(); - } - } - // Paper End - - public static synchronized void a() { - Iterator iterator = RegionFileCache.a.values().iterator(); - - while (iterator.hasNext()) { - RegionFile regionfile = (RegionFile) iterator.next(); - - try { - if (regionfile != null) { - regionfile.c(); - } - } catch (IOException ioexception) { - ioexception.printStackTrace(); - ServerInternalException.reportInternalException(ioexception); // Paper - } - } - - RegionFileCache.a.clear(); - } - - // CraftBukkit start - call sites hoisted for synchronization - public static /*synchronized*/ NBTTagCompound d(File file, int i, int j) throws IOException { // Akarin - 1.13 backport - remove synchronization // OBFHELPER: read - RegionFile regionfile = a(file, i, j); - - DataInputStream datainputstream = regionfile.a(i & 31, j & 31); - - if (datainputstream == null) { - return null; - } - - return NBTCompressedStreamTools.a(datainputstream); - } - - public static /*synchronized*/ void e(File file, int i, int j, NBTTagCompound nbttagcompound) throws IOException { // Akarin - 1.13 backport - remove synchronization // OBFHELPER: write - RegionFile regionfile = a(file, i, j); - - DataOutputStream dataoutputstream = regionfile.b(i & 31, j & 31); - NBTCompressedStreamTools.a(nbttagcompound, (java.io.DataOutput) dataoutputstream); - dataoutputstream.close(); - } - // CraftBukkit end - - public static /*synchronized*/ boolean chunkExists(File file, int i, int j) { // Akarin - 1.13 backport - remove synchronization - RegionFile regionfile = b(file, i, j); - - return regionfile != null ? regionfile.c(i & 31, j & 31) : false; - } -} diff --git a/sources/src/main/java/net/minecraft/server/RegistryID.java b/sources/src/main/java/net/minecraft/server/RegistryID.java deleted file mode 100644 index 89c490cec..000000000 --- a/sources/src/main/java/net/minecraft/server/RegistryID.java +++ /dev/null @@ -1,161 +0,0 @@ -package net.minecraft.server; - -import com.google.common.base.Predicates; -import com.google.common.collect.Iterators; -import java.util.Iterator; -import javax.annotation.Nullable; - -/** - * Akarin Changes Note - * 1) BitSet for faster access (performance) - */ -public class RegistryID implements Registry { - - private static final Object a = null; - private K[] b; - private int[] c; - private K[] d; - private int e; - private int f; - private java.util.BitSet usedIds; // Akarin - 1.13 backport - - public RegistryID(int i) { - i = (int) ((float) i / 0.8F); - this.b = (K[]) (new Object[i]); - this.c = new int[i]; - this.d = (K[]) (new Object[i]); - this.usedIds = new java.util.BitSet(); // Akarin - 1.13 backport - } - - public int getId(@Nullable K k0) { - return this.c(this.b(k0, this.d(k0))); - } - - @Nullable - public K fromId(int i) { - return i >= 0 && i < this.d.length ? this.d[i] : null; - } - - private int c(int i) { - return i == -1 ? -1 : this.c[i]; - } - - public int c(K k0) { - int i = this.c(); - - this.a(k0, i); - return i; - } - - private int c() { - // Akarin start - 1.13 backport - /* - while (this.e < this.d.length && this.d[this.e] != null) { - ++this.e; - } - */ - this.e = this.usedIds.nextClearBit(0); - // Akarin end - 1.13 backport - - return this.e; - } - - private void d(int i) { - K[] aobject = this.b; - int[] aint = this.c; - - this.b = (K[]) (new Object[i]); - this.c = new int[i]; - this.d = (K[]) (new Object[i]); - this.e = 0; - this.f = 0; - this.usedIds.clear(); // Akarin - 1.13 backport - - for (int j = 0; j < aobject.length; ++j) { - if (aobject[j] != null) { - this.a(aobject[j], aint[j]); - } - } - - } - - public void a(K k0, int i) { - int j = Math.max(i, this.f + 1); - int k; - - if ((float) j >= (float) this.b.length * 0.8F) { - for (k = this.b.length << 1; k < i; k <<= 1) { - ; - } - - this.d(k); - } - - k = this.e(this.d(k0)); - this.b[k] = k0; - this.c[k] = i; - this.d[i] = k0; - this.usedIds.set(i); // Akarin - 1.13 backport - ++this.f; - if (i == this.e) { - ++this.e; - } - - } - - private int d(@Nullable K k0) { - return (MathHelper.f(System.identityHashCode(k0)) & Integer.MAX_VALUE) % this.b.length; - } - - private int b(@Nullable K k0, int i) { - int j; - - for (j = i; j < this.b.length; ++j) { - if (this.b[j] == k0) { - return j; - } - - if (this.b[j] == RegistryID.a) { - return -1; - } - } - - for (j = 0; j < i; ++j) { - if (this.b[j] == k0) { - return j; - } - - if (this.b[j] == RegistryID.a) { - return -1; - } - } - - return -1; - } - - private int e(int i) { - int j; - - for (j = i; j < this.b.length; ++j) { - if (this.b[j] == RegistryID.a) { - return j; - } - } - - for (j = 0; j < i; ++j) { - if (this.b[j] == RegistryID.a) { - return j; - } - } - - throw new RuntimeException("Overflowed :("); - } - - public Iterator iterator() { - return Iterators.filter(Iterators.forArray(this.d), Predicates.notNull()); - } - - public int b() { - return this.f; - } -} diff --git a/sources/src/main/java/net/minecraft/server/TileEntitySkull.java b/sources/src/main/java/net/minecraft/server/TileEntitySkull.java index 8d792c478..a66bb1893 100644 --- a/sources/src/main/java/net/minecraft/server/TileEntitySkull.java +++ b/sources/src/main/java/net/minecraft/server/TileEntitySkull.java @@ -9,9 +9,6 @@ import javax.annotation.Nullable; // Spigot start import com.google.common.base.Predicate; -import com.google.common.cache.LoadingCache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; import com.google.common.util.concurrent.Futures; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; @@ -30,13 +27,12 @@ import java.util.concurrent.Callable; */ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Paper - remove tickable - private int a; - public int rotation; - private GameProfile g; - private int h; - private boolean i; - private static UserCache j; - private static MinecraftSessionService k; + private GameProfile a; + private int e; + private boolean f; + public boolean drop = true; + private static UserCache h; + private static MinecraftSessionService i; // Spigot start public static final ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactoryBuilder() @@ -80,7 +76,7 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa if ( property == null ) { - profile = MinecraftServer.getServer().az().fillProfileProperties( profile, true ); + profile = TileEntitySkull.i.fillProfileProperties( profile, true ); } } @@ -90,24 +86,24 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa } ); // Spigot end - public TileEntitySkull() {} + public TileEntitySkull() { + super(TileEntityTypes.p); + } public static void a(UserCache usercache) { - TileEntitySkull.j = usercache; + TileEntitySkull.h = usercache; } public static void a(MinecraftSessionService minecraftsessionservice) { - TileEntitySkull.k = minecraftsessionservice; + TileEntitySkull.i = minecraftsessionservice; } public NBTTagCompound save(NBTTagCompound nbttagcompound) { super.save(nbttagcompound); - nbttagcompound.setByte("SkullType", (byte) (this.a & 255)); - nbttagcompound.setByte("Rot", (byte) (this.rotation & 255)); - if (this.g != null) { + if (this.a != null) { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - GameProfileSerializer.serialize(nbttagcompound1, this.g); + GameProfileSerializer.serialize(nbttagcompound1, this.a); nbttagcompound.set("Owner", nbttagcompound1); } @@ -116,30 +112,28 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa public void load(NBTTagCompound nbttagcompound) { super.load(nbttagcompound); - this.a = nbttagcompound.getByte("SkullType"); - this.rotation = nbttagcompound.getByte("Rot"); - if (this.a == 3) { - if (nbttagcompound.hasKeyOfType("Owner", 10)) { - this.g = GameProfileSerializer.deserialize(nbttagcompound.getCompound("Owner")); - } else if (nbttagcompound.hasKeyOfType("ExtraType", 8)) { - String s = nbttagcompound.getString("ExtraType"); + if (nbttagcompound.hasKeyOfType("Owner", 10)) { + this.a = GameProfileSerializer.deserialize(nbttagcompound.getCompound("Owner")); + } else if (nbttagcompound.hasKeyOfType("ExtraType", 8)) { + String s = nbttagcompound.getString("ExtraType"); - if (!UtilColor.b(s)) { - this.g = new GameProfile((UUID) null, s); - this.i(); - } + if (!UtilColor.b(s)) { + this.a = new GameProfile((UUID) null, s); + this.f(); } } } - public void e() { - if (this.a == 5) { + public void Y_() { + Block block = this.getBlock().getBlock(); + + if (block == Blocks.DRAGON_HEAD || block == Blocks.DRAGON_WALL_HEAD) { if (this.world.isBlockIndirectlyPowered(this.position)) { - this.i = true; - ++this.h; + this.f = true; + ++this.e; } else { - this.i = false; + this.f = false; } } @@ -147,46 +141,35 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa @Nullable public GameProfile getGameProfile() { - return this.g; + return this.a; } @Nullable public PacketPlayOutTileEntityData getUpdatePacket() { - return new PacketPlayOutTileEntityData(this.position, 4, this.d()); + return new PacketPlayOutTileEntityData(this.position, 4, this.aa_()); } - public NBTTagCompound d() { + public NBTTagCompound aa_() { return this.save(new NBTTagCompound()); } - public void setSkullType(int i) { - this.a = i; - this.g = null; - } - public void setGameProfile(@Nullable GameProfile gameprofile) { - this.a = 3; - this.g = gameprofile; - this.i(); + this.a = gameprofile; + this.f(); } - private void i() { + private void f() { // Spigot start - GameProfile profile = this.g; - setSkullType( 0 ); // Work around client bug + GameProfile profile = this.getGameProfile(); b(profile, new Predicate() { @Override public boolean apply(GameProfile input) { - setSkullType(3); // Work around client bug - g = input; + a = input; update(); - if (world != null) { - world.m(position); // PAIL: notify - } return false; } - }, false); + }, false); // Spigot end } @@ -241,25 +224,24 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa } // Spigot end - public int getSkullType() { - return this.a; + // CraftBukkit start + public static void a(IBlockAccess iblockaccess, BlockPosition blockposition) { + setShouldDrop(iblockaccess, blockposition, false); } - public void setRotation(int i) { - this.rotation = i; - } + public static void setShouldDrop(IBlockAccess iblockaccess, BlockPosition blockposition, boolean flag) { + // CraftBukkit end + TileEntity tileentity = iblockaccess.getTileEntity(blockposition); - public void a(EnumBlockMirror enumblockmirror) { - if (this.world != null && this.world.getType(this.getPosition()).get(BlockSkull.FACING) == EnumDirection.UP) { - this.rotation = enumblockmirror.a(this.rotation, 16); + if (tileentity instanceof TileEntitySkull) { + TileEntitySkull tileentityskull = (TileEntitySkull) tileentity; + + tileentityskull.drop = flag; // CraftBukkit } } - public void a(EnumBlockRotation enumblockrotation) { - if (this.world != null && this.world.getType(this.getPosition()).get(BlockSkull.FACING) == EnumDirection.UP) { - this.rotation = enumblockrotation.a(this.rotation, 16); - } - + public boolean shouldDrop() { + return this.drop; } } diff --git a/sources/src/main/java/net/minecraft/server/WorldData.java b/sources/src/main/java/net/minecraft/server/WorldData.java index 9d08664ee..59bf62c83 100644 --- a/sources/src/main/java/net/minecraft/server/WorldData.java +++ b/sources/src/main/java/net/minecraft/server/WorldData.java @@ -1,8 +1,14 @@ package net.minecraft.server; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.mojang.datafixers.DataFixTypes; +import com.mojang.datafixers.DataFixer; +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.types.JsonOps; import java.util.Iterator; import java.util.Map; +import java.util.Set; import java.util.Map.Entry; import javax.annotation.Nullable; // CraftBukkit start @@ -23,85 +29,89 @@ public class WorldData { public static final EnumDifficulty a = EnumDifficulty.NORMAL; private long e; private WorldType f; - private String g; - private int h; + private NBTTagCompound g; + @Nullable + private String h; private int i; private int j; - private volatile long k; // Akarin - volatile - OBFHELPER: time - private volatile long l; // Akarin - volatile - OBFHELPER: dayTime - private long m; + private int k; + private volatile long l; // Akarin - volatile - OBFHELPER: time + private volatile long m; // Akarin - volatile - OBFHELPER: dayTime private long n; - private NBTTagCompound o; - private int p; + private long o; + @Nullable + private final DataFixer p; + private final int q; + private boolean r; + private NBTTagCompound s; + private int t; private String levelName; - private int r; - private int s; - private boolean t; - private int u; - private boolean v; + private int v; private int w; - private EnumGamemode x; - private boolean y; + private boolean x; + private int y; private boolean z; - private boolean A; - private boolean B; - private volatile EnumDifficulty C; // Akarin - volatile + private int A; + private EnumGamemode B; + private boolean C; private boolean D; - private double E; - private double F; - private double G; - private long H; + private boolean E; + private boolean F; + private volatile EnumDifficulty G; // Akarin - volatile + private boolean H; private double I; private double J; private double K; - private int L; - private int M; - private final Map N; - private GameRules O; + private long L; + private double M; + private double N; + private double O; + private int P; + private int Q; + private final Set R; + private final Set S; + private final Map T; + private NBTTagCompound U; + private final GameRules V; public WorldServer world; // CraftBukkit protected WorldData() { this.f = WorldType.NORMAL; - this.g = ""; - this.G = 6.0E7D; - this.J = 5.0D; - this.K = 0.2D; - this.L = 5; - this.M = 15; - this.N = Maps.newEnumMap(DimensionManager.class); - this.O = new GameRules(); + this.g = new NBTTagCompound(); + this.K = 6.0E7D; + this.N = 5.0D; + this.O = 0.2D; + this.P = 5; + this.Q = 15; + this.R = Sets.newHashSet(); + this.S = Sets.newLinkedHashSet(); + this.T = Maps.newEnumMap(DimensionManager.class); + this.V = new GameRules(); + this.p = null; + this.q = 1519; + this.b(new NBTTagCompound()); } - public static void a(DataConverterManager dataconvertermanager) { - dataconvertermanager.a(DataConverterTypes.LEVEL, new DataInspector() { - @Override - public NBTTagCompound a(DataConverter dataconverter, NBTTagCompound nbttagcompound, int i) { - if (nbttagcompound.hasKeyOfType("Player", 10)) { - nbttagcompound.set("Player", dataconverter.a(DataConverterTypes.PLAYER, nbttagcompound.getCompound("Player"), i)); - } - - return nbttagcompound; - } - }); - } - - public WorldData(NBTTagCompound nbttagcompound) { + public WorldData(NBTTagCompound nbttagcompound, DataFixer datafixer, int i, @Nullable NBTTagCompound nbttagcompound1) { this.f = WorldType.NORMAL; - this.g = ""; - this.G = 6.0E7D; - this.J = 5.0D; - this.K = 0.2D; - this.L = 5; - this.M = 15; - this.N = Maps.newEnumMap(DimensionManager.class); - this.O = new GameRules(); - NBTTagCompound nbttagcompound1; + this.g = new NBTTagCompound(); + this.K = 6.0E7D; + this.N = 5.0D; + this.O = 0.2D; + this.P = 5; + this.Q = 15; + this.R = Sets.newHashSet(); + this.S = Sets.newLinkedHashSet(); + this.T = Maps.newEnumMap(DimensionManager.class); + this.V = new GameRules(); + this.p = datafixer; + NBTTagCompound nbttagcompound2; if (nbttagcompound.hasKeyOfType("Version", 10)) { - nbttagcompound1 = nbttagcompound.getCompound("Version"); - this.b = nbttagcompound1.getString("Name"); - this.c = nbttagcompound1.getInt("Id"); - this.d = nbttagcompound1.getBoolean("Snapshot"); + nbttagcompound2 = nbttagcompound.getCompound("Version"); + this.b = nbttagcompound2.getString("Name"); + this.c = nbttagcompound2.getInt("Id"); + this.d = nbttagcompound2.getBoolean("Snapshot"); } this.e = nbttagcompound.getLong("RandomSeed"); @@ -111,202 +121,183 @@ public class WorldData { this.f = WorldType.getType(s); if (this.f == null) { this.f = WorldType.NORMAL; - } else if (this.f.f()) { - int i = 0; + } else if (this.f == WorldType.CUSTOMIZED) { + this.h = nbttagcompound.getString("generatorOptions"); + } else if (this.f.h()) { + int j = 0; if (nbttagcompound.hasKeyOfType("generatorVersion", 99)) { - i = nbttagcompound.getInt("generatorVersion"); + j = nbttagcompound.getInt("generatorVersion"); } - this.f = this.f.a(i); + this.f = this.f.a(j); } - if (nbttagcompound.hasKeyOfType("generatorOptions", 8)) { - this.g = nbttagcompound.getString("generatorOptions"); - } + this.b(nbttagcompound.getCompound("generatorOptions")); + } + + this.B = EnumGamemode.getById(nbttagcompound.getInt("GameType")); + if (nbttagcompound.hasKeyOfType("legacy_custom_options", 8)) { + this.h = nbttagcompound.getString("legacy_custom_options"); } - this.x = EnumGamemode.getById(nbttagcompound.getInt("GameType")); if (nbttagcompound.hasKeyOfType("MapFeatures", 99)) { - this.y = nbttagcompound.getBoolean("MapFeatures"); + this.C = nbttagcompound.getBoolean("MapFeatures"); } else { - this.y = true; + this.C = true; } - this.h = nbttagcompound.getInt("SpawnX"); - this.i = nbttagcompound.getInt("SpawnY"); - this.j = nbttagcompound.getInt("SpawnZ"); - this.k = nbttagcompound.getLong("Time"); + this.i = nbttagcompound.getInt("SpawnX"); + this.j = nbttagcompound.getInt("SpawnY"); + this.k = nbttagcompound.getInt("SpawnZ"); + this.l = nbttagcompound.getLong("Time"); if (nbttagcompound.hasKeyOfType("DayTime", 99)) { - this.l = nbttagcompound.getLong("DayTime"); + this.m = nbttagcompound.getLong("DayTime"); } else { - this.l = this.k; + this.m = this.l; } - this.m = nbttagcompound.getLong("LastPlayed"); - this.n = nbttagcompound.getLong("SizeOnDisk"); + this.n = nbttagcompound.getLong("LastPlayed"); + this.o = nbttagcompound.getLong("SizeOnDisk"); this.levelName = nbttagcompound.getString("LevelName"); - this.r = nbttagcompound.getInt("version"); - this.s = nbttagcompound.getInt("clearWeatherTime"); - this.u = nbttagcompound.getInt("rainTime"); - this.t = nbttagcompound.getBoolean("raining"); - this.w = nbttagcompound.getInt("thunderTime"); - this.v = nbttagcompound.getBoolean("thundering"); - this.z = nbttagcompound.getBoolean("hardcore"); + this.v = nbttagcompound.getInt("version"); + this.w = nbttagcompound.getInt("clearWeatherTime"); + this.y = nbttagcompound.getInt("rainTime"); + this.x = nbttagcompound.getBoolean("raining"); + this.A = nbttagcompound.getInt("thunderTime"); + this.z = nbttagcompound.getBoolean("thundering"); + this.D = nbttagcompound.getBoolean("hardcore"); if (nbttagcompound.hasKeyOfType("initialized", 99)) { - this.B = nbttagcompound.getBoolean("initialized"); + this.F = nbttagcompound.getBoolean("initialized"); } else { - this.B = true; + this.F = true; } if (nbttagcompound.hasKeyOfType("allowCommands", 99)) { - this.A = nbttagcompound.getBoolean("allowCommands"); + this.E = nbttagcompound.getBoolean("allowCommands"); } else { - this.A = this.x == EnumGamemode.CREATIVE; + this.E = this.B == EnumGamemode.CREATIVE; } - if (nbttagcompound.hasKeyOfType("Player", 10)) { - this.o = nbttagcompound.getCompound("Player"); - this.p = this.o.getInt("Dimension"); + this.q = i; + if (nbttagcompound1 != null) { + this.s = nbttagcompound1; } if (nbttagcompound.hasKeyOfType("GameRules", 10)) { - this.O.a(nbttagcompound.getCompound("GameRules")); + this.V.a(nbttagcompound.getCompound("GameRules")); } if (nbttagcompound.hasKeyOfType("Difficulty", 99)) { - this.C = EnumDifficulty.getById(nbttagcompound.getByte("Difficulty")); + this.G = EnumDifficulty.getById(nbttagcompound.getByte("Difficulty")); } if (nbttagcompound.hasKeyOfType("DifficultyLocked", 1)) { - this.D = nbttagcompound.getBoolean("DifficultyLocked"); + this.H = nbttagcompound.getBoolean("DifficultyLocked"); } if (nbttagcompound.hasKeyOfType("BorderCenterX", 99)) { - this.E = nbttagcompound.getDouble("BorderCenterX"); + this.I = nbttagcompound.getDouble("BorderCenterX"); } if (nbttagcompound.hasKeyOfType("BorderCenterZ", 99)) { - this.F = nbttagcompound.getDouble("BorderCenterZ"); + this.J = nbttagcompound.getDouble("BorderCenterZ"); } if (nbttagcompound.hasKeyOfType("BorderSize", 99)) { - this.G = nbttagcompound.getDouble("BorderSize"); + this.K = nbttagcompound.getDouble("BorderSize"); } if (nbttagcompound.hasKeyOfType("BorderSizeLerpTime", 99)) { - this.H = nbttagcompound.getLong("BorderSizeLerpTime"); + this.L = nbttagcompound.getLong("BorderSizeLerpTime"); } if (nbttagcompound.hasKeyOfType("BorderSizeLerpTarget", 99)) { - this.I = nbttagcompound.getDouble("BorderSizeLerpTarget"); + this.M = nbttagcompound.getDouble("BorderSizeLerpTarget"); } if (nbttagcompound.hasKeyOfType("BorderSafeZone", 99)) { - this.J = nbttagcompound.getDouble("BorderSafeZone"); + this.N = nbttagcompound.getDouble("BorderSafeZone"); } if (nbttagcompound.hasKeyOfType("BorderDamagePerBlock", 99)) { - this.K = nbttagcompound.getDouble("BorderDamagePerBlock"); + this.O = nbttagcompound.getDouble("BorderDamagePerBlock"); } if (nbttagcompound.hasKeyOfType("BorderWarningBlocks", 99)) { - this.L = nbttagcompound.getInt("BorderWarningBlocks"); + this.P = nbttagcompound.getInt("BorderWarningBlocks"); } if (nbttagcompound.hasKeyOfType("BorderWarningTime", 99)) { - this.M = nbttagcompound.getInt("BorderWarningTime"); + this.Q = nbttagcompound.getInt("BorderWarningTime"); } if (nbttagcompound.hasKeyOfType("DimensionData", 10)) { - nbttagcompound1 = nbttagcompound.getCompound("DimensionData"); - Iterator iterator = nbttagcompound1.c().iterator(); + nbttagcompound2 = nbttagcompound.getCompound("DimensionData"); + Iterator iterator = nbttagcompound2.getKeys().iterator(); while (iterator.hasNext()) { String s1 = (String) iterator.next(); - this.N.put(DimensionManager.a(Integer.parseInt(s1)), nbttagcompound1.getCompound(s1)); + this.T.put(DimensionManager.a(Integer.parseInt(s1)), nbttagcompound2.getCompound(s1)); } } + if (nbttagcompound.hasKeyOfType("DataPacks", 10)) { + nbttagcompound2 = nbttagcompound.getCompound("DataPacks"); + NBTTagList nbttaglist = nbttagcompound2.getList("Disabled", 8); + + for (int k = 0; k < nbttaglist.size(); ++k) { + this.R.add(nbttaglist.getString(k)); + } + + NBTTagList nbttaglist1 = nbttagcompound2.getList("Enabled", 8); + + for (int l = 0; l < nbttaglist1.size(); ++l) { + this.S.add(nbttaglist1.getString(l)); + } + } + + if (nbttagcompound.hasKeyOfType("CustomBossEvents", 10)) { + this.U = nbttagcompound.getCompound("CustomBossEvents"); + } + } public WorldData(WorldSettings worldsettings, String s) { this.f = WorldType.NORMAL; - this.g = ""; - this.G = 6.0E7D; - this.J = 5.0D; - this.K = 0.2D; - this.L = 5; - this.M = 15; - this.N = Maps.newEnumMap(DimensionManager.class); - this.O = new GameRules(); + this.g = new NBTTagCompound(); + this.K = 6.0E7D; + this.N = 5.0D; + this.O = 0.2D; + this.P = 5; + this.Q = 15; + this.R = Sets.newHashSet(); + this.S = Sets.newLinkedHashSet(); + this.T = Maps.newEnumMap(DimensionManager.class); + this.V = new GameRules(); + this.p = null; + this.q = 1519; this.a(worldsettings); this.levelName = s; - this.C = WorldData.a; - this.B = false; + this.G = WorldData.a; + this.F = false; } public void a(WorldSettings worldsettings) { this.e = worldsettings.d(); - this.x = worldsettings.e(); - this.y = worldsettings.g(); - this.z = worldsettings.f(); + this.B = worldsettings.e(); + this.C = worldsettings.g(); + this.D = worldsettings.f(); this.f = worldsettings.h(); - this.g = worldsettings.j(); - this.A = worldsettings.i(); - } - - public WorldData(WorldData worlddata) { - this.f = WorldType.NORMAL; - this.g = ""; - this.G = 6.0E7D; - this.J = 5.0D; - this.K = 0.2D; - this.L = 5; - this.M = 15; - this.N = Maps.newEnumMap(DimensionManager.class); - this.O = new GameRules(); - this.e = worlddata.e; - this.f = worlddata.f; - this.g = worlddata.g; - this.x = worlddata.x; - this.y = worlddata.y; - this.h = worlddata.h; - this.i = worlddata.i; - this.j = worlddata.j; - this.k = worlddata.k; - this.l = worlddata.l; - this.m = worlddata.m; - this.n = worlddata.n; - this.o = worlddata.o; - this.p = worlddata.p; - this.levelName = worlddata.levelName; - this.r = worlddata.r; - this.u = worlddata.u; - this.t = worlddata.t; - this.w = worlddata.w; - this.v = worlddata.v; - this.z = worlddata.z; - this.A = worlddata.A; - this.B = worlddata.B; - this.O = worlddata.O; - this.C = worlddata.C; - this.D = worlddata.D; - this.E = worlddata.E; - this.F = worlddata.F; - this.G = worlddata.G; - this.H = worlddata.H; - this.I = worlddata.I; - this.J = worlddata.J; - this.K = worlddata.K; - this.M = worlddata.M; - this.L = worlddata.L; + this.b((NBTTagCompound) Dynamic.convert(JsonOps.INSTANCE, DynamicOpsNBT.a, worldsettings.j())); + this.E = worldsettings.i(); } public NBTTagCompound a(@Nullable NBTTagCompound nbttagcompound) { + this.Q(); if (nbttagcompound == null) { - nbttagcompound = this.o; + nbttagcompound = this.s; } NBTTagCompound nbttagcompound1 = new NBTTagCompound(); @@ -318,51 +309,59 @@ public class WorldData { private void a(NBTTagCompound nbttagcompound, NBTTagCompound nbttagcompound1) { NBTTagCompound nbttagcompound2 = new NBTTagCompound(); - nbttagcompound2.setString("Name", "1.12.2"); - nbttagcompound2.setInt("Id", 1343); + nbttagcompound2.setString("Name", "1.13"); + nbttagcompound2.setInt("Id", 1519); nbttagcompound2.setBoolean("Snapshot", false); nbttagcompound.set("Version", nbttagcompound2); - nbttagcompound.setInt("DataVersion", 1343); + nbttagcompound.setInt("DataVersion", 1519); + if (org.bukkit.craftbukkit.util.CraftMagicNumbers.DATA_VERSION != 1519) throw new AssertionError(); // CraftBukkit - sentinel nbttagcompound.setLong("RandomSeed", this.e); - nbttagcompound.setString("generatorName", this.f.name()); + nbttagcompound.setString("generatorName", this.f.b()); nbttagcompound.setInt("generatorVersion", this.f.getVersion()); - nbttagcompound.setString("generatorOptions", this.g); - nbttagcompound.setInt("GameType", this.x.getId()); - nbttagcompound.setBoolean("MapFeatures", this.y); - nbttagcompound.setInt("SpawnX", this.h); - nbttagcompound.setInt("SpawnY", this.i); - nbttagcompound.setInt("SpawnZ", this.j); - nbttagcompound.setLong("Time", this.k); - nbttagcompound.setLong("DayTime", this.l); - nbttagcompound.setLong("SizeOnDisk", this.n); - nbttagcompound.setLong("LastPlayed", MinecraftServer.aw()); - nbttagcompound.setString("LevelName", this.levelName); - nbttagcompound.setInt("version", this.r); - nbttagcompound.setInt("clearWeatherTime", this.s); - nbttagcompound.setInt("rainTime", this.u); - nbttagcompound.setBoolean("raining", this.t); - nbttagcompound.setInt("thunderTime", this.w); - nbttagcompound.setBoolean("thundering", this.v); - nbttagcompound.setBoolean("hardcore", this.z); - nbttagcompound.setBoolean("allowCommands", this.A); - nbttagcompound.setBoolean("initialized", this.B); - nbttagcompound.setDouble("BorderCenterX", this.E); - nbttagcompound.setDouble("BorderCenterZ", this.F); - nbttagcompound.setDouble("BorderSize", this.G); - nbttagcompound.setLong("BorderSizeLerpTime", this.H); - nbttagcompound.setDouble("BorderSafeZone", this.J); - nbttagcompound.setDouble("BorderDamagePerBlock", this.K); - nbttagcompound.setDouble("BorderSizeLerpTarget", this.I); - nbttagcompound.setDouble("BorderWarningBlocks", this.L); - nbttagcompound.setDouble("BorderWarningTime", this.M); - if (this.C != null) { - nbttagcompound.setByte("Difficulty", (byte) this.C.a()); + if (!this.g.isEmpty()) { + nbttagcompound.set("generatorOptions", this.g); } - nbttagcompound.setBoolean("DifficultyLocked", this.D); - nbttagcompound.set("GameRules", this.O.a()); + if (this.h != null) { + nbttagcompound.setString("legacy_custom_options", this.h); + } + + nbttagcompound.setInt("GameType", this.B.getId()); + nbttagcompound.setBoolean("MapFeatures", this.C); + nbttagcompound.setInt("SpawnX", this.i); + nbttagcompound.setInt("SpawnY", this.j); + nbttagcompound.setInt("SpawnZ", this.k); + nbttagcompound.setLong("Time", this.l); + nbttagcompound.setLong("DayTime", this.m); + nbttagcompound.setLong("SizeOnDisk", this.o); + nbttagcompound.setLong("LastPlayed", SystemUtils.d()); + nbttagcompound.setString("LevelName", this.levelName); + nbttagcompound.setInt("version", this.v); + nbttagcompound.setInt("clearWeatherTime", this.w); + nbttagcompound.setInt("rainTime", this.y); + nbttagcompound.setBoolean("raining", this.x); + nbttagcompound.setInt("thunderTime", this.A); + nbttagcompound.setBoolean("thundering", this.z); + nbttagcompound.setBoolean("hardcore", this.D); + nbttagcompound.setBoolean("allowCommands", this.E); + nbttagcompound.setBoolean("initialized", this.F); + nbttagcompound.setDouble("BorderCenterX", this.I); + nbttagcompound.setDouble("BorderCenterZ", this.J); + nbttagcompound.setDouble("BorderSize", this.K); + nbttagcompound.setLong("BorderSizeLerpTime", this.L); + nbttagcompound.setDouble("BorderSafeZone", this.N); + nbttagcompound.setDouble("BorderDamagePerBlock", this.O); + nbttagcompound.setDouble("BorderSizeLerpTarget", this.M); + nbttagcompound.setDouble("BorderWarningBlocks", (double) this.P); + nbttagcompound.setDouble("BorderWarningTime", (double) this.Q); + if (this.G != null) { + nbttagcompound.setByte("Difficulty", (byte) this.G.a()); + } + + nbttagcompound.setBoolean("DifficultyLocked", this.H); + nbttagcompound.set("GameRules", this.V.a()); NBTTagCompound nbttagcompound3 = new NBTTagCompound(); - Iterator iterator = this.N.entrySet().iterator(); + Iterator iterator = this.T.entrySet().iterator(); while (iterator.hasNext()) { Entry entry = (Entry) iterator.next(); @@ -375,6 +374,32 @@ public class WorldData { nbttagcompound.set("Player", nbttagcompound1); } + NBTTagCompound nbttagcompound4 = new NBTTagCompound(); + NBTTagList nbttaglist = new NBTTagList(); + Iterator iterator1 = this.S.iterator(); + + while (iterator1.hasNext()) { + String s = (String) iterator1.next(); + + nbttaglist.add((NBTBase) (new NBTTagString(s))); + } + + nbttagcompound4.set("Enabled", nbttaglist); + NBTTagList nbttaglist1 = new NBTTagList(); + Iterator iterator2 = this.R.iterator(); + + while (iterator2.hasNext()) { + String s1 = (String) iterator2.next(); + + nbttaglist1.add((NBTBase) (new NBTTagString(s1))); + } + + nbttagcompound4.set("Disabled", nbttaglist1); + nbttagcompound.set("DataPacks", nbttagcompound4); + if (this.U != null) { + nbttagcompound.set("CustomBossEvents", this.U); + } + } public long getSeed() { @@ -382,41 +407,57 @@ public class WorldData { } public int b() { - return this.h; - } - - public int c() { return this.i; } - public int d() { + public int c() { return this.j; } - public long getTime() { + public int d() { return this.k; } - public long getDayTime() { + public long getTime() { return this.l; } + public long getDayTime() { + return this.m; + } + + private void Q() { + if (!this.r && this.s != null) { + if (this.q < 1519) { + if (this.p == null) { + throw new NullPointerException("Fixer Upper not set inside LevelData, and the player tag is not upgraded."); + } + + this.s = GameProfileSerializer.a(this.p, DataFixTypes.PLAYER, this.s, this.q); + } + + this.t = this.s.getInt("Dimension"); + this.r = true; + } + } + public NBTTagCompound h() { - return this.o; + this.Q(); + return this.s; } public void setTime(long i) { - this.k = i; - } - - public void setDayTime(long i) { this.l = i; } + public void setDayTime(long i) { + this.m = i; + } + public void setSpawn(BlockPosition blockposition) { - this.h = blockposition.getX(); - this.i = blockposition.getY(); - this.j = blockposition.getZ(); + this.i = blockposition.getX(); + this.j = blockposition.getY(); + this.k = blockposition.getZ(); } public String getName() { @@ -428,23 +469,23 @@ public class WorldData { } public int k() { - return this.r; + return this.v; } - public void e(int i) { - this.r = i; + public void d(int i) { + this.v = i; } public int z() { - return this.s; + return this.w; } - public void i(int i) { - this.s = i; + public void g(int i) { + this.w = i; } public boolean isThundering() { - return this.v; + return this.z; } public void setThundering(boolean flag) { @@ -458,19 +499,19 @@ public class WorldData { } } // CraftBukkit end - this.v = flag; + this.z = flag; } public int getThunderDuration() { - return this.w; + return this.A; } public void setThunderDuration(int i) { - this.w = i; + this.A = i; } public boolean hasStorm() { - return this.t; + return this.x; } public void setStorm(boolean flag) { @@ -484,39 +525,39 @@ public class WorldData { } } // CraftBukkit end - this.t = flag; + this.x = flag; } public int getWeatherDuration() { - return this.u; - } - - public void setWeatherDuration(int i) { - this.u = i; - } - - public EnumGamemode getGameType() { - return this.x; - } - - public boolean shouldGenerateMapFeatures() { return this.y; } + public void setWeatherDuration(int i) { + this.y = i; + } + + public EnumGamemode getGameType() { + return this.B; + } + + public boolean shouldGenerateMapFeatures() { + return this.C; + } + public void f(boolean flag) { - this.y = flag; + this.C = flag; } public void setGameType(EnumGamemode enumgamemode) { - this.x = enumgamemode; + this.B = enumgamemode; } public boolean isHardcore() { - return this.z; + return this.D; } public void g(boolean flag) { - this.z = flag; + this.D = flag; } public WorldType getType() { @@ -527,108 +568,112 @@ public class WorldData { this.f = worldtype; } - public String getGeneratorOptions() { - return this.g == null ? "" : this.g; + public NBTTagCompound getGeneratorOptions() { + return this.g; + } + + public void b(NBTTagCompound nbttagcompound) { + this.g = nbttagcompound; } public boolean u() { - return this.A; - } - - public void c(boolean flag) { - this.A = flag; - } - - public boolean v() { - return this.B; - } - - public void d(boolean flag) { - this.B = flag; - } - - public GameRules w() { - return this.O; - } - - public double B() { return this.E; } - public double C() { + public void c(boolean flag) { + this.E = flag; + } + + public boolean v() { return this.F; } - public double D() { - return this.G; + public void d(boolean flag) { + this.F = flag; } - public void a(double d0) { - this.G = d0; + public GameRules w() { + return this.V; } - public long E() { - return this.H; - } - - public void e(long i) { - this.H = i; - } - - public double F() { + public double B() { return this.I; } - public void b(double d0) { - this.I = d0; - } - - public void c(double d0) { - this.F = d0; - } - - public void d(double d0) { - this.E = d0; - } - - public double G() { + public double C() { return this.J; } - public void e(double d0) { - this.J = d0; - } - - public double H() { + public double D() { return this.K; } - public void f(double d0) { + public void a(double d0) { this.K = d0; } - public int I() { + public long E() { return this.L; } - public int J() { - return this.M; - } - - public void j(int i) { + public void c(long i) { this.L = i; } - public void k(int i) { - this.M = i; + public double F() { + return this.M; + } + + public void b(double d0) { + this.M = d0; + } + + public void c(double d0) { + this.J = d0; + } + + public void d(double d0) { + this.I = d0; + } + + public double G() { + return this.N; + } + + public void e(double d0) { + this.N = d0; + } + + public double H() { + return this.O; + } + + public void f(double d0) { + this.O = d0; + } + + public int I() { + return this.P; + } + + public int J() { + return this.Q; + } + + public void h(int i) { + this.P = i; + } + + public void i(int i) { + this.Q = i; } public EnumDifficulty getDifficulty() { - return this.C; + return this.G; } public void setDifficulty(EnumDifficulty enumdifficulty) { - this.C = enumdifficulty; + this.G = enumdifficulty; // CraftBukkit start PacketPlayOutServerDifficulty packet = new PacketPlayOutServerDifficulty(this.getDifficulty(), this.isDifficultyLocked()); for (EntityPlayer player : (java.util.List) (java.util.List) world.players) { @@ -638,129 +683,83 @@ public class WorldData { } public boolean isDifficultyLocked() { - return this.D; + return this.H; } public void e(boolean flag) { - this.D = flag; + this.H = flag; } public void a(CrashReportSystemDetails crashreportsystemdetails) { - crashreportsystemdetails.a("Level seed", new CrashReportCallable() { - public String a() throws Exception { - return String.valueOf(WorldData.this.getSeed()); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level seed", () -> { + return String.valueOf(this.getSeed()); }); - crashreportsystemdetails.a("Level generator", new CrashReportCallable() { - public String a() throws Exception { - return String.format("ID %02d - %s, ver %d. Features enabled: %b", new Object[] { Integer.valueOf(WorldData.this.f.g()), WorldData.this.f.name(), Integer.valueOf(WorldData.this.f.getVersion()), Boolean.valueOf(WorldData.this.y)}); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level generator", () -> { + return String.format("ID %02d - %s, ver %d. Features enabled: %b", new Object[] { Integer.valueOf(this.f.i()), this.f.name(), Integer.valueOf(this.f.getVersion()), Boolean.valueOf(this.C)}); }); - crashreportsystemdetails.a("Level generator options", new CrashReportCallable() { - public String a() throws Exception { - return WorldData.this.g; - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level generator options", () -> { + return this.g.toString(); }); - crashreportsystemdetails.a("Level spawn location", new CrashReportCallable() { - public String a() throws Exception { - return CrashReportSystemDetails.a(WorldData.this.h, WorldData.this.i, WorldData.this.j); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level spawn location", () -> { + return CrashReportSystemDetails.a(this.i, this.j, this.k); }); - crashreportsystemdetails.a("Level time", new CrashReportCallable() { - public String a() throws Exception { - return String.format("%d game time, %d day time", new Object[] { Long.valueOf(WorldData.this.k), Long.valueOf(WorldData.this.l)}); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level time", () -> { + return String.format("%d game time, %d day time", new Object[] { Long.valueOf(this.l), Long.valueOf(this.m)}); }); - crashreportsystemdetails.a("Level dimension", new CrashReportCallable() { - public String a() throws Exception { - return String.valueOf(WorldData.this.p); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level dimension", () -> { + return String.valueOf(this.t); }); - crashreportsystemdetails.a("Level storage version", new CrashReportCallable() { - public String a() throws Exception { - String s = "Unknown?"; + crashreportsystemdetails.a("Level storage version", () -> { + String s = "Unknown?"; - try { - switch (WorldData.this.r) { - case 19132: - s = "McRegion"; - break; + try { + switch (this.v) { + case 19132: + s = "McRegion"; + break; - case 19133: - s = "Anvil"; - } - } catch (Throwable throwable) { - ; + case 19133: + s = "Anvil"; } - - return String.format("0x%05X - %s", new Object[] { Integer.valueOf(WorldData.this.r), s}); + } catch (Throwable throwable) { + ; } - @Override - public Object call() throws Exception { - return this.a(); - } + return String.format("0x%05X - %s", new Object[] { Integer.valueOf(this.v), s}); }); - crashreportsystemdetails.a("Level weather", new CrashReportCallable() { - public String a() throws Exception { - return String.format("Rain time: %d (now: %b), thunder time: %d (now: %b)", new Object[] { Integer.valueOf(WorldData.this.u), Boolean.valueOf(WorldData.this.t), Integer.valueOf(WorldData.this.w), Boolean.valueOf(WorldData.this.v)}); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level weather", () -> { + return String.format("Rain time: %d (now: %b), thunder time: %d (now: %b)", new Object[] { Integer.valueOf(this.y), Boolean.valueOf(this.x), Integer.valueOf(this.A), Boolean.valueOf(this.z)}); }); - crashreportsystemdetails.a("Level game mode", new CrashReportCallable() { - public String a() throws Exception { - return String.format("Game mode: %s (ID %d). Hardcore: %b. Cheats: %b", new Object[] { WorldData.this.x.b(), Integer.valueOf(WorldData.this.x.getId()), Boolean.valueOf(WorldData.this.z), Boolean.valueOf(WorldData.this.A)}); - } - - @Override - public Object call() throws Exception { - return this.a(); - } + crashreportsystemdetails.a("Level game mode", () -> { + return String.format("Game mode: %s (ID %d). Hardcore: %b. Cheats: %b", new Object[] { this.B.b(), Integer.valueOf(this.B.getId()), Boolean.valueOf(this.D), Boolean.valueOf(this.E)}); }); } public NBTTagCompound a(DimensionManager dimensionmanager) { - NBTTagCompound nbttagcompound = this.N.get(dimensionmanager); + NBTTagCompound nbttagcompound = (NBTTagCompound) this.T.get(dimensionmanager); return nbttagcompound == null ? new NBTTagCompound() : nbttagcompound; } public void a(DimensionManager dimensionmanager, NBTTagCompound nbttagcompound) { - this.N.put(dimensionmanager, nbttagcompound); + this.T.put(dimensionmanager, nbttagcompound); + } + + public Set N() { + return this.R; + } + + public Set O() { + return this.S; + } + + @Nullable + public NBTTagCompound P() { + return this.U; + } + + public void c(@Nullable NBTTagCompound nbttagcompound) { + this.U = nbttagcompound; } // CraftBukkit start - Check if the name stored in NBT is the correct one diff --git a/sources/src/main/java/net/minecraft/server/WorldServer.java b/sources/src/main/java/net/minecraft/server/WorldServer.java index 262dcce6d..f35e99b2b 100644 --- a/sources/src/main/java/net/minecraft/server/WorldServer.java +++ b/sources/src/main/java/net/minecraft/server/WorldServer.java @@ -3,16 +3,18 @@ package net.minecraft.server; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.util.concurrent.ListenableFuture; -import java.io.File; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import java.util.ArrayList; import java.util.Collection; -import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -21,8 +23,6 @@ import org.apache.logging.log4j.Logger; import java.util.logging.Level; import org.bukkit.WeatherType; -import org.bukkit.craftbukkit.util.HashTreeSet; - import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.weather.LightningStrikeEvent; // CraftBukkit end @@ -39,23 +39,22 @@ public class WorldServer extends World implements IAsyncTaskHandler { private final MinecraftServer server; public EntityTracker tracker; public final PlayerChunkMap manager; // Akarin - private -> public - // private final Set nextTickListHash = Sets.newHashSet(); - private final HashTreeSet nextTickList = new HashTreeSet(); // CraftBukkit - HashTreeSet public final Map entitiesByUUID = Maps.newHashMap(); // Paper public boolean savingDisabled; - private boolean Q; + private boolean K; private int emptyTime; private final PortalTravelAgent portalTravelAgent; private final SpawnerCreature spawnerCreature = new SpawnerCreature(); - protected final VillageSiege siegeManager = new VillageSiege(this); - private final WorldServer.BlockActionDataList[] U = new WorldServer.BlockActionDataList[] { new WorldServer.BlockActionDataList(null), new WorldServer.BlockActionDataList(null)}; - private int V; - private final List W = Lists.newArrayList(); + private final TickListServer nextTickListBlock; + private final TickListServer nextTickListFluid; + protected final VillageSiege siegeManager; + ObjectLinkedOpenHashSet d; + private boolean Q; // CraftBukkit start 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 Date()); + return new Throwable(entity + " Added to world at " + new java.util.Date()); } public final int dimension; @@ -66,60 +65,63 @@ public class WorldServer extends World implements IAsyncTaskHandler { 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; + + Block.REGISTRY.getClass(); + Function function = registryblocks::b; + RegistryBlocks registryblocks1 = Block.REGISTRY; // 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) -> { + 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 + 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(this); - this.chunkProvider = this.n(); + this.worldProvider.a((World) this); + this.chunkProvider = this.q(); this.portalTravelAgent = new org.bukkit.craftbukkit.CraftTravelAgent(this); // CraftBukkit - this.J(); - this.K(); - this.getWorldBorder().a(minecraftserver.aE()); + this.O(); + this.P(); + this.getWorldBorder().a(minecraftserver.aw()); } - @Override - public World b() { + public GeneratorAccess b() { this.worldMaps = new PersistentCollection(this.dataManager); String s = PersistentVillage.a(this.worldProvider); - PersistentVillage persistentvillage = (PersistentVillage) this.worldMaps.get(PersistentVillage.class, s); + PersistentVillage persistentvillage = (PersistentVillage) this.worldMaps.get(PersistentVillage::new, s); if (persistentvillage == null) { this.villages = new PersistentVillage(this); this.worldMaps.a(s, this.villages); } else { this.villages = persistentvillage; - this.villages.a(this); + this.villages.a((World) this); } if (getServer().getScoreboardManager() == null) { // CraftBukkit - this.scoreboard = new ScoreboardServer(this.server); - PersistentScoreboard persistentscoreboard = (PersistentScoreboard) this.worldMaps.get(PersistentScoreboard.class, "scoreboard"); + PersistentScoreboard persistentscoreboard = (PersistentScoreboard) this.worldMaps.get(PersistentScoreboard::new, "scoreboard"); if (persistentscoreboard == null) { persistentscoreboard = new PersistentScoreboard(); this.worldMaps.a("scoreboard", persistentscoreboard); } - persistentscoreboard.a(this.scoreboard); - ((ScoreboardServer) this.scoreboard).a((new RunnableSaveScoreboard(persistentscoreboard))); - // CraftBukkit start - } else { - this.scoreboard = getServer().getScoreboardManager().getMainScoreboard().getHandle(); - } - // CraftBukkit end - - this.B = new LootTableRegistry(new File(new File(this.dataManager.getDirectory(), "data"), "loot_tables")); - // CraftBukkit start - if (this.dimension != 0) { // SPIGOT-3899 multiple worlds of advancements not supported - this.C = this.server.getAdvancementData(); - } - if (this.C == null) { - this.C = new AdvancementDataWorld(new File(new File(this.dataManager.getDirectory(), "data"), "advancements")); - } - if (this.D == null) { - this.D = new CustomFunctionData(new File(new File(this.dataManager.getDirectory(), "data"), "functions"), this.server); - } - // CraftBukkit end + persistentscoreboard.a((Scoreboard) this.server.getScoreboard()); + this.server.getScoreboard().a((Runnable) (new RunnableSaveScoreboard(persistentscoreboard))); + } // CraftBukkit this.getWorldBorder().setCenter(this.worldData.B(), this.worldData.C()); this.getWorldBorder().setDamageAmount(this.worldData.H()); this.getWorldBorder().setDamageBuffer(this.worldData.G()); @@ -163,18 +165,14 @@ public class WorldServer extends World implements IAsyncTaskHandler { result = fixTileEntity(pos, type, result); } } else if (type == Blocks.JUKEBOX) { - if (!(result instanceof BlockJukeBox.TileEntityRecordPlayer)) { + if (!(result instanceof TileEntityJukeBox)) { result = fixTileEntity(pos, type, result); } - } else if (type == Blocks.NOTEBLOCK) { - if (!(result instanceof TileEntityNote)) { - result = fixTileEntity(pos, type, result); - } - } else if (type == Blocks.MOB_SPAWNER) { + } else if (type == Blocks.SPAWNER) { if (!(result instanceof TileEntityMobSpawner)) { result = fixTileEntity(pos, type, result); } - } else if ((type == Blocks.STANDING_SIGN) || (type == Blocks.WALL_SIGN)) { + } else if ((type == Blocks.SIGN) || (type == Blocks.WALL_SIGN)) { if (!(result instanceof TileEntitySign)) { result = fixTileEntity(pos, type, result); } @@ -202,23 +200,19 @@ public class WorldServer extends World implements IAsyncTaskHandler { if (!(result instanceof TileEntityEnderPortal)) { result = fixTileEntity(pos, type, result); } - } else if (type == Blocks.SKULL) { + } else if (type instanceof BlockSkullAbstract) { if (!(result instanceof TileEntitySkull)) { result = fixTileEntity(pos, type, result); } - } else if (type == Blocks.DAYLIGHT_DETECTOR || type == Blocks.DAYLIGHT_DETECTOR_INVERTED) { + } else if (type == Blocks.DAYLIGHT_DETECTOR) { if (!(result instanceof TileEntityLightDetector)) { result = fixTileEntity(pos, type, result); } - } else if (type == Blocks.POWERED_COMPARATOR || type == Blocks.UNPOWERED_COMPARATOR) { + } else if (type == Blocks.COMPARATOR) { if (!(result instanceof TileEntityComparator)) { result = fixTileEntity(pos, type, result); } - } else if (type == Blocks.FLOWER_POT) { - if (!(result instanceof TileEntityFlowerPot)) { - result = fixTileEntity(pos, type, result); - } - } else if (type == Blocks.STANDING_BANNER || type == Blocks.WALL_BANNER) { + }else if (type instanceof BlockBannerAbstract) { if (!(result instanceof TileEntityBanner)) { result = fixTileEntity(pos, type, result); } @@ -238,7 +232,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { if (!(result instanceof TileEntityStructure)) { result = fixTileEntity(pos, type, result); } - } else if (type == Blocks.BED) { + } else if (type instanceof BlockBed) { if (!(result instanceof TileEntityBed)) { result = fixTileEntity(pos, type, result); } @@ -256,10 +250,10 @@ public class WorldServer extends World implements IAsyncTaskHandler { private TileEntity fixTileEntity(BlockPosition pos, Block type, TileEntity found) { this.getServer().getLogger().log(Level.SEVERE, "Block at {0},{1},{2} is {3} but has {4}" + ". " - + "Bukkit will attempt to fix this, but there may be additional damage that we cannot recover.", new Object[]{pos.getX(), pos.getY(), pos.getZ(), org.bukkit.Material.getMaterial(Block.getId(type)).toString(), found}); + + "Bukkit will attempt to fix this, but there may be additional damage that we cannot recover.", new Object[]{pos.getX(), pos.getY(), pos.getZ(), type, found}); if (type instanceof ITileEntity) { - TileEntity replacement = ((ITileEntity) type).a(this, type.toLegacyData(this.getType(pos))); + TileEntity replacement = ((ITileEntity) type).a(this); replacement.world = this; this.setTileEntity(pos, replacement); return replacement; @@ -268,41 +262,37 @@ public class WorldServer extends World implements IAsyncTaskHandler { return found; } } - - private boolean canSpawn(int x, int z) { - if (this.generator != null) { - return this.generator.canSpawn(this.getWorld(), x, z); - } else { - return this.worldProvider.canSpawn(x, z); - } - } // CraftBukkit end - @Override public void doTick() { + this.Q = true; super.doTick(); // Akarin start - goes to slack service - /* if (this.getWorldData().isHardcore() && this.getDifficulty() != EnumDifficulty.HARD) { + /* + if (this.getWorldData().isHardcore() && this.getDifficulty() != EnumDifficulty.HARD) { this.getWorldData().setDifficulty(EnumDifficulty.HARD); - } */ // Akarin end + } + */ + // Akarin end - this.worldProvider.k().b(); + this.chunkProvider.getChunkGenerator().getWorldChunkManager().Y_(); if (this.everyoneDeeplySleeping()) { if (this.getGameRules().getBoolean("doDaylightCycle")) { long i = this.worldData.getDayTime() + 24000L; - + this.worldData.setDayTime(i - i % 24000L); } - this.f(); + this.h(); } - this.methodProfiler.a("mobSpawner"); + this.methodProfiler.a("spawner"); // CraftBukkit start - Only call spawner if we have players online and the world allows for mobs or animals long time = this.worldData.getTime(); if (this.getGameRules().getBoolean("doMobSpawning") && this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES && (this.allowMonsters || this.allowAnimals) && (this instanceof WorldServer && this.players.size() > 0)) { timings.mobSpawn.startTiming(); // Spigot this.spawnerCreature.a(this, this.allowMonsters && (this.ticksPerMonsterSpawns != 0 && time % this.ticksPerMonsterSpawns == 0L), this.allowAnimals && (this.ticksPerAnimalSpawns != 0 && time % this.ticksPerAnimalSpawns == 0L), this.worldData.getTime() % 400L == 0L); + this.getChunkProviderServer().a(this, this.allowMonsters && (this.ticksPerMonsterSpawns != 0 && time % this.ticksPerMonsterSpawns == 0L), this.allowAnimals && (this.ticksPerAnimalSpawns != 0 && time % this.ticksPerAnimalSpawns == 0L)); timings.mobSpawn.stopTiming(); // Spigot // CraftBukkit end } @@ -312,7 +302,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.chunkProvider.unloadChunks(); int j = this.a(1.0F); - if (j != this.ah()) { + if (j != this.c()) { this.c(j); } @@ -324,11 +314,11 @@ public class WorldServer extends World implements IAsyncTaskHandler { timings.doChunkUnload.stopTiming(); // Spigot this.methodProfiler.c("tickPending"); timings.scheduledBlocks.startTiming(); // Paper - this.a(false); + this.p(); timings.scheduledBlocks.stopTiming(); // Paper this.methodProfiler.c("tickBlocks"); timings.chunkTicks.startTiming(); // Paper - this.j(); + this.l(); timings.chunkTicks.stopTiming(); // Paper this.methodProfiler.c("chunkMap"); timings.doChunkMap.startTiming(); // Spigot @@ -343,21 +333,26 @@ public class WorldServer extends World implements IAsyncTaskHandler { timings.doPortalForcer.startTiming(); // Spigot this.portalTravelAgent.a(this.getTime()); timings.doPortalForcer.stopTiming(); // Spigot - this.methodProfiler.b(); + this.methodProfiler.e(); timings.doSounds.startTiming(); // Spigot - this.aq(); + this.am(); timings.doSounds.stopTiming(); // Spigot + this.Q = false; timings.doChunkGC.startTiming();// Spigot this.getWorld().processChunkGC(); // CraftBukkit timings.doChunkGC.stopTiming(); // Spigot } + public boolean j_() { + return this.Q; + } + @Nullable public BiomeBase.BiomeMeta a(EnumCreatureType enumcreaturetype, BlockPosition blockposition) { List list = this.getChunkProviderServer().a(enumcreaturetype, blockposition); - return list != null && !list.isEmpty() ? (BiomeBase.BiomeMeta) WeightedRandom.a(this.random, list) : null; + return list.isEmpty() ? null : (BiomeBase.BiomeMeta) WeightedRandom.a(this.random, list); } public boolean a(EnumCreatureType enumcreaturetype, BiomeBase.BiomeMeta biomebase_biomemeta, BlockPosition blockposition) { @@ -366,9 +361,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { return list != null && !list.isEmpty() ? list.contains(biomebase_biomemeta) : false; } - @Override public void everyoneSleeping() { - this.Q = false; + this.K = false; if (!this.players.isEmpty()) { int i = 0; int j = 0; @@ -384,14 +378,18 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } - this.Q = j > 0 && j >= this.players.size() - i; + this.K = j > 0 && j >= this.players.size() - i; } } - protected void f() { - this.Q = false; - List list = this.players.stream().filter(EntityHuman::isSleeping).collect(Collectors.toList()); + public ScoreboardServer l_() { + return this.server.getScoreboard(); + } + + protected void h() { + this.K = false; + List list = (List) this.players.stream().filter(EntityHuman::isSleeping).collect(Collectors.toList()); Iterator iterator = list.iterator(); while (iterator.hasNext()) { @@ -401,14 +399,14 @@ public class WorldServer extends World implements IAsyncTaskHandler { } if (this.getGameRules().getBoolean("doWeatherCycle")) { - this.c(); + this.ai(); } } - private void c() { - this.worldData.setStorm(false); + private void ai() { // CraftBukkit start + this.worldData.setStorm(false); // If we stop due to everyone sleeping we should reset the weather duration to some other random value. // Not that everyone ever manages to get the whole server to sleep at the same time.... if (!this.worldData.hasStorm()) { @@ -426,7 +424,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } public boolean everyoneDeeplySleeping() { - if (this.Q && !this.isClientSide) { + if (this.K && !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 @@ -454,34 +452,36 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } - @Override - protected boolean isChunkLoaded(int i, int j, boolean flag) { + public boolean isChunkLoaded(int i, int j, boolean flag) { + return this.a(i, j); + } + + public boolean a(int i, int j) { return this.getChunkProviderServer().isLoaded(i, j); } - protected void i() { + protected void n_() { this.methodProfiler.a("playerCheckLight"); if (spigotConfig.randomLightUpdates && !this.players.isEmpty()) { // Spigot int i = this.random.nextInt(this.players.size()); - EntityHuman entityhuman = this.players.get(i); + EntityHuman entityhuman = (EntityHuman) this.players.get(i); int j = MathHelper.floor(entityhuman.locX) + this.random.nextInt(11) - 5; int k = MathHelper.floor(entityhuman.locY) + this.random.nextInt(11) - 5; int l = MathHelper.floor(entityhuman.locZ) + this.random.nextInt(11) - 5; - this.w(new BlockPosition(j, k, l)); + this.r(new BlockPosition(j, k, l)); } - this.methodProfiler.b(); + this.methodProfiler.e(); } - @Override - protected void j() { - this.i(); + protected void l() { + this.n_(); if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { Iterator iterator = this.manager.b(); while (iterator.hasNext()) { - ((Chunk) iterator.next()).b(false); + ((Chunk) iterator.next()).d(false); } } else { @@ -491,60 +491,60 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.methodProfiler.a("pollingChunks"); - for (Iterator iterator1 = this.manager.b(); iterator1.hasNext(); this.methodProfiler.b()) { + for (Iterator iterator1 = this.manager.b(); iterator1.hasNext(); this.methodProfiler.e()) { this.methodProfiler.a("getChunk"); Chunk chunk = (Chunk) iterator1.next(); int j = chunk.locX * 16; int k = chunk.locZ * 16; this.methodProfiler.c("checkNextLight"); - chunk.n(); + chunk.x(); this.methodProfiler.c("tickChunk"); - chunk.b(false); + chunk.d(false); if ( !chunk.areNeighborsLoaded( 1 ) ) continue; // Spigot this.methodProfiler.c("thunder"); int l; BlockPosition blockposition; - // Paper - Disable thunder - if (!this.paperConfig.disableThunder && flag && flag1 && this.random.nextInt(100000) == 0) { - this.l = this.l * 3 + 1013904223; - l = this.l >> 2; + if (!this.paperConfig.disableThunder && flag && flag1 && this.random.nextInt(100000) == 0) { // Paper - Disable thunder + this.m = this.m * 3 + 1013904223; + l = this.m >> 2; blockposition = this.a(new BlockPosition(j + (l & 15), 0, k + (l >> 8 & 15))); if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.D(blockposition); + DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); - if (this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance) { + if (this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance) { EntityHorseSkeleton entityhorseskeleton = new EntityHorseSkeleton(this); - entityhorseskeleton.p(true); + entityhorseskeleton.s(true); entityhorseskeleton.setAgeRaw(0); - entityhorseskeleton.setPosition(blockposition.getX(), blockposition.getY(), blockposition.getZ()); + 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, blockposition.getX(), blockposition.getY(), blockposition.getZ(), true)); + this.strikeLightning(new EntityLightning(this, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), true)); } else { - this.strikeLightning(new EntityLightning(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), false)); + this.strikeLightning(new EntityLightning(this, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), false)); } } } this.methodProfiler.c("iceandsnow"); if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow - this.l = this.l * 3 + 1013904223; - l = this.l >> 2; - blockposition = this.p(new BlockPosition(j + (l & 15), 0, k + (l >> 8 & 15))); + this.m = this.m * 3 + 1013904223; + l = this.m >> 2; + blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(j + (l & 15), 0, k + (l >> 8 & 15))); BlockPosition blockposition1 = blockposition.down(); + BiomeBase biomebase = this.getBiome(blockposition); - if (this.v(blockposition1)) { + if (biomebase.a((IWorldReader) this, blockposition1)) { org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.getBlockData(), null); // CraftBukkit } - if (flag && this.f(blockposition, true)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW_LAYER.getBlockData(), null); // CraftBukkit + if (flag && biomebase.b(this, blockposition)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.getBlockData(), null); // CraftBukkit } - if (flag && this.getBiome(blockposition1).d()) { - this.getType(blockposition1).getBlock().h(this, blockposition1); + if (flag && this.getBiome(blockposition1).c() == BiomeBase.Precipitation.RAIN) { + this.getType(blockposition1).getBlock().c(this, blockposition1); } } @@ -556,22 +556,26 @@ public class WorldServer extends World implements IAsyncTaskHandler { for (int j1 = 0; j1 < i1; ++j1) { ChunkSection chunksection = achunksection[j1]; - if (chunksection != Chunk.a && chunksection.shouldTick()) { + if (chunksection != Chunk.a && chunksection.b()) { for (int k1 = 0; k1 < i; ++k1) { - this.l = this.l * 3 + 1013904223; - int l1 = this.l >> 2; + this.m = this.m * 3 + 1013904223; + int l1 = this.m >> 2; int i2 = l1 & 15; int j2 = l1 >> 8 & 15; int k2 = l1 >> 16 & 15; IBlockData iblockdata = chunksection.getType(i2, k2, j2); - Block block = iblockdata.getBlock(); + Fluid fluid = chunksection.b(i2, k2, j2); this.methodProfiler.a("randomTick"); - if (block.isTicking()) { - block.a(this, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, this.random); + if (iblockdata.t()) { + iblockdata.b((World) this, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), this.random); } - this.methodProfiler.b(); + if (fluid.h()) { + fluid.b(this, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), this.random); + } + + this.methodProfiler.e(); } } } @@ -579,22 +583,15 @@ public class WorldServer extends World implements IAsyncTaskHandler { timings.chunkTicksBlocks.stopTiming(); // Paper } - this.methodProfiler.b(); + this.methodProfiler.e(); } } protected BlockPosition a(BlockPosition blockposition) { - BlockPosition blockposition1 = this.p(blockposition); + BlockPosition blockposition1 = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, blockposition); AxisAlignedBB axisalignedbb = (new AxisAlignedBB(blockposition1, new BlockPosition(blockposition1.getX(), this.getHeight(), blockposition1.getZ()))).g(3.0D); - List list = this.a(EntityLiving.class, axisalignedbb, new com.google.common.base.Predicate() { - public boolean a(@Nullable EntityLiving entityliving) { - return entityliving != null && entityliving.isAlive() && WorldServer.this.h(entityliving.getChunkCoordinates()); - } - - @Override - public boolean apply(@Nullable Object object) { - return this.a((EntityLiving) object); - } + List list = this.a(EntityLiving.class, axisalignedbb, (Predicate) (entityliving) -> { // CraftBukkit - decompile error + return entityliving != null && entityliving.isAlive() && this.e(entityliving.getChunkCoordinates()); }); if (!list.isEmpty()) { @@ -608,102 +605,27 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } - @Override - public boolean a(BlockPosition blockposition, Block block) { - NextTickListEntry nextticklistentry = new NextTickListEntry(blockposition, block); - - return this.W.contains(nextticklistentry); - } - - @Override - public boolean b(BlockPosition blockposition, Block block) { - NextTickListEntry nextticklistentry = new NextTickListEntry(blockposition, block); - - return this.nextTickList.contains(nextticklistentry); // CraftBukkit - } - - @Override - public void a(BlockPosition blockposition, Block block, int i) { - this.a(blockposition, block, i, 0); - } - - @Override - public void a(BlockPosition blockposition, Block block, int i, int j) { - Material material = block.getBlockData().getMaterial(); - - if (this.d && material != Material.AIR) { - if (block.r()) { - if (this.areChunksLoadedBetween(blockposition.a(-8, -8, -8), blockposition.a(8, 8, 8))) { - IBlockData iblockdata = this.getType(blockposition); - - if (iblockdata.getMaterial() != Material.AIR && iblockdata.getBlock() == block) { - iblockdata.getBlock().b(this, blockposition, iblockdata, this.random); - } - } - - return; - } - - i = 1; - } - - NextTickListEntry nextticklistentry = new NextTickListEntry(blockposition, block); - - if (this.isLoaded(blockposition)) { - if (material != Material.AIR) { - nextticklistentry.a(i + this.worldData.getTime()); - nextticklistentry.a(j); - } - - // CraftBukkit - use nextTickList - if (!this.nextTickList.contains(nextticklistentry)) { - this.nextTickList.add(nextticklistentry); - } - } - - } - - @Override - public void b(BlockPosition blockposition, Block block, int i, int j) { - NextTickListEntry nextticklistentry = new NextTickListEntry(blockposition, block); - - nextticklistentry.a(j); - Material material = block.getBlockData().getMaterial(); - - if (material != Material.AIR) { - nextticklistentry.a(i + this.worldData.getTime()); - } - - // CraftBukkit - use nextTickList - if (!this.nextTickList.contains(nextticklistentry)) { - this.nextTickList.add(nextticklistentry); - } - - } - - @Override public void tickEntities() { if (false && this.players.isEmpty()) { // CraftBukkit - this prevents entity cleanup, other issues on servers with no players if (this.emptyTime++ >= 300) { return; } } else { - this.m(); + this.q_(); } - this.worldProvider.s(); + this.worldProvider.l(); super.tickEntities(); spigotConfig.currentPrimedTnt = 0; // Spigot } - @Override - protected void l() { - super.l(); + protected void p_() { + super.p_(); this.methodProfiler.c("players"); for (int i = 0; i < this.players.size(); ++i) { - Entity entity = this.players.get(i); - Entity entity1 = entity.bJ(); + Entity entity = (Entity) this.players.get(i); + Entity entity1 = entity.getVehicle(); if (entity1 != null) { if (!entity1.dead && entity1.w(entity)) { @@ -716,7 +638,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.methodProfiler.a("tick"); if (!entity.dead) { try { - this.h(entity); + this.g(entity); } catch (Throwable throwable) { CrashReport crashreport = CrashReport.a(throwable, "Ticking player"); CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Player being ticked"); @@ -726,13 +648,13 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } - this.methodProfiler.b(); + this.methodProfiler.e(); this.methodProfiler.a("remove"); if (entity.dead) { - int j = entity.ab; - int k = entity.ad; + int j = entity.ae; + int k = entity.ag; - if (entity.aa && this.isChunkLoaded(j, k, true)) { + if (entity.inChunk && this.isChunkLoaded(j, k, true)) { this.getChunkAt(j, k).b(entity); } @@ -740,143 +662,39 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.c(entity); } - this.methodProfiler.b(); + this.methodProfiler.e(); } } - public void m() { + public void q_() { this.emptyTime = 0; } - @Override - public boolean a(boolean flag) { - if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { - return false; - } else { - int i = this.nextTickList.size(); - - if (false) { // CraftBukkit - throw new IllegalStateException("TickNextTick list out of synch"); - } else { - if (i > 65536) { - // CraftBukkit start - If the server has too much to process over time, try to alleviate that - if (i > 20 * 65536) { - i = i / 20; - } else { - i = 65536; - } - // CraftBukkit end - } - - this.methodProfiler.a("cleaning"); - - timings.scheduledBlocksCleanup.startTiming(); // Paper - NextTickListEntry nextticklistentry; - - for (int j = 0; j < i; ++j) { - nextticklistentry = this.nextTickList.first(); - if (!flag && nextticklistentry.b > this.worldData.getTime()) { - break; - } - - // CraftBukkit - use nextTickList - this.nextTickList.remove(nextticklistentry); - // this.nextTickListHash.remove(nextticklistentry); - this.W.add(nextticklistentry); - } - timings.scheduledBlocksCleanup.stopTiming(); // Paper - - this.methodProfiler.b(); - this.methodProfiler.a("ticking"); - Iterator iterator = this.W.iterator(); - timings.scheduledBlocksTicking.startTiming(); // Paper - - while (iterator.hasNext()) { - nextticklistentry = (NextTickListEntry) iterator.next(); - iterator.remove(); - boolean flag1 = false; - - if (this.areChunksLoadedBetween(nextticklistentry.a.a(0, 0, 0), nextticklistentry.a.a(0, 0, 0))) { - IBlockData iblockdata = this.getType(nextticklistentry.a); - co.aikar.timings.Timing timing = iblockdata.getBlock().getTiming(); // Paper - timing.startTiming(); // Paper - - if (iblockdata.getMaterial() != Material.AIR && Block.a(iblockdata.getBlock(), nextticklistentry.a())) { - try { - stopPhysicsEvent = !paperConfig.firePhysicsEventForRedstone && (iblockdata.getBlock() instanceof BlockDiodeAbstract || iblockdata.getBlock() instanceof BlockRedstoneTorch); // Paper - iblockdata.getBlock().b(this, nextticklistentry.a, iblockdata, this.random); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Exception while ticking a block"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being ticked"); - - CrashReportSystemDetails.a(crashreportsystemdetails, nextticklistentry.a, iblockdata); - throw new ReportedException(crashreport); - } finally { stopPhysicsEvent = false; } // Paper - } - timing.stopTiming(); // Paper - } else { - this.a(nextticklistentry.a, nextticklistentry.a(), 0); - } - } - timings.scheduledBlocksTicking.stopTiming(); // Paper - - this.methodProfiler.b(); - this.W.clear(); - return !this.nextTickList.isEmpty(); - } + public void p() { + if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { + this.nextTickListBlock.a(); + this.nextTickListFluid.a(); } } - @Override - @Nullable - public List a(Chunk chunk, boolean flag) { - ChunkCoordIntPair chunkcoordintpair = chunk.k(); - int i = (chunkcoordintpair.x << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.z << 4) - 2; - int l = k + 16 + 2; + private void a(NextTickListEntry nextticklistentry) { + Fluid fluid = this.b(nextticklistentry.a); - return this.a(new StructureBoundingBox(i, 0, k, j, 256, l), flag); - } - - @Override - @Nullable - public List a(StructureBoundingBox structureboundingbox, boolean flag) { - ArrayList arraylist = null; - - for (int i = 0; i < 2; ++i) { - Iterator iterator; - - if (i == 0) { - iterator = this.nextTickList.iterator(); - } else { - iterator = this.W.iterator(); - } - - while (iterator.hasNext()) { - NextTickListEntry nextticklistentry = (NextTickListEntry) iterator.next(); - BlockPosition blockposition = nextticklistentry.a; - - if (blockposition.getX() >= structureboundingbox.a && blockposition.getX() < structureboundingbox.d && blockposition.getZ() >= structureboundingbox.c && blockposition.getZ() < structureboundingbox.f) { - if (flag) { - if (i == 0) { - // this.nextTickListHash.remove(nextticklistentry); // CraftBukkit - removed - } - - iterator.remove(); - } - - if (arraylist == null) { - arraylist = Lists.newArrayList(); - } - - arraylist.add(nextticklistentry); - } - } + if (fluid.c() == nextticklistentry.a()) { + fluid.a((World) this, nextticklistentry.a); + } + + } + + private void b(NextTickListEntry nextticklistentry) { + IBlockData iblockdata = this.getType(nextticklistentry.a); + + if (iblockdata.getBlock() == nextticklistentry.a()) { + stopPhysicsEvent = !paperConfig.firePhysicsEventForRedstone && (iblockdata.getBlock() instanceof BlockDiodeAbstract || iblockdata.getBlock() instanceof BlockRedstoneTorch); // Paper + iblockdata.a((World) this, nextticklistentry.a, this.random); } - return arraylist; } /* CraftBukkit start - We prevent spawning in general, so this butchering is not needed @@ -901,8 +719,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { return this.server.getSpawnAnimals(); } - @Override - protected IChunkProvider n() { + protected IChunkProvider q() { IChunkLoader ichunkloader = this.dataManager.createChunkLoader(this.worldProvider); // CraftBukkit start @@ -918,55 +735,20 @@ 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)); // Paper + return new ChunkProviderServer(this, ichunkloader, new co.aikar.timings.TimedChunkGenerator(this, gen), this.server); // Paper // CraftBukkit end } - public List getTileEntities(int i, int j, int k, int l, int i1, int j1) { - ArrayList arraylist = Lists.newArrayList(); - - // CraftBukkit start - Get tile entities from chunks instead of world - for (int chunkX = (i >> 4); chunkX <= ((l - 1) >> 4); chunkX++) { - for (int chunkZ = (k >> 4); chunkZ <= ((j1 - 1) >> 4); chunkZ++) { - Chunk chunk = getChunkAt(chunkX, chunkZ); - if (chunk == null) { - continue; - } - for (Object te : chunk.tileEntities.values()) { - TileEntity tileentity = (TileEntity) te; - if ((tileentity.position.getX() >= i) && (tileentity.position.getY() >= j) && (tileentity.position.getZ() >= k) && (tileentity.position.getX() < l) && (tileentity.position.getY() < i1) && (tileentity.position.getZ() < j1)) { - arraylist.add(tileentity); - } - } - } - } - /* - for (int k1 = 0; k1 < this.tileEntityList.size(); ++k1) { - TileEntity tileentity = (TileEntity) this.tileEntityList.get(k1); - BlockPosition blockposition = tileentity.getPosition(); - - if (blockposition.getX() >= i && blockposition.getY() >= j && blockposition.getZ() >= k && blockposition.getX() < l && blockposition.getY() < i1 && blockposition.getZ() < j1) { - arraylist.add(tileentity); - } - } - */ - // CraftBukkit end - - return arraylist; - } - - @Override public boolean a(EntityHuman entityhuman, BlockPosition blockposition) { return !this.server.a(this, blockposition, entityhuman) && this.getWorldBorder().a(blockposition); } - @Override public void a(WorldSettings worldsettings) { if (!this.worldData.v()) { try { this.b(worldsettings); if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { - this.ap(); + this.al(); } super.a(worldsettings); @@ -987,88 +769,108 @@ public class WorldServer extends World implements IAsyncTaskHandler { } - private void ap() { + private void al() { this.worldData.f(false); this.worldData.c(true); this.worldData.setStorm(false); this.worldData.setThundering(false); - this.worldData.i(1000000000); + this.worldData.g(1000000000); this.worldData.setDayTime(6000L); this.worldData.setGameType(EnumGamemode.SPECTATOR); this.worldData.g(false); this.worldData.setDifficulty(EnumDifficulty.PEACEFUL); this.worldData.e(true); - this.getGameRules().set("doDaylightCycle", "false"); + this.getGameRules().set("doDaylightCycle", "false", this.server); } private void b(WorldSettings worldsettings) { - if (!this.worldProvider.e()) { - this.worldData.setSpawn(BlockPosition.ZERO.up(this.worldProvider.getSeaLevel())); + if (!this.worldProvider.p()) { + this.worldData.setSpawn(BlockPosition.ZERO.up(this.chunkProvider.getChunkGenerator().getSpawnHeight())); } else if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { this.worldData.setSpawn(BlockPosition.ZERO.up()); } else { - this.isLoading = true; - WorldChunkManager worldchunkmanager = this.worldProvider.k(); + WorldChunkManager worldchunkmanager = this.chunkProvider.getChunkGenerator().getWorldChunkManager(); List list = worldchunkmanager.a(); Random random = new Random(this.getSeed()); BlockPosition blockposition = worldchunkmanager.a(0, 0, 256, list, random); - int i = 8; - int j = this.worldProvider.getSeaLevel(); - int k = 8; + ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); // CraftBukkit start if (this.generator != null) { Random rand = new Random(this.getSeed()); - org.bukkit.Location spawn = this.generator.getFixedSpawnLocation(this.getWorld(), rand); + org.bukkit.Location spawn = this.generator.getFixedSpawnLocation(((WorldServer) this).getWorld(), rand); if (spawn != null) { - if (spawn.getWorld() != this.getWorld()) { + if (spawn.getWorld() != ((WorldServer) this).getWorld()) { throw new IllegalStateException("Cannot set spawn point for " + this.worldData.getName() + " to be in another world (" + spawn.getWorld().getName() + ")"); } else { this.worldData.setSpawn(new BlockPosition(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ())); - this.isLoading = false; return; } } } // CraftBukkit end - if (blockposition != null) { - i = blockposition.getX(); - k = blockposition.getZ(); - } else { + if (blockposition == null) { WorldServer.a.warn("Unable to find spawn biome"); } - int l = 0; + boolean flag = false; + Iterator iterator = TagsBlock.I.a().iterator(); - while (!this.canSpawn(i, k)) { // CraftBukkit - use our own canSpawn - i += random.nextInt(64) - random.nextInt(64); - k += random.nextInt(64) - random.nextInt(64); - ++l; - if (l == 1000) { + while (iterator.hasNext()) { + Block block = (Block) iterator.next(); + + if (worldchunkmanager.b().contains(block.getBlockData())) { + flag = true; break; } } - this.worldData.setSpawn(new BlockPosition(i, j, k)); - this.isLoading = false; + this.worldData.setSpawn(chunkcoordintpair.h().a(8, this.chunkProvider.getChunkGenerator().getSpawnHeight(), 8)); + int i = 0; + int j = 0; + int k = 0; + int l = -1; + boolean flag1 = true; + + for (int i1 = 0; i1 < 1024; ++i1) { + if (i > -16 && i <= 16 && j > -16 && j <= 16) { + BlockPosition blockposition1 = this.worldProvider.a(new ChunkCoordIntPair(chunkcoordintpair.x + i, chunkcoordintpair.z + j), flag); + + if (blockposition1 != null) { + this.worldData.setSpawn(blockposition1); + break; + } + } + + if (i == j || i < 0 && i == -j || i > 0 && i == 1 - j) { + int j1 = k; + + k = -l; + l = j1; + } + + i += k; + j += l; + } + if (worldsettings.c()) { - this.o(); + this.r(); } } } - protected void o() { + protected void r() { WorldGenBonusChest worldgenbonuschest = new WorldGenBonusChest(); for (int i = 0; i < 10; ++i) { int j = this.worldData.b() + this.random.nextInt(6) - this.random.nextInt(6); int k = this.worldData.d() + this.random.nextInt(6) - this.random.nextInt(6); - BlockPosition blockposition = this.q(new BlockPosition(j, 0, k)).up(); + BlockPosition blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, new BlockPosition(j, 0, k)).up(); - if (worldgenbonuschest.generate(this, this.random, blockposition)) { + if (worldgenbonuschest.a(this, this.chunkProvider.getChunkGenerator(), this.random, blockposition, WorldGenFeatureConfiguration.e)) { break; } } @@ -1077,7 +879,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { @Nullable public BlockPosition getDimensionSpawn() { - return this.worldProvider.h(); + return this.worldProvider.d(); } public void save(boolean flag, @Nullable IProgressUpdate iprogressupdate) throws ExceptionWorldConflict { @@ -1088,12 +890,12 @@ public class WorldServer extends World implements IAsyncTaskHandler { timings.worldSave.startTiming(); // Paper if (flag || server.serverAutoSave) { // Paper if (iprogressupdate != null) { - iprogressupdate.a("Saving level"); + iprogressupdate.a(new ChatMessage("menu.savingLevel", new Object[0])); } this.a(); if (iprogressupdate != null) { - iprogressupdate.c("Saving chunks"); + iprogressupdate.c(new ChatMessage("menu.savingChunks", new Object[0])); } } // Paper @@ -1134,13 +936,13 @@ public class WorldServer extends World implements IAsyncTaskHandler { WorldServer worldserver = aworldserver[j]; if (worldserver instanceof SecondaryWorldServer) { - ((SecondaryWorldServer) worldserver).c(); + ((SecondaryWorldServer) worldserver).t_(); } } // CraftBukkit start - Save secondary data for nether/end if (this instanceof SecondaryWorldServer) { - ((SecondaryWorldServer) this).c(); + ((SecondaryWorldServer) this).c(); // As above } // CraftBukkit end @@ -1149,17 +951,17 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.worldData.c(this.getWorldBorder().getCenterZ()); this.worldData.e(this.getWorldBorder().getDamageBuffer()); this.worldData.f(this.getWorldBorder().getDamageAmount()); - this.worldData.j(this.getWorldBorder().getWarningDistance()); - this.worldData.k(this.getWorldBorder().getWarningTime()); + this.worldData.h(this.getWorldBorder().getWarningDistance()); + this.worldData.i(this.getWorldBorder().getWarningTime()); this.worldData.b(this.getWorldBorder().j()); - this.worldData.e(this.getWorldBorder().i()); + this.worldData.c(this.getWorldBorder().i()); + this.worldData.c(this.server.aR().c()); this.dataManager.saveWorldData(this.worldData, this.server.getPlayerList().t()); this.worldMaps.a(); timings.worldSaveLevel.stopTiming(); // Paper } // CraftBukkit start - @Override public boolean addEntity(Entity entity, SpawnReason spawnReason) { // Changed signature, added SpawnReason // World.addEntity(Entity) will call this, and we still want to perform // existing entity checking when it's called with a SpawnReason @@ -1167,7 +969,6 @@ public class WorldServer extends World implements IAsyncTaskHandler { } // CraftBukkit end - @Override public void a(Collection collection) { ArrayList arraylist = Lists.newArrayList(collection); Iterator iterator = arraylist.iterator(); @@ -1185,28 +986,28 @@ public class WorldServer extends World implements IAsyncTaskHandler { private boolean j(Entity entity) { if (entity.dead) { - WorldServer.a.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.a(entity)); // CraftBukkit // Paper + WorldServer.a.warn("Tried to add entity {} but it was marked as removed already: " + entity); // CraftBukkit // Paper if (DEBUG_ENTITIES) getAddToWorldStackTrace(entity).printStackTrace(); return false; } else { UUID uuid = entity.getUniqueID(); if (this.entitiesByUUID.containsKey(uuid)) { - Entity entity1 = this.entitiesByUUID.get(uuid); + Entity entity1 = (Entity) this.entitiesByUUID.get(uuid); - if (this.f.contains(entity1) || entity1.dead) { // Paper - overwrite the current dead one - this.f.remove(entity1); + if (this.g.contains(entity1) || entity1.dead) { // Paper - if dupe is dead, overwrite + this.g.remove(entity1); } else { if (!(entity instanceof EntityHuman)) { if (entity.world.paperConfig.duplicateUUIDMode != com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode.NOTHING) { - WorldServer.a.error("Keeping entity {} that already exists with UUID {}", entity1, uuid.toString()); // CraftBukkit // Paper - WorldServer.a.error("Duplicate entity {} will not be added to the world. See paper.yml duplicate-uuid-resolver and set this to either regen, delete or nothing to get rid of this message", entity); // Paper - if (DEBUG_ENTITIES) { - if (entity1.addedToWorldStack != null) { - entity1.addedToWorldStack.printStackTrace(); - } - getAddToWorldStackTrace(entity).printStackTrace(); - } + WorldServer.a.error("Keeping entity {} that already exists with UUID {}", entity1, uuid.toString()); // CraftBukkit // Paper + WorldServer.a.error("Duplicate entity {} will not be added to the world. See paper.yml duplicate-uuid-resolver and set this to either regen, delete or nothing to get rid of this message", entity); // Paper + if (DEBUG_ENTITIES) { + if (entity1.addedToWorldStack != null) { + entity1.addedToWorldStack.printStackTrace(); + } + getAddToWorldStackTrace(entity).printStackTrace(); + } } return false; @@ -1222,7 +1023,6 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } - @Override protected void b(Entity entity) { super.b(entity); this.entitiesById.a(entity.getId(), entity); @@ -1230,6 +1030,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { if (DEBUG_ENTITIES) { entity.addedToWorldStack = getAddToWorldStackTrace(entity); } + Entity old = this.entitiesByUUID.put(entity.getUniqueID(), entity); if (old != null && old.getId() != entity.getId() && old.valid && entity.world.paperConfig.duplicateUUIDMode != com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode.NOTHING) { Logger logger = LogManager.getLogger(); @@ -1244,7 +1045,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } // Paper end - Entity[] aentity = entity.bb(); + Entity[] aentity = entity.bi(); if (aentity != null) { Entity[] aentity1 = aentity; @@ -1259,13 +1060,12 @@ public class WorldServer extends World implements IAsyncTaskHandler { } - @Override protected void c(Entity entity) { - if (!entity.valid) return; // Paper - Already removed, dont fire twice - this looks like it can happen even without our changes + if (!this.entitiesByUUID.containsKey(entity.getUniqueID()) && !entity.valid) return; // Paper - Already removed, dont fire twice - this looks like it can happen even without our changes super.c(entity); this.entitiesById.d(entity.getId()); this.entitiesByUUID.remove(entity.getUniqueID()); - Entity[] aentity = entity.bb(); + Entity[] aentity = entity.bi(); if (aentity != null) { Entity[] aentity1 = aentity; @@ -1280,7 +1080,6 @@ public class WorldServer extends World implements IAsyncTaskHandler { } - @Override public boolean strikeLightning(Entity entity) { // CraftBukkit start LightningStrikeEvent lightning = new LightningStrikeEvent(this.getWorld(), (org.bukkit.entity.LightningStrike) entity.getBukkitEntity()); @@ -1298,7 +1097,6 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } - @Override public void broadcastEntityEffect(Entity entity, byte b0) { this.getTracker().sendPacketToEntity(entity, new PacketPlayOutEntityStatus(entity, b0)); } @@ -1307,10 +1105,9 @@ public class WorldServer extends World implements IAsyncTaskHandler { return (ChunkProviderServer) super.getChunkProvider(); } - @Override - public Explosion createExplosion(@Nullable Entity entity, double d0, double d1, double d2, float f, boolean flag, boolean flag1) { + public Explosion createExplosion(@Nullable Entity entity, DamageSource damagesource, double d0, double d1, double d2, float f, boolean flag, boolean flag1) { // CraftBukkit start - Explosion explosion = super.createExplosion(entity, d0, d1, d2, f, flag, flag1); + Explosion explosion = super.createExplosion(entity, damagesource, d0, d1, d2, f, flag, flag1); if (explosion.wasCanceled) { return explosion; @@ -1319,6 +1116,10 @@ public class WorldServer extends World implements IAsyncTaskHandler { /* Remove Explosion explosion = new Explosion(this, entity, d0, d1, d2, f, flag, flag1); + if (damagesource != null) { + explosion.a(damagesource); + } + explosion.a(); explosion.a(false); */ @@ -1333,48 +1134,25 @@ public class WorldServer extends World implements IAsyncTaskHandler { EntityHuman entityhuman = (EntityHuman) iterator.next(); if (entityhuman.d(d0, d1, d2) < 4096.0D) { - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutExplosion(d0, d1, d2, f, explosion.getBlocks(), explosion.b().get(entityhuman))); + ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutExplosion(d0, d1, d2, f, explosion.getBlocks(), (Vec3D) explosion.c().get(entityhuman))); } } return explosion; } - @Override public void playBlockAction(BlockPosition blockposition, Block block, int i, int j) { - BlockActionData blockactiondata = new BlockActionData(blockposition, block, i, j); - Iterator iterator = this.U[this.V].iterator(); - - BlockActionData blockactiondata1; - - do { - if (!iterator.hasNext()) { - this.U[this.V].add(blockactiondata); - return; - } - - blockactiondata1 = (BlockActionData) iterator.next(); - } while (!blockactiondata1.equals(blockactiondata)); - + this.d.add(new BlockActionData(blockposition, block, i, j)); } - private void aq() { - while (!this.U[this.V].isEmpty()) { - int i = this.V; + private void am() { + while (!this.d.isEmpty()) { + BlockActionData blockactiondata = (BlockActionData) this.d.removeFirst(); - this.V ^= 1; - Iterator iterator = this.U[i].iterator(); - - while (iterator.hasNext()) { - BlockActionData blockactiondata = (BlockActionData) iterator.next(); - - if (this.a(blockactiondata)) { - // CraftBukkit - this.worldProvider.dimension -> this.dimension - this.server.getPlayerList().sendPacketNearby((EntityHuman) null, blockactiondata.a().getX(), blockactiondata.a().getY(), blockactiondata.a().getZ(), 64.0D, dimension, new PacketPlayOutBlockAction(blockactiondata.a(), blockactiondata.d(), blockactiondata.b(), blockactiondata.c())); - } + if (this.a(blockactiondata)) { + // CraftBukkit - this.worldProvider.dimension -> this.dimension + this.server.getPlayerList().sendPacketNearby((EntityHuman) null, (double) blockactiondata.a().getX(), (double) blockactiondata.a().getY(), (double) blockactiondata.a().getZ(), 64.0D, dimension, new PacketPlayOutBlockAction(blockactiondata.a(), blockactiondata.b(), blockactiondata.c(), blockactiondata.d())); } - - this.U[i].clear(); } } @@ -1382,25 +1160,25 @@ public class WorldServer extends World implements IAsyncTaskHandler { private boolean a(BlockActionData blockactiondata) { IBlockData iblockdata = this.getType(blockactiondata.a()); - return iblockdata.getBlock() == blockactiondata.d() ? iblockdata.a(this, blockactiondata.a(), blockactiondata.b(), blockactiondata.c()) : false; + return iblockdata.getBlock() == blockactiondata.b() ? iblockdata.a(this, blockactiondata.a(), blockactiondata.c(), blockactiondata.d()) : false; } - public void saveLevel() { + public void close() { this.dataManager.a(); + super.close(); } - @Override - protected void t() { + protected void v() { boolean flag = this.isRaining(); - super.t(); + super.v(); /* CraftBukkit start - if (this.n != this.o) { - this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(7, this.o)), this.worldProvider.getDimensionManager().getDimensionID()); + if (this.o != this.p) { + this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(7, this.p)), this.worldProvider.getDimensionManager().getDimensionID()); } - if (this.p != this.q) { - this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(8, this.q)), this.worldProvider.getDimensionManager().getDimensionID()); + if (this.q != this.r) { + this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(8, this.r)), this.worldProvider.getDimensionManager().getDimensionID()); } if (flag != this.isRaining()) { @@ -1410,8 +1188,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(1, 0.0F)); } - this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(7, this.o)); - this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(8, this.q)); + this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(7, this.p)); + this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(8, this.r)); } // */ if (flag != this.isRaining()) { @@ -1424,15 +1202,22 @@ public class WorldServer extends World implements IAsyncTaskHandler { } for (int i = 0; i < this.players.size(); ++i) { if (((EntityPlayer) this.players.get(i)).world == this) { - ((EntityPlayer) this.players.get(i)).updateWeather(this.n, this.o, this.p, this.q); + ((EntityPlayer) this.players.get(i)).updateWeather(this.o, this.p, this.q, this.r); } } // CraftBukkit end } - @Override - @Nullable + public TickListServer w() { + return this.nextTickListBlock; + } + + public TickListServer x() { + return this.nextTickListFluid; + } + + @Nonnull public MinecraftServer getMinecraftServer() { return this.server; } @@ -1449,96 +1234,99 @@ public class WorldServer extends World implements IAsyncTaskHandler { return this.portalTravelAgent; } - public DefinedStructureManager y() { + public DefinedStructureManager C() { return this.dataManager.h(); } - public void a(EnumParticle enumparticle, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, int... aint) { - this.a(enumparticle, false, d0, d1, d2, i, d3, d4, d5, d6, aint); - } - - public void a(EnumParticle enumparticle, boolean flag, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, int... aint) { + 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 - sendParticles(null, enumparticle, flag, d0, d1, d2, i, d3, d4, d5, d6, aint); + return sendParticles(null, t0, d0, d1, d2, i, d3, d4, d5, d6); + } + // Paper start - Particle API Expansion + // TODO: rework this, "flag" should probably be exposed as it was before + 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, d0, d1, d2, i, d3, d5, d5, d6); } - // Paper start - Particle API Expansion - public void sendParticles(EntityPlayer sender, EnumParticle enumparticle, boolean flag, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, int... aint) { - sendParticles(this.players, sender, enumparticle, flag, d0, d1, d2, i, d3, d4, d5, d6, aint); - } - public void sendParticles(List receivers, EntityPlayer sender, EnumParticle enumparticle, boolean flag, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, int... aint) { + 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) { // Paper end // CraftBukkit end - PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(enumparticle, flag, (float) d0, (float) d1, (float) d2, (float) d3, (float) d4, (float) d5, (float) d6, i, aint); + PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, false, (float) d0, (float) d1, (float) d2, (float) d3, (float) d4, (float) d5, (float) d6, i); + 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)) { + ++j; + } + } + + return j; + } + + public boolean a(EntityPlayer entityplayer, T t0, boolean flag, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { + PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, flag, (float) d0, (float) d1, (float) d2, (float) d3, (float) d4, (float) d5, (float) d6, i); + + return this.a(entityplayer, flag, d0, d1, d2, packetplayoutworldparticles); + } + + private boolean a(EntityPlayer entityplayer, boolean flag, double d0, double d1, double d2, Packet packet) { + if (entityplayer.getWorldServer() != this) { + return false; + } else { BlockPosition blockposition = entityplayer.getChunkCoordinates(); - double d7 = blockposition.distanceSquared(d0, d1, d2); + double d3 = blockposition.distanceSquared(d0, d1, d2); - - this.a(entityplayer, flag, d0, d1, d2, packetplayoutworldparticles); + if (d3 > 1024.0D && (!flag || d3 > 262144.0D)) { + return false; + } else { + entityplayer.playerConnection.sendPacket(packet); + return true; + } } - - } - - public void a(EntityPlayer entityplayer, EnumParticle enumparticle, boolean flag, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, int... aint) { - PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(enumparticle, flag, (float) d0, (float) d1, (float) d2, (float) d3, (float) d4, (float) d5, (float) d6, i, aint); - - this.a(entityplayer, flag, d0, d1, d2, packetplayoutworldparticles); - } - - private void a(EntityPlayer entityplayer, boolean flag, double d0, double d1, double d2, Packet packet) { - BlockPosition blockposition = entityplayer.getChunkCoordinates(); - double d3 = blockposition.distanceSquared(d0, d1, d2); - - if (d3 <= 1024.0D || flag && d3 <= 262144.0D) { - entityplayer.playerConnection.sendPacket(packet); - } - } @Nullable public Entity getEntity(UUID uuid) { - return this.entitiesByUUID.get(uuid); + return (Entity) this.entitiesByUUID.get(uuid); } - @Override public ListenableFuture postToMainThread(Runnable runnable) { return this.server.postToMainThread(runnable); } - @Override public boolean isMainThread() { return this.server.isMainThread(); } - @Override @Nullable - public BlockPosition a(String s, BlockPosition blockposition, boolean flag) { - return this.getChunkProviderServer().a(this, s, blockposition, flag); + public BlockPosition a(String s, BlockPosition blockposition, int i) { + return this.getChunkProviderServer().a(this, s, blockposition, i); } - public AdvancementDataWorld z() { - return this.C; + public CraftingManager D() { + return this.server.getCraftingManager(); } - public CustomFunctionData A() { - return this.D; + public TagRegistry E() { + return this.server.getTagRegistry(); + } + + public Scoreboard getScoreboard() { + return this.l_(); } - @Override public IChunkProvider getChunkProvider() { return this.getChunkProviderServer(); } - static class BlockActionDataList extends ArrayList { + public TickList H() { + return this.x(); + } - private BlockActionDataList() {} - - BlockActionDataList(Object object) { - this(); - } + public TickList I() { + return this.w(); } } diff --git a/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 71583c422..f7c0b8fcd 100644 --- a/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -17,10 +17,9 @@ import java.util.List; import java.util.Map; import java.util.Set; 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.*; @@ -52,12 +51,10 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.conversations.Conversable; import org.bukkit.craftbukkit.boss.CraftBossBar; -import org.bukkit.craftbukkit.command.VanillaCommandWrapper; 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; @@ -123,14 +120,29 @@ 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.tree.CommandNode; +import com.mojang.brigadier.tree.LiteralCommandNode; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; -import io.netty.handler.codec.base64.Base64; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import org.bukkit.Keyed; import org.apache.commons.lang.StringUtils; import org.bukkit.NamespacedKey; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.command.BukkitCommandWrapper; +import org.bukkit.craftbukkit.command.CraftCommandMap; +import org.bukkit.craftbukkit.command.VanillaCommandWrapper; +import org.bukkit.craftbukkit.inventory.util.CraftInventoryCreator; +import org.bukkit.craftbukkit.tag.CraftBlockTag; +import org.bukkit.craftbukkit.tag.CraftItemTag; import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.event.server.TabCompleteEvent; import net.md_5.bungee.api.chat.BaseComponent; @@ -143,13 +155,13 @@ import javax.annotation.Nonnull; // Paper * 1) Guava -> Caffeine (performance) */ public final class CraftServer implements Server { - private final String serverName = "Paper"; + private final String serverName = "Paper"; // Paper private final String serverVersion; private final String bukkitVersion = Versioning.getBukkitVersion(); private final Logger logger = Logger.getLogger("Minecraft"); private final ServicesManager servicesManager = new SimpleServicesManager(); private final CraftScheduler scheduler = new CraftScheduler(); - private final SimpleCommandMap commandMap = new SimpleCommandMap(this); + private final CraftCommandMap commandMap = new CraftCommandMap(this); private final SimpleHelpMap helpMap = new SimpleHelpMap(this); private final StandardMessenger messenger = new StandardMessenger(); private final SimplePluginManager pluginManager = new SimplePluginManager(this, commandMap); @@ -177,8 +189,7 @@ public final class CraftServer implements Server { private boolean printSaveWarning; private CraftIconCache icon; private boolean overrideAllCommandBlockCommands = false; - private boolean unrestrictedAdvancements; - private boolean unrestrictedSignCommands; // Paper + public boolean ignoreVanillaPermissions = false; private final List playerView; public int reloadCount; public static Exception excessiveVelEx; // Paper - Velocity warnings @@ -256,13 +267,7 @@ public final class CraftServer implements Server { saveCommandsConfig(); overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); - unrestrictedAdvancements = commandsConfiguration.getBoolean("unrestricted-advancements"); - // Paper start - unrestrictedSignCommands = commandsConfiguration.getBoolean("unrestricted-signs"); - if (unrestrictedSignCommands) { - logger.warning("Warning: Commands are no longer restricted on signs. If you allow players to use Creative Mode, there may be risk of players bypassing permissions. Use this setting at your own risk!!!!"); - } - // Paper end + ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); pluginManager.useTimings(configuration.getBoolean("settings.plugin-profiling")); monsterSpawn = configuration.getInt("spawn-limits.monsters"); animalSpawn = configuration.getInt("spawn-limits.animals"); @@ -275,15 +280,6 @@ public final class CraftServer implements Server { loadIcon(); } - public boolean getPermissionOverride(ICommandListener listener) { - while (listener instanceof CommandListenerWrapper) { - listener = ((CommandListenerWrapper) listener).base; - } - - if (unrestrictedSignCommands && listener instanceof TileEntitySign.ISignCommandListener) return true; // Paper - return unrestrictedAdvancements && listener instanceof AdvancementRewards.AdvancementCommandListener; - } - public boolean getCommandBlockOverride(String command) { return overrideAllCommandBlockCommands || commandsConfiguration.getStringList("command-block-overrides").contains(command); } @@ -359,6 +355,7 @@ public final class CraftServer implements Server { DefaultPermissions.registerCorePermissions(); CraftDefaultPermissions.registerCorePermissions(); helpMap.initializeCommands(); + syncCommands(); } } @@ -367,10 +364,12 @@ public final class CraftServer implements Server { } private void setVanillaCommands(boolean first) { // Spigot - Map commands = new CommandDispatcher(console).getCommands(); - for (ICommand cmd : commands.values()) { + CommandDispatcher dispatcher = console.vanillaCommandDispatcher; + + // Build a list of all Vanilla commands and create wrappers + for (CommandNode cmd : dispatcher.a().getRoot().getChildren()) { // Spigot start - VanillaCommandWrapper wrapper = new VanillaCommandWrapper((CommandAbstract) cmd, LocaleI18n.get(cmd.getUsage(null))); + VanillaCommandWrapper wrapper = new VanillaCommandWrapper(dispatcher, cmd); if (org.spigotmc.SpigotConfig.replaceCommands.contains( wrapper.getName() ) ) { if (first) { commandMap.register("minecraft", wrapper); @@ -382,6 +381,38 @@ public final class CraftServer implements Server { } } + private void syncCommands() { + // Clear existing commands + CommandDispatcher dispatcher = console.commandDispatcher = new CommandDispatcher(); + + // Register all commands, vanilla ones will be using the old dispatcher references + for (Map.Entry entry : commandMap.getKnownCommands().entrySet()) { + String label = entry.getKey(); + Command command = entry.getValue(); + + if (command instanceof VanillaCommandWrapper) { + LiteralCommandNode node = (LiteralCommandNode) ((VanillaCommandWrapper) command).vanillaCommand; + if (!node.getLiteral().equals(label)) { + LiteralCommandNode clone = new LiteralCommandNode(label, node.getCommand(), node.getRequirement(), node.getRedirect(), node.getRedirectModifier(), node.isFork()); + + for (CommandNode child : node.getChildren()) { + clone.addChild(child); + } + node = clone; + } + + dispatcher.a().getRoot().addChild(node); + } else { + new BukkitCommandWrapper(this, entry.getValue()).register(dispatcher.a(), label); + } + } + + // Refresh commands + for (EntityPlayer player : getHandle().players) { + dispatcher.a(player); + } + } + private void enablePlugin(Plugin plugin) { try { List perms = plugin.getDescription().getPermissions(); @@ -661,6 +692,7 @@ public final class CraftServer implements Server { public boolean dispatchCommand(CommandSender sender, String commandLine) { Validate.notNull(sender, "Sender cannot be null"); Validate.notNull(commandLine, "CommandLine cannot be null"); + org.spigotmc.AsyncCatcher.catchOp( "command dispatch" ); // Spigot // Paper Start if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { @@ -690,7 +722,7 @@ public final class CraftServer implements Server { } // Spigot start - if (StringUtils.isNotEmpty(org.spigotmc.SpigotConfig.unknownCommandMessage)) { + if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { // Paper start UnknownCommandEvent event = new UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); Bukkit.getServer().getPluginManager().callEvent(event); @@ -781,6 +813,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.registerCommands(); // Spigot com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); + ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); int pollCount = 0; @@ -919,25 +952,7 @@ public final class CraftServer implements Server { generator = getGenerator(name); } - Convertable converter = new WorldLoaderServer(getWorldContainer(), getHandle().getServer().dataConverterManager); - if (converter.isConvertable(name)) { - getLogger().info("Converting world '" + name + "'"); - converter.convert(name, new IProgressUpdate() { - private long b = System.currentTimeMillis(); - - public void a(String s) {} - - public void a(int i) { - if (System.currentTimeMillis() - this.b >= 1000L) { - this.b = System.currentTimeMillis(); - MinecraftServer.LOGGER.info("Converting... " + i + "%"); - } - - } - - public void c(String s) {} - }); - } + console.convertWorld(name); int dimension = CraftWorld.CUSTOM_DIMENSION_OFFSET + console.worlds.size(); boolean used = false; @@ -952,12 +967,15 @@ public final class CraftServer implements Server { } while(used); boolean hardcore = false; - IDataManager sdm = new ServerNBTManager(getWorldContainer(), name, true, getHandle().getServer().dataConverterManager); + IDataManager sdm = new ServerNBTManager(getWorldContainer(), name, getServer(), getHandle().getServer().dataConverterManager); WorldData worlddata = sdm.getWorldData(); WorldSettings worldSettings = null; if (worlddata == null) { worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type); - worldSettings.setGeneratorSettings(creator.generatorSettings()); + JsonElement parsedSettings = new JsonParser().parse(creator.generatorSettings()); + if (parsedSettings.isJsonObject()) { + worldSettings.setGeneratorSettings(parsedSettings.getAsJsonObject()); + } 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) @@ -970,7 +988,6 @@ public final class CraftServer implements Server { if (worldSettings != null) { internal.a(worldSettings); } - internal.scoreboard = getScoreboardManager().getMainScoreboard().getHandle(); internal.tracker = new EntityTracker(internal); internal.addIWorldAccess(new WorldManager(console, internal)); @@ -1044,7 +1061,7 @@ public final class CraftServer implements Server { if (save) { try { handle.save(true, null); - handle.saveLevel(); + handle.close(); } catch (ExceptionWorldConflict ex) { getLogger().log(Level.SEVERE, null, ex); } @@ -1186,19 +1203,12 @@ public final class CraftServer implements Server { @Override public void clearRecipes() { - CraftingManager.recipes = new RegistryMaterials(); - RecipesFurnace.getInstance().recipes.clear(); - RecipesFurnace.getInstance().customRecipes.clear(); - RecipesFurnace.getInstance().customExperience.clear(); + console.getCraftingManager().recipes.clear(); } @Override public void resetRecipes() { - CraftingManager.recipes = new RegistryMaterials(); - CraftingManager.init(); - RecipesFurnace.getInstance().recipes = new RecipesFurnace().recipes; - RecipesFurnace.getInstance().customRecipes.clear(); - RecipesFurnace.getInstance().customExperience.clear(); + console.getCraftingManager().a(console.getResourceManager()); } @Override @@ -1303,7 +1313,7 @@ public final class CraftServer implements Server { @Deprecated public CraftMapView getMap(short id) { PersistentCollection collection = console.worlds.get(0).worldMaps; - WorldMap worldmap = (WorldMap) collection.get(WorldMap.class, "map_" + id); + WorldMap worldmap = (WorldMap) collection.get(WorldMap::new, "map_" + id); if (worldmap == null) { return null; } @@ -1314,8 +1324,8 @@ public final class CraftServer implements Server { public CraftMapView createMap(World world) { Validate.notNull(world, "World cannot be null"); - net.minecraft.server.ItemStack stack = new net.minecraft.server.ItemStack(Items.MAP, 1, -1); - WorldMap worldmap = Items.FILLED_MAP.getSavedMap(stack, ((CraftWorld) world).getHandle()); + net.minecraft.server.ItemStack stack = new net.minecraft.server.ItemStack(Items.MAP, 1); + WorldMap worldmap = ItemWorldMap.getSavedMap(stack, ((CraftWorld) world).getHandle()); return worldmap.mapView; } @@ -1591,25 +1601,26 @@ public final class CraftServer implements Server { @Override public Inventory createInventory(InventoryHolder owner, InventoryType type) { - // TODO: Create the appropriate type, rather than Custom? - return new CraftInventoryCustom(owner, type); + Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); + return CraftInventoryCreator.INSTANCE.createInventory(owner, type); } @Override public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - return new CraftInventoryCustom(owner, type, title); + Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); + return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); } @Override public Inventory createInventory(InventoryHolder owner, int size) throws IllegalArgumentException { Validate.isTrue(size % 9 == 0, "Chests must have a size that is a multiple of 9!"); - return new CraftInventoryCustom(owner, size); + return CraftInventoryCreator.INSTANCE.createInventory(owner, size); } @Override public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { Validate.isTrue(size % 9 == 0, "Chests must have a size that is a multiple of 9!"); - return new CraftInventoryCustom(owner, size, title); + return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); } @Override @@ -1662,26 +1673,26 @@ public final class CraftServer implements Server { return warningState; } - public List tabComplete(net.minecraft.server.ICommandListener sender, String message, BlockPosition pos, boolean forceCommand) { - if (!(sender instanceof EntityPlayer)) { + public List tabComplete(CommandSender sender, String message, WorldServer world, Vec3D pos, boolean forceCommand) { + if (!(sender instanceof Player)) { return ImmutableList.of(); } List offers; - Player player = ((EntityPlayer) sender).getBukkitEntity(); + Player player = (Player) sender; if (message.startsWith("/") || forceCommand) { - offers = tabCompleteCommand(player, message, pos); + offers = tabCompleteCommand(player, message, world, pos); } else { offers = tabCompleteChat(player, message); } - - TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), pos) : null); // Paper + + TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPosition(pos)) : null); // Paper getPluginManager().callEvent(tabEvent); return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); } - public List tabCompleteCommand(Player player, String message, BlockPosition pos) { + public List tabCompleteCommand(Player player, String message, WorldServer world, Vec3D pos) { // Spigot Start if ( (org.spigotmc.SpigotConfig.tabComplete < 0 || message.length() <= org.spigotmc.SpigotConfig.tabComplete) && !message.contains( " " ) ) { @@ -1698,7 +1709,7 @@ public final class CraftServer implements Server { if (pos == null) { completions = getCommandMap().tabComplete(player, message); } else { - completions = getCommandMap().tabComplete(player, message, new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ())); + completions = getCommandMap().tabComplete(player, message, new Location(world.getWorld(), pos.x, pos.y, pos.z)); } } catch (CommandException ex) { player.sendMessage(ChatColor.RED + "An internal error occurred while attempting to tab-complete this command"); @@ -1779,9 +1790,9 @@ public final class CraftServer implements Server { Validate.isTrue(image.getWidth() == 64, "Must be 64 pixels wide"); Validate.isTrue(image.getHeight() == 64, "Must be 64 pixels high"); ImageIO.write(image, "PNG", new ByteBufOutputStream(bytebuf)); - ByteBuf bytebuf1 = Base64.encode(bytebuf); + ByteBuffer bytebuffer = Base64.getEncoder().encode(bytebuf.nioBuffer()); - return new CraftIconCache("data:image/png;base64," + bytebuf1.toString(Charsets.UTF_8)); + return new CraftIconCache("data:image/png;base64," + StandardCharsets.UTF_8.decode(bytebuffer)); } @Override @@ -1796,6 +1807,7 @@ public final class CraftServer implements Server { @Override public ChunkGenerator.ChunkData createChunkData(World world) { + Validate.notNull(world, "World cannot be null"); return new CraftChunkData(world); } @@ -1807,8 +1819,15 @@ public final class CraftServer implements Server { @Override public Entity getEntity(UUID uuid) { Validate.notNull(uuid, "UUID cannot be null"); - net.minecraft.server.Entity entity = console.a(uuid); // PAIL: getEntity - return entity == null ? null : entity.getBukkitEntity(); + + for (WorldServer world : getServer().worlds) { + net.minecraft.server.Entity entity = world.getEntity(uuid); + if (entity != null) { + return entity.getBukkitEntity(); + } + } + + return null; } @Override @@ -1821,7 +1840,7 @@ public final class CraftServer implements Server { @Override public Iterator advancementIterator() { - return Iterators.unmodifiableIterator(Iterators.transform(console.getAdvancementData().c().iterator(), new Function() { // PAIL: rename + return Iterators.unmodifiableIterator(Iterators.transform(console.getAdvancementData().b().iterator(), new Function() { // PAIL: rename @Override public org.bukkit.advancement.Advancement apply(Advancement advancement) { return advancement.bukkit; @@ -1829,6 +1848,57 @@ public final class CraftServer implements Server { })); } + @Override + public BlockData createBlockData(org.bukkit.Material material) { + Validate.isTrue(material != null, "Must provide material"); + + return createBlockData(material, (String) null); + } + + @Override + public BlockData createBlockData(org.bukkit.Material material, Consumer consumer) { + BlockData data = createBlockData(material); + + if (consumer != null) { + consumer.accept(data); + } + + return data; + } + + @Override + public BlockData createBlockData(String data) throws IllegalArgumentException { + Validate.isTrue(data != null, "Must provide data"); + + return createBlockData(null, data); + } + + @Override + public BlockData createBlockData(org.bukkit.Material material, String data) { + Validate.isTrue(material != null || data != null, "Must provide one of material or data"); + + return CraftBlockData.newData(material, data); + } + + @Override + @SuppressWarnings("unchecked") + public org.bukkit.Tag getTag(String registry, NamespacedKey tag, Class clazz) { + MinecraftKey key = CraftNamespacedKey.toMinecraft(tag); + + switch (registry) { + case org.bukkit.Tag.REGISTRY_BLOCKS: + Preconditions.checkArgument(clazz == org.bukkit.Material.class, "Block namespace must have material type"); + + return (org.bukkit.Tag) new CraftBlockTag(console.getTagRegistry().a(), key); + case org.bukkit.Tag.REGISTRY_ITEMS: + Preconditions.checkArgument(clazz == org.bukkit.Material.class, "Item namespace must have material type"); + + return (org.bukkit.Tag) new CraftItemTag(console.getTagRegistry().b(), key); + default: + throw new IllegalArgumentException(); + } + } + @Deprecated @Override public UnsafeValues getUnsafe() { 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 78812800f..b56943664 100644 --- a/sources/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/sources/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -28,8 +28,48 @@ import java.util.logging.Level; import java.util.logging.Logger; import net.md_5.bungee.api.chat.BaseComponent; -import net.minecraft.server.*; -import net.minecraft.server.PacketPlayOutTitle.EnumTitleAction; +import net.minecraft.server.AdvancementDataPlayer; +import net.minecraft.server.AdvancementProgress; +import net.minecraft.server.AttributeInstance; +import net.minecraft.server.AttributeMapServer; +import net.minecraft.server.AttributeModifiable; +import net.minecraft.server.AttributeRanged; +import net.minecraft.server.BlockPosition; +import net.minecraft.server.ChatComponentText; +import net.minecraft.server.Container; +import net.minecraft.server.Entity; +import net.minecraft.server.EntityHuman; +import net.minecraft.server.EntityLiving; +import net.minecraft.server.EntityPlayer; +import net.minecraft.server.EntityTracker; +import net.minecraft.server.EntityTrackerEntry; +import net.minecraft.server.EnumChatFormat; +import net.minecraft.server.EnumGamemode; +import net.minecraft.server.IChatBaseComponent; +import net.minecraft.server.MapIcon; +import net.minecraft.server.MinecraftKey; +import net.minecraft.server.NBTTagCompound; +import net.minecraft.server.PacketDataSerializer; +import net.minecraft.server.PacketPlayOutBlockChange; +import net.minecraft.server.PacketPlayOutChat; +import net.minecraft.server.PacketPlayOutCustomPayload; +import net.minecraft.server.PacketPlayOutCustomSoundEffect; +import net.minecraft.server.PacketPlayOutMap; +import net.minecraft.server.PacketPlayOutNamedSoundEffect; +import net.minecraft.server.PacketPlayOutPlayerInfo; +import net.minecraft.server.PacketPlayOutPlayerListHeaderFooter; +import net.minecraft.server.PacketPlayOutSpawnPosition; +import net.minecraft.server.PacketPlayOutStopSound; +import net.minecraft.server.PacketPlayOutTitle; +import net.minecraft.server.PacketPlayOutUpdateAttributes; +import net.minecraft.server.PacketPlayOutUpdateHealth; +import net.minecraft.server.PacketPlayOutWorldEvent; +import net.minecraft.server.PacketPlayOutWorldParticles; +import net.minecraft.server.PlayerConnection; +import net.minecraft.server.TileEntitySign; +import net.minecraft.server.Vec3D; +import net.minecraft.server.WhiteListEntry; +import net.minecraft.server.WorldServer; import org.apache.commons.lang.Validate; import org.apache.commons.lang.NotImplementedException; @@ -40,12 +80,14 @@ import org.bukkit.Statistic; import org.bukkit.Material; import org.bukkit.Statistic.Type; import org.bukkit.World; +import org.bukkit.block.data.BlockData; import org.bukkit.configuration.serialization.DelegateDeserialization; import org.bukkit.conversations.Conversation; import org.bukkit.conversations.ConversationAbandonedEvent; import org.bukkit.conversations.ManuallyAbandonedConversationCanceller; -import org.bukkit.craftbukkit.*; +import org.bukkit.craftbukkit.CraftParticle; import org.bukkit.craftbukkit.block.CraftSign; +import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.conversations.ConversationTracker; import org.bukkit.craftbukkit.CraftEffect; import org.bukkit.craftbukkit.CraftOfflinePlayer; @@ -78,6 +120,7 @@ import javax.annotation.Nullable; /** * Akarin Changes Note * 1) Make hidden players thread-safe (safety issue) + * 2) Add locks for entry operation (safety issue) */ @DelegateDeserialization(CraftOfflinePlayer.class) public class CraftPlayer extends CraftHumanEntity implements Player { @@ -126,12 +169,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { perm.recalculatePermissions(); } - @Override public boolean isOnline() { return server.getPlayer(getUniqueId()) != null; } - @Override public InetSocketAddress getAddress() { if (getHandle().playerConnection == null) return null; @@ -193,7 +234,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void sendActionBar(String message) { if (getHandle().playerConnection == null || message == null || message.isEmpty()) return; - getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), ChatMessageType.GAME_INFO)); + getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new net.minecraft.server.ChatComponentText(message), net.minecraft.server.ChatMessageType.GAME_INFO)); } @Override @@ -300,14 +341,55 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (name == null) { name = getName(); } - getHandle().listName = name.equals(getName()) ? null : CraftChatMessage.fromString(name)[0]; - for (EntityPlayer player : server.getHandle().players) { + getHandle().listName = name.equals(getName()) ? null : CraftChatMessage.fromStringOrNull(name); + for (EntityPlayer player : (List)server.getHandle().players) { if (player.getBukkitEntity().canSee(this)) { player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle())); } } } + private IChatBaseComponent playerListHeader; + private IChatBaseComponent playerListFooter; + + @Override + public String getPlayerListHeader() { + return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); + } + + @Override + public String getPlayerListFooter() { + return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); + } + + @Override + public void setPlayerListHeader(String header) { + this.playerListHeader = CraftChatMessage.fromStringOrNull(header); + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListFooter(String footer) { + this.playerListFooter = CraftChatMessage.fromStringOrNull(footer); + updatePlayerListHeaderFooter(); + } + + @Override + public void setPlayerListHeaderFooter(String header, String footer) { + this.playerListHeader = CraftChatMessage.fromStringOrNull(header); + this.playerListFooter = CraftChatMessage.fromStringOrNull(footer); + updatePlayerListHeaderFooter(); + } + + private void updatePlayerListHeaderFooter() { + 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; + getHandle().playerConnection.sendPacket(packet); + } + @Override public boolean equals(Object obj) { if (!(obj instanceof OfflinePlayer)) { @@ -400,7 +482,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } float f = (float) Math.pow(2.0D, (note - 12.0D) / 12.0D); - getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note." + instrumentName), net.minecraft.server.SoundCategory.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f)); + getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note_block." + instrumentName), net.minecraft.server.SoundCategory.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f)); } @Override @@ -441,7 +523,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { break; } float f = (float) Math.pow(2.0D, (note.getId() - 12.0D) / 12.0D); - getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note." + instrumentName), net.minecraft.server.SoundCategory.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f)); + getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note_block." + instrumentName), net.minecraft.server.SoundCategory.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f)); } @Override @@ -466,7 +548,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void playSound(Location loc, String sound, org.bukkit.SoundCategory category, float volume, float pitch) { if (loc == null || sound == null || category == null || getHandle().playerConnection == null) return; - PacketPlayOutCustomSoundEffect packet = new PacketPlayOutCustomSoundEffect(sound, net.minecraft.server.SoundCategory.valueOf(category.name()), loc.getX(), loc.getY(), loc.getZ(), volume, pitch); + PacketPlayOutCustomSoundEffect packet = new PacketPlayOutCustomSoundEffect(new MinecraftKey(sound), net.minecraft.server.SoundCategory.valueOf(category.name()), new Vec3D(loc.getX(), loc.getY(), loc.getZ()), volume, pitch); getHandle().playerConnection.sendPacket(packet); } @@ -488,18 +570,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void stopSound(String sound, org.bukkit.SoundCategory category) { if (getHandle().playerConnection == null) return; - PacketDataSerializer packetdataserializer = new PacketDataSerializer(Unpooled.buffer()); - packetdataserializer.a(category == null ? "" : net.minecraft.server.SoundCategory.valueOf(category.name()).a()); - packetdataserializer.a(sound); - getHandle().playerConnection.sendPacket(new PacketPlayOutCustomPayload("MC|StopSound", packetdataserializer)); + getHandle().playerConnection.sendPacket(new PacketPlayOutStopSound(new MinecraftKey(sound), category == null ? net.minecraft.server.SoundCategory.MASTER : net.minecraft.server.SoundCategory.valueOf(category.name()))); } @Override public void playEffect(Location loc, Effect effect, int data) { if (getHandle().playerConnection == null) return; - spigot().playEffect(loc, effect, data, 0, 0, 0, 0, 1, 1, 64); // Spigot + int packetData = effect.getId(); + PacketPlayOutWorldEvent packet = new PacketPlayOutWorldEvent(packetData, new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), data, false); + getHandle().playerConnection.sendPacket(packet); } @Override @@ -516,16 +597,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void sendBlockChange(Location loc, Material material, byte data) { - sendBlockChange(loc, material.getId(), data); - } - - @Override - public void sendBlockChange(Location loc, int material, byte data) { if (getHandle().playerConnection == null) return; PacketPlayOutBlockChange packet = new PacketPlayOutBlockChange(((CraftWorld) loc.getWorld()).getHandle(), new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); - packet.block = CraftMagicNumbers.getBlock(material).fromLegacyData(data); + packet.block = CraftMagicNumbers.getBlock(material, data); + getHandle().playerConnection.sendPacket(packet); + } + + @Override + public void sendBlockChange(Location loc, BlockData block) { + if (getHandle().playerConnection == null) return; + + PacketPlayOutBlockChange packet = new PacketPlayOutBlockChange(((CraftWorld) loc.getWorld()).getHandle(), new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); + + packet.block = ((CraftBlockData) block).getState(); getHandle().playerConnection.sendPacket(packet); } @@ -594,7 +680,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { Collection icons = new ArrayList(); for (MapCursor cursor : data.cursors) { if (cursor.isVisible()) { - icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection())); + icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); } } @@ -604,6 +690,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { + Preconditions.checkArgument(location != null, "location"); + Preconditions.checkArgument(location.getWorld() != null, "location.world"); + location.checkFinite(); + EntityPlayer entity = getHandle(); if (getHealth() == 0 || entity.dead) { @@ -908,9 +998,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setWhitelisted(boolean value) { if (value) { - server.getHandle().addWhitelist(getProfile()); + server.getHandle().getWhitelist().add(new WhiteListEntry(getProfile())); } else { - server.getHandle().removeWhitelist(getProfile()); + server.getHandle().getWhitelist().remove(getProfile()); } } @@ -935,10 +1025,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public int applyMending(int amount) { EntityPlayer handle = getHandle(); // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties - ItemStack itemstack = EnchantmentManager.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); - if (!itemstack.isEmpty() && itemstack.hasDamage()) { + net.minecraft.server.ItemStack itemstack = net.minecraft.server.EnchantmentManager.getRandomEquippedItemWithEnchant(net.minecraft.server.Enchantments.MENDING, handle); + if (!itemstack.isEmpty() && itemstack.getItem().usesDurability()) { - EntityExperienceOrb orb = new EntityExperienceOrb(handle.world); + net.minecraft.server.EntityExperienceOrb orb = new net.minecraft.server.EntityExperienceOrb(handle.world); orb.value = amount; orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; orb.locX = handle.locX; @@ -1107,10 +1197,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { EntityTracker tracker = ((WorldServer) entity.world).tracker; // Paper end + tracker.entriesLock.updateLock().lock(); // Akarin EntityTrackerEntry entry = tracker.trackedEntities.get(other.getId()); if (entry != null) { + tracker.entriesLock.writeLock().lock(); // Akarin entry.clear(getHandle()); + tracker.entriesLock.writeLock().unlock(); // Akarin } + tracker.entriesLock.updateLock().unlock(); // Akarin // Remove the hidden player from this player user list, if they're on it if (other.sentListPacket) { @@ -1157,12 +1251,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, other)); + tracker.entriesLock.updateLock().lock(); // Akarin EntityTrackerEntry entry = tracker.trackedEntities.get(other.getId()); if (entry != null && !entry.trackedPlayers.contains(getHandle())) { - tracker.entriesLock.lock(); // Akarin + tracker.entriesLock.writeLock().lock(); // Akarin entry.updatePlayer(getHandle()); - tracker.entriesLock.unlock(); // Akarin + tracker.entriesLock.writeLock().unlock(); // Akarin } + tracker.entriesLock.updateLock().unlock(); // Akarin } // Paper start private void reregisterPlayer(EntityPlayer player) { @@ -1171,7 +1267,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { registerPlayer(player); } } - @Override public void setPlayerProfile(PlayerProfile profile) { EntityPlayer self = getHandle(); self.setProfile(CraftPlayerProfile.asAuthlibCopy(profile)); @@ -1181,7 +1276,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } refreshPlayer(); } - @Override public PlayerProfile getPlayerProfile() { return new CraftPlayerProfile(this).clone(); } @@ -1195,10 +1289,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { reregisterPlayer(handle); //Respawn the player then update their position and selected slot - connection.sendPacket(new PacketPlayOutRespawn(handle.dimension, handle.world.getDifficulty(), handle.world.getWorldData().getType(), handle.playerInteractManager.getGameMode())); + connection.sendPacket(new net.minecraft.server.PacketPlayOutRespawn(handle.dimension, handle.world.getDifficulty(), handle.world.getWorldData().getType(), handle.playerInteractManager.getGameMode())); handle.updateAbilities(); - connection.sendPacket(new PacketPlayOutPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); - MinecraftServer.getServer().getPlayerList().updateClient(handle); + connection.sendPacket(new net.minecraft.server.PacketPlayOutPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); + net.minecraft.server.MinecraftServer.getServer().getPlayerList().updateClient(handle); if (this.isOp()) { this.setOp(false); @@ -1340,7 +1434,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (getHandle().playerConnection == null) return; if (channels.contains(channel)) { - PacketPlayOutCustomPayload packet = new PacketPlayOutCustomPayload(channel, new PacketDataSerializer(Unpooled.wrappedBuffer(message))); + channel = StandardMessenger.validateAndCorrectChannel(channel); + PacketPlayOutCustomPayload packet = new PacketPlayOutCustomPayload(new MinecraftKey(channel), new PacketDataSerializer(Unpooled.wrappedBuffer(message))); getHandle().playerConnection.sendPacket(packet); } } @@ -1367,13 +1462,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void addChannel(String channel) { - com.google.common.base.Preconditions.checkState( DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Too many channels registered" ); // Spigot // Paper - flag to disable channel limit + com.google.common.base.Preconditions.checkState( DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Too many channels registered" ); // Spigot // Paper - flag to disable channel limit + channel = StandardMessenger.validateAndCorrectChannel(channel); if (channels.add(channel)) { server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); } } public void removeChannel(String channel) { + channel = StandardMessenger.validateAndCorrectChannel(channel); if (channels.remove(channel)) { server.getPluginManager().callEvent(new PlayerUnregisterChannelEvent(this, channel)); } @@ -1400,7 +1497,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } - getHandle().playerConnection.sendPacket(new PacketPlayOutCustomPayload("REGISTER", new PacketDataSerializer(Unpooled.wrappedBuffer(stream.toByteArray())))); + getHandle().playerConnection.sendPacket(new PacketPlayOutCustomPayload(new MinecraftKey("register"), new PacketDataSerializer(Unpooled.wrappedBuffer(stream.toByteArray())))); } } @@ -1437,7 +1534,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } // Paper start if (prop == Property.REPAIR_COST && container instanceof net.minecraft.server.ContainerAnvil) { - ((ContainerAnvil) container).levelCost = value; + ((net.minecraft.server.ContainerAnvil) container).levelCost = value; } // Paper end getHandle().setContainerData(container, prop.getId(), value); @@ -1508,7 +1605,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public float getFlySpeed() { - return getHandle().abilities.flySpeed * 2f; + return (float) getHandle().abilities.flySpeed * 2f; } @Override @@ -1610,7 +1707,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(getHandle().getId(), set)); sendHealthUpdate(); } - getHandle().getDataWatcher().set(EntityLiving.HEALTH, getScaledHealth()); + getHandle().getDataWatcher().set(EntityLiving.HEALTH, (float) getScaledHealth()); getHandle().maxHealthCache = getMaxHealth(); } @@ -1663,19 +1760,19 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getHandle().playerConnection.sendPacket(times); if (title != null) { - PacketPlayOutTitle packetTitle = new PacketPlayOutTitle(EnumTitleAction.TITLE, CraftChatMessage.fromString(title)[0]); + PacketPlayOutTitle packetTitle = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, CraftChatMessage.fromStringOrNull(title)); getHandle().playerConnection.sendPacket(packetTitle); } if (subtitle != null) { - PacketPlayOutTitle packetSubtitle = new PacketPlayOutTitle(EnumTitleAction.SUBTITLE, CraftChatMessage.fromString(subtitle)[0]); + PacketPlayOutTitle packetSubtitle = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, CraftChatMessage.fromStringOrNull(subtitle)); getHandle().playerConnection.sendPacket(packetSubtitle); } } @Override public void resetTitle() { - PacketPlayOutTitle packetReset = new PacketPlayOutTitle(EnumTitleAction.RESET, null); + PacketPlayOutTitle packetReset = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.RESET, null); getHandle().playerConnection.sendPacket(packetReset); } @@ -1739,7 +1836,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (data != null && !particle.getDataType().isInstance(data)) { throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); } - PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count, CraftParticle.toData(particle, data)); + PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); getHandle().playerConnection.sendPacket(packetplayoutworldparticles); } @@ -1763,7 +1860,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper end } - @Override + // Paper start public void setAffectsSpawning(boolean affects) { this.getHandle().affectsSpawning = affects; } @@ -1772,6 +1869,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public boolean getAffectsSpawning() { return this.getHandle().affectsSpawning; } + // Paper end @Override public int getViewDistance() { @@ -1838,63 +1936,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } - @Override - public void playEffect( Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius ) - { - Validate.notNull( location, "Location cannot be null" ); - Validate.notNull( effect, "Effect cannot be null" ); - Validate.notNull( location.getWorld(), "World cannot be null" ); - Packet packet; - if ( effect.getType() != Effect.Type.PARTICLE ) - { - int packetData = effect.getId(); - packet = new PacketPlayOutWorldEvent( packetData, new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ() ), id, false ); - } else - { - net.minecraft.server.EnumParticle particle = null; - int[] extra = null; - for ( net.minecraft.server.EnumParticle p : net.minecraft.server.EnumParticle.values() ) - { - if ( effect.getName().startsWith( p.b().replace("_", "") ) ) - { - particle = p; - if ( effect.getData() != null ) - { - if ( effect.getData().equals( org.bukkit.Material.class ) ) - { - extra = new int[]{ id }; - } else - { - extra = new int[]{ (data << 12) | (id & 0xFFF) }; - } - } - break; - } - } - if ( extra == null ) - { - extra = new int[0]; - } - packet = new PacketPlayOutWorldParticles( particle, true, (float) location.getX(), (float) location.getY(), (float) location.getZ(), offsetX, offsetY, offsetZ, speed, particleCount, extra ); - } - int distance; - radius *= radius; - if ( getHandle().playerConnection == null ) - { - return; - } - if ( !location.getWorld().equals( getWorld() ) ) - { - return; - } - - distance = (int) getLocation().distanceSquared( location ); - if ( distance <= radius ) - { - getHandle().playerConnection.sendPacket( packet ); - } - } - @Override public String getLocale() { @@ -1922,7 +1963,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void sendMessage(BaseComponent... components) { if ( getHandle().playerConnection == null ) return; - PacketPlayOutChat packet = new PacketPlayOutChat(null, ChatMessageType.CHAT); + PacketPlayOutChat packet = new PacketPlayOutChat(null, net.minecraft.server.ChatMessageType.CHAT); packet.components = components; getHandle().playerConnection.sendPacket(packet); } @@ -1936,7 +1977,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void sendMessage(net.md_5.bungee.api.ChatMessageType position, BaseComponent... components) { if ( getHandle().playerConnection == null ) return; - PacketPlayOutChat packet = new PacketPlayOutChat(null, ChatMessageType.a((byte) position.ordinal())); + PacketPlayOutChat packet = new PacketPlayOutChat(null, net.minecraft.server.ChatMessageType.a((byte) position.ordinal())); // Action bar doesn't render colours, replace colours with legacy section symbols if (position == net.md_5.bungee.api.ChatMessageType.ACTION_BAR) { components = new BaseComponent[]{new net.md_5.bungee.api.chat.TextComponent(BaseComponent.toLegacyText(components))}; @@ -1952,7 +1993,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } }; - @Override public Player.Spigot spigot() { return spigot; diff --git a/sources/src/main/resources/configurations/bukkit.yml b/sources/src/main/resources/configurations/bukkit.yml index 334a8107e..8c8e1a977 100644 --- a/sources/src/main/resources/configurations/bukkit.yml +++ b/sources/src/main/resources/configurations/bukkit.yml @@ -19,7 +19,7 @@ settings: update-folder: update plugin-profiling: false connection-throttle: 4000 - query-plugins: false + query-plugins: true deprecated-verbose: default shutdown-message: "Server closed" spawn-limits: diff --git a/sources/src/main/resources/mixins.akarin.core.json b/sources/src/main/resources/mixins.akarin.core.json index 98c68e838..62caecdf8 100644 --- a/sources/src/main/resources/mixins.akarin.core.json +++ b/sources/src/main/resources/mixins.akarin.core.json @@ -9,18 +9,14 @@ "bootstrap.Bootstrap", "bootstrap.DummyEula", "bootstrap.MixinMetrics", - "bootstrap.ParallelRegistry", "bootstrap.MetricsBootstrap", "bootstrap.MixinRestartCommand", - "core.MixinWorld", "core.MixinMCUtil", - "core.MixinCommandBan", - "core.MixinCommandKick", "core.MixinCraftServer", "core.MixinWorldServer", + "core.MixinFileIOThread", "core.MixinWorldManager", - "core.MixinCommandBanIp", "core.MixinChunkSection", "core.MixinAsyncCatcher", "core.MixinTimingHandler", @@ -30,12 +26,9 @@ "core.MixinChunkIOExecutor", "core.MixinPlayerConnectionUtils", - "nsc.OptimisticNetworkManager", "nsc.NonblockingServerConnection", "optimization.MixinEntity", - "optimization.WeakBigTree", - "optimization.WeakEnchantmentManager", "optimization.MixinEntityHorseAbstract", "optimization.MixinEntityTameableAnimal", "optimization.MixinPersistentCollection", diff --git a/sources/src/main/resources/mixins.akarin.optimization.lighting.json b/sources/src/main/resources/mixins.akarin.optimization.lighting.json deleted file mode 100644 index 28cc496c4..000000000 --- a/sources/src/main/resources/mixins.akarin.optimization.lighting.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "required": true, - "minVersion": "0.7.10", - "package": "io.akarin.server.mixin", - "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8", - "server": [ - "cps.MixinChunk", - - "lighting.MixinChunk", - "lighting.MixinWorld", - "lighting.MixinWorldServer", - "lighting.MixinChunkProviderServer", - ] -} \ No newline at end of file diff --git a/sources/src/main/resources/mixins.akarin.optimization.pandawire.json b/sources/src/main/resources/mixins.akarin.optimization.pandawire.json deleted file mode 100644 index 794ce2fdb..000000000 --- a/sources/src/main/resources/mixins.akarin.optimization.pandawire.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "required": true, - "minVersion": "0.7.10", - "package": "io.akarin.server.mixin", - "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8", - "server": [ - "optimization.PandaRedstoneWire", - ] -} \ No newline at end of file diff --git a/sources/src/main/resources/mixins.akarin.optimization.realtime.json b/sources/src/main/resources/mixins.akarin.optimization.realtime.json deleted file mode 100644 index e87c12e8c..000000000 --- a/sources/src/main/resources/mixins.akarin.optimization.realtime.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "required": true, - "minVersion": "0.7.10", - "package": "io.akarin.server.mixin", - "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8", - "server": [ - "realtime.MixinWorld", - "realtime.MixinEntity", - "realtime.MixinEntityItem", - "realtime.MixinWorldServer", - "realtime.MixinEntityHuman", - "realtime.MixinEntityPlayer", - "realtime.MixinEntityAgeable", - "realtime.MixinMinecraftServer", - "realtime.MixinEntityInsentient", - "realtime.MixinPlayerConnection", - "realtime.MixinTileEntityFurnace", - "realtime.MixinEntityExperienceOrb", - "realtime.MixinEntityZombieVillager", - "realtime.MixinPlayerInteractManager", - "realtime.MixinTileEntityBrewingStand", - ] -} \ No newline at end of file diff --git a/work/Paper b/work/Paper index 8b96ee7ea..98b996cf4 160000 --- a/work/Paper +++ b/work/Paper @@ -1 +1 @@ -Subproject commit 8b96ee7ea8d947a979896eb7a1353c7e8f1479f6 +Subproject commit 98b996cf40831c2d6cc0453b77d292da7503d0bc