From 0c1d58f235ef23e26e7baa3b3183c251c14a4d72 Mon Sep 17 00:00:00 2001 From: Villagers654 Date: Sun, 4 Jun 2023 00:54:22 +0900 Subject: [PATCH 1/5] Removing timings --- src/main/java/cn/nukkit/level/Level.java | 48 ---- src/main/java/cn/nukkit/timings/JsonUtil.java | 72 ----- .../java/cn/nukkit/timings/LevelTimings.java | 47 --- .../aikar/timings/FullServerTickTiming.java | 108 ------- src/main/java/co/aikar/timings/Timing.java | 169 ----------- .../java/co/aikar/timings/TimingData.java | 91 ------ .../co/aikar/timings/TimingIdentifier.java | 82 ------ src/main/java/co/aikar/timings/Timings.java | 256 ----------------- .../java/co/aikar/timings/TimingsExport.java | 272 ------------------ .../java/co/aikar/timings/TimingsHistory.java | 221 -------------- .../co/aikar/timings/TimingsHistoryEntry.java | 49 ---- .../java/co/aikar/timings/TimingsManager.java | 138 --------- 12 files changed, 1553 deletions(-) delete mode 100644 src/main/java/cn/nukkit/timings/JsonUtil.java delete mode 100644 src/main/java/cn/nukkit/timings/LevelTimings.java delete mode 100644 src/main/java/co/aikar/timings/FullServerTickTiming.java delete mode 100644 src/main/java/co/aikar/timings/Timing.java delete mode 100644 src/main/java/co/aikar/timings/TimingData.java delete mode 100644 src/main/java/co/aikar/timings/TimingIdentifier.java delete mode 100644 src/main/java/co/aikar/timings/Timings.java delete mode 100644 src/main/java/co/aikar/timings/TimingsExport.java delete mode 100644 src/main/java/co/aikar/timings/TimingsHistory.java delete mode 100644 src/main/java/co/aikar/timings/TimingsHistoryEntry.java delete mode 100644 src/main/java/co/aikar/timings/TimingsManager.java diff --git a/src/main/java/cn/nukkit/level/Level.java b/src/main/java/cn/nukkit/level/Level.java index e4b8f62eadb..5dd10eec565 100644 --- a/src/main/java/cn/nukkit/level/Level.java +++ b/src/main/java/cn/nukkit/level/Level.java @@ -53,10 +53,7 @@ import cn.nukkit.potion.Effect; import cn.nukkit.scheduler.AsyncTask; import cn.nukkit.scheduler.BlockUpdateScheduler; -import cn.nukkit.timings.LevelTimings; import cn.nukkit.utils.*; -import co.aikar.timings.Timings; -import co.aikar.timings.TimingsHistory; import com.google.common.base.Preconditions; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; @@ -222,8 +219,6 @@ public int size() { private static final int LCG_CONSTANT = 1013904223; - public LevelTimings timings; - private int tickRate; public int tickRateTime = 0; public int tickRateCounter = 0; @@ -278,8 +273,6 @@ public Level(Server server, String name, String path, Class(this.updateEntities.keySet())) { Entity entity = this.updateEntities.get(id); @@ -835,16 +819,10 @@ public void doTick(int currentTick) { } } } - this.timings.entityTick.stopTiming(); - TimingsHistory.tileEntityTicks += this.updateBlockEntities.size(); - this.timings.blockEntityTick.startTiming(); this.updateBlockEntities.removeIf(blockEntity -> !blockEntity.isValid() || !blockEntity.onUpdate()); - this.timings.blockEntityTick.stopTiming(); - this.timings.tickChunks.startTiming(); this.tickChunks(); - this.timings.tickChunks.stopTiming(); synchronized (changedBlocks) { if (!this.changedBlocks.isEmpty()) { @@ -905,8 +883,6 @@ public void doTick(int currentTick) { Server.broadcastPacket(players.values().toArray(new Player[0]), packet); gameRules.refresh(); } - - this.timings.doTick.stopTiming(); } private void performThunder(long index, FullChunk chunk) { @@ -2481,7 +2457,6 @@ public void generateChunkCallback(int x, int z, BaseFullChunk chunk) { } public void generateChunkCallback(int x, int z, BaseFullChunk chunk, boolean isPopulated) { - Timings.generationCallbackTimer.startTiming(); long index = Level.chunkHash(x, z); if (this.chunkPopulationQueue.containsKey(index)) { FullChunk oldChunk = this.getChunk(x, z, false); @@ -2511,7 +2486,6 @@ public void generateChunkCallback(int x, int z, BaseFullChunk chunk, boolean isP chunk.setProvider(this.provider); this.setChunk(x, z, chunk, false); } - Timings.generationCallbackTimer.stopTiming(); } @Override @@ -2663,7 +2637,6 @@ private void sendChunk(int x, int z, long index, DataPacket packet) { } private void processChunkRequest() { - this.timings.syncChunkSendTimer.startTiming(); for (long index : this.chunkSendQueue.keySet()) { if (this.chunkSendTasks.contains(index)) { continue; @@ -2679,18 +2652,14 @@ private void processChunkRequest() { continue; } } - this.timings.syncChunkSendPrepareTimer.startTiming(); AsyncTask task = this.provider.requestChunkTask(x, z); if (task != null) { this.server.getScheduler().scheduleAsyncTask(task); } - this.timings.syncChunkSendPrepareTimer.stopTiming(); } - this.timings.syncChunkSendTimer.stopTiming(); } public void chunkRequestCallback(long timestamp, int x, int z, int subChunkCount, byte[] payload) { - this.timings.syncChunkSendTimer.startTiming(); long index = Level.chunkHash(x, z); if (this.cacheChunks) { @@ -2700,7 +2669,6 @@ public void chunkRequestCallback(long timestamp, int x, int z, int subChunkCount chunk.setChunkPacket(data); } this.sendChunk(x, z, index, data); - this.timings.syncChunkSendTimer.stopTiming(); return; } @@ -2714,7 +2682,6 @@ public void chunkRequestCallback(long timestamp, int x, int z, int subChunkCount this.chunkSendQueue.remove(index); this.chunkSendTasks.remove(index); } - this.timings.syncChunkSendTimer.stopTiming(); } public void removeEntity(Entity entity) { @@ -2787,13 +2754,11 @@ public boolean loadChunk(int x, int z, boolean generate) { } private synchronized BaseFullChunk forceLoadChunk(long index, int x, int z, boolean generate) { - this.timings.syncChunkLoadTimer.startTiming(); BaseFullChunk chunk = this.provider.getChunk(x, z, generate); if (chunk == null) { if (generate) { throw new IllegalStateException("Could not create new Chunk"); } - this.timings.syncChunkLoadTimer.stopTiming(); return chunk; } @@ -2801,7 +2766,6 @@ private synchronized BaseFullChunk forceLoadChunk(long index, int x, int z, bool this.server.getPluginManager().callEvent(new ChunkLoadEvent(chunk, !chunk.isGenerated())); } else { this.unloadChunk(x, z, false); - this.timings.syncChunkLoadTimer.stopTiming(); return chunk; } @@ -2820,7 +2784,6 @@ private synchronized BaseFullChunk forceLoadChunk(long index, int x, int z, bool } else { this.unloadQueue.put(index, System.currentTimeMillis()); } - this.timings.syncChunkLoadTimer.stopTiming(); return chunk; } @@ -2868,15 +2831,12 @@ public synchronized boolean unloadChunk(int x, int z, boolean safe, boolean tryS return true; } - this.timings.doChunkUnload.startTiming(); - BaseFullChunk chunk = this.getChunk(x, z); if (chunk != null && chunk.getProvider() != null) { ChunkUnloadEvent ev = new ChunkUnloadEvent(chunk); this.server.getPluginManager().callEvent(ev); if (ev.isCancelled()) { - this.timings.doChunkUnload.stopTiming(); return false; } } @@ -2908,8 +2868,6 @@ public synchronized boolean unloadChunk(int x, int z, boolean safe, boolean tryS logger.logException(e); } - this.timings.doChunkUnload.stopTiming(); - return true; } @@ -3028,7 +2986,6 @@ public boolean populateChunk(int x, int z, boolean force) { BaseFullChunk chunk = this.getChunk(x, z, true); boolean populate; if (!chunk.isPopulated()) { - Timings.populationTimer.startTiming(); populate = true; for (int xx = -1; xx <= 1; ++xx) { for (int zz = -1; zz <= 1; ++zz) { @@ -3053,7 +3010,6 @@ public boolean populateChunk(int x, int z, boolean force) { this.server.getScheduler().scheduleAsyncTask(task); } } - Timings.populationTimer.stopTiming(); return false; } @@ -3071,11 +3027,9 @@ public void generateChunk(int x, int z, boolean force) { long index = Level.chunkHash(x, z); if (!this.chunkGenerationQueue.containsKey(index)) { - Timings.generationTimer.startTiming(); this.chunkGenerationQueue.put(index, Boolean.TRUE); GenerationTask task = new GenerationTask(this, this.getChunk(x, z, true)); this.server.getScheduler().scheduleAsyncTask(task); - Timings.generationTimer.stopTiming(); } } @@ -3091,7 +3045,6 @@ public void regenerateChunk(int x, int z) { } public void doChunkGarbageCollection() { - this.timings.doChunkGC.startTiming(); // remove all invaild block entities. if (!blockEntities.isEmpty()) { ObjectIterator iter = blockEntities.values().iterator(); @@ -3121,7 +3074,6 @@ public void doChunkGarbageCollection() { } this.provider.doGarbageCollection(); - this.timings.doChunkGC.stopTiming(); } public void doGarbageCollection(long allocatedTime) { diff --git a/src/main/java/cn/nukkit/timings/JsonUtil.java b/src/main/java/cn/nukkit/timings/JsonUtil.java deleted file mode 100644 index 104ffd0eb8f..00000000000 --- a/src/main/java/cn/nukkit/timings/JsonUtil.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.nukkit.timings; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import java.util.*; -import java.util.function.Function; - -/** - * @author Tee7even - *

- * Various methods for more compact JSON object constructing - */ -@SuppressWarnings("unchecked") -public class JsonUtil { - private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); - - public static JsonArray toArray(Object... objects) { - List array = new ArrayList(); - Collections.addAll(array, objects); - return GSON.toJsonTree(array).getAsJsonArray(); - } - - public static JsonObject toObject(Object object) { - return GSON.toJsonTree(object).getAsJsonObject(); - } - - public static JsonObject mapToObject(Iterable collection, Function mapper) { - Map object = new LinkedHashMap(); - for (E e : collection) { - JSONPair pair = mapper.apply(e); - if (pair != null) { - object.put(pair.key, pair.value); - } - } - return GSON.toJsonTree(object).getAsJsonObject(); - } - - public static JsonArray mapToArray(E[] elements, Function mapper) { - ArrayList array = new ArrayList(); - Collections.addAll(array, elements); - return mapToArray(array, mapper); - } - - public static JsonArray mapToArray(Iterable collection, Function mapper) { - List array = new ArrayList(); - for (E e : collection) { - Object obj = mapper.apply(e); - if (obj != null) { - array.add(obj); - } - } - return GSON.toJsonTree(array).getAsJsonArray(); - } - - public static class JSONPair { - public final String key; - public final Object value; - - public JSONPair(String key, Object value) { - this.key = key; - this.value = value; - } - - public JSONPair(int key, Object value) { - this.key = String.valueOf(key); - this.value = value; - } - } -} diff --git a/src/main/java/cn/nukkit/timings/LevelTimings.java b/src/main/java/cn/nukkit/timings/LevelTimings.java deleted file mode 100644 index be2416b236d..00000000000 --- a/src/main/java/cn/nukkit/timings/LevelTimings.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.nukkit.timings; - -import cn.nukkit.level.Level; -import co.aikar.timings.Timing; -import co.aikar.timings.TimingsManager; - -/** - * @author Pub4Game - * @author Tee7even - */ -public class LevelTimings { - public final Timing doChunkUnload; - public final Timing doTickPending; - public final Timing doChunkGC; - public final Timing doTick; - - public final Timing tickChunks; - public final Timing entityTick; - public final Timing blockEntityTick; - - public final Timing syncChunkSendTimer; - public final Timing syncChunkSendPrepareTimer; - public final Timing syncChunkLoadTimer; - public final Timing syncChunkLoadDataTimer; - public final Timing syncChunkLoadEntitiesTimer; - public final Timing syncChunkLoadBlockEntitiesTimer; - - public LevelTimings(Level level) { - String name = level.getFolderName() + " - "; - - this.doChunkUnload = TimingsManager.getTiming(name + "doChunkUnload"); - this.doTickPending = TimingsManager.getTiming(name + "doTickPending"); - this.doChunkGC = TimingsManager.getTiming(name + "doChunkGC"); - this.doTick = TimingsManager.getTiming(name + "doTick"); - - this.tickChunks = TimingsManager.getTiming(name + "tickChunks"); - this.entityTick = TimingsManager.getTiming(name + "entityTick"); - this.blockEntityTick = TimingsManager.getTiming(name + "blockEntityTick"); - - this.syncChunkSendTimer = TimingsManager.getTiming(name + "syncChunkSend"); - this.syncChunkSendPrepareTimer = TimingsManager.getTiming(name + "syncChunkSendPrepare"); - this.syncChunkLoadTimer = TimingsManager.getTiming(name + "syncChunkLoad"); - this.syncChunkLoadDataTimer = TimingsManager.getTiming(name + "syncChunkLoad - Data"); - this.syncChunkLoadEntitiesTimer = TimingsManager.getTiming(name + "syncChunkLoad - Entities"); - this.syncChunkLoadBlockEntitiesTimer = TimingsManager.getTiming(name + "syncChunkLoad - BlockEntities"); - } -} diff --git a/src/main/java/co/aikar/timings/FullServerTickTiming.java b/src/main/java/co/aikar/timings/FullServerTickTiming.java deleted file mode 100644 index 66526bf8ec6..00000000000 --- a/src/main/java/co/aikar/timings/FullServerTickTiming.java +++ /dev/null @@ -1,108 +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 static co.aikar.timings.TimingIdentifier.DEFAULT_GROUP; -import static co.aikar.timings.TimingsManager.*; - -public class FullServerTickTiming extends Timing { - private static final TimingIdentifier IDENTIFIER = new TimingIdentifier(DEFAULT_GROUP.name, "Full Server Tick", null); - final TimingData minuteData; - double avgFreeMemory = -1D; - double avgUsedMemory = -1D; - - FullServerTickTiming() { - super(IDENTIFIER); - this.minuteData = new TimingData(this.id); - - TIMING_MAP.put(IDENTIFIER, this); - } - - @Override - public Timing startTiming() { - if (TimingsManager.needsFullReset) { - TimingsManager.resetTimings(); - } else if (TimingsManager.needsRecheckEnabled) { - TimingsManager.recheckEnabled(); - } - super.startTiming(); - return this; - } - - @Override - public void stopTiming() { - super.stopTiming(); - if (!this.enabled) { - return; - } - - if (TimingsHistory.timedTicks % 20 == 0) { - final Runtime runtime = Runtime.getRuntime(); - double usedMemory = runtime.totalMemory() - runtime.freeMemory(); - double freeMemory = runtime.maxMemory() - usedMemory; - - if (this.avgFreeMemory == -1) { - this.avgFreeMemory = freeMemory; - } else { - this.avgFreeMemory = (this.avgFreeMemory * (59 / 60D)) + (freeMemory * (1 / 60D)); - } - - if (this.avgUsedMemory == -1) { - this.avgUsedMemory = usedMemory; - } else { - this.avgUsedMemory = (this.avgUsedMemory * (59 / 60D)) + (usedMemory * (1 / 60D)); - } - } - - long start = System.nanoTime(); - TimingsManager.tick(); - long diff = System.nanoTime() - start; - - CURRENT = Timings.timingsTickTimer; - Timings.timingsTickTimer.addDiff(diff); - //addDiff for timingsTickTimer incremented this, bring it back down to 1 per tick. - this.record.curTickCount--; - this.minuteData.curTickTotal = this.record.curTickTotal; - this.minuteData.curTickCount = 1; - boolean violated = isViolated(); - this.minuteData.tick(violated); - Timings.timingsTickTimer.tick(violated); - tick(violated); - - if (TimingsHistory.timedTicks % 1200 == 0) { - MINUTE_REPORTS.add(new TimingsHistory.MinuteReport()); - TimingsHistory.resetTicks(false); - this.minuteData.reset(); - } - - if (TimingsHistory.timedTicks % Timings.getHistoryInterval() == 0) { - TimingsManager.HISTORY.add(new TimingsHistory()); - TimingsManager.resetTimings(); - } - } - - boolean isViolated() { - return this.record.curTickTotal > 50000000; - } -} diff --git a/src/main/java/co/aikar/timings/Timing.java b/src/main/java/co/aikar/timings/Timing.java deleted file mode 100644 index b9430d2d4ae..00000000000 --- a/src/main/java/co/aikar/timings/Timing.java +++ /dev/null @@ -1,169 +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 java.util.HashMap; -import java.util.Map; - -public class Timing implements AutoCloseable { - private static int idPool = 1; - final int id = idPool++; - - final String name; - private final boolean verbose; - - final Map children = new HashMap<>(); - private Timing parent; - - private final Timing groupTiming; - final TimingData record; - - private long start = 0; - private int timingDepth = 0; - private boolean added; - boolean timed; - boolean enabled; - - Timing(TimingIdentifier id) { - if (id.name.startsWith("##")) { - this.verbose = true; - this.name = id.name.substring(3); - } else { - this.name = id.name; - this.verbose = false; - } - - this.record = new TimingData(this.id); - this.groupTiming = id.groupTiming; - - TimingIdentifier.getGroup(id.group).timings.add(this); - this.checkEnabled(); - } - - final void checkEnabled() { - this.enabled = Timings.isTimingsEnabled() && (!this.verbose || Timings.isVerboseEnabled()); - } - - void tick(boolean violated) { - if (this.timingDepth != 0 || this.record.curTickCount == 0) { - this.timingDepth = 0; - this.start = 0; - return; - } - - this.record.tick(violated); - for (TimingData data : this.children.values()) { - data.tick(violated); - } - } - - public Timing startTiming() { - if (!this.enabled) { - return this; - } - - if (++this.timingDepth == 1) { - this.start = System.nanoTime(); - this.parent = TimingsManager.CURRENT; - TimingsManager.CURRENT = this; - } - - return this; - } - - public void stopTiming() { - if (!this.enabled) { - return; - } - - if (--this.timingDepth == 0 && this.start != 0) { - this.addDiff(System.nanoTime() - this.start); - this.start = 0; - } - } - - public void abort() { - if (this.enabled && this.timingDepth > 0) { - this.start = 0; - } - } - - void addDiff(long diff) { - if (TimingsManager.CURRENT == this) { - TimingsManager.CURRENT = this.parent; - if (this.parent != null) { - if (!this.parent.children.containsKey(this.id)) - this.parent.children.put(this.id, new TimingData(this.id)); - this.parent.children.get(this.id).add(diff); - } - } - - this.record.add(diff); - if (!this.added) { - this.added = true; - this.timed = true; - TimingsManager.TIMINGS.add(this); - } - - if (this.groupTiming != null) { - this.groupTiming.addDiff(diff); - - if (!this.groupTiming.children.containsKey(this.id)) - this.groupTiming.children.put(this.id, new TimingData(this.id)); - this.groupTiming.children.get(this.id).add(diff); - } - } - - void reset(boolean full) { - this.record.reset(); - if (full) { - this.timed = false; - } - this.start = 0; - this.timingDepth = 0; - this.added = false; - this.children.clear(); - this.checkEnabled(); - } - - @Override - public boolean equals(Object o) { - return (o instanceof Timing && this == o); - } - - @Override - public int hashCode() { - return this.id; - } - - //For try-with-resources - @Override - public void close() { - this.stopTiming(); - } - - boolean isSpecial() { - return this == Timings.fullServerTickTimer || this == Timings.timingsTickTimer; - } -} diff --git a/src/main/java/co/aikar/timings/TimingData.java b/src/main/java/co/aikar/timings/TimingData.java deleted file mode 100644 index 8757d6990cf..00000000000 --- a/src/main/java/co/aikar/timings/TimingData.java +++ /dev/null @@ -1,91 +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 com.google.gson.JsonArray; - -import cn.nukkit.timings.JsonUtil; - -class TimingData { - private int id; - int count = 0; - private int lagCount = 0; - long totalTime = 0; - private long lagTotalTime = 0; - - int curTickCount = 0; - int curTickTotal = 0; - - TimingData(int id) { - this.id = id; - } - - TimingData(TimingData data) { - this.id = data.id; - this.count = data.count; - this.lagCount = data.lagCount; - this.totalTime = data.totalTime; - this.lagTotalTime = data.lagTotalTime; - } - - void add(long diff) { - ++this.curTickCount; - this.curTickTotal += diff; - } - - void tick(boolean violated) { - this.count += this.curTickCount; - this.totalTime += this.curTickTotal; - - if (violated) { - this.lagCount += this.curTickCount; - this.lagTotalTime += this.curTickTotal; - } - - this.curTickCount = 0; - this.curTickTotal = 0; - } - - void reset() { - this.count = 0; - this.lagCount = 0; - this.totalTime = 0; - this.lagTotalTime = 0; - this.curTickCount = 0; - this.curTickTotal = 0; - } - - protected TimingData clone() { - return new TimingData(this); - } - - JsonArray export() { - JsonArray json = JsonUtil.toArray(this.id, this.count, this.totalTime); - if (this.lagCount > 0) { - json.add(this.lagCount); - json.add(this.lagTotalTime); - } - return json; - } -} diff --git a/src/main/java/co/aikar/timings/TimingIdentifier.java b/src/main/java/co/aikar/timings/TimingIdentifier.java deleted file mode 100644 index 845f071a03d..00000000000 --- a/src/main/java/co/aikar/timings/TimingIdentifier.java +++ /dev/null @@ -1,82 +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 java.util.ArrayDeque; -import java.util.IdentityHashMap; -import java.util.Map; - -class TimingIdentifier { - static final Map GROUP_MAP = new IdentityHashMap<>(64); - static final TimingGroup DEFAULT_GROUP = getGroup("Nukkit"); - - final String group; - final String name; - final Timing groupTiming; - private final int hashCode; - - TimingIdentifier(String group, String name, Timing groupTiming) { - this.group = group != null ? group.intern() : DEFAULT_GROUP.name; - this.name = name.intern(); - this.groupTiming = groupTiming; - this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode(); - } - - static TimingGroup getGroup(String name) { - if (name == null) { - return DEFAULT_GROUP; - } - - return GROUP_MAP.computeIfAbsent(name, k -> new TimingGroup(name)); - } - - @Override - @SuppressWarnings("all") - public boolean equals(Object o) { - if (o == null || !(o instanceof TimingIdentifier)) { - return false; - } - - TimingIdentifier that = (TimingIdentifier) o; - //Using intern() method on strings makes possible faster string comparison with == - return this.group == that.group && this.name == that.name; - } - - @Override - public int hashCode() { - return this.hashCode; - } - - static class TimingGroup { - private static int idPool = 1; - final int id = idPool++; - - final String name; - ArrayDeque timings = new ArrayDeque<>(64); - - TimingGroup(String name) { - this.name = name.intern(); - } - } -} diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java deleted file mode 100644 index 0dc60448421..00000000000 --- a/src/main/java/co/aikar/timings/Timings.java +++ /dev/null @@ -1,256 +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 cn.nukkit.Server; -import cn.nukkit.blockentity.BlockEntity; -import cn.nukkit.command.Command; -import cn.nukkit.entity.Entity; -import cn.nukkit.event.Event; -import cn.nukkit.event.Listener; -import cn.nukkit.network.protocol.DataPacket; -import cn.nukkit.plugin.EventExecutor; -import cn.nukkit.plugin.MethodEventExecutor; -import cn.nukkit.plugin.Plugin; -import cn.nukkit.scheduler.PluginTask; -import cn.nukkit.scheduler.TaskHandler; - -import java.util.HashSet; -import java.util.Queue; -import java.util.Set; - -import static co.aikar.timings.TimingIdentifier.DEFAULT_GROUP; - -public final class Timings { - private static boolean timingsEnabled = false; - private static boolean verboseEnabled = false; - private static boolean privacy = false; - private static Set ignoredConfigSections = new HashSet<>(); - - private static final int MAX_HISTORY_FRAMES = 12; - private static int historyInterval = -1; - private static int historyLength = -1; - - public static final FullServerTickTiming fullServerTickTimer; - public static final Timing timingsTickTimer; - public static final Timing pluginEventTimer; - - public static final Timing connectionTimer; - public static final Timing schedulerTimer; - public static final Timing schedulerAsyncTimer; - public static final Timing schedulerSyncTimer; - public static final Timing commandTimer; - public static final Timing serverCommandTimer; - public static final Timing levelSaveTimer; - - public static final Timing playerNetworkSendTimer; - public static final Timing playerNetworkReceiveTimer; - public static final Timing playerChunkOrderTimer; - public static final Timing playerChunkSendTimer; - public static final Timing playerCommandTimer; - - public static final Timing tickEntityTimer; - public static final Timing tickBlockEntityTimer; - public static final Timing entityMoveTimer; - public static final Timing entityBaseTickTimer; - public static final Timing livingEntityBaseTickTimer; - - public static final Timing generationTimer; - public static final Timing populationTimer; - public static final Timing generationCallbackTimer; - - public static final Timing permissibleCalculationTimer; - public static final Timing permissionDefaultTimer; - - static { - setTimingsEnabled(Server.getInstance().getConfig("timings.enabled", false)); - setVerboseEnabled(Server.getInstance().getConfig("timings.verbose", false)); - setHistoryInterval(Server.getInstance().getConfig("timings.history-interval", 6000)); - setHistoryLength(Server.getInstance().getConfig("timings.history-length", 72000)); - - privacy = Server.getInstance().getConfig("timings.privacy", false); - ignoredConfigSections.addAll(Server.getInstance().getConfig().getStringList("timings.ignore")); - - Server.getInstance().getLogger().debug("Timings: \n" + - "Enabled - " + isTimingsEnabled() + "\n" + - "Verbose - " + isVerboseEnabled() + "\n" + - "History Interval - " + getHistoryInterval() + "\n" + - "History Length - " + getHistoryLength()); - - fullServerTickTimer = new FullServerTickTiming(); - timingsTickTimer = TimingsManager.getTiming(DEFAULT_GROUP.name, "Timings Tick", fullServerTickTimer); - pluginEventTimer = TimingsManager.getTiming("Plugin Events"); - - connectionTimer = TimingsManager.getTiming("Connection Handler"); - schedulerTimer = TimingsManager.getTiming("Scheduler"); - schedulerAsyncTimer = TimingsManager.getTiming("## Scheduler - Async Tasks"); - schedulerSyncTimer = TimingsManager.getTiming("## Scheduler - Sync Tasks"); - commandTimer = TimingsManager.getTiming("Commands"); - serverCommandTimer = TimingsManager.getTiming("Server Command"); - levelSaveTimer = TimingsManager.getTiming("Level Save"); - - playerNetworkSendTimer = TimingsManager.getTiming("Player Network Send"); - playerNetworkReceiveTimer = TimingsManager.getTiming("Player Network Receive"); - playerChunkOrderTimer = TimingsManager.getTiming("Player Order Chunks"); - playerChunkSendTimer = TimingsManager.getTiming("Player Send Chunks"); - playerCommandTimer = TimingsManager.getTiming("Player Command"); - - tickEntityTimer = TimingsManager.getTiming("## Entity Tick"); - tickBlockEntityTimer = TimingsManager.getTiming("## BlockEntity Tick"); - entityMoveTimer = TimingsManager.getTiming("## Entity Move"); - entityBaseTickTimer = TimingsManager.getTiming("## Entity Base Tick"); - livingEntityBaseTickTimer = TimingsManager.getTiming("## LivingEntity Base Tick"); - - generationTimer = TimingsManager.getTiming("Level Generation"); - populationTimer = TimingsManager.getTiming("Level Population"); - generationCallbackTimer = TimingsManager.getTiming("Level Generation Callback"); - - permissibleCalculationTimer = TimingsManager.getTiming("Permissible Calculation"); - permissionDefaultTimer = TimingsManager.getTiming("Default Permission Calculation"); - } - - public static boolean isTimingsEnabled() { - return timingsEnabled; - } - - public static void setTimingsEnabled(boolean enabled) { - timingsEnabled = enabled; - TimingsManager.reset(); - } - - public static boolean isVerboseEnabled() { - return verboseEnabled; - } - - public static void setVerboseEnabled(boolean enabled) { - verboseEnabled = enabled; - TimingsManager.needsRecheckEnabled = true; - } - - public static boolean isPrivacy() { - return privacy; - } - - public static Set getIgnoredConfigSections() { - return ignoredConfigSections; - } - - public static int getHistoryInterval() { - return historyInterval; - } - - public static void setHistoryInterval(int interval) { - historyInterval = Math.max(20 * 60, interval); - //Recheck the history length with the new Interval - if (historyLength != -1) { - setHistoryLength(historyLength); - } - } - - public static int getHistoryLength() { - return historyLength; - } - - public static void setHistoryLength(int length) { - //Cap at 12 History Frames, 1 hour at 5 minute frames. - int maxLength = historyInterval * MAX_HISTORY_FRAMES; - //For special cases of servers with special permission to bypass the max. - //This max helps keep data file sizes reasonable for processing on Aikar's Timing parser side. - //Setting this will not help you bypass the max unless Aikar has added an exception on the API side. - if (Server.getInstance().getConfig().getBoolean("timings.bypass-max", false)) { - maxLength = Integer.MAX_VALUE; - } - - historyLength = Math.max(Math.min(maxLength, length), historyInterval); - - Queue oldQueue = TimingsManager.HISTORY; - int frames = (getHistoryLength() / getHistoryInterval()); - if (length > maxLength) { - Server.getInstance().getLogger().warning( - "Timings Length too high. Requested " + length + ", max is " + maxLength - + ". To get longer history, you must increase your interval. Set Interval to " - + Math.ceil((float) length / MAX_HISTORY_FRAMES) - + " to achieve this length."); - } - - TimingsManager.HISTORY = new TimingsManager.BoundedQueue<>(frames); - TimingsManager.HISTORY.addAll(oldQueue); - } - - public static void reset() { - TimingsManager.reset(); - } - - - public static Timing getCommandTiming(Command command) { - return TimingsManager.getTiming(DEFAULT_GROUP.name, "Command: " + command.getLabel(), commandTimer); - } - - public static Timing getTaskTiming(TaskHandler handler, long period) { - String repeating = " "; - if (period > 0) { - repeating += "(interval:" + period + ")"; - } else { - repeating += "(Single)"; - } - - if (handler.getTask() instanceof PluginTask) { - String owner = ((PluginTask) handler.getTask()).getOwner().getName(); - return TimingsManager.getTiming(owner, "PluginTask: " + handler.getTaskId() + repeating, schedulerSyncTimer); - } else if (!handler.isAsynchronous()) { - return TimingsManager.getTiming(DEFAULT_GROUP.name, "Task: " + handler.getTaskId() + repeating, schedulerSyncTimer); - } else { - return null; - } - } - - public static Timing getPluginEventTiming(Class event, Listener listener, EventExecutor executor, Plugin plugin) { - Timing group = TimingsManager.getTiming(plugin.getName(), "Combined Total", pluginEventTimer); - - return TimingsManager.getTiming(plugin.getName(), "Event: " + listener.getClass().getName() + "." - + (executor instanceof MethodEventExecutor ? ((MethodEventExecutor) executor).getMethod().getName() : "???") - + " (" + event.getSimpleName() + ")", group); - } - - public static Timing getEntityTiming(Entity entity) { - return TimingsManager.getTiming(DEFAULT_GROUP.name, "## Entity Tick: " + entity.getClass().getSimpleName(), tickEntityTimer); - } - - public static Timing getBlockEntityTiming(BlockEntity blockEntity) { - return TimingsManager.getTiming(DEFAULT_GROUP.name, "## BlockEntity Tick: " + blockEntity.getClass().getSimpleName(), tickBlockEntityTimer); - } - - public static Timing getReceiveDataPacketTiming(DataPacket pk) { - return TimingsManager.getTiming(DEFAULT_GROUP.name, "## Receive Packet: " + pk.getClass().getSimpleName(), playerNetworkReceiveTimer); - } - - public static Timing getSendDataPacketTiming(DataPacket pk) { - return TimingsManager.getTiming(DEFAULT_GROUP.name, "## Send Packet: " + pk.getClass().getSimpleName(), playerNetworkSendTimer); - } - - public static void stopServer() { - setTimingsEnabled(false); - TimingsManager.recheckEnabled(); - } -} diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java deleted file mode 100644 index 9c322a3c82c..00000000000 --- a/src/main/java/co/aikar/timings/TimingsExport.java +++ /dev/null @@ -1,272 +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 cn.nukkit.Server; -import cn.nukkit.command.CommandSender; -import cn.nukkit.command.ConsoleCommandSender; -import cn.nukkit.command.RemoteConsoleCommandSender; -import cn.nukkit.lang.TranslationContainer; -import cn.nukkit.nbt.stream.PGZIPOutputStream; -import cn.nukkit.timings.JsonUtil; -import cn.nukkit.utils.TextFormat; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonObject; - -import java.io.*; -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.zip.Deflater; - -import static co.aikar.timings.TimingsManager.HISTORY; - -public class TimingsExport extends Thread { - private final CommandSender sender; - private final JsonObject out; - private final TimingsHistory[] history; - - private TimingsExport(CommandSender sender, JsonObject out, TimingsHistory[] history) { - super("Timings paste thread"); - this.sender = sender; - this.out = out; - this.history = history; - } - - /** - * Builds a JSON timings report and sends it to Aikar's viewer - * - * @param sender Sender that issued the command - */ - public static void reportTimings(CommandSender sender) { - JsonObject out = new JsonObject(); - out.addProperty("version", Server.getInstance().getVersion()); - out.addProperty("maxplayers", Server.getInstance().getMaxPlayers()); - out.addProperty("start", TimingsManager.timingStart / 1000); - out.addProperty("end", System.currentTimeMillis() / 1000); - out.addProperty("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000); - - if (!Timings.isPrivacy()) { - out.addProperty("server", Server.getInstance().getName()); - out.addProperty("motd", Server.getInstance().getMotd()); - out.addProperty("online-mode", false); //In MCPE we have permanent offline mode. - out.addProperty("icon", ""); //"data:image/png;base64," - } - - final Runtime runtime = Runtime.getRuntime(); - RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); - - JsonObject system = new JsonObject(); - system.addProperty("timingcost", getCost()); - system.addProperty("name", System.getProperty("os.name")); - system.addProperty("version", System.getProperty("os.version")); - system.addProperty("jvmversion", System.getProperty("java.version")); - system.addProperty("arch", System.getProperty("os.arch")); - system.addProperty("maxmem", runtime.maxMemory()); - system.addProperty("cpu", runtime.availableProcessors()); - system.addProperty("runtime", ManagementFactory.getRuntimeMXBean().getUptime()); - system.addProperty("flags", String.join(" ", runtimeBean.getInputArguments())); - system.add("gc", JsonUtil.mapToObject(ManagementFactory.getGarbageCollectorMXBeans(), (input) -> - new JsonUtil.JSONPair(input.getName(), JsonUtil.toArray(input.getCollectionCount(), input.getCollectionTime())))); - out.add("system", system); - - TimingsHistory[] history = HISTORY.toArray(new TimingsHistory[HISTORY.size() + 1]); - history[HISTORY.size()] = new TimingsHistory(); //Current snapshot - - JsonObject timings = new JsonObject(); - for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { - for (Timing id : group.timings) { - if (!id.timed && !id.isSpecial()) { - continue; - } - - timings.add(String.valueOf(id.id), JsonUtil.toArray(group.id, id.name)); - } - } - - JsonObject idmap = new JsonObject(); - idmap.add("groups", JsonUtil.mapToObject(TimingIdentifier.GROUP_MAP.values(), (group) -> - new JsonUtil.JSONPair(group.id, group.name))); - idmap.add("handlers", timings); - idmap.add("worlds", JsonUtil.mapToObject(TimingsHistory.levelMap.entrySet(), (entry) -> - new JsonUtil.JSONPair(entry.getValue(), entry.getKey()))); - idmap.add("tileentity", JsonUtil.mapToObject(TimingsHistory.blockEntityMap.entrySet(), (entry) -> - new JsonUtil.JSONPair(entry.getKey(), entry.getValue()))); - idmap.add("entity", JsonUtil.mapToObject(TimingsHistory.entityMap.entrySet(), (entry) -> - new JsonUtil.JSONPair(entry.getKey(), entry.getValue()))); - out.add("idmap", idmap); - - //Information about loaded plugins - out.add("plugins", JsonUtil.mapToObject(Server.getInstance().getPluginManager().getPlugins().values(), (plugin) -> { - JsonObject jsonPlugin = new JsonObject(); - jsonPlugin.addProperty("version", plugin.getDescription().getVersion()); - jsonPlugin.addProperty("description", plugin.getDescription().getDescription());// Sounds legit - jsonPlugin.addProperty("website", plugin.getDescription().getWebsite()); - jsonPlugin.addProperty("authors", String.join(", ", plugin.getDescription().getAuthors())); - return new JsonUtil.JSONPair(plugin.getName(), jsonPlugin); - })); - - //Information on the users Config - JsonObject config = new JsonObject(); - if (!Timings.getIgnoredConfigSections().contains("all")) { - JsonObject nukkit = JsonUtil.toObject(Server.getInstance().getConfig().getRootSection()); - Timings.getIgnoredConfigSections().forEach(nukkit::remove); - config.add("nukkit", nukkit); - } else { - config.add("nukkit", null); - } - out.add("config", config); - - new TimingsExport(sender, out, history).start(); - } - - private static long getCost() { - int passes = 200; - Timing SAMPLER1 = TimingsManager.getTiming(null, "Timings sampler 1", null); - Timing SAMPLER2 = TimingsManager.getTiming(null, "Timings sampler 2", null); - Timing SAMPLER3 = TimingsManager.getTiming(null, "Timings sampler 3", null); - Timing SAMPLER4 = TimingsManager.getTiming(null, "Timings sampler 4", null); - Timing SAMPLER5 = TimingsManager.getTiming(null, "Timings sampler 5", null); - Timing SAMPLER6 = TimingsManager.getTiming(null, "Timings sampler 6", null); - - long start = System.nanoTime(); - for (int i = 0; i < passes; i++) { - SAMPLER1.startTiming(); - SAMPLER2.startTiming(); - SAMPLER3.startTiming(); - SAMPLER4.startTiming(); - SAMPLER5.startTiming(); - SAMPLER6.startTiming(); - SAMPLER6.stopTiming(); - SAMPLER5.stopTiming(); - SAMPLER4.stopTiming(); - SAMPLER3.stopTiming(); - SAMPLER2.stopTiming(); - SAMPLER1.stopTiming(); - } - - long timingsCost = (System.nanoTime() - start) / passes / 6; - - SAMPLER1.reset(true); - SAMPLER2.reset(true); - SAMPLER3.reset(true); - SAMPLER4.reset(true); - SAMPLER5.reset(true); - SAMPLER6.reset(true); - - return timingsCost; - } - - @Override - public synchronized void start() { - if (this.sender instanceof RemoteConsoleCommandSender) { - this.sender.sendMessage(new TranslationContainer("nukkit.command.timings.rcon")); - run(); - } else { - super.start(); - } - } - - @Override - public void run() { - this.sender.sendMessage(new TranslationContainer("nukkit.command.timings.uploadStart")); - this.out.add("data", JsonUtil.mapToArray(this.history, TimingsHistory::export)); - - String response = null; - try { - HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); - con.setDoOutput(true); - con.setRequestProperty("User-Agent", "Nukkit/" + Server.getInstance().getName() + "/" + InetAddress.getLocalHost().getHostName()); - con.setRequestMethod("POST"); - con.setInstanceFollowRedirects(false); - - PGZIPOutputStream request = new PGZIPOutputStream(con.getOutputStream()); - request.setLevel(Deflater.BEST_COMPRESSION); - - request.write(new Gson().toJson(this.out).getBytes(StandardCharsets.UTF_8)); - request.close(); - - response = getResponse(con); - - if (con.getResponseCode() != 302) { - this.sender.sendMessage(new TranslationContainer("nukkit.command.timings.uploadError", String.valueOf(con.getResponseCode()), con.getResponseMessage())); - if (response != null) { - Server.getInstance().getLogger().alert(response); - } - return; - } - - String location = con.getHeaderField("Location"); - this.sender.sendMessage(new TranslationContainer("nukkit.command.timings.timingsLocation", location)); - if (!(this.sender instanceof ConsoleCommandSender)) { - Server.getInstance().getLogger().info(Server.getInstance().getLanguage().translateString("nukkit.command.timings.timingsLocation", location)); - } - - if (response != null && !response.isEmpty()) { - Server.getInstance().getLogger().info(Server.getInstance().getLanguage().translateString("nukkit.command.timings.timingsResponse", response)); - } - - File timingFolder = new File(Server.getInstance().getDataPath() + File.separator + "timings"); - timingFolder.mkdirs(); - String fileName = timingFolder + File.separator + new SimpleDateFormat("'timings-'yyyy-MM-dd-hh-mm'.txt'").format(new Date()); - - FileWriter writer = new FileWriter(fileName); - writer.write(Server.getInstance().getLanguage().translateString("nukkit.command.timings.timingsLocation", location) + "\n\n"); - writer.write(new GsonBuilder().setPrettyPrinting().create().toJson(this.out)); - writer.close(); - - Server.getInstance().getLogger().info(Server.getInstance().getLanguage().translateString("nukkit.command.timings.timingsWrite", fileName)); - } catch (IOException exception) { - this.sender.sendMessage(TextFormat.RED + "" + new TranslationContainer("nukkit.command.timings.reportError")); - if (response != null) { - Server.getInstance().getLogger().alert(response); - } - Server.getInstance().getLogger().logException(exception); - } - } - - private String getResponse(HttpURLConnection con) throws IOException { - try (InputStream is = con.getInputStream()) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - - byte[] b = new byte[1024]; - int bytesRead; - while ((bytesRead = is.read(b)) != -1) { - bos.write(b, 0, bytesRead); - } - return bos.toString(); - - } catch (IOException exception) { - this.sender.sendMessage(TextFormat.RED + "" + new TranslationContainer("nukkit.command.timings.reportError")); - Server.getInstance().getLogger().warning(con.getResponseMessage(), exception); - return null; - } - } -} diff --git a/src/main/java/co/aikar/timings/TimingsHistory.java b/src/main/java/co/aikar/timings/TimingsHistory.java deleted file mode 100644 index e7e25c07cd9..00000000000 --- a/src/main/java/co/aikar/timings/TimingsHistory.java +++ /dev/null @@ -1,221 +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 cn.nukkit.Player; -import cn.nukkit.Server; -import cn.nukkit.blockentity.BlockEntity; -import cn.nukkit.entity.Entity; -import cn.nukkit.level.Level; -import cn.nukkit.level.format.FullChunk; -import cn.nukkit.timings.JsonUtil; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import java.lang.management.ManagementFactory; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import static co.aikar.timings.Timings.fullServerTickTimer; -import static co.aikar.timings.TimingsManager.MINUTE_REPORTS; - -public class TimingsHistory { - public static long lastMinuteTime; - public static long timedTicks; - public static long playerTicks; - public static long entityTicks; - public static long tileEntityTicks; - public static long activatedEntityTicks; - - private static int levelIdPool = 1; - static Map levelMap = new HashMap<>(); - static Map entityMap = new HashMap<>(); - static Map blockEntityMap = new HashMap<>(); - - private final long endTime; - private final long startTime; - private final long totalTicks; - // Represents all time spent running the server this history - private final long totalTime; - private final MinuteReport[] minuteReports; - - private final TimingsHistoryEntry[] entries; - private final JsonObject levels = new JsonObject(); - - TimingsHistory() { - this.endTime = System.currentTimeMillis() / 1000; - this.startTime = TimingsManager.historyStart / 1000; - - if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) { - this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]); - this.minuteReports[this.minuteReports.length - 1] = new MinuteReport(); - } else { - this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[0]); - } - - long ticks = 0; - for (MinuteReport mr : this.minuteReports) { - ticks += mr.ticksRecord.timed; - } - - this.totalTicks = ticks; - this.totalTime = fullServerTickTimer.record.totalTime; - this.entries = new TimingsHistoryEntry[TimingsManager.TIMINGS.size()]; - - int i = 0; - for (Timing timing : TimingsManager.TIMINGS) { - this.entries[i++] = new TimingsHistoryEntry(timing); - } - - final Map entityCounts = new HashMap<>(); - final Map blockEntityCounts = new HashMap<>(); - final Gson GSON = new Gson(); - // Information about all loaded entities/block entities - for (Level level : Server.getInstance().getLevels().values()) { - JsonArray jsonLevel = new JsonArray(); - for (FullChunk chunk : level.getChunks().values()) { - entityCounts.clear(); - blockEntityCounts.clear(); - - //count entities - for (Entity entity : chunk.getEntities().values()) { - if (!entityCounts.containsKey(entity.getNetworkId())) - entityCounts.put(entity.getNetworkId(), new AtomicInteger(0)); - entityCounts.get(entity.getNetworkId()).incrementAndGet(); - entityMap.put(entity.getNetworkId(), entity.getClass().getSimpleName()); - } - - //count block entities - for (BlockEntity blockEntity : chunk.getBlockEntities().values()) { - if (!blockEntityCounts.containsKey(blockEntity.getBlock().getId())) - blockEntityCounts.put(blockEntity.getBlock().getId(), new AtomicInteger(0)); - blockEntityCounts.get(blockEntity.getBlock().getId()).incrementAndGet(); - blockEntityMap.put(blockEntity.getBlock().getId(), blockEntity.getClass().getSimpleName()); - } - - if (blockEntityCounts.isEmpty() && entityCounts.isEmpty()) { - continue; - } - - JsonArray jsonChunk = new JsonArray(); - jsonChunk.add(chunk.getX()); - jsonChunk.add(chunk.getZ()); - jsonChunk.add(GSON.toJsonTree(JsonUtil.mapToObject(entityCounts.entrySet(), (entry) -> new JsonUtil.JSONPair(entry.getKey(), entry.getValue().get()))).getAsJsonObject()); - jsonChunk.add(GSON.toJsonTree(JsonUtil.mapToObject(blockEntityCounts.entrySet(), (entry) -> new JsonUtil.JSONPair(entry.getKey(), entry.getValue().get()))).getAsJsonObject()); - jsonLevel.add(jsonChunk); - } - - if (!levelMap.containsKey(level.getName())) levelMap.put(level.getName(), levelIdPool++); - levels.add(String.valueOf(levelMap.get(level.getName())), jsonLevel); - } - } - - static void resetTicks(boolean fullReset) { - if (fullReset) { - timedTicks = 0; - } - lastMinuteTime = System.nanoTime(); - playerTicks = 0; - tileEntityTicks = 0; - entityTicks = 0; - activatedEntityTicks = 0; - } - - JsonObject export() { - JsonObject json = new JsonObject(); - json.addProperty("s", this.startTime); - json.addProperty("e", this.endTime); - json.addProperty("tk", this.totalTicks); - json.addProperty("tm", this.totalTime); - json.add("w", this.levels); - json.add("h", JsonUtil.mapToArray(this.entries, (entry) -> { - if (entry.data.count == 0) { - return null; - } - return entry.export(); - })); - json.add("mp", JsonUtil.mapToArray(this.minuteReports, MinuteReport::export)); - return json; - } - - static class MinuteReport { - final long time = System.currentTimeMillis() / 1000; - - final TicksRecord ticksRecord = new TicksRecord(); - final PingRecord pingRecord = new PingRecord(); - final TimingData fst = Timings.fullServerTickTimer.minuteData.clone(); - final double tps = 1E9 / (System.nanoTime() - lastMinuteTime) * this.ticksRecord.timed; - final double usedMemory = Timings.fullServerTickTimer.avgUsedMemory; - final double freeMemory = Timings.fullServerTickTimer.avgFreeMemory; - final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage(); - - JsonArray export() { - return JsonUtil.toArray(this.time, - Math.round(this.tps * 100D) / 100D, - Math.round(this.pingRecord.avg * 100D) / 100D, - this.fst.export(), - JsonUtil.toArray(this.ticksRecord.timed, - this.ticksRecord.player, - this.ticksRecord.entity, - this.ticksRecord.activatedEntity, - this.ticksRecord.tileEntity), - this.usedMemory, - this.freeMemory, - this.loadAvg); - } - } - - private static class TicksRecord { - final long timed; - final long player; - final long entity; - final long activatedEntity; - final long tileEntity; - - TicksRecord() { - this.timed = timedTicks - (TimingsManager.MINUTE_REPORTS.size() * 1200); - this.player = playerTicks; - this.entity = entityTicks; - this.activatedEntity = activatedEntityTicks; - this.tileEntity = tileEntityTicks; - } - } - - private static class PingRecord { - final double avg; - - PingRecord() { - final Collection onlinePlayers = Server.getInstance().getOnlinePlayers().values(); - int totalPing = 0; - for (Player player : onlinePlayers) { - totalPing += player.getPing(); - } - - this.avg = onlinePlayers.isEmpty() ? 0 : (float) totalPing / onlinePlayers.size(); - } - } -} diff --git a/src/main/java/co/aikar/timings/TimingsHistoryEntry.java b/src/main/java/co/aikar/timings/TimingsHistoryEntry.java deleted file mode 100644 index 6782b7184dd..00000000000 --- a/src/main/java/co/aikar/timings/TimingsHistoryEntry.java +++ /dev/null @@ -1,49 +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 com.google.gson.JsonArray; - -import cn.nukkit.timings.JsonUtil; - -class TimingsHistoryEntry { - final TimingData data; - final TimingData[] children; - - TimingsHistoryEntry(Timing timing) { - this.data = timing.record.clone(); - this.children = new TimingData[timing.children.size()]; - - int i = 0; - for (TimingData child : timing.children.values()) { - this.children[i++] = child.clone(); - } - } - - JsonArray export() { - JsonArray json = this.data.export(); - if (this.children.length > 0) json.add(JsonUtil.mapToArray(this.children, TimingData::export)); - return json; - } -} diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java deleted file mode 100644 index 3622b329cd6..00000000000 --- a/src/main/java/co/aikar/timings/TimingsManager.java +++ /dev/null @@ -1,138 +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 cn.nukkit.Server; - -import java.util.*; - -public class TimingsManager { - static final Map TIMING_MAP = Collections.synchronizedMap(new HashMap<>(256, 0.5f)); - - static final Queue TIMINGS = new ArrayDeque<>(); - static final ArrayDeque MINUTE_REPORTS = new ArrayDeque<>(); - - static Queue HISTORY = new BoundedQueue<>(12); - - static Timing CURRENT; - - static long timingStart = 0; - static long historyStart = 0; - static boolean needsFullReset = false; - static boolean needsRecheckEnabled = false; - - static void reset() { - needsFullReset = true; - } - - /** - * Called every tick to count the number of times a timer caused TPS loss. - */ - static void tick() { - if (Timings.isTimingsEnabled()) { - boolean violated = Timings.fullServerTickTimer.isViolated(); - - synchronized (TIMINGS) { - for (Timing timing : TIMINGS) { - if (timing.isSpecial()) { - // Called manually - continue; - } - - timing.tick(violated); - } - } - - TimingsHistory.playerTicks += Server.getInstance().getOnlinePlayers().size(); - TimingsHistory.timedTicks++; - } - } - - static void recheckEnabled() { - synchronized (TIMING_MAP) { - TIMING_MAP.values().forEach(Timing::checkEnabled); - } - - needsRecheckEnabled = false; - } - - static void resetTimings() { - if (needsFullReset) { - // Full resets need to re-check every handlers enabled state - // Timing map can be modified from async so we must sync on it. - synchronized (TIMING_MAP) { - for (Timing timing : TIMING_MAP.values()) { - timing.reset(true); - } - } - - HISTORY.clear(); - needsFullReset = false; - needsRecheckEnabled = false; - timingStart = System.currentTimeMillis(); - } else { - // Soft resets only need to act on timings that have done something - // Handlers can only be modified on main thread. - for (Timing timing : TIMINGS) { - timing.reset(false); - } - } - - TIMINGS.clear(); - MINUTE_REPORTS.clear(); - - TimingsHistory.resetTicks(true); - historyStart = System.currentTimeMillis(); - } - - public static Timing getTiming(String name) { - return getTiming(null, name, null); - } - - static Timing getTiming(String group, String name, Timing groupTiming) { - TimingIdentifier id = new TimingIdentifier(group, name, groupTiming); - return TIMING_MAP.computeIfAbsent(id, k -> new Timing(id)); - } - - static final class BoundedQueue extends LinkedList { - final int maxSize; - - BoundedQueue(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize must be greater than zero"); - } - - this.maxSize = maxSize; - } - - @Override - public boolean add(E e) { - if (this.size() == maxSize) { - this.remove(); - } - - return super.add(e); - } - } -} From b16695b1862188c139c0a2d15793e5f55978fd12 Mon Sep 17 00:00:00 2001 From: Villagers654 Date: Sun, 4 Jun 2023 00:54:54 +0900 Subject: [PATCH 2/5] Remove timings --- src/main/java/cn/nukkit/Player.java | 2472 ++++++++--------- src/main/java/cn/nukkit/Server.java | 14 - .../cn/nukkit/blockentity/BlockEntity.java | 4 - .../blockentity/BlockEntityFurnace.java | 4 - src/main/java/cn/nukkit/command/Command.java | 6 - .../cn/nukkit/command/SimpleCommandMap.java | 3 - .../command/defaults/TimingsCommand.java | 74 - .../java/cn/nukkit/console/NukkitConsole.java | 3 - src/main/java/cn/nukkit/entity/Entity.java | 19 - .../java/cn/nukkit/entity/EntityLiving.java | 4 - .../nukkit/entity/item/EntityExpBottle.java | 4 - .../entity/item/EntityFallingBlock.java | 4 - .../cn/nukkit/entity/item/EntityFirework.java | 5 - .../cn/nukkit/entity/item/EntityItem.java | 4 - .../nukkit/entity/item/EntityMinecartTNT.java | 4 - .../cn/nukkit/entity/item/EntityPotion.java | 3 - .../nukkit/entity/item/EntityPrimedTNT.java | 4 - .../nukkit/entity/projectile/EntityArrow.java | 4 - .../entity/projectile/EntityEnderPearl.java | 4 - .../entity/projectile/EntitySnowball.java | 4 - .../cn/nukkit/level/format/anvil/Anvil.java | 2 - .../level/format/generic/BaseFullChunk.java | 4 - .../nukkit/level/format/leveldb/LevelDB.java | 2 - .../level/format/mcregion/McRegion.java | 2 - .../cn/nukkit/permission/PermissibleBase.java | 4 - .../java/cn/nukkit/plugin/PluginManager.java | 7 +- .../cn/nukkit/plugin/RegisteredListener.java | 8 +- .../java/cn/nukkit/scheduler/AsyncTask.java | 4 - .../cn/nukkit/scheduler/ServerScheduler.java | 2 - .../java/cn/nukkit/scheduler/TaskHandler.java | 5 - 30 files changed, 1236 insertions(+), 1447 deletions(-) delete mode 100644 src/main/java/cn/nukkit/command/defaults/TimingsCommand.java diff --git a/src/main/java/cn/nukkit/Player.java b/src/main/java/cn/nukkit/Player.java index 76f821d16eb..a10ea4b81f7 100644 --- a/src/main/java/cn/nukkit/Player.java +++ b/src/main/java/cn/nukkit/Player.java @@ -9,7 +9,10 @@ import cn.nukkit.command.CommandSender; import cn.nukkit.command.data.CommandDataVersions; import cn.nukkit.entity.*; -import cn.nukkit.entity.data.*; +import cn.nukkit.entity.data.IntPositionEntityData; +import cn.nukkit.entity.data.ShortEntityData; +import cn.nukkit.entity.data.Skin; +import cn.nukkit.entity.data.StringEntityData; import cn.nukkit.entity.item.*; import cn.nukkit.entity.projectile.EntityArrow; import cn.nukkit.entity.projectile.EntityThrownTrident; @@ -67,8 +70,6 @@ import cn.nukkit.resourcepacks.ResourcePack; import cn.nukkit.scheduler.AsyncTask; import cn.nukkit.utils.*; -import co.aikar.timings.Timing; -import co.aikar.timings.Timings; import com.google.common.base.Strings; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; @@ -316,6 +317,7 @@ public String getClientSecret() { /** * This might disappear in the future. * Please use getUniqueId() instead (IP + clientId + name combo, in the future it'll change to real UUID for online auth) + * * @return random client id */ @Deprecated @@ -810,8 +812,6 @@ protected void sendNextChunk() { return; } - Timings.playerChunkSendTimer.startTiming(); - if (!loadQueue.isEmpty()) { int count = 0; ObjectIterator> iter = loadQueue.long2ObjectEntrySet().fastIterator(); @@ -850,7 +850,6 @@ protected void sendNextChunk() { if (this.chunkLoadCount >= this.spawnThreshold && !this.spawned && this.teleportPosition == null) { this.doFirstSpawn(); } - Timings.playerChunkSendTimer.stopTiming(); } protected void doFirstSpawn() { @@ -940,8 +939,6 @@ protected boolean orderChunks() { return false; } - Timings.playerChunkOrderTimer.startTiming(); - this.nextChunkOrderRun = 200; loadQueue.clear(); @@ -954,7 +951,6 @@ protected boolean orderChunks() { int radiusSqr = radius * radius; - long index; for (int x = 0; x <= radius; x++) { int xx = x * x; @@ -963,43 +959,43 @@ protected boolean orderChunks() { if (distanceSqr > radiusSqr) continue; /* Top right quadrant */ - if(this.usedChunks.get(index = Level.chunkHash(centerX + x, centerZ + z)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX + x, centerZ + z)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); /* Top left quadrant */ - if(this.usedChunks.get(index = Level.chunkHash(centerX - x - 1, centerZ + z)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX - x - 1, centerZ + z)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); /* Bottom right quadrant */ - if(this.usedChunks.get(index = Level.chunkHash(centerX + x, centerZ - z - 1)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX + x, centerZ - z - 1)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); /* Bottom left quadrant */ - if(this.usedChunks.get(index = Level.chunkHash(centerX - x - 1, centerZ - z - 1)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX - x - 1, centerZ - z - 1)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); - if(x != z){ + if (x != z) { /* Top right quadrant mirror */ - if(this.usedChunks.get(index = Level.chunkHash(centerX + z, centerZ + x)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX + z, centerZ + x)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); /* Top left quadrant mirror */ - if(this.usedChunks.get(index = Level.chunkHash(centerX - z - 1, centerZ + x)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX - z - 1, centerZ + x)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); /* Bottom right quadrant mirror */ - if(this.usedChunks.get(index = Level.chunkHash(centerX + z, centerZ - x - 1)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX + z, centerZ - x - 1)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); /* Bottom left quadrant mirror */ - if(this.usedChunks.get(index = Level.chunkHash(centerX - z - 1, centerZ - x - 1)) != Boolean.TRUE) { + if (this.usedChunks.get(index = Level.chunkHash(centerX - z - 1, centerZ - x - 1)) != Boolean.TRUE) { this.loadQueue.put(index, Boolean.TRUE); } lastChunk.remove(index); @@ -1020,7 +1016,6 @@ protected boolean orderChunks() { this.dataPacket(packet); } - Timings.playerChunkOrderTimer.stopTiming(); return true; } @@ -1033,6 +1028,7 @@ public boolean batchDataPacket(DataPacket packet) { * 0 is true * -1 is false * other is identifer + * * @param packet packet to send * @return packet successfully sent */ @@ -1041,19 +1037,17 @@ public boolean dataPacket(DataPacket packet) { return false; } - try (Timing ignored = Timings.getSendDataPacketTiming(packet)) { - DataPacketSendEvent ev = new DataPacketSendEvent(this, packet); - this.server.getPluginManager().callEvent(ev); - if (ev.isCancelled()) { - return false; - } - - if (log.isTraceEnabled() && !server.isIgnoredPacket(packet.getClass())) { - log.trace("Outbound {}: {}", this.getName(), packet); - } + DataPacketSendEvent ev = new DataPacketSendEvent(this, packet); + this.server.getPluginManager().callEvent(ev); + if (ev.isCancelled()) { + return false; + } - this.networkSession.sendPacket(packet); + if (log.isTraceEnabled() && !server.isIgnoredPacket(packet.getClass())) { + log.trace("Outbound {}: {}", this.getName(), packet); } + + this.networkSession.sendPacket(packet); return true; } @@ -1066,6 +1060,7 @@ public int dataPacket(DataPacket packet, boolean needACK) { * 0 is true * -1 is false * other is identifer + * * @param packet packet to send * @return packet successfully sent */ @@ -1080,7 +1075,8 @@ public int directDataPacket(DataPacket packet, boolean needACK) { } public void forceDataPacket(DataPacket packet, Runnable callback) { - this.networkSession.sendImmediatePacket(packet, (callback == null ? () -> {} : callback)); + this.networkSession.sendImmediatePacket(packet, (callback == null ? () -> { + } : callback)); } public int getPing() { @@ -1320,8 +1316,6 @@ public boolean fastMove(double dx, double dy, double dz) { return true; } - Timings.entityMoveTimer.startTiming(); - AxisAlignedBB newBB = this.boundingBox.getOffsetBoundingBox(dx, dy, dz); if (this.isSpectator() || server.getAllowFlight() || !this.level.hasCollision(this, newBB.shrink(0, this.getStepHeight(), 0), false)) { @@ -1345,7 +1339,6 @@ public boolean fastMove(double dx, double dy, double dz) { this.updateFallState(this.onGround); } - Timings.entityMoveTimer.stopTiming(); return true; } @@ -1787,8 +1780,6 @@ public void checkInteractNearby() { * @return Entity|null either NULL if no entity is found or an instance of the entity */ public EntityInteractable getEntityPlayerLookingAt(int maxDistance) { - timing.startTiming(); - EntityInteractable entity = null; // just a fix because player MAY not be fully initialized @@ -1813,8 +1804,6 @@ public EntityInteractable getEntityPlayerLookingAt(int maxDistance) { } } - timing.stopTiming(); - return entity; } @@ -2017,9 +2006,9 @@ protected void completeLoginSequence() { } Level level = this.server.getLevelByName(this.namedTag.getString("SpawnLevel")); - if(level != null){ + if (level != null) { this.spawnPosition = new Position(this.namedTag.getInt("SpawnX"), this.namedTag.getInt("SpawnY"), this.namedTag.getInt("SpawnZ"), level); - }else{ + } else { this.spawnPosition = this.level.getSafeSpawn(); } @@ -2108,1476 +2097,1479 @@ public void handleDataPacket(DataPacket packet) { return; } - try (Timing ignored = Timings.getReceiveDataPacketTiming(packet)) { - DataPacketReceiveEvent ev = new DataPacketReceiveEvent(this, packet); - this.server.getPluginManager().callEvent(ev); - if (ev.isCancelled()) { - return; - } + DataPacketReceiveEvent ev = new DataPacketReceiveEvent(this, packet); + this.server.getPluginManager().callEvent(ev); + if (ev.isCancelled()) { + return; + } - if (packet.pid() == ProtocolInfo.BATCH_PACKET) { - this.server.getNetwork().processBatch((BatchPacket) packet, this); - return; - } + if (packet.pid() == ProtocolInfo.BATCH_PACKET) { + this.server.getNetwork().processBatch((BatchPacket) packet, this); + return; + } - if (log.isTraceEnabled() && !server.isIgnoredPacket(packet.getClass())) { - log.trace("Inbound {}: {}", this.getName(), packet); - } + if (log.isTraceEnabled() && !server.isIgnoredPacket(packet.getClass())) { + log.trace("Inbound {}: {}", this.getName(), packet); + } - BlockFace face; + BlockFace face; - packetswitch: - switch (packet.pid()) { - case ProtocolInfo.REQUEST_NETWORK_SETTINGS_PACKET: - if (this.loggedIn) { - break; - } + packetswitch: + switch (packet.pid()) { + case ProtocolInfo.REQUEST_NETWORK_SETTINGS_PACKET: + if (this.loggedIn) { + break; + } - int protocolVersion = ((RequestNetworkSettingsPacket) packet).protocolVersion; + int protocolVersion = ((RequestNetworkSettingsPacket) packet).protocolVersion; - if (!ProtocolInfo.SUPPORTED_PROTOCOLS.contains(protocolVersion)) { - String message; - if (protocolVersion < ProtocolInfo.CURRENT_PROTOCOL) { - message = "disconnectionScreen.outdatedClient"; - } else { - message = "disconnectionScreen.outdatedServer"; - } - this.close("", message, true); - break; + if (!ProtocolInfo.SUPPORTED_PROTOCOLS.contains(protocolVersion)) { + String message; + if (protocolVersion < ProtocolInfo.CURRENT_PROTOCOL) { + message = "disconnectionScreen.outdatedClient"; + } else { + message = "disconnectionScreen.outdatedServer"; } - - NetworkSettingsPacket settingsPacket = new NetworkSettingsPacket(); - settingsPacket.compressionAlgorithm = PacketCompressionAlgorithm.ZLIB; - settingsPacket.compressionThreshold = 1; // compress everything - this.forceDataPacket(settingsPacket, () -> { - this.networkSession.setCompression(CompressionProvider.ZLIB); - }); + this.close("", message, true); break; - case ProtocolInfo.LOGIN_PACKET: - if (this.loggedIn) { - break; - } + } - LoginPacket loginPacket = (LoginPacket) packet; - this.username = TextFormat.clean(loginPacket.username); - this.displayName = this.username; - this.iusername = this.username.toLowerCase(); + NetworkSettingsPacket settingsPacket = new NetworkSettingsPacket(); + settingsPacket.compressionAlgorithm = PacketCompressionAlgorithm.ZLIB; + settingsPacket.compressionThreshold = 1; // compress everything + this.forceDataPacket(settingsPacket, () -> { + this.networkSession.setCompression(CompressionProvider.ZLIB); + }); + break; - this.setDataProperty(new StringEntityData(DATA_NAMETAG, this.username), false); - this.loginChainData = ClientChainData.read(loginPacket); + case ProtocolInfo.LOGIN_PACKET: + if (this.loggedIn) { + break; + } - if (!loginChainData.isXboxAuthed() && server.getPropertyBoolean("xbox-auth")) { - this.close("", "disconnectionScreen.notAuthenticated"); - break; - } + LoginPacket loginPacket = (LoginPacket) packet; + this.username = TextFormat.clean(loginPacket.username); + this.displayName = this.username; + this.iusername = this.username.toLowerCase(); - if (this.server.getOnlinePlayers().size() >= this.server.getMaxPlayers() && this.kick(PlayerKickEvent.Reason.SERVER_FULL, "disconnectionScreen.serverFull", false)) { - break; - } + this.setDataProperty(new StringEntityData(DATA_NAMETAG, this.username), false); - this.randomClientId = loginPacket.clientId; + this.loginChainData = ClientChainData.read(loginPacket); - this.uuid = loginPacket.clientUUID; - this.rawUUID = Binary.writeUUID(this.uuid); + if (!loginChainData.isXboxAuthed() && server.getPropertyBoolean("xbox-auth")) { + this.close("", "disconnectionScreen.notAuthenticated"); + break; + } - boolean valid = true; - int len = loginPacket.username.length(); - if (len > 16 || len < 3) { - valid = false; - } + if (this.server.getOnlinePlayers().size() >= this.server.getMaxPlayers() && this.kick(PlayerKickEvent.Reason.SERVER_FULL, "disconnectionScreen.serverFull", false)) { + break; + } - for (int i = 0; i < len && valid; i++) { - char c = loginPacket.username.charAt(i); - if ((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - c == '_' || c == ' ' - ) { - continue; - } + this.randomClientId = loginPacket.clientId; - valid = false; - break; - } + this.uuid = loginPacket.clientUUID; + this.rawUUID = Binary.writeUUID(this.uuid); - if (!valid || Objects.equals(this.iusername, "rcon") || Objects.equals(this.iusername, "console")) { - this.close("", "disconnectionScreen.invalidName"); + boolean valid = true; + int len = loginPacket.username.length(); + if (len > 16 || len < 3) { + valid = false; + } - break; + for (int i = 0; i < len && valid; i++) { + char c = loginPacket.username.charAt(i); + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '_' || c == ' ' + ) { + continue; } - if (!loginPacket.skin.isValid()) { - this.close("", "disconnectionScreen.invalidSkin"); - break; - } else { - this.setSkin(loginPacket.skin); - } + valid = false; + break; + } - PlayerPreLoginEvent playerPreLoginEvent; - this.server.getPluginManager().callEvent(playerPreLoginEvent = new PlayerPreLoginEvent(this, "Plugin reason")); - if (playerPreLoginEvent.isCancelled()) { - this.close("", playerPreLoginEvent.getKickMessage()); + if (!valid || Objects.equals(this.iusername, "rcon") || Objects.equals(this.iusername, "console")) { + this.close("", "disconnectionScreen.invalidName"); - break; - } + break; + } - Player playerInstance = this; - this.verified = true; + if (!loginPacket.skin.isValid()) { + this.close("", "disconnectionScreen.invalidSkin"); + break; + } else { + this.setSkin(loginPacket.skin); + } - this.preLoginEventTask = new AsyncTask() { - private PlayerAsyncPreLoginEvent event; + PlayerPreLoginEvent playerPreLoginEvent; + this.server.getPluginManager().callEvent(playerPreLoginEvent = new PlayerPreLoginEvent(this, "Plugin reason")); + if (playerPreLoginEvent.isCancelled()) { + this.close("", playerPreLoginEvent.getKickMessage()); - @Override - public void onRun() { - this.event = new PlayerAsyncPreLoginEvent(username, uuid, loginChainData, playerInstance.getSkin(), playerInstance.getAddress(), playerInstance.getPort()); - server.getPluginManager().callEvent(this.event); - } + break; + } - @Override - public void onCompletion(Server server) { - if (playerInstance.closed) { - return; - } + Player playerInstance = this; + this.verified = true; - if (this.event.getLoginResult() == LoginResult.KICK) { - playerInstance.close(this.event.getKickMessage(), this.event.getKickMessage()); - } else if (playerInstance.shouldLogin) { - playerInstance.setSkin(this.event.getSkin()); - playerInstance.completeLoginSequence(); - for (Consumer action : this.event.getScheduledActions()) { - action.accept(server); - } - } - } - }; + this.preLoginEventTask = new AsyncTask() { + private PlayerAsyncPreLoginEvent event; - this.server.getScheduler().scheduleAsyncTask(this.preLoginEventTask); - this.processLogin(); - break; - case ProtocolInfo.RESOURCE_PACK_CLIENT_RESPONSE_PACKET: - ResourcePackClientResponsePacket responsePacket = (ResourcePackClientResponsePacket) packet; - switch (responsePacket.responseStatus) { - case ResourcePackClientResponsePacket.STATUS_REFUSED: - this.close("", "disconnectionScreen.noReason"); - break; - case ResourcePackClientResponsePacket.STATUS_SEND_PACKS: - for (ResourcePackClientResponsePacket.Entry entry : responsePacket.packEntries) { - ResourcePack resourcePack = this.server.getResourcePackManager().getPackById(entry.uuid); - if (resourcePack == null) { - this.close("", "disconnectionScreen.resourcePack"); - break; - } + @Override + public void onRun() { + this.event = new PlayerAsyncPreLoginEvent(username, uuid, loginChainData, playerInstance.getSkin(), playerInstance.getAddress(), playerInstance.getPort()); + server.getPluginManager().callEvent(this.event); + } - ResourcePackDataInfoPacket dataInfoPacket = new ResourcePackDataInfoPacket(); - dataInfoPacket.packId = resourcePack.getPackId(); - dataInfoPacket.maxChunkSize = RESOURCE_PACK_CHUNK_SIZE; - dataInfoPacket.chunkCount = MathHelper.ceil(resourcePack.getPackSize() / (float) RESOURCE_PACK_CHUNK_SIZE); - dataInfoPacket.compressedPackSize = resourcePack.getPackSize(); - dataInfoPacket.sha256 = resourcePack.getSha256(); - this.dataPacket(dataInfoPacket); - } - break; - case ResourcePackClientResponsePacket.STATUS_HAVE_ALL_PACKS: - ResourcePackStackPacket stackPacket = new ResourcePackStackPacket(); - stackPacket.mustAccept = this.server.getForceResources(); - stackPacket.resourcePackStack = this.server.getResourcePackManager().getResourceStack(); - this.dataPacket(stackPacket); - break; - case ResourcePackClientResponsePacket.STATUS_COMPLETED: - this.shouldLogin = true; + @Override + public void onCompletion(Server server) { + if (playerInstance.closed) { + return; + } - if (this.preLoginEventTask.isFinished()) { - this.preLoginEventTask.onCompletion(server); + if (this.event.getLoginResult() == LoginResult.KICK) { + playerInstance.close(this.event.getKickMessage(), this.event.getKickMessage()); + } else if (playerInstance.shouldLogin) { + playerInstance.setSkin(this.event.getSkin()); + playerInstance.completeLoginSequence(); + for (Consumer action : this.event.getScheduledActions()) { + action.accept(server); } - break; - } - break; - case ProtocolInfo.RESOURCE_PACK_CHUNK_REQUEST_PACKET: - ResourcePackChunkRequestPacket requestPacket = (ResourcePackChunkRequestPacket) packet; - ResourcePack resourcePack = this.server.getResourcePackManager().getPackById(requestPacket.packId); - if (resourcePack == null) { - this.close("", "disconnectionScreen.resourcePack"); - break; - } - - ResourcePackChunkDataPacket dataPacket = new ResourcePackChunkDataPacket(); - dataPacket.packId = resourcePack.getPackId(); - dataPacket.chunkIndex = requestPacket.chunkIndex; - dataPacket.data = resourcePack.getPackChunk(RESOURCE_PACK_CHUNK_SIZE * requestPacket.chunkIndex, RESOURCE_PACK_CHUNK_SIZE); - dataPacket.progress = (long) RESOURCE_PACK_CHUNK_SIZE * requestPacket.chunkIndex; - this.dataPacket(dataPacket); - break; - case ProtocolInfo.SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET: - if (this.locallyInitialized) { - break; + } } - this.locallyInitialized = true; - PlayerLocallyInitializedEvent locallyInitializedEvent = new PlayerLocallyInitializedEvent(this); - this.server.getPluginManager().callEvent(locallyInitializedEvent); - break; - case ProtocolInfo.PLAYER_SKIN_PACKET: - PlayerSkinPacket skinPacket = (PlayerSkinPacket) packet; - Skin skin = skinPacket.skin; + }; - if (!skin.isValid()) { - this.getServer().getLogger().debug(username + ": PlayerSkinPacket with invalid skin"); + this.server.getScheduler().scheduleAsyncTask(this.preLoginEventTask); + this.processLogin(); + break; + case ProtocolInfo.RESOURCE_PACK_CLIENT_RESPONSE_PACKET: + ResourcePackClientResponsePacket responsePacket = (ResourcePackClientResponsePacket) packet; + switch (responsePacket.responseStatus) { + case ResourcePackClientResponsePacket.STATUS_REFUSED: + this.close("", "disconnectionScreen.noReason"); break; - } - - PlayerChangeSkinEvent playerChangeSkinEvent = new PlayerChangeSkinEvent(this, skin); - playerChangeSkinEvent.setCancelled(TimeUnit.SECONDS.toMillis(this.server.getPlayerSkinChangeCooldown()) > System.currentTimeMillis() - this.lastSkinChange); - this.server.getPluginManager().callEvent(playerChangeSkinEvent); - if (!playerChangeSkinEvent.isCancelled()) { - this.lastSkinChange = System.currentTimeMillis(); - this.setSkin(skin); - } + case ResourcePackClientResponsePacket.STATUS_SEND_PACKS: + for (ResourcePackClientResponsePacket.Entry entry : responsePacket.packEntries) { + ResourcePack resourcePack = this.server.getResourcePackManager().getPackById(entry.uuid); + if (resourcePack == null) { + this.close("", "disconnectionScreen.resourcePack"); + break; + } - break; - case ProtocolInfo.PACKET_VIOLATION_WARNING_PACKET: - log.warn("Violation warning from {}: {}", this.getName(), packet.toString()); - break; - case ProtocolInfo.EMOTE_PACKET: - if (!this.spawned) { - return; - } - EmotePacket emotePacket = (EmotePacket) packet; - if (emotePacket.runtimeId != this.id) { - server.getLogger().warning(this.username + " sent EmotePacket with invalid entity id: " + emotePacket.runtimeId + " != " + this.id); - return; - } - for (Player viewer : this.getViewers().values()) { - viewer.dataPacket(emotePacket); - } - return; - case ProtocolInfo.PLAYER_INPUT_PACKET: - if (!this.isAlive() || !this.spawned) { + ResourcePackDataInfoPacket dataInfoPacket = new ResourcePackDataInfoPacket(); + dataInfoPacket.packId = resourcePack.getPackId(); + dataInfoPacket.maxChunkSize = RESOURCE_PACK_CHUNK_SIZE; + dataInfoPacket.chunkCount = MathHelper.ceil(resourcePack.getPackSize() / (float) RESOURCE_PACK_CHUNK_SIZE); + dataInfoPacket.compressedPackSize = resourcePack.getPackSize(); + dataInfoPacket.sha256 = resourcePack.getSha256(); + this.dataPacket(dataInfoPacket); + } break; - } - PlayerInputPacket ipk = (PlayerInputPacket) packet; - if (riding instanceof EntityMinecartAbstract) { - ((EntityMinecartAbstract) riding).setCurrentSpeed(ipk.motionY); - } - break; - case ProtocolInfo.MOVE_PLAYER_PACKET: - if (this.teleportPosition != null) { + case ResourcePackClientResponsePacket.STATUS_HAVE_ALL_PACKS: + ResourcePackStackPacket stackPacket = new ResourcePackStackPacket(); + stackPacket.mustAccept = this.server.getForceResources(); + stackPacket.resourcePackStack = this.server.getResourcePackManager().getResourceStack(); + this.dataPacket(stackPacket); break; - } + case ResourcePackClientResponsePacket.STATUS_COMPLETED: + this.shouldLogin = true; - MovePlayerPacket movePlayerPacket = (MovePlayerPacket) packet; - Vector3 newPos = new Vector3(movePlayerPacket.x, movePlayerPacket.y - this.getEyeHeight(), movePlayerPacket.z); - - double dis = newPos.distanceSquared(this); - if (dis == 0 && movePlayerPacket.yaw % 360 == this.yaw && movePlayerPacket.pitch % 360 == this.pitch) { + if (this.preLoginEventTask.isFinished()) { + this.preLoginEventTask.onCompletion(server); + } break; - } + } + break; + case ProtocolInfo.RESOURCE_PACK_CHUNK_REQUEST_PACKET: + ResourcePackChunkRequestPacket requestPacket = (ResourcePackChunkRequestPacket) packet; + ResourcePack resourcePack = this.server.getResourcePackManager().getPackById(requestPacket.packId); + if (resourcePack == null) { + this.close("", "disconnectionScreen.resourcePack"); + break; + } - if (dis > 100) { - this.sendPosition(this, movePlayerPacket.yaw, movePlayerPacket.pitch, MovePlayerPacket.MODE_RESET); - break; - } + ResourcePackChunkDataPacket dataPacket = new ResourcePackChunkDataPacket(); + dataPacket.packId = resourcePack.getPackId(); + dataPacket.chunkIndex = requestPacket.chunkIndex; + dataPacket.data = resourcePack.getPackChunk(RESOURCE_PACK_CHUNK_SIZE * requestPacket.chunkIndex, RESOURCE_PACK_CHUNK_SIZE); + dataPacket.progress = (long) RESOURCE_PACK_CHUNK_SIZE * requestPacket.chunkIndex; + this.dataPacket(dataPacket); + break; + case ProtocolInfo.SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET: + if (this.locallyInitialized) { + break; + } + this.locallyInitialized = true; + PlayerLocallyInitializedEvent locallyInitializedEvent = new PlayerLocallyInitializedEvent(this); + this.server.getPluginManager().callEvent(locallyInitializedEvent); + break; + case ProtocolInfo.PLAYER_SKIN_PACKET: + PlayerSkinPacket skinPacket = (PlayerSkinPacket) packet; + Skin skin = skinPacket.skin; - boolean revert = false; - if (!this.isAlive() || !this.spawned) { - revert = true; - this.forceMovement = new Vector3(this.x, this.y, this.z); - } + if (!skin.isValid()) { + this.getServer().getLogger().debug(username + ": PlayerSkinPacket with invalid skin"); + break; + } - if (this.forceMovement != null && (newPos.distanceSquared(this.forceMovement) > 0.1 || revert)) { - this.sendPosition(this.forceMovement, movePlayerPacket.yaw, movePlayerPacket.pitch, MovePlayerPacket.MODE_RESET); - } else { + PlayerChangeSkinEvent playerChangeSkinEvent = new PlayerChangeSkinEvent(this, skin); + playerChangeSkinEvent.setCancelled(TimeUnit.SECONDS.toMillis(this.server.getPlayerSkinChangeCooldown()) > System.currentTimeMillis() - this.lastSkinChange); + this.server.getPluginManager().callEvent(playerChangeSkinEvent); + if (!playerChangeSkinEvent.isCancelled()) { + this.lastSkinChange = System.currentTimeMillis(); + this.setSkin(skin); + } - movePlayerPacket.yaw %= 360; - movePlayerPacket.pitch %= 360; + break; + case ProtocolInfo.PACKET_VIOLATION_WARNING_PACKET: + log.warn("Violation warning from {}: {}", this.getName(), packet.toString()); + break; + case ProtocolInfo.EMOTE_PACKET: + if (!this.spawned) { + return; + } + EmotePacket emotePacket = (EmotePacket) packet; + if (emotePacket.runtimeId != this.id) { + server.getLogger().warning(this.username + " sent EmotePacket with invalid entity id: " + emotePacket.runtimeId + " != " + this.id); + return; + } + for (Player viewer : this.getViewers().values()) { + viewer.dataPacket(emotePacket); + } + return; + case ProtocolInfo.PLAYER_INPUT_PACKET: + if (!this.isAlive() || !this.spawned) { + break; + } + PlayerInputPacket ipk = (PlayerInputPacket) packet; + if (riding instanceof EntityMinecartAbstract) { + ((EntityMinecartAbstract) riding).setCurrentSpeed(ipk.motionY); + } + break; + case ProtocolInfo.MOVE_PLAYER_PACKET: + if (this.teleportPosition != null) { + break; + } - if (movePlayerPacket.yaw < 0) { - movePlayerPacket.yaw += 360; - } + MovePlayerPacket movePlayerPacket = (MovePlayerPacket) packet; + Vector3 newPos = new Vector3(movePlayerPacket.x, movePlayerPacket.y - this.getEyeHeight(), movePlayerPacket.z); - this.setRotation(movePlayerPacket.yaw, movePlayerPacket.pitch); - this.newPosition = newPos; - this.forceMovement = null; - } + double dis = newPos.distanceSquared(this); + if (dis == 0 && movePlayerPacket.yaw % 360 == this.yaw && movePlayerPacket.pitch % 360 == this.pitch) { break; - case ProtocolInfo.PLAYER_AUTH_INPUT_PACKET: - PlayerAuthInputPacket authPacket = (PlayerAuthInputPacket) packet; - - if (!authPacket.getBlockActionData().isEmpty()) { - for (PlayerBlockActionData action : authPacket.getBlockActionData().values()) { - BlockVector3 blockPos = action.getPosition(); - BlockFace blockFace = BlockFace.fromIndex(action.getFacing()); - if (this.lastBlockAction != null && this.lastBlockAction.getAction() == PlayerActionType.PREDICT_DESTROY_BLOCK && - action.getAction() == PlayerActionType.CONTINUE_DESTROY_BLOCK) { - this.onBlockBreakStart(blockPos.asVector3(), blockFace); - } - - BlockVector3 lastBreakPos = this.lastBlockAction == null ? null : this.lastBlockAction.getPosition(); - if (lastBreakPos != null && (lastBreakPos.getX() != blockPos.getX() || - lastBreakPos.getY() != blockPos.getY() || lastBreakPos.getZ() != blockPos.getZ())) { - this.onBlockBreakAbort(lastBreakPos.asVector3(), BlockFace.DOWN); - this.onBlockBreakStart(blockPos.asVector3(), blockFace); - } + } - switch (action.getAction()) { - case START_DESTROY_BLOCK: - this.onBlockBreakStart(blockPos.asVector3(), blockFace); - break; - case ABORT_DESTROY_BLOCK: - case STOP_DESTROY_BLOCK: - this.onBlockBreakAbort(blockPos.asVector3(), blockFace); - break; - case CONTINUE_DESTROY_BLOCK: - this.onBlockBreakContinue(blockPos.asVector3(), blockFace); - break; - case PREDICT_DESTROY_BLOCK: - this.onBlockBreakAbort(blockPos.asVector3(), blockFace); - this.onBlockBreakComplete(blockPos, blockFace); - break; - } - this.lastBlockAction = action; - } - } + if (dis > 100) { + this.sendPosition(this, movePlayerPacket.yaw, movePlayerPacket.pitch, MovePlayerPacket.MODE_RESET); + break; + } - if (this.teleportPosition != null) { - break; - } + boolean revert = false; + if (!this.isAlive() || !this.spawned) { + revert = true; + this.forceMovement = new Vector3(this.x, this.y, this.z); + } - // Proper player.isPassenger() check may be needed - if (this.riding instanceof EntityMinecartAbstract) { - ((EntityMinecartAbstract) riding).setCurrentSpeed(authPacket.getMotion().getY()); - break; - } + if (this.forceMovement != null && (newPos.distanceSquared(this.forceMovement) > 0.1 || revert)) { + this.sendPosition(this.forceMovement, movePlayerPacket.yaw, movePlayerPacket.pitch, MovePlayerPacket.MODE_RESET); + } else { + movePlayerPacket.yaw %= 360; + movePlayerPacket.pitch %= 360; - if (authPacket.getInputData().contains(AuthInputAction.START_SPRINTING)) { - PlayerToggleSprintEvent event = new PlayerToggleSprintEvent(this, true); - this.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.sendData(this); - } else { - this.setSprinting(true); - } + if (movePlayerPacket.yaw < 0) { + movePlayerPacket.yaw += 360; } - if (authPacket.getInputData().contains(AuthInputAction.STOP_SPRINTING)) { - PlayerToggleSprintEvent event = new PlayerToggleSprintEvent(this, false); - this.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.sendData(this); - } else { - this.setSprinting(false); + this.setRotation(movePlayerPacket.yaw, movePlayerPacket.pitch); + this.newPosition = newPos; + this.forceMovement = null; + } + break; + case ProtocolInfo.PLAYER_AUTH_INPUT_PACKET: + PlayerAuthInputPacket authPacket = (PlayerAuthInputPacket) packet; + + if (!authPacket.getBlockActionData().isEmpty()) { + for (PlayerBlockActionData action : authPacket.getBlockActionData().values()) { + BlockVector3 blockPos = action.getPosition(); + BlockFace blockFace = BlockFace.fromIndex(action.getFacing()); + if (this.lastBlockAction != null && this.lastBlockAction.getAction() == PlayerActionType.PREDICT_DESTROY_BLOCK && + action.getAction() == PlayerActionType.CONTINUE_DESTROY_BLOCK) { + this.onBlockBreakStart(blockPos.asVector3(), blockFace); } - } - if (authPacket.getInputData().contains(AuthInputAction.START_SNEAKING)) { - PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this, true); - this.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.sendData(this); - } else { - this.setSneaking(true); + BlockVector3 lastBreakPos = this.lastBlockAction == null ? null : this.lastBlockAction.getPosition(); + if (lastBreakPos != null && (lastBreakPos.getX() != blockPos.getX() || + lastBreakPos.getY() != blockPos.getY() || lastBreakPos.getZ() != blockPos.getZ())) { + this.onBlockBreakAbort(lastBreakPos.asVector3(), BlockFace.DOWN); + this.onBlockBreakStart(blockPos.asVector3(), blockFace); } - } - if (authPacket.getInputData().contains(AuthInputAction.STOP_SNEAKING)) { - PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this, false); - this.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.sendData(this); - } else { - this.setSneaking(false); + switch (action.getAction()) { + case START_DESTROY_BLOCK: + this.onBlockBreakStart(blockPos.asVector3(), blockFace); + break; + case ABORT_DESTROY_BLOCK: + case STOP_DESTROY_BLOCK: + this.onBlockBreakAbort(blockPos.asVector3(), blockFace); + break; + case CONTINUE_DESTROY_BLOCK: + this.onBlockBreakContinue(blockPos.asVector3(), blockFace); + break; + case PREDICT_DESTROY_BLOCK: + this.onBlockBreakAbort(blockPos.asVector3(), blockFace); + this.onBlockBreakComplete(blockPos, blockFace); + break; } + this.lastBlockAction = action; } + } - if (authPacket.getInputData().contains(AuthInputAction.START_JUMPING)) { - PlayerJumpEvent playerJumpEvent = new PlayerJumpEvent(this); - this.server.getPluginManager().callEvent(playerJumpEvent); - } - - if (authPacket.getInputData().contains(AuthInputAction.START_GLIDING)) { - PlayerToggleGlideEvent playerToggleGlideEvent = new PlayerToggleGlideEvent(this, true); - this.server.getPluginManager().callEvent(playerToggleGlideEvent); - if (playerToggleGlideEvent.isCancelled()) { - this.sendData(this); - } else { - this.setGliding(true); - } - } + if (this.teleportPosition != null) { + break; + } - if (authPacket.getInputData().contains(AuthInputAction.STOP_GLIDING)) { - PlayerToggleGlideEvent playerToggleGlideEvent = new PlayerToggleGlideEvent(this, false); - this.server.getPluginManager().callEvent(playerToggleGlideEvent); - if (playerToggleGlideEvent.isCancelled()) { - this.sendData(this); - } else { - this.setGliding(false); - } - } + // Proper player.isPassenger() check may be needed + if (this.riding instanceof EntityMinecartAbstract) { + ((EntityMinecartAbstract) riding).setCurrentSpeed(authPacket.getMotion().getY()); + break; + } - if (authPacket.getInputData().contains(AuthInputAction.START_SWIMMING)) { - PlayerToggleSwimEvent ptse = new PlayerToggleSwimEvent(this, true); - this.server.getPluginManager().callEvent(ptse); - if (ptse.isCancelled()) { - this.sendData(this); - } else { - this.setSwimming(true); - } + if (authPacket.getInputData().contains(AuthInputAction.START_SPRINTING)) { + PlayerToggleSprintEvent event = new PlayerToggleSprintEvent(this, true); + this.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.sendData(this); + } else { + this.setSprinting(true); } + } - if (authPacket.getInputData().contains(AuthInputAction.STOP_SWIMMING)) { - PlayerToggleSwimEvent ptse = new PlayerToggleSwimEvent(this, false); - this.server.getPluginManager().callEvent(ptse); - if (ptse.isCancelled()) { - this.sendData(this); - } else { - this.setSwimming(false); - } + if (authPacket.getInputData().contains(AuthInputAction.STOP_SPRINTING)) { + PlayerToggleSprintEvent event = new PlayerToggleSprintEvent(this, false); + this.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.sendData(this); + } else { + this.setSprinting(false); } + } - Vector3 clientPosition = authPacket.getPosition().asVector3() - .subtract(0, this.getEyeHeight(), 0); - - double distSqrt = clientPosition.distanceSquared(this); - if (distSqrt == 0.0 && authPacket.getYaw() % 360 == this.yaw && authPacket.getPitch() % 360 == this.pitch) { - break; + if (authPacket.getInputData().contains(AuthInputAction.START_SNEAKING)) { + PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this, true); + this.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.sendData(this); + } else { + this.setSneaking(true); } + } - if (distSqrt > 100) { - this.sendPosition(this, authPacket.getYaw(), authPacket.getPitch(), MovePlayerPacket.MODE_RESET); - break; + if (authPacket.getInputData().contains(AuthInputAction.STOP_SNEAKING)) { + PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this, false); + this.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.sendData(this); + } else { + this.setSneaking(false); } + } - boolean revertMotion = false; - if (!this.isAlive() || !this.spawned) { - revertMotion = true; - this.forceMovement = new Vector3(this.x, this.y, this.z); - } + if (authPacket.getInputData().contains(AuthInputAction.START_JUMPING)) { + PlayerJumpEvent playerJumpEvent = new PlayerJumpEvent(this); + this.server.getPluginManager().callEvent(playerJumpEvent); + } - if (this.forceMovement != null && (clientPosition.distanceSquared(this.forceMovement) > 0.1 || revertMotion)) { - this.sendPosition(this.forceMovement, authPacket.getYaw(), authPacket.getPitch(), MovePlayerPacket.MODE_RESET); + if (authPacket.getInputData().contains(AuthInputAction.START_GLIDING)) { + PlayerToggleGlideEvent playerToggleGlideEvent = new PlayerToggleGlideEvent(this, true); + this.server.getPluginManager().callEvent(playerToggleGlideEvent); + if (playerToggleGlideEvent.isCancelled()) { + this.sendData(this); } else { - float yaw = authPacket.getYaw() % 360; - float pitch = authPacket.getPitch() % 360; - if (yaw < 0) { - yaw += 360; - } - - this.setRotation(yaw, pitch); - this.newPosition = clientPosition; - this.clientMovements.offer(clientPosition); - this.forceMovement = null; - } - break; - case ProtocolInfo.MOVE_ENTITY_ABSOLUTE_PACKET: - MoveEntityAbsolutePacket moveEntityAbsolutePacket = (MoveEntityAbsolutePacket) packet; - if (this.riding == null || this.riding.getId() != moveEntityAbsolutePacket.eid || !this.riding.isControlling(this)) { - break; - } - if (this.riding instanceof EntityBoat) { - if (this.temporalVector.setComponents(moveEntityAbsolutePacket.x, moveEntityAbsolutePacket.y, moveEntityAbsolutePacket.z).distanceSquared(this.riding) < 1000) { - ((EntityBoat) this.riding).onInput(moveEntityAbsolutePacket.x, moveEntityAbsolutePacket.y, moveEntityAbsolutePacket.z, moveEntityAbsolutePacket.headYaw); - } + this.setGliding(true); } - break; - case ProtocolInfo.REQUEST_ABILITY_PACKET: - RequestAbilityPacket abilityPacket = (RequestAbilityPacket) packet; + } - PlayerAbility ability = abilityPacket.getAbility(); - if (ability != PlayerAbility.FLYING) { - this.server.getLogger().info("[" + this.getName() + "] has tried to trigger " + ability + " ability " + (abilityPacket.isBoolValue() ? "on" : "off")); - return; + if (authPacket.getInputData().contains(AuthInputAction.STOP_GLIDING)) { + PlayerToggleGlideEvent playerToggleGlideEvent = new PlayerToggleGlideEvent(this, false); + this.server.getPluginManager().callEvent(playerToggleGlideEvent); + if (playerToggleGlideEvent.isCancelled()) { + this.sendData(this); + } else { + this.setGliding(false); } + } - if (!server.getAllowFlight() && abilityPacket.isBoolValue() && !this.getAdventureSettings().get(Type.ALLOW_FLIGHT)) { - this.kick(PlayerKickEvent.Reason.FLYING_DISABLED, "Flying is not enabled on this server"); - break; + if (authPacket.getInputData().contains(AuthInputAction.START_SWIMMING)) { + PlayerToggleSwimEvent ptse = new PlayerToggleSwimEvent(this, true); + this.server.getPluginManager().callEvent(ptse); + if (ptse.isCancelled()) { + this.sendData(this); + } else { + this.setSwimming(true); } + } - PlayerToggleFlightEvent playerToggleFlightEvent = new PlayerToggleFlightEvent(this, abilityPacket.isBoolValue()); - if (this.isSpectator()) { - playerToggleFlightEvent.setCancelled(); - } - this.server.getPluginManager().callEvent(playerToggleFlightEvent); - if (playerToggleFlightEvent.isCancelled()) { - this.getAdventureSettings().update(); + if (authPacket.getInputData().contains(AuthInputAction.STOP_SWIMMING)) { + PlayerToggleSwimEvent ptse = new PlayerToggleSwimEvent(this, false); + this.server.getPluginManager().callEvent(ptse); + if (ptse.isCancelled()) { + this.sendData(this); } else { - this.getAdventureSettings().set(Type.FLYING, playerToggleFlightEvent.isFlying()); - } - break; - case ProtocolInfo.MOB_EQUIPMENT_PACKET: - if (!this.spawned || !this.isAlive()) { - break; + this.setSwimming(false); } + } - MobEquipmentPacket mobEquipmentPacket = (MobEquipmentPacket) packet; + Vector3 clientPosition = authPacket.getPosition().asVector3() + .subtract(0, this.getEyeHeight(), 0); - Inventory inv = this.getWindowById(mobEquipmentPacket.windowId); + double distSqrt = clientPosition.distanceSquared(this); + if (distSqrt == 0.0 && authPacket.getYaw() % 360 == this.yaw && authPacket.getPitch() % 360 == this.pitch) { + break; + } - if (inv == null) { - this.server.getLogger().debug(this.getName() + " has no open container with window ID " + mobEquipmentPacket.windowId); - return; - } + if (distSqrt > 100) { + this.sendPosition(this, authPacket.getYaw(), authPacket.getPitch(), MovePlayerPacket.MODE_RESET); + break; + } - Item item = inv.getItem(mobEquipmentPacket.hotbarSlot); + boolean revertMotion = false; + if (!this.isAlive() || !this.spawned) { + revertMotion = true; + this.forceMovement = new Vector3(this.x, this.y, this.z); + } - if (!item.equals(mobEquipmentPacket.item)) { - this.server.getLogger().debug(this.getName() + " tried to equip " + mobEquipmentPacket.item + " but have " + item + " in target slot"); - inv.sendContents(this); - return; + if (this.forceMovement != null && (clientPosition.distanceSquared(this.forceMovement) > 0.1 || revertMotion)) { + this.sendPosition(this.forceMovement, authPacket.getYaw(), authPacket.getPitch(), MovePlayerPacket.MODE_RESET); + } else { + float yaw = authPacket.getYaw() % 360; + float pitch = authPacket.getPitch() % 360; + if (yaw < 0) { + yaw += 360; } - if (inv instanceof PlayerInventory) { - ((PlayerInventory) inv).equipItem(mobEquipmentPacket.hotbarSlot); + this.setRotation(yaw, pitch); + this.newPosition = clientPosition; + this.clientMovements.offer(clientPosition); + this.forceMovement = null; + } + break; + case ProtocolInfo.MOVE_ENTITY_ABSOLUTE_PACKET: + MoveEntityAbsolutePacket moveEntityAbsolutePacket = (MoveEntityAbsolutePacket) packet; + if (this.riding == null || this.riding.getId() != moveEntityAbsolutePacket.eid || !this.riding.isControlling(this)) { + break; + } + if (this.riding instanceof EntityBoat) { + if (this.temporalVector.setComponents(moveEntityAbsolutePacket.x, moveEntityAbsolutePacket.y, moveEntityAbsolutePacket.z).distanceSquared(this.riding) < 1000) { + ((EntityBoat) this.riding).onInput(moveEntityAbsolutePacket.x, moveEntityAbsolutePacket.y, moveEntityAbsolutePacket.z, moveEntityAbsolutePacket.headYaw); } + } + break; + case ProtocolInfo.REQUEST_ABILITY_PACKET: + RequestAbilityPacket abilityPacket = (RequestAbilityPacket) packet; - this.setDataFlag(Player.DATA_FLAGS, Player.DATA_FLAG_ACTION, false); + PlayerAbility ability = abilityPacket.getAbility(); + if (ability != PlayerAbility.FLYING) { + this.server.getLogger().info("[" + this.getName() + "] has tried to trigger " + ability + " ability " + (abilityPacket.isBoolValue() ? "on" : "off")); + return; + } + if (!server.getAllowFlight() && abilityPacket.isBoolValue() && !this.getAdventureSettings().get(Type.ALLOW_FLIGHT)) { + this.kick(PlayerKickEvent.Reason.FLYING_DISABLED, "Flying is not enabled on this server"); break; - case ProtocolInfo.PLAYER_ACTION_PACKET: - PlayerActionPacket playerActionPacket = (PlayerActionPacket) packet; - if (!this.spawned || !this.isAlive() && playerActionPacket.action != PlayerActionPacket.ACTION_RESPAWN) { - break; - } + } - switch (playerActionPacket.action) { - case PlayerActionPacket.ACTION_STOP_SLEEPING: - this.stopSleep(); - break; - case PlayerActionPacket.ACTION_RESPAWN: - if (!this.spawned || this.isAlive() || !this.isOnline()) { - break; - } - this.respawn(); - break; - case PlayerActionPacket.ACTION_DIMENSION_CHANGE_ACK: - this.sendPosition(this, this.yaw, this.pitch, MovePlayerPacket.MODE_RESET); - break; - } + PlayerToggleFlightEvent playerToggleFlightEvent = new PlayerToggleFlightEvent(this, abilityPacket.isBoolValue()); + if (this.isSpectator()) { + playerToggleFlightEvent.setCancelled(); + } - this.setUsingItem(false); - break; - case ProtocolInfo.MOB_ARMOR_EQUIPMENT_PACKET: + this.server.getPluginManager().callEvent(playerToggleFlightEvent); + if (playerToggleFlightEvent.isCancelled()) { + this.getAdventureSettings().update(); + } else { + this.getAdventureSettings().set(Type.FLYING, playerToggleFlightEvent.isFlying()); + } + break; + case ProtocolInfo.MOB_EQUIPMENT_PACKET: + if (!this.spawned || !this.isAlive()) { break; - case ProtocolInfo.MODAL_FORM_RESPONSE_PACKET: - if (!this.spawned || !this.isAlive()) { - break; - } + } - ModalFormResponsePacket modalFormPacket = (ModalFormResponsePacket) packet; + MobEquipmentPacket mobEquipmentPacket = (MobEquipmentPacket) packet; - if (formWindows.containsKey(modalFormPacket.formId)) { - FormWindow window = formWindows.remove(modalFormPacket.formId); - window.setResponse(modalFormPacket.data.trim()); + Inventory inv = this.getWindowById(mobEquipmentPacket.windowId); - for (FormResponseHandler handler : window.getHandlers()) { - handler.handle(this, modalFormPacket.formId); - } + if (inv == null) { + this.server.getLogger().debug(this.getName() + " has no open container with window ID " + mobEquipmentPacket.windowId); + return; + } - PlayerFormRespondedEvent event = new PlayerFormRespondedEvent(this, modalFormPacket.formId, window); - getServer().getPluginManager().callEvent(event); - } else if (serverSettings.containsKey(modalFormPacket.formId)) { - FormWindow window = serverSettings.get(modalFormPacket.formId); - window.setResponse(modalFormPacket.data.trim()); + Item item = inv.getItem(mobEquipmentPacket.hotbarSlot); - for (FormResponseHandler handler : window.getHandlers()) { - handler.handle(this, modalFormPacket.formId); - } + if (!item.equals(mobEquipmentPacket.item)) { + this.server.getLogger().debug(this.getName() + " tried to equip " + mobEquipmentPacket.item + " but have " + item + " in target slot"); + inv.sendContents(this); + return; + } - PlayerSettingsRespondedEvent event = new PlayerSettingsRespondedEvent(this, modalFormPacket.formId, window); - getServer().getPluginManager().callEvent(event); + if (inv instanceof PlayerInventory) { + ((PlayerInventory) inv).equipItem(mobEquipmentPacket.hotbarSlot); + } - //Set back new settings if not been cancelled - if (!event.isCancelled() && window instanceof FormWindowCustom) - ((FormWindowCustom) window).setElementsFromResponse(); - } + this.setDataFlag(Player.DATA_FLAGS, Player.DATA_FLAG_ACTION, false); + break; + case ProtocolInfo.PLAYER_ACTION_PACKET: + PlayerActionPacket playerActionPacket = (PlayerActionPacket) packet; + if (!this.spawned || !this.isAlive() && playerActionPacket.action != PlayerActionPacket.ACTION_RESPAWN) { break; + } - case ProtocolInfo.INTERACT_PACKET: - if (!this.spawned || !this.isAlive()) { + switch (playerActionPacket.action) { + case PlayerActionPacket.ACTION_STOP_SLEEPING: + this.stopSleep(); break; - } + case PlayerActionPacket.ACTION_RESPAWN: + if (!this.spawned || this.isAlive() || !this.isOnline()) { + break; + } + this.respawn(); + break; + case PlayerActionPacket.ACTION_DIMENSION_CHANGE_ACK: + this.sendPosition(this, this.yaw, this.pitch, MovePlayerPacket.MODE_RESET); + break; + } + this.setUsingItem(false); + break; + case ProtocolInfo.MOB_ARMOR_EQUIPMENT_PACKET: + break; + case ProtocolInfo.MODAL_FORM_RESPONSE_PACKET: + if (!this.spawned || !this.isAlive()) { + break; + } - InteractPacket interactPacket = (InteractPacket) packet; + ModalFormResponsePacket modalFormPacket = (ModalFormResponsePacket) packet; - if (interactPacket.target == 0 && interactPacket.action == InteractPacket.ACTION_MOUSEOVER) { - this.setButtonText(""); - break; + if (formWindows.containsKey(modalFormPacket.formId)) { + FormWindow window = formWindows.remove(modalFormPacket.formId); + window.setResponse(modalFormPacket.data.trim()); + + for (FormResponseHandler handler : window.getHandlers()) { + handler.handle(this, modalFormPacket.formId); } - Entity targetEntity = interactPacket.target == this.getId() ? this : this.level.getEntity(interactPacket.target); + PlayerFormRespondedEvent event = new PlayerFormRespondedEvent(this, modalFormPacket.formId, window); + getServer().getPluginManager().callEvent(event); + } else if (serverSettings.containsKey(modalFormPacket.formId)) { + FormWindow window = serverSettings.get(modalFormPacket.formId); + window.setResponse(modalFormPacket.data.trim()); - if (targetEntity == null || !this.isAlive() || !targetEntity.isAlive()) { - break; + for (FormResponseHandler handler : window.getHandlers()) { + handler.handle(this, modalFormPacket.formId); } - if (targetEntity instanceof EntityItem || targetEntity instanceof EntityArrow || targetEntity instanceof EntityXPOrb) { - this.kick(PlayerKickEvent.Reason.INVALID_PVE, "Attempting to interact with an invalid entity"); - this.server.getLogger().warning(this.getServer().getLanguage().translateString("nukkit.player.invalidEntity", this.getName())); - break; - } + PlayerSettingsRespondedEvent event = + new PlayerSettingsRespondedEvent(this, modalFormPacket.formId, window); + getServer().getPluginManager().callEvent(event); - switch (interactPacket.action) { - case InteractPacket.ACTION_MOUSEOVER: - String buttonText = ""; - if (targetEntity instanceof EntityInteractable) { - buttonText = ((EntityInteractable) targetEntity).getInteractButtonText(this); - if (buttonText == null) { - buttonText = ""; - } - } - this.setButtonText(buttonText); + //Set back new settings if not been cancelled + if (!event.isCancelled() && window instanceof FormWindowCustom) + ((FormWindowCustom) window).setElementsFromResponse(); + } - this.getServer().getPluginManager().callEvent(new PlayerMouseOverEntityEvent(this, targetEntity)); - break; - case InteractPacket.ACTION_VEHICLE_EXIT: - if (!(targetEntity instanceof EntityRideable) || this.riding != targetEntity) { - break; - } + break; - ((EntityRideable) riding).dismountEntity(this); - break; - case InteractPacket.ACTION_OPEN_INVENTORY: - if (targetEntity != this) { - break; - } - if (!this.inventoryOpen) { - this.inventory.open(this); - this.inventoryOpen = true; - } - break; - } + case ProtocolInfo.INTERACT_PACKET: + if (!this.spawned || !this.isAlive()) { break; - case ProtocolInfo.BLOCK_PICK_REQUEST_PACKET: - BlockPickRequestPacket pickRequestPacket = (BlockPickRequestPacket) packet; - Block block = this.level.getBlock(pickRequestPacket.x, pickRequestPacket.y, pickRequestPacket.z, false); - if (block.distanceSquared(this) > 1000) { - this.getServer().getLogger().debug(username + ": Block pick request for a block too far away"); - return; - } - item = block.toItem(); - - if (pickRequestPacket.addUserData) { - BlockEntity blockEntity = this.getLevel().getBlockEntity(new Vector3(pickRequestPacket.x, pickRequestPacket.y, pickRequestPacket.z)); - if (blockEntity != null) { - CompoundTag nbt = blockEntity.getCleanedNBT(); - if (nbt != null) { - item.setCustomBlockData(nbt); - item.setLore("+(DATA)"); - } - } - } + } - PlayerBlockPickEvent pickEvent = new PlayerBlockPickEvent(this, block, item); - if (this.isSpectator()) { - log.debug("Got block-pick request from " + this.getName() + " when in spectator mode"); - pickEvent.setCancelled(); - } + InteractPacket interactPacket = (InteractPacket) packet; + + if (interactPacket.target == 0 && interactPacket.action == InteractPacket.ACTION_MOUSEOVER) { + this.setButtonText(""); + break; + } - this.server.getPluginManager().callEvent(pickEvent); + Entity targetEntity = interactPacket.target == this.getId() ? this : this.level.getEntity(interactPacket.target); - if (!pickEvent.isCancelled()) { - boolean itemExists = false; - int itemSlot = -1; - for (int slot = 0; slot < this.inventory.getSize(); slot++) { - if (this.inventory.getItem(slot).equals(pickEvent.getItem())) { - if (slot < this.inventory.getHotbarSize()) { - this.inventory.setHeldItemSlot(slot); - } else { - itemSlot = slot; - } - itemExists = true; - break; + if (targetEntity == null || !this.isAlive() || !targetEntity.isAlive()) { + break; + } + + if (targetEntity instanceof EntityItem || targetEntity instanceof EntityArrow || targetEntity instanceof EntityXPOrb) { + this.kick(PlayerKickEvent.Reason.INVALID_PVE, "Attempting to interact with an invalid entity"); + this.server.getLogger().warning(this.getServer().getLanguage().translateString("nukkit.player.invalidEntity", this.getName())); + break; + } + + switch (interactPacket.action) { + case InteractPacket.ACTION_MOUSEOVER: + String buttonText = ""; + if (targetEntity instanceof EntityInteractable) { + buttonText = + ((EntityInteractable) targetEntity).getInteractButtonText(this); + if (buttonText == null) { + buttonText = ""; } } + this.setButtonText(buttonText); - for (int slot = 0; slot < this.inventory.getHotbarSize(); slot++) { - if (this.inventory.getItem(slot).isNull()) { - if (!itemExists && this.isCreative()) { - this.inventory.setHeldItemSlot(slot); - this.inventory.setItemInHand(pickEvent.getItem()); - break packetswitch; - } else if (itemSlot > -1) { - this.inventory.setHeldItemSlot(slot); - this.inventory.setItemInHand(this.inventory.getItem(itemSlot)); - this.inventory.clear(itemSlot, true); - break packetswitch; - } - } + this.getServer().getPluginManager() + .callEvent(new PlayerMouseOverEntityEvent(this, targetEntity)); + break; + case InteractPacket.ACTION_VEHICLE_EXIT: + if (!(targetEntity instanceof EntityRideable) || + this.riding != targetEntity) { + break; } - if (!itemExists && this.isCreative()) { - Item itemInHand = this.inventory.getItemInHand(); - this.inventory.setItemInHand(pickEvent.getItem()); - if (!this.inventory.isFull()) { - for (int slot = 0; slot < this.inventory.getSize(); slot++) { - if (this.inventory.getItem(slot).isNull()) { - this.inventory.setItem(slot, itemInHand); - break; - } - } - } - } else if (itemSlot > -1) { - Item itemInHand = this.inventory.getItemInHand(); - this.inventory.setItemInHand(this.inventory.getItem(itemSlot)); - this.inventory.setItem(itemSlot, itemInHand); + ((EntityRideable) riding).dismountEntity(this); + break; + case InteractPacket.ACTION_OPEN_INVENTORY: + if (targetEntity != this) { + break; + } + if (!this.inventoryOpen) { + this.inventory.open(this); + this.inventoryOpen = true; } - } - break; - case ProtocolInfo.ANIMATE_PACKET: - if (!this.spawned || !this.isAlive()) { break; + } + break; + case ProtocolInfo.BLOCK_PICK_REQUEST_PACKET: + BlockPickRequestPacket pickRequestPacket = (BlockPickRequestPacket) packet; + Block block = this.level.getBlock(pickRequestPacket.x, pickRequestPacket.y, pickRequestPacket.z, false); + if (block.distanceSquared(this) > 1000) { + this.getServer().getLogger().debug(username + ": Block pick request for a block too far away"); + return; + } + item = block.toItem(); + + if (pickRequestPacket.addUserData) { + BlockEntity blockEntity = this.getLevel().getBlockEntity(new Vector3(pickRequestPacket.x, pickRequestPacket.y, pickRequestPacket.z)); + if (blockEntity != null) { + CompoundTag nbt = blockEntity.getCleanedNBT(); + if (nbt != null) { + item.setCustomBlockData(nbt); + item.setLore("+(DATA)"); + } } + } - AnimatePacket animatePacket = (AnimatePacket) packet; - PlayerAnimationEvent animationEvent = new PlayerAnimationEvent(this, animatePacket.action); + PlayerBlockPickEvent pickEvent = new PlayerBlockPickEvent(this, block, item); + if (this.isSpectator()) { + log.debug("Got block-pick request from " + this.getName() + " when in spectator mode"); + pickEvent.setCancelled(); + } - // prevent client send illegal packet to server and broadcast to other client and make other client crash - if(animatePacket.action == null // illegal action id - || animatePacket.action == AnimatePacket.Action.WAKE_UP // these actions are only for server to client - || animatePacket.action == AnimatePacket.Action.CRITICAL_HIT - || animatePacket.action == AnimatePacket.Action.MAGIC_CRITICAL_HIT) { - break; // maybe we should cancel the event here? but if client send too many packets, server will lag + this.server.getPluginManager().callEvent(pickEvent); + + if (!pickEvent.isCancelled()) { + boolean itemExists = false; + int itemSlot = -1; + for (int slot = 0; slot < this.inventory.getSize(); slot++) { + if (this.inventory.getItem(slot).equals(pickEvent.getItem())) { + if (slot < this.inventory.getHotbarSize()) { + this.inventory.setHeldItemSlot(slot); + } else { + itemSlot = slot; + } + itemExists = true; + break; + } } - this.server.getPluginManager().callEvent(animationEvent); - if (animationEvent.isCancelled()) { - break; + for (int slot = 0; slot < this.inventory.getHotbarSize(); slot++) { + if (this.inventory.getItem(slot).isNull()) { + if (!itemExists && this.isCreative()) { + this.inventory.setHeldItemSlot(slot); + this.inventory.setItemInHand(pickEvent.getItem()); + break packetswitch; + } else if (itemSlot > -1) { + this.inventory.setHeldItemSlot(slot); + this.inventory.setItemInHand(this.inventory.getItem(itemSlot)); + this.inventory.clear(itemSlot, true); + break packetswitch; + } + } } - AnimatePacket.Action animation = animationEvent.getAnimationType(); - - switch (animation) { - case ROW_RIGHT: - case ROW_LEFT: - if (this.riding instanceof EntityBoat) { - ((EntityBoat) this.riding).onPaddle(animation, ((AnimatePacket) packet).rowingTime); + if (!itemExists && this.isCreative()) { + Item itemInHand = this.inventory.getItemInHand(); + this.inventory.setItemInHand(pickEvent.getItem()); + if (!this.inventory.isFull()) { + for (int slot = 0; slot < this.inventory.getSize(); slot++) { + if (this.inventory.getItem(slot).isNull()) { + this.inventory.setItem(slot, itemInHand); + break; + } } - break; + } + } else if (itemSlot > -1) { + Item itemInHand = this.inventory.getItemInHand(); + this.inventory.setItemInHand(this.inventory.getItem(itemSlot)); + this.inventory.setItem(itemSlot, itemInHand); } - - animatePacket.eid = this.getId(); - animatePacket.action = animationEvent.getAnimationType(); - Server.broadcastPacket(this.getViewers().values(), animatePacket); - break; - case ProtocolInfo.SET_HEALTH_PACKET: - //use UpdateAttributePacket instead + } + break; + case ProtocolInfo.ANIMATE_PACKET: + if (!this.spawned || !this.isAlive()) { break; + } - case ProtocolInfo.ENTITY_EVENT_PACKET: - if (!this.spawned || !this.isAlive()) { - break; - } - EntityEventPacket entityEventPacket = (EntityEventPacket) packet; - if (entityEventPacket.event != EntityEventPacket.ENCHANT) - this.craftingType = CRAFTING_SMALL; - //this.resetCraftingGridType(); + AnimatePacket animatePacket = (AnimatePacket) packet; + PlayerAnimationEvent animationEvent = new PlayerAnimationEvent(this, animatePacket.action); + // prevent client send illegal packet to server and broadcast to other client and make other client crash + if (animatePacket.action == null // illegal action id + || animatePacket.action == AnimatePacket.Action.WAKE_UP // these actions are only for server to client + || animatePacket.action == AnimatePacket.Action.CRITICAL_HIT + || animatePacket.action == AnimatePacket.Action.MAGIC_CRITICAL_HIT) { + break; // maybe we should cancel the event here? but if client send too many packets, server will lag + } - if (entityEventPacket.event == EntityEventPacket.EATING_ITEM) { - if (entityEventPacket.data == 0 || entityEventPacket.eid != this.id) { - break; - } + this.server.getPluginManager().callEvent(animationEvent); + if (animationEvent.isCancelled()) { + break; + } - entityEventPacket.eid = this.id; - entityEventPacket.isEncoded = false; + AnimatePacket.Action animation = animationEvent.getAnimationType(); - this.dataPacket(entityEventPacket); - Server.broadcastPacket(this.getViewers().values(), entityEventPacket); - } else if (entityEventPacket.event == EntityEventPacket.ENCHANT) { - if (entityEventPacket.eid != this.id) { - break; + switch (animation) { + case ROW_RIGHT: + case ROW_LEFT: + if (this.riding instanceof EntityBoat) { + ((EntityBoat) this.riding).onPaddle(animation, + ((AnimatePacket) packet).rowingTime); } + break; + } - Inventory inventory = this.getWindowById(ANVIL_WINDOW_ID); - if (inventory instanceof AnvilInventory) { - ((AnvilInventory) inventory).setCost(-entityEventPacket.data); - } - } + animatePacket.eid = this.getId(); + animatePacket.action = animationEvent.getAnimationType(); + Server.broadcastPacket(this.getViewers().values(), animatePacket); + break; + case ProtocolInfo.SET_HEALTH_PACKET: + //use UpdateAttributePacket instead + break; + + case ProtocolInfo.ENTITY_EVENT_PACKET: + if (!this.spawned || !this.isAlive()) { break; - case ProtocolInfo.COMMAND_REQUEST_PACKET: - if (!this.spawned || !this.isAlive()) { - break; - } + } + EntityEventPacket entityEventPacket = (EntityEventPacket) packet; + if (entityEventPacket.event != EntityEventPacket.ENCHANT) this.craftingType = CRAFTING_SMALL; - CommandRequestPacket commandRequestPacket = (CommandRequestPacket) packet; - PlayerCommandPreprocessEvent playerCommandPreprocessEvent = new PlayerCommandPreprocessEvent(this, commandRequestPacket.command); - this.server.getPluginManager().callEvent(playerCommandPreprocessEvent); - if (playerCommandPreprocessEvent.isCancelled()) { - break; - } + //this.resetCraftingGridType(); - Timings.playerCommandTimer.startTiming(); - this.server.dispatchCommand(playerCommandPreprocessEvent.getPlayer(), playerCommandPreprocessEvent.getMessage().substring(1)); - Timings.playerCommandTimer.stopTiming(); - break; - case ProtocolInfo.TEXT_PACKET: - if (!this.spawned || !this.isAlive()) { + if (entityEventPacket.event == EntityEventPacket.EATING_ITEM) { + if (entityEventPacket.data == 0 || entityEventPacket.eid != this.id) { break; } - TextPacket textPacket = (TextPacket) packet; + entityEventPacket.eid = this.id; + entityEventPacket.isEncoded = false; - if (textPacket.type == TextPacket.TYPE_CHAT) { - String chatMessage = textPacket.message; - int breakLine = chatMessage.indexOf('\n'); - // Chat messages shouldn't contain break lines so ignore text afterwards - if (breakLine != -1) { - chatMessage = chatMessage.substring(0, breakLine); - } - this.chat(chatMessage); - } - break; - case ProtocolInfo.CONTAINER_CLOSE_PACKET: - ContainerClosePacket containerClosePacket = (ContainerClosePacket) packet; - if (!this.spawned || containerClosePacket.windowId == ContainerIds.INVENTORY && !inventoryOpen) { + this.dataPacket(entityEventPacket); + Server.broadcastPacket(this.getViewers().values(), entityEventPacket); + } else if (entityEventPacket.event == EntityEventPacket.ENCHANT) { + if (entityEventPacket.eid != this.id) { break; } - if (this.windowIndex.containsKey(containerClosePacket.windowId)) { - this.server.getPluginManager().callEvent(new InventoryCloseEvent(this.windowIndex.get(containerClosePacket.windowId), this)); - if (containerClosePacket.windowId == ContainerIds.INVENTORY) this.inventoryOpen = false; - this.closingWindowId = containerClosePacket.windowId; - this.removeWindow(this.windowIndex.get(containerClosePacket.windowId), true); - this.closingWindowId = Integer.MIN_VALUE; - } - if (containerClosePacket.windowId == -1) { - this.craftingType = CRAFTING_SMALL; - this.resetCraftingGridType(); - this.addWindow(this.craftingGrid, ContainerIds.NONE); - ContainerClosePacket pk = new ContainerClosePacket(); - pk.wasServerInitiated = false; - pk.windowId = -1; - this.dataPacket(pk); + Inventory inventory = this.getWindowById(ANVIL_WINDOW_ID); + if (inventory instanceof AnvilInventory) { + ((AnvilInventory) inventory).setCost(-entityEventPacket.data); } + } + break; + case ProtocolInfo.COMMAND_REQUEST_PACKET: + if (!this.spawned || !this.isAlive()) { break; - case ProtocolInfo.CRAFTING_EVENT_PACKET: + } + this.craftingType = CRAFTING_SMALL; + CommandRequestPacket commandRequestPacket = (CommandRequestPacket) packet; + PlayerCommandPreprocessEvent playerCommandPreprocessEvent = new PlayerCommandPreprocessEvent(this, commandRequestPacket.command); + this.server.getPluginManager().callEvent(playerCommandPreprocessEvent); + if (playerCommandPreprocessEvent.isCancelled()) { break; - case ProtocolInfo.BLOCK_ENTITY_DATA_PACKET: - if (!this.spawned || !this.isAlive()) { - break; + } + + this.server.dispatchCommand(playerCommandPreprocessEvent.getPlayer(), playerCommandPreprocessEvent.getMessage().substring(1)); + break; + case ProtocolInfo.TEXT_PACKET: + if (!this.spawned || !this.isAlive()) { + break; + } + + TextPacket textPacket = (TextPacket) packet; + + if (textPacket.type == TextPacket.TYPE_CHAT) { + String chatMessage = textPacket.message; + int breakLine = chatMessage.indexOf('\n'); + // Chat messages shouldn't contain break lines so ignore text afterwards + if (breakLine != -1) { + chatMessage = chatMessage.substring(0, breakLine); } + this.chat(chatMessage); + } + break; + case ProtocolInfo.CONTAINER_CLOSE_PACKET: + ContainerClosePacket containerClosePacket = (ContainerClosePacket) packet; + if (!this.spawned || containerClosePacket.windowId == ContainerIds.INVENTORY && !inventoryOpen) { + break; + } - BlockEntityDataPacket blockEntityDataPacket = (BlockEntityDataPacket) packet; + if (this.windowIndex.containsKey(containerClosePacket.windowId)) { + this.server.getPluginManager().callEvent(new InventoryCloseEvent(this.windowIndex.get(containerClosePacket.windowId), this)); + if (containerClosePacket.windowId == ContainerIds.INVENTORY) this.inventoryOpen = false; + this.closingWindowId = containerClosePacket.windowId; + this.removeWindow(this.windowIndex.get(containerClosePacket.windowId), true); + this.closingWindowId = Integer.MIN_VALUE; + } + if (containerClosePacket.windowId == -1) { this.craftingType = CRAFTING_SMALL; this.resetCraftingGridType(); + this.addWindow(this.craftingGrid, ContainerIds.NONE); + ContainerClosePacket pk = new ContainerClosePacket(); + pk.wasServerInitiated = false; + pk.windowId = -1; + this.dataPacket(pk); + } + break; + case ProtocolInfo.CRAFTING_EVENT_PACKET: + break; + case ProtocolInfo.BLOCK_ENTITY_DATA_PACKET: + if (!this.spawned || !this.isAlive()) { + break; + } - Vector3 pos = new Vector3(blockEntityDataPacket.x, blockEntityDataPacket.y, blockEntityDataPacket.z); - if (pos.distanceSquared(this) > 10000) { - break; - } + BlockEntityDataPacket blockEntityDataPacket = (BlockEntityDataPacket) packet; + this.craftingType = CRAFTING_SMALL; + this.resetCraftingGridType(); - BlockEntity t = this.level.getBlockEntity(pos); - if (t instanceof BlockEntitySpawnable) { - CompoundTag nbt; - try { - nbt = NBTIO.read(blockEntityDataPacket.namedTag, ByteOrder.LITTLE_ENDIAN, true); - } catch (IOException e) { - throw new RuntimeException(e); - } + Vector3 pos = new Vector3(blockEntityDataPacket.x, blockEntityDataPacket.y, blockEntityDataPacket.z); + if (pos.distanceSquared(this) > 10000) { + break; + } - if (!((BlockEntitySpawnable) t).updateCompoundTag(nbt, this)) { - ((BlockEntitySpawnable) t).spawnTo(this); - } + BlockEntity t = this.level.getBlockEntity(pos); + if (t instanceof BlockEntitySpawnable) { + CompoundTag nbt; + try { + nbt = NBTIO.read(blockEntityDataPacket.namedTag, ByteOrder.LITTLE_ENDIAN, true); + } catch (IOException e) { + throw new RuntimeException(e); } - break; - case ProtocolInfo.REQUEST_CHUNK_RADIUS_PACKET: - RequestChunkRadiusPacket requestChunkRadiusPacket = (RequestChunkRadiusPacket) packet; - ChunkRadiusUpdatedPacket chunkRadiusUpdatePacket = new ChunkRadiusUpdatedPacket(); - this.chunkRadius = Math.max(3, Math.min(requestChunkRadiusPacket.radius, this.viewDistance)); - chunkRadiusUpdatePacket.radius = this.chunkRadius; - this.dataPacket(chunkRadiusUpdatePacket); - break; - case ProtocolInfo.SET_PLAYER_GAME_TYPE_PACKET: - SetPlayerGameTypePacket setPlayerGameTypePacket = (SetPlayerGameTypePacket) packet; - if (setPlayerGameTypePacket.gamemode != this.gamemode) { - if (!this.hasPermission("nukkit.command.gamemode")) { - SetPlayerGameTypePacket setPlayerGameTypePacket1 = new SetPlayerGameTypePacket(); - setPlayerGameTypePacket1.gamemode = this.gamemode & 0x01; - this.dataPacket(setPlayerGameTypePacket1); - this.getAdventureSettings().update(); - break; - } - this.setGamemode(setPlayerGameTypePacket.gamemode, true); - Command.broadcastCommandMessage(this, new TranslationContainer("commands.gamemode.success.self", Server.getGamemodeString(this.gamemode))); + + if (!((BlockEntitySpawnable) t).updateCompoundTag(nbt, this)) { + ((BlockEntitySpawnable) t).spawnTo(this); } - break; - case ProtocolInfo.ITEM_FRAME_DROP_ITEM_PACKET: - ItemFrameDropItemPacket itemFrameDropItemPacket = (ItemFrameDropItemPacket) packet; - Vector3 vector3 = this.temporalVector.setComponents(itemFrameDropItemPacket.x, itemFrameDropItemPacket.y, itemFrameDropItemPacket.z); - if (vector3.distanceSquared(this) < 1000) { - BlockEntity itemFrame = this.level.getBlockEntity(vector3); - if (itemFrame instanceof BlockEntityItemFrame) { - ((BlockEntityItemFrame) itemFrame).dropItem(this); - } + } + break; + case ProtocolInfo.REQUEST_CHUNK_RADIUS_PACKET: + RequestChunkRadiusPacket requestChunkRadiusPacket = (RequestChunkRadiusPacket) packet; + ChunkRadiusUpdatedPacket chunkRadiusUpdatePacket = new ChunkRadiusUpdatedPacket(); + this.chunkRadius = Math.max(3, Math.min(requestChunkRadiusPacket.radius, this.viewDistance)); + chunkRadiusUpdatePacket.radius = this.chunkRadius; + this.dataPacket(chunkRadiusUpdatePacket); + break; + case ProtocolInfo.SET_PLAYER_GAME_TYPE_PACKET: + SetPlayerGameTypePacket setPlayerGameTypePacket = (SetPlayerGameTypePacket) packet; + if (setPlayerGameTypePacket.gamemode != this.gamemode) { + if (!this.hasPermission("nukkit.command.gamemode")) { + SetPlayerGameTypePacket setPlayerGameTypePacket1 = new SetPlayerGameTypePacket(); + setPlayerGameTypePacket1.gamemode = this.gamemode & 0x01; + this.dataPacket(setPlayerGameTypePacket1); + this.getAdventureSettings().update(); + break; } - break; - case ProtocolInfo.MAP_INFO_REQUEST_PACKET: - MapInfoRequestPacket pk = (MapInfoRequestPacket) packet; - Item mapItem = null; + this.setGamemode(setPlayerGameTypePacket.gamemode, true); + Command.broadcastCommandMessage(this, new TranslationContainer("commands.gamemode.success.self", Server.getGamemodeString(this.gamemode))); + } + break; + case ProtocolInfo.ITEM_FRAME_DROP_ITEM_PACKET: + ItemFrameDropItemPacket itemFrameDropItemPacket = (ItemFrameDropItemPacket) packet; + Vector3 vector3 = this.temporalVector.setComponents(itemFrameDropItemPacket.x, itemFrameDropItemPacket.y, itemFrameDropItemPacket.z); + if (vector3.distanceSquared(this) < 1000) { + BlockEntity itemFrame = this.level.getBlockEntity(vector3); + if (itemFrame instanceof BlockEntityItemFrame) { + ((BlockEntityItemFrame) itemFrame).dropItem(this); + } + } + break; + case ProtocolInfo.MAP_INFO_REQUEST_PACKET: + MapInfoRequestPacket pk = (MapInfoRequestPacket) packet; + Item mapItem = null; - for (Item item1 : this.offhandInventory.getContents().values()) { - if (item1 instanceof ItemMap && ((ItemMap) item1).getMapId() == pk.mapId) { - mapItem = item1; - } + for (Item item1 : this.offhandInventory.getContents().values()) { + if (item1 instanceof ItemMap && ((ItemMap) item1).getMapId() == pk.mapId) { + mapItem = item1; } + } - if (mapItem == null) { - for (Item item1 : this.inventory.getContents().values()) { - if (item1 instanceof ItemMap && ((ItemMap) item1).getMapId() == pk.mapId) { - mapItem = item1; - } + if (mapItem == null) { + for (Item item1 : this.inventory.getContents().values()) { + if (item1 instanceof ItemMap && ((ItemMap) item1).getMapId() == pk.mapId) { + mapItem = item1; } } + } - if (mapItem == null) { - for (BlockEntity be : this.level.getBlockEntities().values()) { - if (be instanceof BlockEntityItemFrame) { - BlockEntityItemFrame itemFrame1 = (BlockEntityItemFrame) be; + if (mapItem == null) { + for (BlockEntity be : this.level.getBlockEntities().values()) { + if (be instanceof BlockEntityItemFrame) { + BlockEntityItemFrame itemFrame1 = (BlockEntityItemFrame) be; - if (itemFrame1.getItem() instanceof ItemMap && ((ItemMap) itemFrame1.getItem()).getMapId() == pk.mapId) { - ((ItemMap) itemFrame1.getItem()).sendImage(this); - break; - } + if (itemFrame1.getItem() instanceof ItemMap && ((ItemMap) itemFrame1.getItem()).getMapId() == pk.mapId) { + ((ItemMap) itemFrame1.getItem()).sendImage(this); + break; } } } + } - if (mapItem != null) { - PlayerMapInfoRequestEvent event; - getServer().getPluginManager().callEvent(event = new PlayerMapInfoRequestEvent(this, mapItem)); + if (mapItem != null) { + PlayerMapInfoRequestEvent event; + getServer().getPluginManager().callEvent(event = new PlayerMapInfoRequestEvent(this, mapItem)); - if (!event.isCancelled()) { - ((ItemMap) mapItem).sendImage(this); - } + if (!event.isCancelled()) { + ((ItemMap) mapItem).sendImage(this); } + } + break; + case ProtocolInfo.LEVEL_SOUND_EVENT_PACKET_V1: + case ProtocolInfo.LEVEL_SOUND_EVENT_PACKET_V2: + case ProtocolInfo.LEVEL_SOUND_EVENT_PACKET: + if (!this.isSpectator()) { + this.level.addChunkPacket(this.getChunkX(), this.getChunkZ(), packet); + } + break; + case ProtocolInfo.INVENTORY_TRANSACTION_PACKET: + if (this.isSpectator()) { + this.sendAllInventories(); break; - case ProtocolInfo.LEVEL_SOUND_EVENT_PACKET_V1: - case ProtocolInfo.LEVEL_SOUND_EVENT_PACKET_V2: - case ProtocolInfo.LEVEL_SOUND_EVENT_PACKET: - if (!this.isSpectator()) { - this.level.addChunkPacket(this.getChunkX(), this.getChunkZ(), packet); - } - break; - case ProtocolInfo.INVENTORY_TRANSACTION_PACKET: - if (this.isSpectator()) { - this.sendAllInventories(); - break; - } - - InventoryTransactionPacket transactionPacket = (InventoryTransactionPacket) packet; + } - List actions = new ArrayList<>(); - for (NetworkInventoryAction networkInventoryAction : transactionPacket.actions) { - InventoryAction a = networkInventoryAction.createInventoryAction(this); + InventoryTransactionPacket transactionPacket = (InventoryTransactionPacket) packet; - if (a == null) { - this.getServer().getLogger().debug("Unmatched inventory action from " + this.getName() + ": " + networkInventoryAction); - this.sendAllInventories(); - break packetswitch; - } + List actions = new ArrayList<>(); + for (NetworkInventoryAction networkInventoryAction : transactionPacket.actions) { + InventoryAction a = networkInventoryAction.createInventoryAction(this); - actions.add(a); + if (a == null) { + this.getServer().getLogger().debug("Unmatched inventory action from " + this.getName() + ": " + networkInventoryAction); + this.sendAllInventories(); + break packetswitch; } - if (transactionPacket.isCraftingPart) { - if (this.craftingTransaction == null) { - this.craftingTransaction = new CraftingTransaction(this, actions); - } else { - for (InventoryAction action : actions) { - this.craftingTransaction.addAction(action); - } + actions.add(a); + } + + if (transactionPacket.isCraftingPart) { + if (this.craftingTransaction == null) { + this.craftingTransaction = new CraftingTransaction(this, actions); + } else { + for (InventoryAction action : actions) { + this.craftingTransaction.addAction(action); } + } - if (this.craftingTransaction.getPrimaryOutput() != null && this.craftingTransaction.canExecute()) { - //we get the actions for this in several packets, so we can't execute it until we get the result + if (this.craftingTransaction.getPrimaryOutput() != null && this.craftingTransaction.canExecute()) { + //we get the actions for this in several packets, so we can't execute it until we get the result - this.craftingTransaction.execute(); - this.craftingTransaction = null; - } + this.craftingTransaction.execute(); + this.craftingTransaction = null; + } - return; - } else if (transactionPacket.isEnchantingPart) { - if (this.enchantTransaction == null) { - this.enchantTransaction = new EnchantTransaction(this, actions); - } else { - for (InventoryAction action : actions) { - this.enchantTransaction.addAction(action); - } - } - if (this.enchantTransaction.canExecute()) { - this.enchantTransaction.execute(); - this.enchantTransaction = null; - } - return; - } else if (transactionPacket.isRepairItemPart) { - if (this.repairItemTransaction == null) { - this.repairItemTransaction = new RepairItemTransaction(this, actions); - } else { - for (InventoryAction action : actions) { - this.repairItemTransaction.addAction(action); - } + return; + } else if (transactionPacket.isEnchantingPart) { + if (this.enchantTransaction == null) { + this.enchantTransaction = new EnchantTransaction(this, actions); + } else { + for (InventoryAction action : actions) { + this.enchantTransaction.addAction(action); } - if (this.repairItemTransaction.canExecute()) { - this.repairItemTransaction.execute(); - this.repairItemTransaction = null; + } + if (this.enchantTransaction.canExecute()) { + this.enchantTransaction.execute(); + this.enchantTransaction = null; + } + return; + } else if (transactionPacket.isRepairItemPart) { + if (this.repairItemTransaction == null) { + this.repairItemTransaction = new RepairItemTransaction(this, actions); + } else { + for (InventoryAction action : actions) { + this.repairItemTransaction.addAction(action); } - return; - } else if (this.craftingTransaction != null) { - if (craftingTransaction.checkForCraftingPart(actions)) { - for (InventoryAction action : actions) { - craftingTransaction.addAction(action); - } - return; - } else { - this.server.getLogger().debug("Got unexpected normal inventory action with incomplete crafting transaction from " + this.getName() + ", refusing to execute crafting"); - this.removeAllWindows(false); - this.sendAllInventories(); - this.craftingTransaction = null; + } + if (this.repairItemTransaction.canExecute()) { + this.repairItemTransaction.execute(); + this.repairItemTransaction = null; + } + return; + } else if (this.craftingTransaction != null) { + if (craftingTransaction.checkForCraftingPart(actions)) { + for (InventoryAction action : actions) { + craftingTransaction.addAction(action); } - } else if (this.enchantTransaction != null) { - if (enchantTransaction.checkForEnchantPart(actions)) { - for (InventoryAction action : actions) { - enchantTransaction.addAction(action); - } - return; - } else { - this.server.getLogger().debug("Got unexpected normal inventory action with incomplete enchanting transaction from " + this.getName() + ", refusing to execute enchant " + transactionPacket.toString()); - this.removeAllWindows(false); - this.sendAllInventories(); - this.enchantTransaction = null; + return; + } else { + this.server.getLogger().debug("Got unexpected normal inventory action with incomplete crafting transaction from " + this.getName() + ", refusing to execute crafting"); + this.removeAllWindows(false); + this.sendAllInventories(); + this.craftingTransaction = null; + } + } else if (this.enchantTransaction != null) { + if (enchantTransaction.checkForEnchantPart(actions)) { + for (InventoryAction action : actions) { + enchantTransaction.addAction(action); } - } else if (this.repairItemTransaction != null) { - if (RepairItemTransaction.checkForRepairItemPart(actions)) { - for (InventoryAction action : actions) { - this.repairItemTransaction.addAction(action); - } - return; - } else { - this.server.getLogger().debug("Got unexpected normal inventory action with incomplete repair item transaction from " + this.getName() + ", refusing to execute repair item " + transactionPacket.toString()); - this.removeAllWindows(false); - this.sendAllInventories(); - this.repairItemTransaction = null; + return; + } else { + this.server.getLogger().debug("Got unexpected normal inventory action with incomplete enchanting transaction from " + this.getName() + ", refusing to execute enchant " + transactionPacket.toString()); + this.removeAllWindows(false); + this.sendAllInventories(); + this.enchantTransaction = null; + } + } else if (this.repairItemTransaction != null) { + if (RepairItemTransaction.checkForRepairItemPart(actions)) { + for (InventoryAction action : actions) { + this.repairItemTransaction.addAction(action); } + return; + } else { + this.server.getLogger().debug("Got unexpected normal inventory action with incomplete repair item transaction from " + this.getName() + ", refusing to execute repair item " + transactionPacket.toString()); + this.removeAllWindows(false); + this.sendAllInventories(); + this.repairItemTransaction = null; } + } - switch (transactionPacket.transactionType) { - case InventoryTransactionPacket.TYPE_NORMAL: - InventoryTransaction transaction = new InventoryTransaction(this, actions); - - if (!transaction.execute()) { - this.server.getLogger().debug("Failed to execute inventory transaction from " + this.getName() + " with actions: " + Arrays.toString(transactionPacket.actions)); - break packetswitch; //oops! - } + switch (transactionPacket.transactionType) { + case InventoryTransactionPacket.TYPE_NORMAL: + InventoryTransaction transaction = new InventoryTransaction(this, actions); - //TODO: fix achievement for getting iron from furnace + if (!transaction.execute()) { + this.server.getLogger().debug("Failed to execute inventory transaction from " + this.getName() + " with actions: " + Arrays.toString(transactionPacket.actions)); + break packetswitch; //oops! + } - break packetswitch; - case InventoryTransactionPacket.TYPE_MISMATCH: - if (transactionPacket.actions.length > 0) { - this.server.getLogger().debug("Expected 0 actions for mismatch, got " + transactionPacket.actions.length + ", " + Arrays.toString(transactionPacket.actions)); - } - this.sendAllInventories(); + //TODO: fix achievement for getting iron from furnace - break packetswitch; - case InventoryTransactionPacket.TYPE_USE_ITEM: - UseItemData useItemData = (UseItemData) transactionPacket.transactionData; + break packetswitch; - BlockVector3 blockVector = useItemData.blockPos; - face = useItemData.face; + case InventoryTransactionPacket.TYPE_MISMATCH: + if (transactionPacket.actions.length > 0) { + this.server.getLogger().debug("Expected 0 actions for mismatch, got " + transactionPacket.actions.length + ", " + Arrays.toString(transactionPacket.actions)); + } + this.sendAllInventories(); - int type = useItemData.actionType; - switch (type) { - case InventoryTransactionPacket.USE_ITEM_ACTION_CLICK_BLOCK: - // Remove if client bug is ever fixed - boolean spamBug = (lastRightClickPos != null && System.currentTimeMillis() - lastRightClickTime < 100.0 && blockVector.distanceSquared(lastRightClickPos) < 0.00001); - lastRightClickPos = blockVector.asVector3(); - lastRightClickTime = System.currentTimeMillis(); - if (spamBug) { - return; - } + break packetswitch; + case InventoryTransactionPacket.TYPE_USE_ITEM: + UseItemData useItemData = (UseItemData) transactionPacket.transactionData; + + BlockVector3 blockVector = useItemData.blockPos; + face = useItemData.face; + + int type = useItemData.actionType; + switch (type) { + case InventoryTransactionPacket.USE_ITEM_ACTION_CLICK_BLOCK: + // Remove if client bug is ever fixed + boolean spamBug = (lastRightClickPos != null && System.currentTimeMillis() - lastRightClickTime < 100.0 && blockVector.distanceSquared(lastRightClickPos) < 0.00001); + lastRightClickPos = blockVector.asVector3(); + lastRightClickTime = System.currentTimeMillis(); + if (spamBug) { + return; + } - this.setDataFlag(DATA_FLAGS, DATA_FLAG_ACTION, false); + this.setDataFlag(DATA_FLAGS, DATA_FLAG_ACTION, false); - if (this.canInteract(blockVector.add(0.5, 0.5, 0.5), this.isCreative() ? 13 : 7)) { - if (this.isCreative()) { - Item i = inventory.getItemInHand(); - if (this.level.useItemOn(blockVector.asVector3(), i, face, useItemData.clickPos.x, useItemData.clickPos.y, useItemData.clickPos.z, this) != null) { - break packetswitch; - } - } else if (inventory.getItemInHand().equals(useItemData.itemInHand)) { - Item i = inventory.getItemInHand(); - Item oldItem = i.clone(); - //TODO: Implement adventure mode checks - if ((i = this.level.useItemOn(blockVector.asVector3(), i, face, useItemData.clickPos.x, useItemData.clickPos.y, useItemData.clickPos.z, this)) != null) { - if (!i.equals(oldItem) || i.getCount() != oldItem.getCount()) { - if (oldItem.getId() == i.getId() || i.getId() == 0) { - inventory.setItemInHand(i); - } else { - server.getLogger().debug("Tried to set item " + i.getId() + " but " + this.username + " had item " + oldItem.getId() + " in their hand slot"); - } - inventory.sendHeldItem(this.getViewers().values()); + if (this.canInteract(blockVector.add(0.5, 0.5, 0.5), this.isCreative() ? 13 : 7)) { + if (this.isCreative()) { + Item i = inventory.getItemInHand(); + if (this.level.useItemOn(blockVector.asVector3(), i, face, useItemData.clickPos.x, useItemData.clickPos.y, useItemData.clickPos.z, this) != null) { + break packetswitch; + } + } else if (inventory.getItemInHand().equals(useItemData.itemInHand)) { + Item i = inventory.getItemInHand(); + Item oldItem = i.clone(); + //TODO: Implement adventure mode checks + if ((i = this.level.useItemOn(blockVector.asVector3(), i, face, useItemData.clickPos.x, useItemData.clickPos.y, useItemData.clickPos.z, this)) != null) { + if (!i.equals(oldItem) || i.getCount() != oldItem.getCount()) { + if (oldItem.getId() == i.getId() || i.getId() == 0) { + inventory.setItemInHand(i); + } else { + server.getLogger().debug("Tried to set item " + i.getId() + " but " + this.username + " had item " + oldItem.getId() + " in their hand slot"); } - break packetswitch; + inventory.sendHeldItem(this.getViewers().values()); } + break packetswitch; } } + } - inventory.sendHeldItem(this); + inventory.sendHeldItem(this); - if (blockVector.distanceSquared(this) > 10000) { - break packetswitch; - } + if (blockVector.distanceSquared(this) > 10000) { + break packetswitch; + } - Block target = this.level.getBlock(blockVector.asVector3()); - block = target.getSide(face); + Block target = this.level.getBlock(blockVector.asVector3()); + block = target.getSide(face); - this.level.sendBlocks(new Player[]{this}, new Block[]{target, block}, UpdateBlockPacket.FLAG_ALL_PRIORITY); + this.level.sendBlocks(new Player[]{this}, new Block[]{target, block}, UpdateBlockPacket.FLAG_ALL_PRIORITY); + break packetswitch; + case InventoryTransactionPacket.USE_ITEM_ACTION_BREAK_BLOCK: + if (!this.spawned || !this.isAlive()) { break packetswitch; - case InventoryTransactionPacket.USE_ITEM_ACTION_BREAK_BLOCK: - if (!this.spawned || !this.isAlive()) { - break packetswitch; - } + } - System.out.println("USE_ITEM_ACTION_BREAK_BLOCK"); + System.out.println("USE_ITEM_ACTION_BREAK_BLOCK"); - this.resetCraftingGridType(); + this.resetCraftingGridType(); - Item i = this.getInventory().getItemInHand(); + Item i = this.getInventory().getItemInHand(); - Item oldItem = i.clone(); + Item oldItem = i.clone(); - if (this.canInteract(blockVector.add(0.5, 0.5, 0.5), this.isCreative() ? 13 : 7) && (i = this.level.useBreakOn(blockVector.asVector3(), face, i, this, true)) != null) { - if (this.isSurvival()) { - this.getFoodData().updateFoodExpLevel(0.005); - if (!i.equals(oldItem) || i.getCount() != oldItem.getCount()) { - if (oldItem.getId() == i.getId() || i.getId() == 0) { - inventory.setItemInHand(i); - } else { - server.getLogger().debug("Tried to set item " + i.getId() + " but " + this.username + " had item " + oldItem.getId() + " in their hand slot"); - } - inventory.sendHeldItem(this.getViewers().values()); + if (this.canInteract(blockVector.add(0.5, 0.5, 0.5), this.isCreative() ? 13 : 7) && (i = this.level.useBreakOn(blockVector.asVector3(), face, i, this, true)) != null) { + if (this.isSurvival()) { + this.getFoodData().updateFoodExpLevel(0.005); + if (!i.equals(oldItem) || i.getCount() != oldItem.getCount()) { + if (oldItem.getId() == i.getId() || i.getId() == 0) { + inventory.setItemInHand(i); + } else { + server.getLogger().debug("Tried to set item " + i.getId() + " but " + this.username + " had item " + oldItem.getId() + " in their hand slot"); } + inventory.sendHeldItem(this.getViewers().values()); } - break packetswitch; } + break packetswitch; + } - inventory.sendContents(this); - inventory.sendHeldItem(this); + inventory.sendContents(this); + inventory.sendHeldItem(this); - if (blockVector.distanceSquared(this) < 10000) { - target = this.level.getBlock(blockVector.asVector3()); - this.level.sendBlocks(new Player[]{this}, new Block[]{target}, UpdateBlockPacket.FLAG_ALL_PRIORITY); + if (blockVector.distanceSquared(this) < 10000) { + target = this.level.getBlock(blockVector.asVector3()); + this.level.sendBlocks(new Player[]{this}, new Block[]{target}, UpdateBlockPacket.FLAG_ALL_PRIORITY); - BlockEntity blockEntity = this.level.getBlockEntity(blockVector.asVector3()); - if (blockEntity instanceof BlockEntitySpawnable) { - ((BlockEntitySpawnable) blockEntity).spawnTo(this); - } + BlockEntity blockEntity = this.level.getBlockEntity(blockVector.asVector3()); + if (blockEntity instanceof BlockEntitySpawnable) { + ((BlockEntitySpawnable) blockEntity).spawnTo(this); } + } - break packetswitch; - case InventoryTransactionPacket.USE_ITEM_ACTION_CLICK_AIR: - Vector3 directionVector = this.getDirectionVector(); + break packetswitch; + case InventoryTransactionPacket.USE_ITEM_ACTION_CLICK_AIR: + Vector3 directionVector = this.getDirectionVector(); - if (this.isCreative()) { - item = this.inventory.getItemInHand(); - } else if (!this.inventory.getItemInHand().equals(useItemData.itemInHand)) { - this.inventory.sendHeldItem(this); - break packetswitch; - } else { - item = this.inventory.getItemInHand(); - } + if (this.isCreative()) { + item = this.inventory.getItemInHand(); + } else if (!this.inventory.getItemInHand().equals(useItemData.itemInHand)) { + this.inventory.sendHeldItem(this); + break packetswitch; + } else { + item = this.inventory.getItemInHand(); + } - PlayerInteractEvent interactEvent = new PlayerInteractEvent(this, item, directionVector, face, Action.RIGHT_CLICK_AIR); + PlayerInteractEvent interactEvent = new PlayerInteractEvent(this, item, directionVector, face, Action.RIGHT_CLICK_AIR); - this.server.getPluginManager().callEvent(interactEvent); + this.server.getPluginManager().callEvent(interactEvent); - if (interactEvent.isCancelled()) { - this.inventory.sendHeldItem(this); - break packetswitch; - } + if (interactEvent.isCancelled()) { + this.inventory.sendHeldItem(this); + break packetswitch; + } - if (item.onClickAir(this, directionVector)) { - if (!this.isCreative()) { - if (item.getId() == 0 || this.inventory.getItemInHand().getId() == item.getId()) { - this.inventory.setItemInHand(item); - } else { - server.getLogger().debug("Tried to set item " + item.getId() + " but " + this.username + " had item " + this.inventory.getItemInHand().getId() + " in their hand slot"); - } + if (item.onClickAir(this, directionVector)) { + if (!this.isCreative()) { + if (item.getId() == 0 || this.inventory.getItemInHand().getId() == item.getId()) { + this.inventory.setItemInHand(item); + } else { + server.getLogger().debug("Tried to set item " + item.getId() + " but " + this.username + " had item " + this.inventory.getItemInHand().getId() + " in their hand slot"); } + } - if (!this.isUsingItem()) { - this.setUsingItem(true); - break packetswitch; - } + if (!this.isUsingItem()) { + this.setUsingItem(true); + break packetswitch; + } - // Used item - int ticksUsed = this.server.getTick() - this.startAction; - this.setUsingItem(false); + // Used item + int ticksUsed = this.server.getTick() - this.startAction; + this.setUsingItem(false); - if (!item.onUse(this, ticksUsed)) { - this.inventory.sendContents(this); - } + if (!item.onUse(this, ticksUsed)) { + this.inventory.sendContents(this); } + } - break packetswitch; - default: - //unknown - break; - } - break; - case InventoryTransactionPacket.TYPE_USE_ITEM_ON_ENTITY: - UseItemOnEntityData useItemOnEntityData = (UseItemOnEntityData) transactionPacket.transactionData; + break packetswitch; + default: + //unknown + break; + } + break; + case InventoryTransactionPacket.TYPE_USE_ITEM_ON_ENTITY: + UseItemOnEntityData useItemOnEntityData = (UseItemOnEntityData) transactionPacket.transactionData; - Entity target = this.level.getEntity(useItemOnEntityData.entityRuntimeId); - if (target == null) { - return; - } + Entity target = this.level.getEntity(useItemOnEntityData.entityRuntimeId); + if (target == null) { + return; + } - type = useItemOnEntityData.actionType; + type = useItemOnEntityData.actionType; - if (!useItemOnEntityData.itemInHand.equalsExact(this.inventory.getItemInHand())) { - this.inventory.sendHeldItem(this); - } + if (!useItemOnEntityData.itemInHand.equalsExact(this.inventory.getItemInHand())) { + this.inventory.sendHeldItem(this); + } - item = this.inventory.getItemInHand(); + item = this.inventory.getItemInHand(); - switch (type) { - case InventoryTransactionPacket.USE_ITEM_ON_ENTITY_ACTION_INTERACT: - PlayerInteractEntityEvent playerInteractEntityEvent = new PlayerInteractEntityEvent(this, target, item, useItemOnEntityData.clickPos); - if (this.isSpectator()) playerInteractEntityEvent.setCancelled(); - getServer().getPluginManager().callEvent(playerInteractEntityEvent); + switch (type) { + case InventoryTransactionPacket.USE_ITEM_ON_ENTITY_ACTION_INTERACT: + PlayerInteractEntityEvent playerInteractEntityEvent = new PlayerInteractEntityEvent(this, target, item, useItemOnEntityData.clickPos); + if (this.isSpectator()) playerInteractEntityEvent.setCancelled(); + getServer().getPluginManager().callEvent(playerInteractEntityEvent); - if (playerInteractEntityEvent.isCancelled()) { - break; - } - if (target.onInteract(this, item, useItemOnEntityData.clickPos) && this.isSurvival()) { - if (item.isTool()) { - if (item.useOn(target) && item.getDamage() >= item.getMaxDurability()) { - item = new ItemBlock(Block.get(BlockID.AIR)); - } - } else { - if (item.count > 1) { - item.count--; - } else { - item = new ItemBlock(Block.get(BlockID.AIR)); - } + if (playerInteractEntityEvent.isCancelled()) { + break; + } + if (target.onInteract(this, item, useItemOnEntityData.clickPos) && this.isSurvival()) { + if (item.isTool()) { + if (item.useOn(target) && item.getDamage() >= item.getMaxDurability()) { + item = new ItemBlock(Block.get(BlockID.AIR)); } - - if (item.getId() == 0 || this.inventory.getItemInHand().getId() == item.getId()) { - this.inventory.setItemInHand(item); + } else { + if (item.count > 1) { + item.count--; } else { - server.getLogger().debug("Tried to set item " + item.getId() + " but " + this.username + " had item " + this.inventory.getItemInHand().getId() + " in their hand slot"); + item = new ItemBlock(Block.get(BlockID.AIR)); } } + + if (item.getId() == 0 || this.inventory.getItemInHand().getId() == item.getId()) { + this.inventory.setItemInHand(item); + } else { + server.getLogger().debug("Tried to set item " + item.getId() + " but " + this.username + " had item " + this.inventory.getItemInHand().getId() + " in their hand slot"); + } + } + break; + case InventoryTransactionPacket.USE_ITEM_ON_ENTITY_ACTION_ATTACK: + if (!this.canInteract(target, isCreative() ? 8 : 5)) { break; - case InventoryTransactionPacket.USE_ITEM_ON_ENTITY_ACTION_ATTACK: - if (!this.canInteract(target, isCreative() ? 8 : 5)) { + } else if (target instanceof Player) { + if ((((Player) target).getGamemode() & 0x01) > 0) { + break; + } else if (!this.server.getPropertyBoolean("pvp")) { break; - } else if (target instanceof Player) { - if ((((Player) target).getGamemode() & 0x01) > 0) { - break; - } else if (!this.server.getPropertyBoolean("pvp")) { - break; - } } + } - Enchantment[] enchantments = item.getEnchantments(); + Enchantment[] enchantments = item.getEnchantments(); - float itemDamage = item.getAttackDamage(); - for (Enchantment enchantment : enchantments) { - itemDamage += enchantment.getDamageBonus(target); - } + float itemDamage = item.getAttackDamage(); + for (Enchantment enchantment : enchantments) { + itemDamage += enchantment.getDamageBonus(target); + } - Map damage = new EnumMap<>(DamageModifier.class); - damage.put(DamageModifier.BASE, itemDamage); + Map damage = new EnumMap<>(DamageModifier.class); + damage.put(DamageModifier.BASE, itemDamage); - float knockBack = 0.3f; - Enchantment knockBackEnchantment = item.getEnchantment(Enchantment.ID_KNOCKBACK); - if (knockBackEnchantment != null) { - knockBack += knockBackEnchantment.getLevel() * 0.1f; - } + float knockBack = 0.3f; + Enchantment knockBackEnchantment = item.getEnchantment(Enchantment.ID_KNOCKBACK); + if (knockBackEnchantment != null) { + knockBack += knockBackEnchantment.getLevel() * 0.1f; + } - EntityDamageByEntityEvent entityDamageByEntityEvent = new EntityDamageByEntityEvent(this, target, DamageCause.ENTITY_ATTACK, damage, knockBack, enchantments); - if (this.isSpectator()) entityDamageByEntityEvent.setCancelled(); - if ((target instanceof Player) && !this.level.getGameRules().getBoolean(GameRule.PVP)) { - entityDamageByEntityEvent.setCancelled(); - } + EntityDamageByEntityEvent entityDamageByEntityEvent = new EntityDamageByEntityEvent(this, target, DamageCause.ENTITY_ATTACK, damage, knockBack, enchantments); + if (this.isSpectator()) entityDamageByEntityEvent.setCancelled(); + if ((target instanceof Player) && !this.level.getGameRules().getBoolean(GameRule.PVP)) { + entityDamageByEntityEvent.setCancelled(); + } - if (!target.attack(entityDamageByEntityEvent)) { - if (item.isTool() && this.isSurvival()) { - this.inventory.sendContents(this); - } - break; + if (!target.attack(entityDamageByEntityEvent)) { + if (item.isTool() && this.isSurvival()) { + this.inventory.sendContents(this); } + break; + } - for (Enchantment enchantment : item.getEnchantments()) { - enchantment.doPostAttack(this, target); - } + for (Enchantment enchantment : item.getEnchantments()) { + enchantment.doPostAttack(this, target); + } - if (item.isTool() && (this.isSurvival() || this.isAdventure())) { - if (item.useOn(target) && item.getDamage() >= item.getMaxDurability()) { - this.inventory.setItemInHand(Item.get(0)); + if (item.isTool() && (this.isSurvival() || this.isAdventure())) { + if (item.useOn(target) && item.getDamage() >= item.getMaxDurability()) { + this.inventory.setItemInHand(Item.get(0)); + } else { + if (item.getId() == 0 || this.inventory.getItemInHand().getId() == item.getId()) { + this.inventory.setItemInHand(item); } else { - if (item.getId() == 0 || this.inventory.getItemInHand().getId() == item.getId()) { - this.inventory.setItemInHand(item); - } else { - server.getLogger().debug("Tried to set item " + item.getId() + " but " + this.username + " had item " + this.inventory.getItemInHand().getId() + " in their hand slot"); - } + server.getLogger().debug("Tried to set item " + item.getId() + " but " + this.username + " had item " + this.inventory.getItemInHand().getId() + " in their hand slot"); } } - return; - default: - break; //unknown - } + } + return; + default: + break; //unknown + } + break; - break; - case InventoryTransactionPacket.TYPE_RELEASE_ITEM: - if (this.isSpectator()) { - this.sendAllInventories(); - break packetswitch; - } - ReleaseItemData releaseItemData = (ReleaseItemData) transactionPacket.transactionData; - - try { - type = releaseItemData.actionType; - switch (type) { - case InventoryTransactionPacket.RELEASE_ITEM_ACTION_RELEASE: - if (this.isUsingItem()) { - item = this.inventory.getItemInHand(); - - int ticksUsed = this.server.getTick() - this.startAction; - if (!item.onRelease(this, ticksUsed)) { - this.inventory.sendContents(this); - } + case InventoryTransactionPacket.TYPE_RELEASE_ITEM: + if (this.isSpectator()) { + this.sendAllInventories(); + break packetswitch; + } + ReleaseItemData releaseItemData = (ReleaseItemData) transactionPacket.transactionData; - this.setUsingItem(false); - } else { + try { + type = releaseItemData.actionType; + switch (type) { + case InventoryTransactionPacket.RELEASE_ITEM_ACTION_RELEASE: + if (this.isUsingItem()) { + item = this.inventory.getItemInHand(); + + int ticksUsed = this.server.getTick() - this.startAction; + if (!item.onRelease(this, ticksUsed)) { this.inventory.sendContents(this); } - return; - case InventoryTransactionPacket.RELEASE_ITEM_ACTION_CONSUME: - log.debug("Unexpected release item action consume from {}", this::getName); - return; - default: - break; - } - } finally { - this.setUsingItem(false); + + this.setUsingItem(false); + } else { + this.inventory.sendContents(this); + } + return; + case InventoryTransactionPacket.RELEASE_ITEM_ACTION_CONSUME: + log.debug("Unexpected release item action consume from {}", + this::getName); + return; + default: + break; } - break; - default: - this.inventory.sendContents(this); - break; - } - break; - case ProtocolInfo.PLAYER_HOTBAR_PACKET: - PlayerHotbarPacket hotbarPacket = (PlayerHotbarPacket) packet; + } finally { + this.setUsingItem(false); + } + break; + default: + this.inventory.sendContents(this); + break; + } + break; + case ProtocolInfo.PLAYER_HOTBAR_PACKET: + PlayerHotbarPacket hotbarPacket = (PlayerHotbarPacket) packet; - if (hotbarPacket.windowId != ContainerIds.INVENTORY) { - return; //In PE this should never happen - } + if (hotbarPacket.windowId != ContainerIds.INVENTORY) { + return; //In PE this should never happen + } - this.inventory.equipItem(hotbarPacket.selectedHotbarSlot); - break; - case ProtocolInfo.SERVER_SETTINGS_REQUEST_PACKET: - PlayerServerSettingsRequestEvent settingsRequestEvent = new PlayerServerSettingsRequestEvent(this, new HashMap<>(this.serverSettings)); - this.getServer().getPluginManager().callEvent(settingsRequestEvent); - - if (!settingsRequestEvent.isCancelled()) { - settingsRequestEvent.getSettings().forEach((id, window) -> { - ServerSettingsResponsePacket re = new ServerSettingsResponsePacket(); - re.formId = id; - re.data = window.getJSONData(); - this.dataPacket(re); - }); - } - break; - case ProtocolInfo.RESPAWN_PACKET: - if (this.isAlive()) { - break; - } - RespawnPacket respawnPacket = (RespawnPacket) packet; - if (respawnPacket.respawnState == RespawnPacket.STATE_CLIENT_READY_TO_SPAWN) { - RespawnPacket respawn1 = new RespawnPacket(); - respawn1.x = (float) this.getX(); - respawn1.y = (float) this.getY(); - respawn1.z = (float) this.getZ(); - respawn1.respawnState = RespawnPacket.STATE_READY_TO_SPAWN; - this.dataPacket(respawn1); - } + this.inventory.equipItem(hotbarPacket.selectedHotbarSlot); + break; + case ProtocolInfo.SERVER_SETTINGS_REQUEST_PACKET: + PlayerServerSettingsRequestEvent settingsRequestEvent = new PlayerServerSettingsRequestEvent(this, new HashMap<>(this.serverSettings)); + this.getServer().getPluginManager().callEvent(settingsRequestEvent); + + if (!settingsRequestEvent.isCancelled()) { + settingsRequestEvent.getSettings().forEach((id, window) -> { + ServerSettingsResponsePacket re = new ServerSettingsResponsePacket(); + re.formId = id; + re.data = window.getJSONData(); + this.dataPacket(re); + }); + } + break; + case ProtocolInfo.RESPAWN_PACKET: + if (this.isAlive()) { break; - case ProtocolInfo.BOOK_EDIT_PACKET: - BookEditPacket bookEditPacket = (BookEditPacket) packet; - Item oldBook = this.inventory.getItem(bookEditPacket.inventorySlot); - if (oldBook.getId() != Item.BOOK_AND_QUILL) { - return; - } + } + RespawnPacket respawnPacket = (RespawnPacket) packet; + if (respawnPacket.respawnState == RespawnPacket.STATE_CLIENT_READY_TO_SPAWN) { + RespawnPacket respawn1 = new RespawnPacket(); + respawn1.x = (float) this.getX(); + respawn1.y = (float) this.getY(); + respawn1.z = (float) this.getZ(); + respawn1.respawnState = RespawnPacket.STATE_READY_TO_SPAWN; + this.dataPacket(respawn1); + } + break; + case ProtocolInfo.BOOK_EDIT_PACKET: + BookEditPacket bookEditPacket = (BookEditPacket) packet; + Item oldBook = this.inventory.getItem(bookEditPacket.inventorySlot); + if (oldBook.getId() != Item.BOOK_AND_QUILL) { + return; + } - if (bookEditPacket.text != null && bookEditPacket.text.length() > 256) { - this.getServer().getLogger().debug(username + ": BookEditPacket with too long text"); - return; - } + if (bookEditPacket.text != null && bookEditPacket.text.length() > 256) { + this.getServer().getLogger().debug(username + ": BookEditPacket with too long text"); + return; + } - Item newBook = oldBook.clone(); - boolean success; - switch (bookEditPacket.action) { - case REPLACE_PAGE: - success = ((ItemBookAndQuill) newBook).setPageText(bookEditPacket.pageNumber, bookEditPacket.text); - break; - case ADD_PAGE: - success = ((ItemBookAndQuill) newBook).insertPage(bookEditPacket.pageNumber, bookEditPacket.text); - break; - case DELETE_PAGE: - success = ((ItemBookAndQuill) newBook).deletePage(bookEditPacket.pageNumber); - break; - case SWAP_PAGES: - success = ((ItemBookAndQuill) newBook).swapPages(bookEditPacket.pageNumber, bookEditPacket.secondaryPageNumber); - break; - case SIGN_BOOK: - if (bookEditPacket.title == null || bookEditPacket.author == null || bookEditPacket.xuid == null || bookEditPacket.title.length() > 64 || bookEditPacket.author.length() > 64 || bookEditPacket.xuid.length() > 64) { - this.getServer().getLogger().debug(username + ": Invalid BookEditPacket action SIGN_BOOK: title/author/xuid is too long"); - return; - } - newBook = Item.get(Item.WRITTEN_BOOK, 0, 1, oldBook.getCompoundTag()); - success = ((ItemBookWritten) newBook).signBook(bookEditPacket.title, bookEditPacket.author, bookEditPacket.xuid, ItemBookWritten.GENERATION_ORIGINAL); - break; - default: + Item newBook = oldBook.clone(); + boolean success; + switch (bookEditPacket.action) { + case REPLACE_PAGE: + success = ((ItemBookAndQuill) newBook).setPageText(bookEditPacket.pageNumber, bookEditPacket.text); + break; + case ADD_PAGE: + success = ((ItemBookAndQuill) newBook).insertPage(bookEditPacket.pageNumber, bookEditPacket.text); + break; + case DELETE_PAGE: + success = ((ItemBookAndQuill) newBook).deletePage(bookEditPacket.pageNumber); + break; + case SWAP_PAGES: + success = ((ItemBookAndQuill) newBook).swapPages(bookEditPacket.pageNumber, bookEditPacket.secondaryPageNumber); + break; + case SIGN_BOOK: + if (bookEditPacket.title == null || bookEditPacket.author == null || bookEditPacket.xuid == null || bookEditPacket.title.length() > 64 || bookEditPacket.author.length() > 64 || bookEditPacket.xuid.length() > 64) { + this.getServer().getLogger().debug(username + ": Invalid BookEditPacket action SIGN_BOOK: title/author/xuid is too long"); return; - } - - if (success) { - PlayerEditBookEvent editBookEvent = new PlayerEditBookEvent(this, oldBook, newBook, bookEditPacket.action); - this.server.getPluginManager().callEvent(editBookEvent); - if (!editBookEvent.isCancelled()) { - this.inventory.setItem(bookEditPacket.inventorySlot, editBookEvent.getNewBook()); } - } - break; - case ProtocolInfo.FILTER_TEXT_PACKET: - FilterTextPacket filterTextPacket = (FilterTextPacket) packet; - if (filterTextPacket.text == null || filterTextPacket.text.length() > 64) { - this.getServer().getLogger().debug(username + ": FilterTextPacket with too long text"); - return; - } - FilterTextPacket textResponsePacket = new FilterTextPacket(); - textResponsePacket.text = filterTextPacket.text; - textResponsePacket.fromServer = true; - this.dataPacket(textResponsePacket); - break; - case ProtocolInfo.SET_DIFFICULTY_PACKET: - if (!this.spawned || !this.hasPermission("nukkit.command.difficulty")) { + newBook = Item.get(Item.WRITTEN_BOOK, 0, 1, oldBook.getCompoundTag()); + success = ((ItemBookWritten) newBook).signBook(bookEditPacket.title, bookEditPacket.author, bookEditPacket.xuid, ItemBookWritten.GENERATION_ORIGINAL); + break; + default: return; + } + + if (success) { + PlayerEditBookEvent editBookEvent = new PlayerEditBookEvent(this, oldBook, newBook, bookEditPacket.action); + this.server.getPluginManager().callEvent(editBookEvent); + if (!editBookEvent.isCancelled()) { + this.inventory.setItem(bookEditPacket.inventorySlot, editBookEvent.getNewBook()); } - server.setDifficulty(((SetDifficultyPacket) packet).difficulty); - SetDifficultyPacket difficultyPacket = new SetDifficultyPacket(); - difficultyPacket.difficulty = server.getDifficulty(); - Server.broadcastPacket(server.getOnlinePlayers().values(), difficultyPacket); - Command.broadcastCommandMessage(this, new TranslationContainer("commands.difficulty.success", String.valueOf(server.getDifficulty()))); - break; - default: - break; - } + } + break; + case ProtocolInfo.FILTER_TEXT_PACKET: + FilterTextPacket filterTextPacket = (FilterTextPacket) packet; + if (filterTextPacket.text == null || filterTextPacket.text.length() > 64) { + this.getServer().getLogger().debug(username + ": FilterTextPacket with too long text"); + return; + } + FilterTextPacket textResponsePacket = new FilterTextPacket(); + textResponsePacket.text = filterTextPacket.text; + textResponsePacket.fromServer = true; + this.dataPacket(textResponsePacket); + break; + case ProtocolInfo.SET_DIFFICULTY_PACKET: + if (!this.spawned || !this.hasPermission("nukkit.command.difficulty")) { + return; + } + server.setDifficulty(((SetDifficultyPacket) packet).difficulty); + SetDifficultyPacket difficultyPacket = new SetDifficultyPacket(); + difficultyPacket.difficulty = server.getDifficulty(); + Server.broadcastPacket(server.getOnlinePlayers().values(), difficultyPacket); + Command.broadcastCommandMessage(this, new TranslationContainer("commands.difficulty.success", String.valueOf(server.getDifficulty()))); + break; + default: + break; } } @@ -3709,6 +3701,7 @@ private void onBlockBreakComplete(BlockVector3 blockPos, BlockFace face) { /** * Sends a chat message as this player. If the message begins with a / (forward-slash) it will be treated * as a command. + * * @param message message to send * @return successful */ @@ -4463,7 +4456,7 @@ public void setMovementSpeed(float speed, boolean send) { } } - public void sendMovementSpeed(float speed){ + public void sendMovementSpeed(float speed) { Attribute attribute = Attribute.getAttribute(Attribute.MOVEMENT_SPEED).setValue(speed); this.setAttribute(attribute); } @@ -4775,7 +4768,7 @@ public int showFormWindow(FormWindow window) { * You can find out FormWindow result by listening to PlayerFormRespondedEvent * * @param window to show - * @param id form id + * @param id form id * @return form id to use in {@link PlayerFormRespondedEvent} */ public int showFormWindow(FormWindow window, int id) { @@ -5196,7 +5189,7 @@ public void setSprinting(boolean value) { if (isSprinting() != value) { super.setSprinting(value); - if(this.hasEffect(Effect.SPEED)) { + if (this.hasEffect(Effect.SPEED)) { float movementSpeed = this.getMovementSpeed(); this.sendMovementSpeed(value ? movementSpeed * 1.3f : movementSpeed); } @@ -5331,11 +5324,11 @@ public boolean pickupEntity(Entity entity, boolean near) { //Mending ArrayList itemsWithMending = new ArrayList<>(); for (int i = 0; i < 4; i++) { - if (inventory.getArmorItem(i).getEnchantment((short)Enchantment.ID_MENDING) != null) { + if (inventory.getArmorItem(i).getEnchantment((short) Enchantment.ID_MENDING) != null) { itemsWithMending.add(inventory.getSize() + i); } } - if (inventory.getItemInHand().getEnchantment((short)Enchantment.ID_MENDING) != null) { + if (inventory.getItemInHand().getEnchantment((short) Enchantment.ID_MENDING) != null) { itemsWithMending.add(inventory.getHeldItemIndex()); } if (itemsWithMending.size() > 0) { @@ -5387,6 +5380,7 @@ public boolean isBreakingBlock() { /** * Show a window of a XBOX account's profile + * * @param xuid XUID */ public void showXboxProfile(String xuid) { @@ -5397,6 +5391,7 @@ public void showXboxProfile(String xuid) { /** * Start fishing + * * @param fishingRod fishing rod item */ public void startFishing(Item fishingRod) { @@ -5430,6 +5425,7 @@ public void startFishing(Item fishingRod) { /** * Stop fishing + * * @param click clicked or forced */ public void stopFishing(boolean click) { diff --git a/src/main/java/cn/nukkit/Server.java b/src/main/java/cn/nukkit/Server.java index b1e6ee363f7..66ebe38822d 100644 --- a/src/main/java/cn/nukkit/Server.java +++ b/src/main/java/cn/nukkit/Server.java @@ -79,7 +79,6 @@ import cn.nukkit.scheduler.Task; import cn.nukkit.utils.*; import cn.nukkit.utils.bugreport.ExceptionHandler; -import co.aikar.timings.Timings; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import io.netty.buffer.ByteBuf; @@ -690,7 +689,6 @@ public void batchPackets(Player[] players, DataPacket[] packets, boolean forceSy return; } - Timings.playerNetworkSendTimer.startTiming(); byte[][] payload = new byte[packets.length * 2][]; for (int i = 0; i < packets.length; i++) { DataPacket p = packets[i]; @@ -719,7 +717,6 @@ public void batchPackets(Player[] players, DataPacket[] packets, boolean forceSy throw new RuntimeException(e); } } - Timings.playerNetworkSendTimer.stopTiming(); } public void broadcastPacketsCallback(byte[] data, List targets) { @@ -817,7 +814,6 @@ public void reload() { this.pluginManager.loadPlugins(this.pluginPath); this.enablePlugins(PluginLoadOrder.STARTUP); this.enablePlugins(PluginLoadOrder.POSTWORLD); - Timings.reset(); } public void shutdown() { @@ -874,7 +870,6 @@ public void forceShutdown() { } this.getLogger().debug("Disabling timings"); - Timings.stopServer(); if (this.watchdog != null) { this.watchdog.kill(); } @@ -1122,7 +1117,6 @@ private void checkTickUpdates(int currentTick, long tickTime) { public void doAutoSave() { if (this.getAutoSave()) { - Timings.levelSaveTimer.startTiming(); for (Player player : new ArrayList<>(this.players.values())) { if (player.isOnline()) { player.save(true); @@ -1134,7 +1128,6 @@ public void doAutoSave() { for (Level level : this.levelArray) { level.save(); } - Timings.levelSaveTimer.stopTiming(); } } @@ -1156,21 +1149,15 @@ private boolean tick() { return false; } - Timings.fullServerTickTimer.startTiming(); - ++this.tickCounter; - Timings.connectionTimer.startTiming(); this.network.processInterfaces(); if (this.rcon != null) { this.rcon.check(); } - Timings.connectionTimer.stopTiming(); - Timings.schedulerTimer.startTiming(); this.scheduler.mainThreadHeartbeat(this.tickCounter); - Timings.schedulerTimer.stopTiming(); this.checkTickUpdates(this.tickCounter, tickTime); @@ -1214,7 +1201,6 @@ private boolean tick() { } } - Timings.fullServerTickTimer.stopTiming(); //long now = System.currentTimeMillis(); long nowNano = System.nanoTime(); //float tick = Math.min(20, 1000 / Math.max(1, now - tickTime)); diff --git a/src/main/java/cn/nukkit/blockentity/BlockEntity.java b/src/main/java/cn/nukkit/blockentity/BlockEntity.java index cbc97c453e7..ce2f25d937b 100644 --- a/src/main/java/cn/nukkit/blockentity/BlockEntity.java +++ b/src/main/java/cn/nukkit/blockentity/BlockEntity.java @@ -8,8 +8,6 @@ import cn.nukkit.nbt.tag.CompoundTag; import cn.nukkit.utils.ChunkException; import cn.nukkit.utils.MainLogger; -import co.aikar.timings.Timing; -import co.aikar.timings.Timings; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; @@ -58,14 +56,12 @@ public abstract class BlockEntity extends Position { public CompoundTag namedTag; protected long lastUpdate; protected Server server; - protected Timing timing; public BlockEntity(FullChunk chunk, CompoundTag nbt) { if (chunk == null || chunk.getProvider() == null) { throw new ChunkException("Invalid garbage Chunk given to Block Entity"); } - this.timing = Timings.getBlockEntityTiming(this); this.server = chunk.getProvider().getLevel().getServer(); this.chunk = chunk; this.setLevel(chunk.getProvider().getLevel()); diff --git a/src/main/java/cn/nukkit/blockentity/BlockEntityFurnace.java b/src/main/java/cn/nukkit/blockentity/BlockEntityFurnace.java index 6bf2223a965..aeb54b9f688 100644 --- a/src/main/java/cn/nukkit/blockentity/BlockEntityFurnace.java +++ b/src/main/java/cn/nukkit/blockentity/BlockEntityFurnace.java @@ -226,8 +226,6 @@ public boolean onUpdate() { return false; } - this.timing.startTiming(); - boolean ret = false; Item fuel = this.inventory.getFuel(); Item raw = this.inventory.getSmelting(); @@ -304,8 +302,6 @@ public boolean onUpdate() { this.lastUpdate = System.currentTimeMillis(); - this.timing.stopTiming(); - return ret; } diff --git a/src/main/java/cn/nukkit/command/Command.java b/src/main/java/cn/nukkit/command/Command.java index fbbd4954eb7..fed8fc52e9b 100644 --- a/src/main/java/cn/nukkit/command/Command.java +++ b/src/main/java/cn/nukkit/command/Command.java @@ -7,8 +7,6 @@ import cn.nukkit.lang.TranslationContainer; import cn.nukkit.permission.Permissible; import cn.nukkit.utils.TextFormat; -import co.aikar.timings.Timing; -import co.aikar.timings.Timings; import java.util.*; @@ -44,8 +42,6 @@ public abstract class Command { protected Map commandParameters = new HashMap<>(); - public Timing timing; - public Command(String name) { this(name, "", null, new String[0]); } @@ -67,7 +63,6 @@ public Command(String name, String description, String usageMessage, String[] al this.usageMessage = usageMessage == null ? "/" + name : usageMessage; this.aliases = aliases; this.activeAliases = aliases; - this.timing = Timings.getCommandTiming(this); this.commandParameters.put("default", new CommandParameter[]{CommandParameter.newType("args", true, CommandParamType.RAWTEXT)}); } @@ -186,7 +181,6 @@ public boolean setLabel(String name) { this.nextLabel = name; if (!this.isRegistered()) { this.label = name; - this.timing = Timings.getCommandTiming(this); return true; } return false; diff --git a/src/main/java/cn/nukkit/command/SimpleCommandMap.java b/src/main/java/cn/nukkit/command/SimpleCommandMap.java index 366dfb16933..db808b089bb 100644 --- a/src/main/java/cn/nukkit/command/SimpleCommandMap.java +++ b/src/main/java/cn/nukkit/command/SimpleCommandMap.java @@ -71,7 +71,6 @@ private void setDefaultCommands() { // if ((boolean) this.server.getConfig("debug.commands", false)) { this.register("nukkit", new StatusCommand("status")); this.register("nukkit", new GarbageCollectorCommand("gc")); - this.register("nukkit", new TimingsCommand("timings")); this.register("nukkit", new DebugPasteCommand("debugpaste")); //this.register("nukkit", new DumpMemoryCommand("dumpmemory")); // } @@ -252,7 +251,6 @@ public boolean dispatch(CommandSender sender, String cmdLine) { return false; } - target.timing.startTiming(); try { target.execute(sender, sentCommandLabel, args); } catch (Exception e) { @@ -263,7 +261,6 @@ public boolean dispatch(CommandSender sender, String cmdLine) { logger.logException(e); } } - target.timing.stopTiming(); return true; } diff --git a/src/main/java/cn/nukkit/command/defaults/TimingsCommand.java b/src/main/java/cn/nukkit/command/defaults/TimingsCommand.java deleted file mode 100644 index beb9354e2ba..00000000000 --- a/src/main/java/cn/nukkit/command/defaults/TimingsCommand.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.nukkit.command.defaults; - -import cn.nukkit.command.CommandSender; -import cn.nukkit.command.data.CommandEnum; -import cn.nukkit.command.data.CommandParameter; -import cn.nukkit.lang.TranslationContainer; -import co.aikar.timings.Timings; -import co.aikar.timings.TimingsExport; - -/** - * @author fromgate - * @author Pub4Game - */ -public class TimingsCommand extends VanillaCommand { - - public TimingsCommand(String name) { - super(name, "%nukkit.command.timings.description", "%nukkit.command.timings.usage"); - this.setPermission("nukkit.command.timings"); - this.commandParameters.clear(); - this.commandParameters.put("default", new CommandParameter[]{ - CommandParameter.newEnum("action", new CommandEnum("TimingsAction", "on", "off", "paste", "verbon", "verboff", "reset", "report")) - }); - } - - @Override - public boolean execute(CommandSender sender, String commandLabel, String[] args) { - if (!this.testPermission(sender)) { - return true; - } - - if (args.length != 1) { - sender.sendMessage(new TranslationContainer("commands.generic.usage", usageMessage)); - return true; - } - - String mode = args[0].toLowerCase(); - - if (mode.equals("on")) { - Timings.setTimingsEnabled(true); - Timings.reset(); - sender.sendMessage(new TranslationContainer("nukkit.command.timings.enable")); - return true; - } else if (mode.equals("off")) { - Timings.setTimingsEnabled(false); - sender.sendMessage(new TranslationContainer("nukkit.command.timings.disable")); - return true; - } - - if (!Timings.isTimingsEnabled()) { - sender.sendMessage(new TranslationContainer("nukkit.command.timings.timingsDisabled")); - return true; - } - - switch (mode) { - case "verbon": - sender.sendMessage(new TranslationContainer("nukkit.command.timings.verboseEnable")); - Timings.setVerboseEnabled(true); - break; - case "verboff": - sender.sendMessage(new TranslationContainer("nukkit.command.timings.verboseDisable")); - Timings.setVerboseEnabled(true); - break; - case "reset": - Timings.reset(); - sender.sendMessage(new TranslationContainer("nukkit.command.timings.reset")); - break; - case "report": - case "paste": - TimingsExport.reportTimings(sender); - break; - } - return true; - } -} diff --git a/src/main/java/cn/nukkit/console/NukkitConsole.java b/src/main/java/cn/nukkit/console/NukkitConsole.java index a83a589b770..6e45024f30f 100644 --- a/src/main/java/cn/nukkit/console/NukkitConsole.java +++ b/src/main/java/cn/nukkit/console/NukkitConsole.java @@ -2,7 +2,6 @@ import cn.nukkit.Server; import cn.nukkit.event.server.ServerCommandEvent; -import co.aikar.timings.Timings; import lombok.RequiredArgsConstructor; import net.minecrell.terminalconsole.SimpleTerminalConsole; import org.jline.reader.LineReader; @@ -26,7 +25,6 @@ protected boolean isRunning() { @Override protected void runCommand(String command) { if (executingCommands.get()) { - Timings.serverCommandTimer.startTiming(); ServerCommandEvent event = new ServerCommandEvent(server.getConsoleSender(), command); if (server.getPluginManager() != null) { server.getPluginManager().callEvent(event); @@ -34,7 +32,6 @@ protected void runCommand(String command) { if (!event.isCancelled()) { Server.getInstance().getScheduler().scheduleTask(() -> server.dispatchCommand(event.getSender(), event.getCommand())); } - Timings.serverCommandTimer.stopTiming(); } else { consoleQueue.add(command); } diff --git a/src/main/java/cn/nukkit/entity/Entity.java b/src/main/java/cn/nukkit/entity/Entity.java index f07715ca0c6..883f481750b 100644 --- a/src/main/java/cn/nukkit/entity/Entity.java +++ b/src/main/java/cn/nukkit/entity/Entity.java @@ -30,9 +30,6 @@ import cn.nukkit.scheduler.Task; import cn.nukkit.utils.ChunkException; import cn.nukkit.utils.MainLogger; -import co.aikar.timings.Timing; -import co.aikar.timings.Timings; -import co.aikar.timings.TimingsHistory; import com.google.common.collect.Iterables; import java.lang.reflect.Constructor; @@ -401,8 +398,6 @@ public abstract class Entity extends Location implements Metadatable { public boolean closed = false; - protected Timing timing; - protected boolean isPlayer = this instanceof Player; private volatile boolean initialized; @@ -495,8 +490,6 @@ protected final void init(FullChunk chunk, CompoundTag nbt) { } this.initialized = true; - this.timing = Timings.getEntityTiming(this); - this.temporalVector = new Vector3(); this.id = Entity.entityCount++; @@ -1333,8 +1326,6 @@ public boolean entityBaseTick() { } public boolean entityBaseTick(int tickDiff) { - Timings.entityBaseTickTimer.startTiming(); - if (!this.isPlayer) { this.blocksAround = null; this.collisionBlocks = null; @@ -1347,7 +1338,6 @@ public boolean entityBaseTick(int tickDiff) { if (!this.isPlayer) { this.close(); } - Timings.entityBaseTickTimer.stopTiming(); return false; } if (riding != null && !riding.isAlive() && riding instanceof EntityRideable) { @@ -1442,9 +1432,7 @@ public void onRun(int currentTick) { this.age += tickDiff; this.ticksLived += tickDiff; - TimingsHistory.activatedEntityTicks++; - Timings.entityBaseTickTimer.stopTiming(); return hasUpdate; } @@ -1912,8 +1900,6 @@ public boolean fastMove(double dx, double dy, double dz) { return true; } - Timings.entityMoveTimer.startTiming(); - AxisAlignedBB newBB = this.boundingBox.getOffsetBoundingBox(dx, dy, dz); if (server.getAllowFlight() || !this.level.hasCollision(this, newBB, false)) { @@ -1934,7 +1920,6 @@ public boolean fastMove(double dx, double dy, double dz) { } this.isCollided = this.onGround; this.updateFallState(this.onGround); - Timings.entityMoveTimer.stopTiming(); return true; } @@ -1949,9 +1934,6 @@ public boolean move(double dx, double dy, double dz) { this.onGround = this.isPlayer; return true; } else { - - Timings.entityMoveTimer.startTiming(); - this.ySize *= 0.4; double movX = dx; @@ -2049,7 +2031,6 @@ public boolean move(double dx, double dy, double dz) { } //TODO: vehicle collision events (first we need to spawn them!) - Timings.entityMoveTimer.stopTiming(); return true; } } diff --git a/src/main/java/cn/nukkit/entity/EntityLiving.java b/src/main/java/cn/nukkit/entity/EntityLiving.java index baae0c55054..257c84b2cba 100644 --- a/src/main/java/cn/nukkit/entity/EntityLiving.java +++ b/src/main/java/cn/nukkit/entity/EntityLiving.java @@ -23,7 +23,6 @@ import cn.nukkit.network.protocol.LevelSoundEventPacket; import cn.nukkit.potion.Effect; import cn.nukkit.utils.BlockIterator; -import co.aikar.timings.Timings; import java.util.ArrayList; import java.util.Arrays; @@ -204,7 +203,6 @@ public boolean entityBaseTick() { @Override public boolean entityBaseTick(int tickDiff) { - Timings.livingEntityBaseTickTimer.startTiming(); boolean isBreathing = !this.isInsideOfWater(); if (this instanceof Player) { @@ -288,8 +286,6 @@ public boolean entityBaseTick(int tickDiff) { Block block = this.level.getBlock((int) x, (int) y - 1, (int) z); if (block instanceof BlockMagma) block.onEntityCollide(this); - Timings.livingEntityBaseTickTimer.stopTiming(); - return hasUpdate; } diff --git a/src/main/java/cn/nukkit/entity/item/EntityExpBottle.java b/src/main/java/cn/nukkit/entity/item/EntityExpBottle.java index 16963a25c9a..203c3db061d 100644 --- a/src/main/java/cn/nukkit/entity/item/EntityExpBottle.java +++ b/src/main/java/cn/nukkit/entity/item/EntityExpBottle.java @@ -61,8 +61,6 @@ public boolean onUpdate(int currentTick) { return false; } - this.timing.startTiming(); - boolean hasUpdate = super.onUpdate(currentTick); if (this.age > 1200) { @@ -76,8 +74,6 @@ public boolean onUpdate(int currentTick) { hasUpdate = true; } - this.timing.stopTiming(); - return hasUpdate; } diff --git a/src/main/java/cn/nukkit/entity/item/EntityFallingBlock.java b/src/main/java/cn/nukkit/entity/item/EntityFallingBlock.java index 1d146ea97b0..c8952baf726 100644 --- a/src/main/java/cn/nukkit/entity/item/EntityFallingBlock.java +++ b/src/main/java/cn/nukkit/entity/item/EntityFallingBlock.java @@ -111,8 +111,6 @@ public boolean onUpdate(int currentTick) { return false; } - this.timing.startTiming(); - int tickDiff = currentTick - lastUpdate; if (tickDiff <= 0 && !justCreated) { return true; @@ -194,8 +192,6 @@ public boolean onUpdate(int currentTick) { updateMovement(); } - this.timing.stopTiming(); - return hasUpdate || !onGround || Math.abs(motionX) > 0.00001 || Math.abs(motionY) > 0.00001 || Math.abs(motionZ) > 0.00001; } diff --git a/src/main/java/cn/nukkit/entity/item/EntityFirework.java b/src/main/java/cn/nukkit/entity/item/EntityFirework.java index 88a9aa74733..4d4baa75425 100644 --- a/src/main/java/cn/nukkit/entity/item/EntityFirework.java +++ b/src/main/java/cn/nukkit/entity/item/EntityFirework.java @@ -71,9 +71,6 @@ public boolean onUpdate(int currentTick) { this.lastUpdate = currentTick; - this.timing.startTiming(); - - boolean hasUpdate = this.entityBaseTick(tickDiff); if (this.isAlive()) { @@ -114,8 +111,6 @@ public boolean onUpdate(int currentTick) { } } - this.timing.stopTiming(); - return hasUpdate || !this.onGround || Math.abs(this.motionX) > 0.00001 || Math.abs(this.motionY) > 0.00001 || Math.abs(this.motionZ) > 0.00001; } diff --git a/src/main/java/cn/nukkit/entity/item/EntityItem.java b/src/main/java/cn/nukkit/entity/item/EntityItem.java index 1b2ec8074ed..9f6df3aec38 100644 --- a/src/main/java/cn/nukkit/entity/item/EntityItem.java +++ b/src/main/java/cn/nukkit/entity/item/EntityItem.java @@ -159,8 +159,6 @@ public boolean onUpdate(int currentTick) { this.lastUpdate = currentTick; - this.timing.startTiming(); - if (this.age % 60 == 0 && this.onGround && this.getItem() != null && this.isAlive()) { if (this.getItem().getCount() < this.getItem().getMaxStackSize()) { for (Entity entity : this.getLevel().getNearbyEntities(getBoundingBox().grow(1, 1, 1), this, false)) { @@ -254,8 +252,6 @@ public boolean onUpdate(int currentTick) { } } - this.timing.stopTiming(); - return hasUpdate || !this.onGround || Math.abs(this.motionX) > 0.00001 || Math.abs(this.motionY) > 0.00001 || Math.abs(this.motionZ) > 0.00001; } diff --git a/src/main/java/cn/nukkit/entity/item/EntityMinecartTNT.java b/src/main/java/cn/nukkit/entity/item/EntityMinecartTNT.java index c5ce3074bed..dbd30465dc2 100644 --- a/src/main/java/cn/nukkit/entity/item/EntityMinecartTNT.java +++ b/src/main/java/cn/nukkit/entity/item/EntityMinecartTNT.java @@ -60,8 +60,6 @@ public void initEntity() { @Override public boolean onUpdate(int currentTick) { - this.timing.startTiming(); - if (fuse < 80) { int tickDiff = currentTick - lastUpdate; @@ -82,8 +80,6 @@ public boolean onUpdate(int currentTick) { } } - this.timing.stopTiming(); - return super.onUpdate(currentTick); } diff --git a/src/main/java/cn/nukkit/entity/item/EntityPotion.java b/src/main/java/cn/nukkit/entity/item/EntityPotion.java index 54062ee422a..fa3a9c9f00c 100644 --- a/src/main/java/cn/nukkit/entity/item/EntityPotion.java +++ b/src/main/java/cn/nukkit/entity/item/EntityPotion.java @@ -145,8 +145,6 @@ public boolean onUpdate(int currentTick) { return false; } - this.timing.startTiming(); - boolean hasUpdate = super.onUpdate(currentTick); if (this.age > 1200) { @@ -157,7 +155,6 @@ public boolean onUpdate(int currentTick) { hasUpdate = true; } - this.timing.stopTiming(); return hasUpdate; } } diff --git a/src/main/java/cn/nukkit/entity/item/EntityPrimedTNT.java b/src/main/java/cn/nukkit/entity/item/EntityPrimedTNT.java index 01fa145d0c4..174804609a0 100644 --- a/src/main/java/cn/nukkit/entity/item/EntityPrimedTNT.java +++ b/src/main/java/cn/nukkit/entity/item/EntityPrimedTNT.java @@ -108,8 +108,6 @@ public boolean onUpdate(int currentTick) { return false; } - this.timing.startTiming(); - int tickDiff = currentTick - lastUpdate; if (tickDiff <= 0 && !justCreated) { @@ -154,8 +152,6 @@ public boolean onUpdate(int currentTick) { } - this.timing.stopTiming(); - return hasUpdate || fuse >= 0 || Math.abs(motionX) > 0.00001 || Math.abs(motionY) > 0.00001 || Math.abs(motionZ) > 0.00001; } diff --git a/src/main/java/cn/nukkit/entity/projectile/EntityArrow.java b/src/main/java/cn/nukkit/entity/projectile/EntityArrow.java index 74a4a266b45..591481ba291 100644 --- a/src/main/java/cn/nukkit/entity/projectile/EntityArrow.java +++ b/src/main/java/cn/nukkit/entity/projectile/EntityArrow.java @@ -104,8 +104,6 @@ public boolean onUpdate(int currentTick) { return false; } - this.timing.startTiming(); - boolean hasUpdate = super.onUpdate(currentTick); if (this.onGround || this.hadCollision) { @@ -117,8 +115,6 @@ public boolean onUpdate(int currentTick) { hasUpdate = true; } - this.timing.stopTiming(); - return hasUpdate; } diff --git a/src/main/java/cn/nukkit/entity/projectile/EntityEnderPearl.java b/src/main/java/cn/nukkit/entity/projectile/EntityEnderPearl.java index 8d59b5c78f5..e2eaff40ab8 100644 --- a/src/main/java/cn/nukkit/entity/projectile/EntityEnderPearl.java +++ b/src/main/java/cn/nukkit/entity/projectile/EntityEnderPearl.java @@ -59,8 +59,6 @@ public boolean onUpdate(int currentTick) { return false; } - this.timing.startTiming(); - boolean hasUpdate = super.onUpdate(currentTick); if (this.isCollided && this.shootingEntity instanceof Player) { @@ -80,8 +78,6 @@ public boolean onUpdate(int currentTick) { hasUpdate = true; } - this.timing.stopTiming(); - return hasUpdate; } diff --git a/src/main/java/cn/nukkit/entity/projectile/EntitySnowball.java b/src/main/java/cn/nukkit/entity/projectile/EntitySnowball.java index ebad4aa4e94..5d4539830ef 100644 --- a/src/main/java/cn/nukkit/entity/projectile/EntitySnowball.java +++ b/src/main/java/cn/nukkit/entity/projectile/EntitySnowball.java @@ -55,8 +55,6 @@ public boolean onUpdate(int currentTick) { return false; } - this.timing.startTiming(); - boolean hasUpdate = super.onUpdate(currentTick); if (this.age > 1200 || this.isCollided) { @@ -64,8 +62,6 @@ public boolean onUpdate(int currentTick) { hasUpdate = true; } - this.timing.stopTiming(); - return hasUpdate; } } diff --git a/src/main/java/cn/nukkit/level/format/anvil/Anvil.java b/src/main/java/cn/nukkit/level/format/anvil/Anvil.java index cffd7a2e89a..8608e12f74a 100644 --- a/src/main/java/cn/nukkit/level/format/anvil/Anvil.java +++ b/src/main/java/cn/nukkit/level/format/anvil/Anvil.java @@ -149,7 +149,6 @@ public synchronized BaseFullChunk loadChunk(long index, int chunkX, int chunkZ, int regionX = getRegionIndexX(chunkX); int regionZ = getRegionIndexZ(chunkZ); BaseRegionLoader region = this.loadRegion(regionX, regionZ); - this.level.timings.syncChunkLoadDataTimer.startTiming(); BaseFullChunk chunk; try { chunk = region.readChunk(chunkX - regionX * 32, chunkZ - regionZ * 32); @@ -164,7 +163,6 @@ public synchronized BaseFullChunk loadChunk(long index, int chunkX, int chunkZ, } else { putChunk(index, chunk); } - this.level.timings.syncChunkLoadDataTimer.stopTiming(); return chunk; } diff --git a/src/main/java/cn/nukkit/level/format/generic/BaseFullChunk.java b/src/main/java/cn/nukkit/level/format/generic/BaseFullChunk.java index 0b9127a2ba7..9dee0161084 100644 --- a/src/main/java/cn/nukkit/level/format/generic/BaseFullChunk.java +++ b/src/main/java/cn/nukkit/level/format/generic/BaseFullChunk.java @@ -121,7 +121,6 @@ public void initChunk() { if (this.getProvider() != null && !this.isInit) { boolean changed = false; if (this.NBTentities != null) { - this.getProvider().getLevel().timings.syncChunkLoadEntitiesTimer.startTiming(); for (CompoundTag nbt : NBTentities) { if (!nbt.contains("id")) { this.setChanged(); @@ -137,12 +136,10 @@ public void initChunk() { changed = true; } } - this.getProvider().getLevel().timings.syncChunkLoadEntitiesTimer.stopTiming(); this.NBTentities = null; } if (this.NBTtiles != null) { - this.getProvider().getLevel().timings.syncChunkLoadBlockEntitiesTimer.startTiming(); for (CompoundTag nbt : NBTtiles) { if (nbt != null) { if (!nbt.contains("id")) { @@ -159,7 +156,6 @@ public void initChunk() { } } } - this.getProvider().getLevel().timings.syncChunkLoadBlockEntitiesTimer.stopTiming(); this.NBTtiles = null; } diff --git a/src/main/java/cn/nukkit/level/format/leveldb/LevelDB.java b/src/main/java/cn/nukkit/level/format/leveldb/LevelDB.java index 5ad5bae06d6..cc151d867a7 100644 --- a/src/main/java/cn/nukkit/level/format/leveldb/LevelDB.java +++ b/src/main/java/cn/nukkit/level/format/leveldb/LevelDB.java @@ -276,12 +276,10 @@ public boolean loadChunk(int x, int z, boolean create) { return true; } - this.level.timings.syncChunkLoadDataTimer.startTiming(); Chunk chunk = this.readChunk(x, z); if (chunk == null && create) { chunk = Chunk.getEmptyChunk(x, z, this); } - this.level.timings.syncChunkLoadDataTimer.stopTiming(); if (chunk != null) { this.chunks.put(index, chunk); return true; diff --git a/src/main/java/cn/nukkit/level/format/mcregion/McRegion.java b/src/main/java/cn/nukkit/level/format/mcregion/McRegion.java index ae9f0ad5366..96f07b5debe 100644 --- a/src/main/java/cn/nukkit/level/format/mcregion/McRegion.java +++ b/src/main/java/cn/nukkit/level/format/mcregion/McRegion.java @@ -148,7 +148,6 @@ public BaseFullChunk loadChunk(long index, int chunkX, int chunkZ, boolean creat int regionX = getRegionIndexX(chunkX); int regionZ = getRegionIndexZ(chunkZ); BaseRegionLoader region = this.loadRegion(regionX, regionZ); - this.level.timings.syncChunkLoadDataTimer.startTiming(); BaseFullChunk chunk; try { chunk = region.readChunk(chunkX - regionX * 32, chunkZ - regionZ * 32); @@ -163,7 +162,6 @@ public BaseFullChunk loadChunk(long index, int chunkX, int chunkZ, boolean creat } else { putChunk(index, chunk); } - this.level.timings.syncChunkLoadDataTimer.stopTiming(); return chunk; } diff --git a/src/main/java/cn/nukkit/permission/PermissibleBase.java b/src/main/java/cn/nukkit/permission/PermissibleBase.java index d521a475310..6fcdc0569ac 100644 --- a/src/main/java/cn/nukkit/permission/PermissibleBase.java +++ b/src/main/java/cn/nukkit/permission/PermissibleBase.java @@ -4,7 +4,6 @@ import cn.nukkit.plugin.Plugin; import cn.nukkit.utils.PluginException; import cn.nukkit.utils.ServerException; -import co.aikar.timings.Timings; import java.util.HashMap; import java.util.HashSet; @@ -118,8 +117,6 @@ public void removeAttachment(PermissionAttachment attachment) { @Override public void recalculatePermissions() { - Timings.permissibleCalculationTimer.startTiming(); - this.clearPermissions(); Map defaults = Server.getInstance().getPluginManager().getDefaultPermissions(this.isOp()); Server.getInstance().getPluginManager().subscribeToDefaultPerms(this.isOp(), this.parent != null ? this.parent : this); @@ -134,7 +131,6 @@ public void recalculatePermissions() { for (PermissionAttachment attachment : this.attachments) { this.calculateChildPermissions(attachment.getPermissions(), false, attachment); } - Timings.permissibleCalculationTimer.stopTiming(); } public void clearPermissions() { diff --git a/src/main/java/cn/nukkit/plugin/PluginManager.java b/src/main/java/cn/nukkit/plugin/PluginManager.java index 0b09fd3983e..f48540a0652 100644 --- a/src/main/java/cn/nukkit/plugin/PluginManager.java +++ b/src/main/java/cn/nukkit/plugin/PluginManager.java @@ -9,8 +9,6 @@ import cn.nukkit.utils.MainLogger; import cn.nukkit.utils.PluginException; import cn.nukkit.utils.Utils; -import co.aikar.timings.Timing; -import co.aikar.timings.Timings; import java.io.File; import java.lang.reflect.Constructor; @@ -349,7 +347,6 @@ public void recalculatePermissionDefaults(Permission permission) { } private void calculatePermissionDefault(Permission permission) { - Timings.permissionDefaultTimer.startTiming(); if (permission.getDefault().equals(Permission.DEFAULT_OP) || permission.getDefault().equals(Permission.DEFAULT_TRUE)) { this.defaultPermsOp.put(permission.getName(), permission); this.dirtyPermissibles(true); @@ -359,7 +356,6 @@ private void calculatePermissionDefault(Permission permission) { this.defaultPerms.put(permission.getName(), permission); this.dirtyPermissibles(false); } - Timings.permissionDefaultTimer.startTiming(); } private void dirtyPermissibles(boolean op) { @@ -608,8 +604,7 @@ public void registerEvent(Class event, Listener listener, Event } try { - Timing timing = Timings.getPluginEventTiming(event, listener, executor, plugin); - this.getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled, timing)); + this.getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); } catch (IllegalAccessException e) { Server.getInstance().getLogger().logException(e); } diff --git a/src/main/java/cn/nukkit/plugin/RegisteredListener.java b/src/main/java/cn/nukkit/plugin/RegisteredListener.java index 0744db1f04c..659e16b7294 100644 --- a/src/main/java/cn/nukkit/plugin/RegisteredListener.java +++ b/src/main/java/cn/nukkit/plugin/RegisteredListener.java @@ -5,7 +5,6 @@ import cn.nukkit.event.EventPriority; import cn.nukkit.event.Listener; import cn.nukkit.utils.EventException; -import co.aikar.timings.Timing; /** * author: MagicDroidX @@ -23,15 +22,12 @@ public class RegisteredListener { private final boolean ignoreCancelled; - private final Timing timing; - - public RegisteredListener(Listener listener, EventExecutor executor, EventPriority priority, Plugin plugin, boolean ignoreCancelled, Timing timing) { + public RegisteredListener(Listener listener, EventExecutor executor, EventPriority priority, Plugin plugin, boolean ignoreCancelled) { this.listener = listener; this.priority = priority; this.plugin = plugin; this.executor = executor; this.ignoreCancelled = ignoreCancelled; - this.timing = timing; } public Listener getListener() { @@ -52,9 +48,7 @@ public void callEvent(Event event) throws EventException { return; } } - this.timing.startTiming(); executor.execute(listener, event); - this.timing.stopTiming(); } public boolean isIgnoringCancelled() { diff --git a/src/main/java/cn/nukkit/scheduler/AsyncTask.java b/src/main/java/cn/nukkit/scheduler/AsyncTask.java index 29698d7c5f8..8c65dc08345 100644 --- a/src/main/java/cn/nukkit/scheduler/AsyncTask.java +++ b/src/main/java/cn/nukkit/scheduler/AsyncTask.java @@ -2,7 +2,6 @@ import cn.nukkit.Server; import cn.nukkit.utils.ThreadStore; -import co.aikar.timings.Timings; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -76,7 +75,6 @@ public void cleanObject() { } public static void collectTask() { - Timings.schedulerAsyncTimer.startTiming(); while (!FINISHED_LIST.isEmpty()) { AsyncTask task = FINISHED_LIST.poll(); try { @@ -87,7 +85,5 @@ public static void collectTask() { + " invoking onCompletion", e); } } - Timings.schedulerAsyncTimer.stopTiming(); } - } diff --git a/src/main/java/cn/nukkit/scheduler/ServerScheduler.java b/src/main/java/cn/nukkit/scheduler/ServerScheduler.java index d36de738939..54ddfdbe7bb 100644 --- a/src/main/java/cn/nukkit/scheduler/ServerScheduler.java +++ b/src/main/java/cn/nukkit/scheduler/ServerScheduler.java @@ -291,14 +291,12 @@ private void runTasks(int currentTick) { } else if (taskHandler.isAsynchronous()) { asyncPool.execute(taskHandler.getTask()); } else { - taskHandler.timing.startTiming(); try { taskHandler.run(currentTick); } catch (Throwable e) { Server.getInstance().getLogger().critical("Could not execute taskHandler " + taskHandler.getTaskId() + ": " + e.getMessage()); Server.getInstance().getLogger().logException(e instanceof Exception ? (Exception) e : new RuntimeException(e)); } - taskHandler.timing.stopTiming(); } if (taskHandler.isRepeating()) { taskHandler.setNextRunTick(currentTick + taskHandler.getPeriod()); diff --git a/src/main/java/cn/nukkit/scheduler/TaskHandler.java b/src/main/java/cn/nukkit/scheduler/TaskHandler.java index 99e2d8c88a9..db5fb1af4a9 100644 --- a/src/main/java/cn/nukkit/scheduler/TaskHandler.java +++ b/src/main/java/cn/nukkit/scheduler/TaskHandler.java @@ -2,8 +2,6 @@ import cn.nukkit.Server; import cn.nukkit.plugin.Plugin; -import co.aikar.timings.Timing; -import co.aikar.timings.Timings; /** * @author MagicDroidX @@ -23,14 +21,11 @@ public class TaskHandler { private boolean cancelled; - public final Timing timing; - public TaskHandler(Plugin plugin, Runnable task, int taskId, boolean asynchronous) { this.asynchronous = asynchronous; this.plugin = plugin; this.task = task; this.taskId = taskId; - this.timing = Timings.getTaskTiming(this, period); } public boolean isCancelled() { From 855e7a8f6891eb40dd6855c75abc8dbd577fc9ea Mon Sep 17 00:00:00 2001 From: Villagers654 Date: Sun, 4 Jun 2023 01:07:44 +0900 Subject: [PATCH 3/5] Bundle spark with the server --- src/main/java/cn/nukkit/Server.java | 4 +- .../java/cn/nukkit/spark/SparkInstaller.java | 76 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/main/java/cn/nukkit/spark/SparkInstaller.java diff --git a/src/main/java/cn/nukkit/Server.java b/src/main/java/cn/nukkit/Server.java index 66ebe38822d..bd7768419df 100644 --- a/src/main/java/cn/nukkit/Server.java +++ b/src/main/java/cn/nukkit/Server.java @@ -77,6 +77,7 @@ import cn.nukkit.resourcepacks.ResourcePackManager; import cn.nukkit.scheduler.ServerScheduler; import cn.nukkit.scheduler.Task; +import cn.nukkit.spark.SparkInstaller; import cn.nukkit.utils.*; import cn.nukkit.utils.bugreport.ExceptionHandler; import com.google.common.base.Preconditions; @@ -283,7 +284,7 @@ public Level remove(Object key) { try { InputStream languageList = this.getClass().getClassLoader().getResourceAsStream("lang/language.list"); if (languageList == null) { - throw new IllegalStateException("lang/language.list is missing. If you are running a development version, make sure you have run 'git submodule update --init'."); + throw new IllegalStateException("lang/language.list is missing. If you are running a development version, make sure you have run 'git submodule update --checkSpark'."); } String[] lines = Utils.readFile(languageList).split("\n"); for (String line : lines) { @@ -812,6 +813,7 @@ public void reload() { this.pluginManager.registerInterface(JavaPluginLoader.class); this.pluginManager.loadPlugins(this.pluginPath); + SparkInstaller.checkSpark(this); this.enablePlugins(PluginLoadOrder.STARTUP); this.enablePlugins(PluginLoadOrder.POSTWORLD); } diff --git a/src/main/java/cn/nukkit/spark/SparkInstaller.java b/src/main/java/cn/nukkit/spark/SparkInstaller.java new file mode 100644 index 00000000000..f650cfe82bb --- /dev/null +++ b/src/main/java/cn/nukkit/spark/SparkInstaller.java @@ -0,0 +1,76 @@ +package cn.nukkit.spark; + +import cn.nukkit.Server; +import cn.nukkit.plugin.PluginManager; +import cn.nukkit.utils.Logger; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.security.MessageDigest; +import java.util.stream.Collectors; + +public class SparkInstaller { + public static void checkSpark(Server server) { + Logger log = server.getLogger(); + PluginManager manager = server.getPluginManager(); + + try { + if (hasSpark(server)) { + log.info("Using already user-installed spark plugin"); + return; + } + + File file = new File(Server.getInstance().getDataPath() + "/spark/" + "spark.jar"); + file.getParentFile().mkdirs(); + + boolean shouldDownload = true; + + if (file.exists()) { + String fileSha1 = String.format("%040x", new BigInteger(1, + MessageDigest.getInstance("SHA-1").digest(Files.readAllBytes(file.toPath())))); + String sparkSha1; + URLConnection urlConnection = + new URL("https://sparkapi.lucko.me/download/nukkit/sha1").openConnection(); + urlConnection.setReadTimeout(5000); + urlConnection.setConnectTimeout(5000); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(urlConnection.getInputStream()))) { + sparkSha1 = reader.lines().collect(Collectors.joining("")); + } + + if (fileSha1.equals(sparkSha1)) { + shouldDownload = false; + } + } + + if (shouldDownload) { + log.info("Downloading updated spark plugin"); + + URLConnection urlConnection = + new URL("https://sparkapi.lucko.me/download/nukkit").openConnection(); + urlConnection.setReadTimeout(5000); + urlConnection.setConnectTimeout(5000); + Files.copy(urlConnection.getInputStream(), file.toPath(), + StandardCopyOption.REPLACE_EXISTING); + } + + manager.loadPlugin(file); + } catch (Exception e) { + log.error("Failed to install spark"); + e.printStackTrace(); + } + } + + public static boolean hasSpark(Server server) { + PluginManager manager = server.getPluginManager(); + + return manager.getPlugin("spark") != null; + } +} \ No newline at end of file From d6e83b8a39879a3c47f4dc5a435df8dd0f56ac8e Mon Sep 17 00:00:00 2001 From: Villagers654 Date: Sun, 4 Jun 2023 01:17:13 +0900 Subject: [PATCH 4/5] Fix Intellij refactor being annoying --- src/main/java/cn/nukkit/Server.java | 2 +- src/main/java/cn/nukkit/spark/SparkInstaller.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/cn/nukkit/Server.java b/src/main/java/cn/nukkit/Server.java index bd7768419df..6e98c55a209 100644 --- a/src/main/java/cn/nukkit/Server.java +++ b/src/main/java/cn/nukkit/Server.java @@ -284,7 +284,7 @@ public Level remove(Object key) { try { InputStream languageList = this.getClass().getClassLoader().getResourceAsStream("lang/language.list"); if (languageList == null) { - throw new IllegalStateException("lang/language.list is missing. If you are running a development version, make sure you have run 'git submodule update --checkSpark'."); + throw new IllegalStateException("lang/language.list is missing. If you are running a development version, make sure you have run 'git submodule update --init'."); } String[] lines = Utils.readFile(languageList).split("\n"); for (String line : lines) { diff --git a/src/main/java/cn/nukkit/spark/SparkInstaller.java b/src/main/java/cn/nukkit/spark/SparkInstaller.java index f650cfe82bb..376cf575508 100644 --- a/src/main/java/cn/nukkit/spark/SparkInstaller.java +++ b/src/main/java/cn/nukkit/spark/SparkInstaller.java @@ -6,7 +6,6 @@ import java.io.BufferedReader; import java.io.File; -import java.io.IOException; import java.io.InputStreamReader; import java.math.BigInteger; import java.net.URL; From 06acdf77d6c75a802c096da0ccf47cf3a02546d8 Mon Sep 17 00:00:00 2001 From: Villagers654 Date: Wed, 28 Jun 2023 14:39:50 +0900 Subject: [PATCH 5/5] Don't only load spark when the server is reloaded --- src/main/java/cn/nukkit/Server.java | 4 +++- src/main/java/cn/nukkit/spark/SparkInstaller.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/cn/nukkit/Server.java b/src/main/java/cn/nukkit/Server.java index 6e98c55a209..d494b6d5b2b 100644 --- a/src/main/java/cn/nukkit/Server.java +++ b/src/main/java/cn/nukkit/Server.java @@ -504,6 +504,8 @@ public Level remove(Object key) { this.pluginManager.loadPlugins(this.pluginPath); + SparkInstaller.initSpark(this); + this.enablePlugins(PluginLoadOrder.STARTUP); LevelProviderManager.addProvider(this, Anvil.class); @@ -813,7 +815,7 @@ public void reload() { this.pluginManager.registerInterface(JavaPluginLoader.class); this.pluginManager.loadPlugins(this.pluginPath); - SparkInstaller.checkSpark(this); + SparkInstaller.initSpark(this); this.enablePlugins(PluginLoadOrder.STARTUP); this.enablePlugins(PluginLoadOrder.POSTWORLD); } diff --git a/src/main/java/cn/nukkit/spark/SparkInstaller.java b/src/main/java/cn/nukkit/spark/SparkInstaller.java index 376cf575508..d2d16e16573 100644 --- a/src/main/java/cn/nukkit/spark/SparkInstaller.java +++ b/src/main/java/cn/nukkit/spark/SparkInstaller.java @@ -16,7 +16,7 @@ import java.util.stream.Collectors; public class SparkInstaller { - public static void checkSpark(Server server) { + public static void initSpark(Server server) { Logger log = server.getLogger(); PluginManager manager = server.getPluginManager();