Restore 0129-Optimize-World.isLoaded-BlockPosition-Z.patch
This commit is contained in:
parent
16071c7e1a
commit
c47cf32c7c
290 changed files with 1073 additions and 1072 deletions
251
Spigot-Server-Patches/0303-Optimize-Server-World-Map.patch
Normal file
251
Spigot-Server-Patches/0303-Optimize-Server-World-Map.patch
Normal file
|
@ -0,0 +1,251 @@
|
|||
From f654df6d267b4933ca2fd0ec65e504a5ec74be3a Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 17 Sep 2018 23:37:31 -0400
|
||||
Subject: [PATCH] Optimize Server World Map
|
||||
|
||||
Minecraft moved worlds to a hashmap in 1.13.1.
|
||||
This creates inconsistent order for iteration of the map.
|
||||
|
||||
This patch restores World management to be back as an Array.
|
||||
|
||||
.values() will allow us to iterate as it was pre 1.13.1 by
|
||||
ArrayList, giving consistent ordering and effecient iteration performance.
|
||||
|
||||
KeySet and EntrySet iteration is proxied to the List iterator,
|
||||
and should retain manipulation behavior but nothing should be doing that.
|
||||
|
||||
Getting a World by dimension ID is now back a constant time operation.
|
||||
|
||||
Hopefully no other plugins try to mess with this map, as we are only handling
|
||||
known NMS used methods, but we can add more if naughty plugins are found later.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldMap.java b/src/main/java/com/destroystokyo/paper/PaperWorldMap.java
|
||||
new file mode 100644
|
||||
index 0000000000..6bb2f98b45
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldMap.java
|
||||
@@ -0,0 +1,191 @@
|
||||
+package com.destroystokyo.paper;
|
||||
+
|
||||
+import net.minecraft.server.DimensionManager;
|
||||
+import net.minecraft.server.WorldServer;
|
||||
+
|
||||
+import javax.annotation.Nonnull;
|
||||
+import java.util.AbstractSet;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collection;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+
|
||||
+public class PaperWorldMap extends HashMap<DimensionManager, WorldServer> {
|
||||
+ private final List<WorldServer> worlds = new ArrayList<>();
|
||||
+ private final List<WorldServer> worldsIterable = new ArrayList<WorldServer>() {
|
||||
+ @Override
|
||||
+ public Iterator<WorldServer> iterator() {
|
||||
+ Iterator<WorldServer> iterator = super.iterator();
|
||||
+ return new Iterator<WorldServer>() {
|
||||
+ private WorldServer last;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ return iterator.hasNext();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public WorldServer next() {
|
||||
+ this.last = iterator.next();
|
||||
+ return last;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ worlds.set(last.worldProvider.getDimensionManager().getDimensionID() + 1, null);
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+ };
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return worldsIterable.size();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isEmpty() {
|
||||
+ return worldsIterable.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public WorldServer get(Object key) {
|
||||
+ // Will hit the below method
|
||||
+ return key instanceof DimensionManager ? get((DimensionManager) key) : null;
|
||||
+ }
|
||||
+
|
||||
+ public WorldServer get(DimensionManager key) {
|
||||
+ int id = key.getDimensionID()+1;
|
||||
+ return worlds.size() > id ? worlds.get(id) : null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean containsKey(Object key) {
|
||||
+ // will hit below method
|
||||
+ return key instanceof DimensionManager && containsKey((DimensionManager) key);
|
||||
+ }
|
||||
+ public boolean containsKey(DimensionManager key) {
|
||||
+ return get(key) != null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public WorldServer put(DimensionManager key, WorldServer value) {
|
||||
+ while (worlds.size() <= key.getDimensionID()+1) {
|
||||
+ worlds.add(null);
|
||||
+ }
|
||||
+ WorldServer old = worlds.set(key.getDimensionID()+1, value);
|
||||
+ if (old != null) {
|
||||
+ worldsIterable.remove(old);
|
||||
+ }
|
||||
+ worldsIterable.add(value);
|
||||
+ return old;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void putAll(Map<? extends DimensionManager, ? extends WorldServer> m) {
|
||||
+ for (Entry<? extends DimensionManager, ? extends WorldServer> e : m.entrySet()) {
|
||||
+ put(e.getKey(), e.getValue());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public WorldServer remove(Object key) {
|
||||
+ return key instanceof DimensionManager ? remove((DimensionManager) key) : null;
|
||||
+ }
|
||||
+
|
||||
+ public WorldServer remove(DimensionManager key) {
|
||||
+ WorldServer old;
|
||||
+ if (key.getDimensionID()+1 == worlds.size() - 1) {
|
||||
+ old = worlds.remove(key.getDimensionID()+1);
|
||||
+ } else {
|
||||
+ old = worlds.set(key.getDimensionID() + 1, null);
|
||||
+ }
|
||||
+ if (old != null) {
|
||||
+ worldsIterable.remove(old);
|
||||
+ }
|
||||
+ return old;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void clear() {
|
||||
+ throw new RuntimeException("What the hell are you doing?");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean containsValue(Object value) {
|
||||
+ return value instanceof WorldServer && get(((WorldServer) value).worldProvider.getDimensionManager()) != null;
|
||||
+ }
|
||||
+
|
||||
+ @Nonnull
|
||||
+ @Override
|
||||
+ public Set<DimensionManager> keySet() {
|
||||
+ return new AbstractSet<DimensionManager>() {
|
||||
+ @Override
|
||||
+ public Iterator<DimensionManager> iterator() {
|
||||
+ Iterator<WorldServer> iterator = worldsIterable.iterator();
|
||||
+ return new Iterator<DimensionManager>() {
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ return iterator.hasNext();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public DimensionManager next() {
|
||||
+ return iterator.next().worldProvider.getDimensionManager();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return worlds.size();
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Collection<WorldServer> values() {
|
||||
+ return worldsIterable;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Set<Entry<DimensionManager, WorldServer>> entrySet() {
|
||||
+ return new AbstractSet<Entry<DimensionManager, WorldServer>>() {
|
||||
+ @Override
|
||||
+ public Iterator<Entry<DimensionManager, WorldServer>> iterator() {
|
||||
+ Iterator<WorldServer> iterator = worldsIterable.iterator();
|
||||
+ return new Iterator<Entry<DimensionManager, WorldServer>>() {
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ return iterator.hasNext();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Entry<DimensionManager, WorldServer> next() {
|
||||
+ WorldServer entry = iterator.next();
|
||||
+ return new SimpleEntry<>(entry.worldProvider.getDimensionManager(), entry);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void remove() {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return worldsIterable.size();
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 7fd0404093..553014b79e 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -88,7 +88,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
public final DataFixer dataConverterManager;
|
||||
private String serverIp;
|
||||
private int serverPort = -1;
|
||||
- public final Map<DimensionManager, WorldServer> worldServer = Maps.newLinkedHashMap(); // CraftBukkit - keep order, k+v already use identity methods
|
||||
+ public final Map<DimensionManager, WorldServer> worldServer = new com.destroystokyo.paper.PaperWorldMap(); // Paper;
|
||||
private PlayerList playerList;
|
||||
private volatile boolean isRunning = true;
|
||||
private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart
|
||||
@@ -458,7 +458,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
}
|
||||
}
|
||||
this.a(this.getDifficulty(), true);
|
||||
- for (WorldServer worldserver : this.getWorlds()) {
|
||||
+ for (WorldServer worldserver : com.google.common.collect.Lists.newArrayList(this.getWorlds())) { // Paper - avoid como if 1 world triggers another world
|
||||
this.loadSpawn(worldserver.getChunkProvider().playerChunkMap.worldLoadListener, worldserver);
|
||||
this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld()));
|
||||
}
|
||||
@@ -606,7 +606,6 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
// this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
|
||||
this.executeModerately();
|
||||
// Iterator iterator = DimensionManager.a().iterator();
|
||||
-
|
||||
if (true) {
|
||||
DimensionManager dimensionmanager = worldserver.worldProvider.getDimensionManager();
|
||||
ForcedChunk forcedchunk = (ForcedChunk) worldserver.getWorldPersistentData().b(ForcedChunk::new, "chunks");
|
||||
--
|
||||
2.24.1
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue