mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-28 13:36:16 +01:00
1.18 misc performance dev branch (#7368)
- Port player chunk loader patch Makes the chunk system act as it did in 1.17, no additional tickets (and thus logic) to make a chunk ticking. Adds simulation distance API, deprecates old no-tick method. - More collision optimisations Ancient patch from tuinity that never could be pushed to master. - Fix Optimise ArraySetSorted#removeIf patch - Execute chunk tasks fairly for worlds while waiting for next tick - Port Replace ticket level propagator
This commit is contained in:
parent
b173c3ee2c
commit
286bd1bfb5
@ -8,10 +8,10 @@ Add per player no-tick, tick, and send view distances.
|
||||
Also add send/no-tick view distance to World.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
|
||||
index cf6fe1b5a1531e8d30c0386e36c023d003458b7e..bf23ef001fb5177b7aab0b3ed8752f58641bb840 100644
|
||||
index cf6fe1b5a1531e8d30c0386e36c023d003458b7e..ad342ecd8b86903276c62644624cff55cf190026 100644
|
||||
--- a/src/main/java/org/bukkit/World.java
|
||||
+++ b/src/main/java/org/bukkit/World.java
|
||||
@@ -2597,6 +2597,52 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
@@ -2597,6 +2597,62 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
int getSimulationDistance();
|
||||
// Spigot end
|
||||
|
||||
@ -23,13 +23,21 @@ index cf6fe1b5a1531e8d30c0386e36c023d003458b7e..bf23ef001fb5177b7aab0b3ed8752f58
|
||||
+ void setViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the simulation distance for this world.
|
||||
+ * @param simulationDistance simulation distance in [2, 32]
|
||||
+ */
|
||||
+ void setSimulationDistance(int simulationDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the no-tick view distance for this world.
|
||||
+ * <p>
|
||||
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @return The no-tick view distance for this world.
|
||||
+ * @deprecated Use {@link #getViewDistance()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ int getNoTickViewDistance();
|
||||
+
|
||||
+ /**
|
||||
@ -39,7 +47,9 @@ index cf6fe1b5a1531e8d30c0386e36c023d003458b7e..bf23ef001fb5177b7aab0b3ed8752f58
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @param viewDistance view distance in [2, 32]
|
||||
+ * @deprecated Use {@link #setViewDistance(int)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ void setNoTickViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
@ -49,7 +59,7 @@ index cf6fe1b5a1531e8d30c0386e36c023d003458b7e..bf23ef001fb5177b7aab0b3ed8752f58
|
||||
+ * </p>
|
||||
+ * @return The sending view distance for this world.
|
||||
+ */
|
||||
+ public int getSendViewDistance();
|
||||
+ int getSendViewDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the sending view distance for this world.
|
||||
@ -58,17 +68,17 @@ index cf6fe1b5a1531e8d30c0386e36c023d003458b7e..bf23ef001fb5177b7aab0b3ed8752f58
|
||||
+ * </p>
|
||||
+ * @param viewDistance view distance in [2, 32] or -1
|
||||
+ */
|
||||
+ public void setSendViewDistance(int viewDistance);
|
||||
+ void setSendViewDistance(int viewDistance);
|
||||
+ // Paper end - view distance api
|
||||
+
|
||||
// Spigot start
|
||||
public class Spigot {
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 43d91f578b0aefd18f7f5ecd120a366af4ee98e6..2d93f5ad7f9c0df08bcd099a813c1d8e9b8c16eb 100644
|
||||
index 43d91f578b0aefd18f7f5ecd120a366af4ee98e6..9f861fcc350b803e63b08631f7a6c30d13b4cb7c 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1793,6 +1793,62 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -1793,6 +1793,78 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* @param affects Whether the player can affect mob spawning
|
||||
*/
|
||||
public void setAffectsSpawning(boolean affects);
|
||||
@ -78,7 +88,6 @@ index 43d91f578b0aefd18f7f5ecd120a366af4ee98e6..2d93f5ad7f9c0df08bcd099a813c1d8e
|
||||
+ *
|
||||
+ * @return the player's view distance
|
||||
+ * @see org.bukkit.World#getViewDistance()
|
||||
+ * @see org.bukkit.World#getNoTickViewDistance()
|
||||
+ */
|
||||
+ public int getViewDistance();
|
||||
+
|
||||
@ -87,18 +96,33 @@ index 43d91f578b0aefd18f7f5ecd120a366af4ee98e6..2d93f5ad7f9c0df08bcd099a813c1d8e
|
||||
+ *
|
||||
+ * @param viewDistance the player's view distance
|
||||
+ * @see org.bukkit.World#setViewDistance(int)
|
||||
+ * @see org.bukkit.World#setNoTickViewDistance(int)
|
||||
+ */
|
||||
+ public void setViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the simulation distance for this player
|
||||
+ *
|
||||
+ * @return the player's simulation distance
|
||||
+ */
|
||||
+ public int getSimulationDistance();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the simulation distance for this player
|
||||
+ *
|
||||
+ * @param simulationDistance the player's new simulation distance
|
||||
+ */
|
||||
+ public void setSimulationDistance(int simulationDistance);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the no-ticking view distance for this player.
|
||||
+ * <p>
|
||||
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @return The no-tick view distance for this player.
|
||||
+ * @deprecated Use {@link #getViewDistance()}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public int getNoTickViewDistance();
|
||||
+
|
||||
+ /**
|
||||
@ -108,7 +132,9 @@ index 43d91f578b0aefd18f7f5ecd120a366af4ee98e6..2d93f5ad7f9c0df08bcd099a813c1d8e
|
||||
+ * be set to tick.
|
||||
+ * </p>
|
||||
+ * @param viewDistance view distance in [2, 32] or -1
|
||||
+ * @deprecated Use {@link #setViewDistance(int)}
|
||||
+ */
|
||||
+ @Deprecated
|
||||
+ public void setNoTickViewDistance(int viewDistance);
|
||||
+
|
||||
+ /**
|
||||
|
@ -5,7 +5,7 @@ Subject: [PATCH] Complete resource pack API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 5f5cde854dd7928e0b640ab1713f42194eab0833..09b5941bcd412420ffc6edfe62bc95cff426ba06 100644
|
||||
index 29bd571bd270b9c6ed05d95122d42d9bc0c797f6..fd8a40bacaaa39c20428bbebe8611ba8cdd33e0b 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -1284,7 +1284,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@ -18,7 +18,7 @@ index 5f5cde854dd7928e0b640ab1713f42194eab0833..09b5941bcd412420ffc6edfe62bc95cf
|
||||
public void setResourcePack(@NotNull String url);
|
||||
|
||||
/**
|
||||
@@ -2058,6 +2060,124 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2074,6 +2076,124 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
default net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowEntity> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowEntity> op) {
|
||||
return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName())));
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ Subject: [PATCH] Add String based Action Bar API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 09b5941bcd412420ffc6edfe62bc95cff426ba06..a0777f9dc7cb6d4274635d794cf66de714535cde 100644
|
||||
index fd8a40bacaaa39c20428bbebe8611ba8cdd33e0b..d6a2e66e07590013bf1596012a96ec1018493e06 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -3,6 +3,7 @@ package org.bukkit.entity;
|
||||
@ -68,7 +68,7 @@ index 09b5941bcd412420ffc6edfe62bc95cff426ba06..a0777f9dc7cb6d4274635d794cf66de7
|
||||
public default void sendMessage(net.md_5.bungee.api.ChatMessageType position, net.md_5.bungee.api.chat.BaseComponent... components) {
|
||||
spigot().sendMessage(position, components);
|
||||
}
|
||||
@@ -2249,6 +2285,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2265,6 +2301,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
/**
|
||||
* Sends the component to the specified screen position of this player
|
||||
*
|
||||
@ -76,7 +76,7 @@ index 09b5941bcd412420ffc6edfe62bc95cff426ba06..a0777f9dc7cb6d4274635d794cf66de7
|
||||
* @param position the screen position
|
||||
* @param component the components to send
|
||||
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
|
||||
@@ -2261,6 +2298,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2277,6 +2314,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
/**
|
||||
* Sends an array of components as a single message to the specified screen position of this player
|
||||
*
|
||||
|
@ -62,10 +62,10 @@ index 51c96a0b6645cf31f4ca051f6a8c75b5f188484c..80d474a979add473c99692ccde93439d
|
||||
|
||||
/**
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index b68f2774e4f88e905cc195df6d1592d96103df7a..23df52c7ac4ec5e687e763c13a0937c3fbc5dd47 100644
|
||||
index c16716e77427d0968c004a5b30600a40a36d5137..888a60fe60e6242680c153fd8edd95f6e37e26d5 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2235,6 +2235,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2251,6 +2251,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* was {@link org.bukkit.event.player.PlayerResourcePackStatusEvent.Status#SUCCESSFULLY_LOADED}
|
||||
*/
|
||||
boolean hasResourcePack();
|
||||
|
@ -24,10 +24,10 @@ index 8a479c7dfd3825fab8bb057d8afa5ae0cb01b071..6ef0d7f3dcb779fb7dc5786e74332620
|
||||
/**
|
||||
* Make the entity drop the item in their hand.
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 23df52c7ac4ec5e687e763c13a0937c3fbc5dd47..fd4613f702ebbd32ec22a81f993a1ea9d8dd896f 100644
|
||||
index 888a60fe60e6242680c153fd8edd95f6e37e26d5..87f62e65dbf8128d684abaf4fde88cfa566f7a1f 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2090,7 +2090,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2106,7 +2106,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
/**
|
||||
* Open a Sign for editing by the Player.
|
||||
*
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Expose attack cooldown methods for Player
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 61e75620b205cfeda0aee433651c45235bf21181..11e85e664fdd875c2a6e84b158b78d4784999932 100644
|
||||
index 81b3d2da2bb92c874845688a8b8a2b15b2a4bd59..ffbc26048e359044be6b0c96f3bd8cd1048fb316 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2405,6 +2405,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2421,6 +2421,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* @param profile The new profile to use
|
||||
*/
|
||||
void setPlayerProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile);
|
||||
|
@ -193,7 +193,7 @@ index 0000000000000000000000000000000000000000..f7f171c4ee0b8339b2f8fbe82442d65f
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 11e85e664fdd875c2a6e84b158b78d4784999932..385846a2011ec07d4f37c98f38d3369199780418 100644
|
||||
index ffbc26048e359044be6b0c96f3bd8cd1048fb316..db12ce34a7fa4f309e7cc52c953bb409e9b6ab0c 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2,6 +2,7 @@ package org.bukkit.entity;
|
||||
@ -204,7 +204,7 @@ index 11e85e664fdd875c2a6e84b158b78d4784999932..385846a2011ec07d4f37c98f38d33691
|
||||
import com.destroystokyo.paper.Title; // Paper
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.DyeColor;
|
||||
@@ -2425,6 +2426,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2441,6 +2442,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
* Reset the cooldown counter to 0, effectively starting the cooldown period.
|
||||
*/
|
||||
void resetCooldown();
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Brand support
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 385846a2011ec07d4f37c98f38d3369199780418..e61d0ff51674213e4711d5bbe9e8aaed31ed00df 100644
|
||||
index db12ce34a7fa4f309e7cc52c953bb409e9b6ab0c..6983b3d6d5402ea1ed3646bffdd4d8bc613a6121 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2560,6 +2560,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2576,6 +2576,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
// Paper end
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Player elytra boost API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index e61d0ff51674213e4711d5bbe9e8aaed31ed00df..45284317f195f08e88a4977a32a1757afb6c4b17 100644
|
||||
index 6983b3d6d5402ea1ed3646bffdd4d8bc613a6121..167ea1fe8d5d16098559745a67e5128e4ef78082 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2432,6 +2432,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2448,6 +2448,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
*/
|
||||
@NotNull
|
||||
<T> T getClientOption(@NotNull ClientOption<T> option);
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Add sendOpLevel API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 45284317f195f08e88a4977a32a1757afb6c4b17..71de9f4c7f07c4c0b1155df14794de3ba8e28d69 100644
|
||||
index 167ea1fe8d5d16098559745a67e5128e4ef78082..6efcd4c5b89af422c630a566e8a851062e05b69a 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -2445,6 +2445,17 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@@ -2461,6 +2461,17 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
*/
|
||||
@Nullable
|
||||
Firework boostElytra(@NotNull ItemStack firework);
|
||||
|
@ -298,7 +298,7 @@ index 0000000000000000000000000000000000000000..bee2fa2bfbb61209381f24ed6508d3d1
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e4368db074da7b5e48b47d41875c1e63b9745c2a
|
||||
index 0000000000000000000000000000000000000000..5c7b2850d311e4d54236ba9acce148bca05672fd
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -0,0 +1,188 @@
|
||||
@ -364,8 +364,8 @@ index 0000000000000000000000000000000000000000..e4368db074da7b5e48b47d41875c1e63
|
||||
+ commands = new HashMap<String, Command>();
|
||||
+ commands.put("paper", new PaperCommand("paper"));
|
||||
+
|
||||
+ version = getInt("config-version", 24);
|
||||
+ set("config-version", 24);
|
||||
+ version = getInt("config-version", 25);
|
||||
+ set("config-version", 25);
|
||||
+ readConfig(PaperConfig.class, null);
|
||||
+ }
|
||||
+
|
||||
|
@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..d0211d4f39f9d6af1d751ac66342b42c
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index e683e5bf47abe7bd3d2f7e9811a377549308ded4..c20fe23174d8a12bfc5acb4b0e947c6fca5ab897 100644
|
||||
index a3c3656ba4e8bb85bfb3186d6284f02f09975b13..6cfaef1886b517c56ed9a96347be6e51efa84d9f 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -69,6 +69,7 @@ public class PaperConfig {
|
||||
@ -84,8 +84,8 @@ index e683e5bf47abe7bd3d2f7e9811a377549308ded4..c20fe23174d8a12bfc5acb4b0e947c6f
|
||||
commands.put("paper", new PaperCommand("paper"));
|
||||
+ commands.put("mspt", new MSPTCommand("mspt"));
|
||||
|
||||
version = getInt("config-version", 24);
|
||||
set("config-version", 24);
|
||||
version = getInt("config-version", 25);
|
||||
set("config-version", 25);
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 76da16590f27702883c07200a02db823d9720c61..3c2af39f7bd62448a3075d327132ebc19af6bd77 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
|
@ -5,6 +5,41 @@ Subject: [PATCH] Optimise ArraySetSorted#removeIf
|
||||
|
||||
Remove iterator allocation and ensure the call is always O(n)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index 07b616d9d7cde77c001f5c627daef0731d883e61..e8b4de332cc655a55621e40360fa46d893d903f4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -85,13 +85,27 @@ public abstract class DistanceManager {
|
||||
protected void purgeStaleTickets() {
|
||||
++this.ticketTickCounter;
|
||||
ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().fastIterator();
|
||||
+ // Paper start - use optimised removeIf
|
||||
+ long[] currChunk = new long[1];
|
||||
+ long ticketCounter = DistanceManager.this.ticketTickCounter;
|
||||
+ java.util.function.Predicate<Ticket<?>> removeIf = (ticket) -> {
|
||||
+ final boolean ret = ticket.timedOut(ticketCounter);
|
||||
+ if (ret) {
|
||||
+ this.tickingTicketsTracker.removeTicket(currChunk[0], ticket);
|
||||
+ }
|
||||
+ return ret;
|
||||
+ };
|
||||
+ // Paper end - use optimised removeIf
|
||||
|
||||
while (objectiterator.hasNext()) {
|
||||
Entry<SortedArraySet<Ticket<?>>> entry = (Entry) objectiterator.next();
|
||||
- Iterator<Ticket<?>> iterator = ((SortedArraySet) entry.getValue()).iterator();
|
||||
- boolean flag = false;
|
||||
+ // Paper start - use optimised removeIf
|
||||
+ Iterator<Ticket<?>> iterator = null;
|
||||
+ currChunk[0] = entry.getLongKey();
|
||||
+ boolean flag = entry.getValue().removeIf(removeIf);
|
||||
|
||||
- while (iterator.hasNext()) {
|
||||
+ while (false && iterator.hasNext()) {
|
||||
+ // Paper end - use optimised removeIf
|
||||
Ticket<?> ticket = (Ticket) iterator.next();
|
||||
|
||||
if (ticket.timedOut(this.ticketTickCounter)) {
|
||||
diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java
|
||||
index d1b2ba24ef54e01c6249c3b2ca16e80f03c001a6..5f1c4c6b9e36f2d6ec43b82cc0e2cae24b800dc4 100644
|
||||
--- a/src/main/java/net/minecraft/util/SortedArraySet.java
|
||||
|
@ -7,10 +7,10 @@ Subject: [PATCH] Don't crash if player is attempted to be removed from
|
||||
I suspect it deals with teleporting as it uses players current x/y/z
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index f0dac1f596911eb2109192ef16a619f8ae71d1f7..8868ffcda194e8c2300181a2cdda9337dbde6284 100644
|
||||
index e8b4de332cc655a55621e40360fa46d893d903f4..75f11490737018096e7645ce0b991fd210c8f596 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -283,8 +283,8 @@ public abstract class DistanceManager {
|
||||
@@ -297,8 +297,8 @@ public abstract class DistanceManager {
|
||||
ObjectSet<ServerPlayer> objectset = (ObjectSet) this.playersPerChunk.get(i);
|
||||
if (objectset == null) return; // CraftBukkit - SPIGOT-6208
|
||||
|
||||
|
@ -6,10 +6,10 @@ Subject: [PATCH] Optimize anyPlayerCloseEnoughForSpawning to use distance maps
|
||||
Use a distance map to find the players in range quickly
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 74d674b2684b0db4aa6c183edc6091d53e9ee882..626bcbc6dd013260c3f8b38a1d14e7ba35dc1e01 100644
|
||||
index 74d674b2684b0db4aa6c183edc6091d53e9ee882..560cc04ee7a8fd0c3c7217e08d53d1da682054e2 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -73,6 +73,18 @@ public class ChunkHolder {
|
||||
@@ -73,6 +73,23 @@ public class ChunkHolder {
|
||||
boolean isUpdateQueued = false; // Paper
|
||||
private final ChunkMap chunkMap; // Paper
|
||||
|
||||
@ -18,26 +18,31 @@ index 74d674b2684b0db4aa6c183edc6091d53e9ee882..626bcbc6dd013260c3f8b38a1d14e7ba
|
||||
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> playersInMobSpawnRange;
|
||||
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> playersInChunkTickRange;
|
||||
+
|
||||
+ void updateRanges() {
|
||||
+ void onChunkAdd() {
|
||||
+ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.pos);
|
||||
+ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
|
||||
+ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
||||
+ }
|
||||
+
|
||||
+ void onChunkRemove() {
|
||||
+ this.playersInMobSpawnRange = null;
|
||||
+ this.playersInChunkTickRange = null;
|
||||
+ }
|
||||
+ // Paper end - optimise anyPlayerCloseEnoughForSpawning
|
||||
+
|
||||
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
|
||||
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
|
||||
this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE;
|
||||
@@ -94,6 +106,7 @@ public class ChunkHolder {
|
||||
@@ -94,6 +111,7 @@ public class ChunkHolder {
|
||||
this.setTicketLevel(level);
|
||||
this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()];
|
||||
this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper
|
||||
+ this.updateRanges(); // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ this.onChunkAdd(); // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 7f8c82f2f50934bcc2eacd40a5fbd93d5dae68f6..745b8c16600ba106907302daa9630abdce6807b0 100644
|
||||
index 00eeaa04c98a658bac63f72da6b6d157131e9120..cd58121bfa059366919e098005299dde0c55f46f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -177,11 +177,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@ -122,15 +127,23 @@ index 7f8c82f2f50934bcc2eacd40a5fbd93d5dae68f6..745b8c16600ba106907302daa9630abd
|
||||
}
|
||||
|
||||
protected ChunkGenerator generator() {
|
||||
@@ -487,6 +536,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
} else {
|
||||
@@ -501,6 +550,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
holder = (ChunkHolder) this.pendingUnloads.remove(pos);
|
||||
if (holder != null) {
|
||||
holder.setTicketLevel(level);
|
||||
+ holder.updateRanges(); // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
}
|
||||
+ holder.onChunkAdd(); // Paper - optimise anyPlayerCloseEnoughForSpawning - PUT HERE AFTER RE-ADDING ONLY
|
||||
} else {
|
||||
holder = new ChunkHolder(new ChunkPos(pos), level, this.level, this.lightEngine, this.queueSorter, this);
|
||||
// Paper start
|
||||
@@ -600,6 +650,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.remove(j);
|
||||
|
||||
if (holder != null) {
|
||||
@@ -1331,43 +1381,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (playerchunk != null) {
|
||||
+ playerchunk.onChunkRemove(); // Paper
|
||||
this.pendingUnloads.put(j, playerchunk);
|
||||
this.modified = true;
|
||||
this.scheduleUnload(j, playerchunk); // Paper - Move up - don't leak chunks
|
||||
@@ -1331,43 +1382,48 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return this.anyPlayerCloseEnoughForSpawning(pos, false);
|
||||
}
|
||||
|
||||
@ -211,7 +224,7 @@ index 7f8c82f2f50934bcc2eacd40a5fbd93d5dae68f6..745b8c16600ba106907302daa9630abd
|
||||
|
||||
public List<ServerPlayer> getPlayersCloseForSpawning(ChunkPos pos) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index f11e9421d393ef5a04f24c78a1214359710cc2f8..3865146697051e01a778414064425ea0e5162b8d 100644
|
||||
index 75f11490737018096e7645ce0b991fd210c8f596..14774d51dd35a98471d29230a64fadee74651d19 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -48,7 +48,7 @@ public abstract class DistanceManager {
|
||||
@ -223,7 +236,7 @@ index f11e9421d393ef5a04f24c78a1214359710cc2f8..3865146697051e01a778414064425ea0
|
||||
private final TickingTracker tickingTicketsTracker = new TickingTracker();
|
||||
private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33);
|
||||
// Paper start use a queue, but still keep unique requirement
|
||||
@@ -125,7 +125,7 @@ public abstract class DistanceManager {
|
||||
@@ -139,7 +139,7 @@ public abstract class DistanceManager {
|
||||
protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k);
|
||||
|
||||
public boolean runAllUpdates(ChunkMap chunkStorage) {
|
||||
@ -232,7 +245,7 @@ index f11e9421d393ef5a04f24c78a1214359710cc2f8..3865146697051e01a778414064425ea0
|
||||
this.tickingTicketsTracker.runAllUpdates();
|
||||
this.playerTicketManager.runAllUpdates();
|
||||
int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE);
|
||||
@@ -272,7 +272,7 @@ public abstract class DistanceManager {
|
||||
@@ -286,7 +286,7 @@ public abstract class DistanceManager {
|
||||
((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> {
|
||||
return new ObjectOpenHashSet();
|
||||
})).add(player);
|
||||
@ -241,7 +254,7 @@ index f11e9421d393ef5a04f24c78a1214359710cc2f8..3865146697051e01a778414064425ea0
|
||||
this.playerTicketManager.update(i, 0, true);
|
||||
this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair);
|
||||
}
|
||||
@@ -286,7 +286,7 @@ public abstract class DistanceManager {
|
||||
@@ -300,7 +300,7 @@ public abstract class DistanceManager {
|
||||
if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully.
|
||||
if (objectset == null || objectset.isEmpty()) { // Paper
|
||||
this.playersPerChunk.remove(i);
|
||||
@ -250,7 +263,7 @@ index f11e9421d393ef5a04f24c78a1214359710cc2f8..3865146697051e01a778414064425ea0
|
||||
this.playerTicketManager.update(i, Integer.MAX_VALUE, false);
|
||||
this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair);
|
||||
}
|
||||
@@ -330,13 +330,17 @@ public abstract class DistanceManager {
|
||||
@@ -344,13 +344,17 @@ public abstract class DistanceManager {
|
||||
// Paper end
|
||||
|
||||
public int getNaturalSpawnChunkCount() {
|
||||
@ -273,7 +286,7 @@ index f11e9421d393ef5a04f24c78a1214359710cc2f8..3865146697051e01a778414064425ea0
|
||||
|
||||
public String getDebugStatus() {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 02516d4a6ee08908765f5bc84b14560754a67680..b327bd2f48166a4a0c831b0209695fe5935f6a68 100644
|
||||
index 8cfd38617b49ea6be318abc819f2ed5b7dabd2e1..59cd2b8ecdd2c962a027526fe45032559aa2ee8c 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -881,6 +881,37 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
@ -6,7 +6,7 @@ Subject: [PATCH] Use distance map to optimise entity tracker
|
||||
Use the distance map to find candidate players for tracking.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index d924dfe452244633bcf62e7ccefe3a5a1a3d7f37..e35a47e0c8eebbad7154a1357a6b868887bc4a0c 100644
|
||||
index cd58121bfa059366919e098005299dde0c55f46f..25c71ca93c54976cc319abb0d932beb6f95deb79 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -67,6 +67,7 @@ import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
|
||||
@ -126,7 +126,7 @@ index d924dfe452244633bcf62e7ccefe3a5a1a3d7f37..e35a47e0c8eebbad7154a1357a6b8688
|
||||
// Paper start - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
||||
this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
||||
(ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
||||
@@ -1504,17 +1582,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1505,17 +1583,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public void move(ServerPlayer player) {
|
||||
@ -145,7 +145,7 @@ index d924dfe452244633bcf62e7ccefe3a5a1a3d7f37..e35a47e0c8eebbad7154a1357a6b8688
|
||||
|
||||
int i = SectionPos.blockToSectionCoord(player.getBlockX());
|
||||
int j = SectionPos.blockToSectionCoord(player.getBlockZ());
|
||||
@@ -1641,7 +1709,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1642,7 +1710,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker
|
||||
this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
|
||||
@ -154,7 +154,7 @@ index d924dfe452244633bcf62e7ccefe3a5a1a3d7f37..e35a47e0c8eebbad7154a1357a6b8688
|
||||
if (entity instanceof ServerPlayer) {
|
||||
ServerPlayer entityplayer = (ServerPlayer) entity;
|
||||
|
||||
@@ -1685,7 +1753,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1686,7 +1754,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
entity.tracker = null; // Paper - We're no longer tracked
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ index d924dfe452244633bcf62e7ccefe3a5a1a3d7f37..e35a47e0c8eebbad7154a1357a6b8688
|
||||
List<ServerPlayer> list = Lists.newArrayList();
|
||||
List<ServerPlayer> list1 = this.level.players();
|
||||
ObjectIterator objectiterator = this.entityMap.values().iterator();
|
||||
@@ -1761,23 +1859,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1762,23 +1860,31 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos());
|
||||
List<Entity> list = Lists.newArrayList();
|
||||
List<Entity> list1 = Lists.newArrayList();
|
||||
@ -236,7 +236,7 @@ index d924dfe452244633bcf62e7ccefe3a5a1a3d7f37..e35a47e0c8eebbad7154a1357a6b8688
|
||||
|
||||
Iterator iterator;
|
||||
Entity entity1;
|
||||
@@ -1853,6 +1959,42 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1854,6 +1960,42 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.lastSectionPos = SectionPos.of(entity);
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ index d924dfe452244633bcf62e7ccefe3a5a1a3d7f37..e35a47e0c8eebbad7154a1357a6b8688
|
||||
return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index a02eb37845e0609ddf14a4214395e00443534b08..8e59a63e8c161e90ccff951ecb2b6530fadf3b80 100644
|
||||
index 7bf62752b6604abe0bda6f5d0024f0e93efb3a9a..9a4454746452f64d7a8caa52eef2dca86e9edd94 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -51,6 +51,7 @@ import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
|
@ -35,10 +35,10 @@ index bc880a78381b9c30e4ec92bdf17c9eca1ded41f2..eae27a641ee69f3383f1200f8c8ab8dd
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index 3865146697051e01a778414064425ea0e5162b8d..cd81e7844c985d7d0f0930faa96478af6a7f6cd4 100644
|
||||
index 14774d51dd35a98471d29230a64fadee74651d19..93a642cd6cf21a268074a73bff22249d32992ad3 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -197,6 +197,27 @@ public abstract class DistanceManager {
|
||||
@@ -211,6 +211,27 @@ public abstract class DistanceManager {
|
||||
boolean removed = false; // CraftBukkit
|
||||
if (arraysetsorted.remove(ticket)) {
|
||||
removed = true; // CraftBukkit
|
||||
|
@ -5,7 +5,7 @@ Subject: [PATCH] incremental chunk and player saving
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index a545a882335094daa787ec5c7005939080195263..933d3ace21f5a313f1d5e4dfd86777f6fa235f3f 100644
|
||||
index df1337c89c943a80a31d127c844f061c1e56eb91..cb967380155d34ff511346d54b61e1c2109780f3 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -459,4 +459,14 @@ public class PaperConfig {
|
||||
@ -24,7 +24,7 @@ index a545a882335094daa787ec5c7005939080195263..933d3ace21f5a313f1d5e4dfd86777f6
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index d6d549df6e8920c936dd0d1b7ba828dbebc60b32..8b4b521a84c8623665d21d0340bca7665953d20b 100644
|
||||
index eae27a641ee69f3383f1200f8c8ab8dd7a4105a4..12a6f12ffa8a45b054b01a7edc73ca8a5bcb59b5 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -64,6 +64,21 @@ public class PaperWorldConfig {
|
||||
@ -50,7 +50,7 @@ index d6d549df6e8920c936dd0d1b7ba828dbebc60b32..8b4b521a84c8623665d21d0340bca766
|
||||
config.addDefault("world-settings.default." + path, def);
|
||||
return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path));
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 918fdf14080338983b8725bf2619088fd23c332a..95842327aa08d4717f86e9dcc0519ab24c41ca14 100644
|
||||
index 9a926114aa550ca5a6329e3ce993bf1f686cd10e..ab7ca991e5d7940a386a820e1953df1ac2428107 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -902,7 +902,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@ -98,11 +98,11 @@ index 918fdf14080338983b8725bf2619088fd23c332a..95842327aa08d4717f86e9dcc0519ab2
|
||||
// Paper start - move executeAll() into full server tick timing
|
||||
try (co.aikar.timings.Timing ignored = MinecraftTimings.processTasksTimer.startTiming()) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 626bcbc6dd013260c3f8b38a1d14e7ba35dc1e01..9e96b0465717bfa761289c255fd8d2f1df1be3d8 100644
|
||||
index 560cc04ee7a8fd0c3c7217e08d53d1da682054e2..5479deb3f80a95c58cb6f0f532b2f56b71a68a3a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -84,6 +84,8 @@ public class ChunkHolder {
|
||||
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
||||
@@ -89,6 +89,8 @@ public class ChunkHolder {
|
||||
this.playersInChunkTickRange = null;
|
||||
}
|
||||
// Paper end - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ long lastAutoSaveTime; // Paper - incremental autosave
|
||||
@ -110,7 +110,7 @@ index 626bcbc6dd013260c3f8b38a1d14e7ba35dc1e01..9e96b0465717bfa761289c255fd8d2f1
|
||||
|
||||
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
|
||||
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
|
||||
@@ -473,7 +475,19 @@ public class ChunkHolder {
|
||||
@@ -478,7 +480,19 @@ public class ChunkHolder {
|
||||
boolean flag2 = playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER);
|
||||
boolean flag3 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER);
|
||||
|
||||
@ -130,7 +130,7 @@ index 626bcbc6dd013260c3f8b38a1d14e7ba35dc1e01..9e96b0465717bfa761289c255fd8d2f1
|
||||
if (!flag2 && flag3) {
|
||||
int expectCreateCount = ++this.fullChunkCreateCount; // Paper
|
||||
this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this);
|
||||
@@ -604,9 +618,33 @@ public class ChunkHolder {
|
||||
@@ -609,9 +623,33 @@ public class ChunkHolder {
|
||||
}
|
||||
|
||||
public void refreshAccessibility() {
|
||||
@ -165,7 +165,7 @@ index 626bcbc6dd013260c3f8b38a1d14e7ba35dc1e01..9e96b0465717bfa761289c255fd8d2f1
|
||||
for (int i = 0; i < this.futures.length(); ++i) {
|
||||
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = (CompletableFuture) this.futures.get(i);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index e35a47e0c8eebbad7154a1357a6b868887bc4a0c..cac9c9ede6024653f4ae83cbbdd9939f75ccad48 100644
|
||||
index 25c71ca93c54976cc319abb0d932beb6f95deb79..e66e4d1656e5f6f042c5c63715e13a6b5e7d81c5 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -101,6 +101,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana
|
||||
@ -241,7 +241,7 @@ index e35a47e0c8eebbad7154a1357a6b868887bc4a0c..cac9c9ede6024653f4ae83cbbdd9939f
|
||||
protected void saveAllChunks(boolean flush) {
|
||||
if (flush) {
|
||||
List<ChunkHolder> list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList());
|
||||
@@ -751,13 +810,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -752,13 +811,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
int l = 0;
|
||||
@ -256,7 +256,7 @@ index e35a47e0c8eebbad7154a1357a6b868887bc4a0c..cac9c9ede6024653f4ae83cbbdd9939f
|
||||
|
||||
}
|
||||
|
||||
@@ -795,6 +848,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -796,6 +849,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
this.level.unload(chunk);
|
||||
}
|
||||
@ -264,7 +264,7 @@ index e35a47e0c8eebbad7154a1357a6b868887bc4a0c..cac9c9ede6024653f4ae83cbbdd9939f
|
||||
|
||||
this.lightEngine.updateChunkStatus(ichunkaccess.getPos());
|
||||
this.lightEngine.tryScheduleUpdate();
|
||||
@@ -1192,6 +1246,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1193,6 +1247,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
asyncSaveData, chunk);
|
||||
|
||||
chunk.setUnsaved(false);
|
||||
@ -272,7 +272,7 @@ index e35a47e0c8eebbad7154a1357a6b868887bc4a0c..cac9c9ede6024653f4ae83cbbdd9939f
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -1201,6 +1256,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1202,6 +1257,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (!chunk.isUnsaved()) {
|
||||
return false;
|
||||
} else {
|
||||
@ -281,7 +281,7 @@ index e35a47e0c8eebbad7154a1357a6b868887bc4a0c..cac9c9ede6024653f4ae83cbbdd9939f
|
||||
ChunkPos chunkcoordintpair = chunk.getPos();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index b327bd2f48166a4a0c831b0209695fe5935f6a68..73b1018b0aca377ed0ff188e74040cef57036b0b 100644
|
||||
index 59cd2b8ecdd2c962a027526fe45032559aa2ee8c..fdc027bc5a7e9d691ac90c5fee0cdfebd959bc5f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -825,6 +825,15 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@ -301,7 +301,7 @@ index b327bd2f48166a4a0c831b0209695fe5935f6a68..73b1018b0aca377ed0ff188e74040cef
|
||||
public void close() throws IOException {
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 0d70647bdd08371beaf476bd4eb5a45d985e498d..b27fb07aacb66259f640de5c5aa6849eb7e8cc9c 100644
|
||||
index 04aae918f1951291459ce17b25986e5cac9d2378..3b99a6dda3638f3a7212d7c9fab5470409de4e6f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1058,6 +1058,37 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
@ -80,7 +80,7 @@ index 89e0181af99cba2368f875fc192342efc972f2ef..b3516862d796c2d9fcc1c67a60734454
|
||||
chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.longKey));
|
||||
chunkData.addProperty("status", status == null ? "unloaded" : status.toString());
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48fe4b30bf3 100644
|
||||
index 5479deb3f80a95c58cb6f0f532b2f56b71a68a3a..b62d7a85db012265dd4fae02cbed5363a41d536b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -57,7 +57,7 @@ public class ChunkHolder {
|
||||
@ -100,7 +100,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
boolean isUpdateQueued = false; // Paper
|
||||
private final ChunkMap chunkMap; // Paper
|
||||
|
||||
@@ -419,12 +420,18 @@ public class ChunkHolder {
|
||||
@@ -424,12 +425,18 @@ public class ChunkHolder {
|
||||
});
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel);
|
||||
ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel);
|
||||
boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE;
|
||||
@@ -435,9 +442,22 @@ public class ChunkHolder {
|
||||
@@ -440,9 +447,22 @@ public class ChunkHolder {
|
||||
// ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
|
||||
if (playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
|
||||
this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
||||
@ -143,7 +143,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
// Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick
|
||||
// lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag.
|
||||
// These actions may however happen deferred, so we manually set the needsSaving flag already here.
|
||||
@@ -494,12 +514,14 @@ public class ChunkHolder {
|
||||
@@ -499,12 +519,14 @@ public class ChunkHolder {
|
||||
this.scheduleFullChunkPromotion(chunkStorage, this.fullChunkFuture, executor, ChunkHolder.FullChunkStatus.BORDER);
|
||||
// Paper start - cache ticking ready status
|
||||
this.fullChunkFuture.thenAccept(either -> {
|
||||
@ -158,7 +158,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
}
|
||||
});
|
||||
this.updateChunkToSave(this.fullChunkFuture, "full");
|
||||
@@ -520,6 +542,7 @@ public class ChunkHolder {
|
||||
@@ -525,6 +547,7 @@ public class ChunkHolder {
|
||||
this.scheduleFullChunkPromotion(chunkStorage, this.tickingChunkFuture, executor, ChunkHolder.FullChunkStatus.TICKING);
|
||||
// Paper start - cache ticking ready status
|
||||
this.tickingChunkFuture.thenAccept(either -> {
|
||||
@ -166,7 +166,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
either.ifLeft(chunk -> {
|
||||
// note: Here is a very good place to add callbacks to logic waiting on this.
|
||||
ChunkHolder.this.isTickingReady = true;
|
||||
@@ -555,6 +578,7 @@ public class ChunkHolder {
|
||||
@@ -560,6 +583,7 @@ public class ChunkHolder {
|
||||
this.scheduleFullChunkPromotion(chunkStorage, this.entityTickingChunkFuture, executor, ChunkHolder.FullChunkStatus.ENTITY_TICKING);
|
||||
// Paper start - cache ticking ready status
|
||||
this.entityTickingChunkFuture.thenAccept(either -> {
|
||||
@ -174,7 +174,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
either.ifLeft(chunk -> {
|
||||
ChunkHolder.this.isEntityTickingReady = true;
|
||||
// Paper start - entity ticking chunk set
|
||||
@@ -581,16 +605,45 @@ public class ChunkHolder {
|
||||
@@ -586,16 +610,45 @@ public class ChunkHolder {
|
||||
this.demoteFullChunk(chunkStorage, playerchunk_state1);
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
});
|
||||
}
|
||||
}).exceptionally((throwable) -> {
|
||||
@@ -705,7 +758,134 @@ public class ChunkHolder {
|
||||
@@ -710,7 +763,134 @@ public class ChunkHolder {
|
||||
};
|
||||
}
|
||||
|
||||
@ -360,7 +360,7 @@ index 9e96b0465717bfa761289c255fd8d2f1df1be3d8..87271552aa85626f22f7f8569c8fb48f
|
||||
return this.isEntityTickingReady;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 92cb20466d2747e6013bf433d87c5bb30a89ba4f..11b3a3105cac879d8a52290967b9d3b638fb3721 100644
|
||||
index e66e4d1656e5f6f042c5c63715e13a6b5e7d81c5..aef2974ecec878a014ada9619d814ae333f4923a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -128,6 +128,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@ -448,7 +448,7 @@ index 92cb20466d2747e6013bf433d87c5bb30a89ba4f..11b3a3105cac879d8a52290967b9d3b6
|
||||
|
||||
list1.add(playerchunk);
|
||||
list.add(completablefuture);
|
||||
@@ -888,11 +938,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -889,11 +939,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (requiredStatus == ChunkStatus.EMPTY) {
|
||||
return this.scheduleChunkLoad(chunkcoordintpair);
|
||||
} else {
|
||||
@ -469,7 +469,7 @@ index 92cb20466d2747e6013bf433d87c5bb30a89ba4f..11b3a3105cac879d8a52290967b9d3b6
|
||||
|
||||
if (optional.isPresent() && ((ChunkAccess) optional.get()).getStatus().isOrAfter(requiredStatus)) {
|
||||
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = requiredStatus.load(this.level, this.structureManager, this.lightEngine, (ichunkaccess) -> {
|
||||
@@ -904,6 +962,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -905,6 +963,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
} else {
|
||||
return this.scheduleChunkGeneration(holder, requiredStatus);
|
||||
}
|
||||
@ -477,7 +477,7 @@ index 92cb20466d2747e6013bf433d87c5bb30a89ba4f..11b3a3105cac879d8a52290967b9d3b6
|
||||
}
|
||||
}
|
||||
|
||||
@@ -960,14 +1019,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -961,14 +1020,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
};
|
||||
|
||||
CompletableFuture<CompoundTag> chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z);
|
||||
@ -507,7 +507,7 @@ index 92cb20466d2747e6013bf433d87c5bb30a89ba4f..11b3a3105cac879d8a52290967b9d3b6
|
||||
return ret;
|
||||
// Paper end
|
||||
}
|
||||
@@ -1019,7 +1088,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1020,7 +1089,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.releaseLightTicket(chunkcoordintpair);
|
||||
return CompletableFuture.completedFuture(Either.right(playerchunk_failure));
|
||||
});
|
||||
@ -519,7 +519,7 @@ index 92cb20466d2747e6013bf433d87c5bb30a89ba4f..11b3a3105cac879d8a52290967b9d3b6
|
||||
}
|
||||
|
||||
protected void releaseLightTicket(ChunkPos pos) {
|
||||
@@ -1103,7 +1175,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1104,7 +1176,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
long i = chunkHolder.getPos().toLong();
|
||||
|
||||
Objects.requireNonNull(chunkHolder);
|
||||
@ -529,10 +529,10 @@ index 92cb20466d2747e6013bf433d87c5bb30a89ba4f..11b3a3105cac879d8a52290967b9d3b6
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index cd81e7844c985d7d0f0930faa96478af6a7f6cd4..1744f4983b24a87f3861ebd5d68120cfce904934 100644
|
||||
index 93a642cd6cf21a268074a73bff22249d32992ad3..7c66e4ed02c80521196b4ca797477dd9573752d8 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -113,6 +113,7 @@ public abstract class DistanceManager {
|
||||
@@ -127,6 +127,7 @@ public abstract class DistanceManager {
|
||||
}
|
||||
|
||||
private static int getTicketLevelAt(SortedArraySet<Ticket<?>> tickets) {
|
||||
@ -540,7 +540,7 @@ index cd81e7844c985d7d0f0930faa96478af6a7f6cd4..1744f4983b24a87f3861ebd5d68120cf
|
||||
return !tickets.isEmpty() ? ((Ticket) tickets.first()).getTicketLevel() : ChunkMap.MAX_CHUNK_DISTANCE + 1;
|
||||
}
|
||||
|
||||
@@ -127,6 +128,7 @@ public abstract class DistanceManager {
|
||||
@@ -141,6 +142,7 @@ public abstract class DistanceManager {
|
||||
public boolean runAllUpdates(ChunkMap chunkStorage) {
|
||||
//this.f.a(); // Paper - no longer used
|
||||
this.tickingTicketsTracker.runAllUpdates();
|
||||
@ -548,7 +548,7 @@ index cd81e7844c985d7d0f0930faa96478af6a7f6cd4..1744f4983b24a87f3861ebd5d68120cf
|
||||
this.playerTicketManager.runAllUpdates();
|
||||
int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE);
|
||||
boolean flag = i != 0;
|
||||
@@ -137,11 +139,13 @@ public abstract class DistanceManager {
|
||||
@@ -151,11 +153,13 @@ public abstract class DistanceManager {
|
||||
|
||||
// Paper start
|
||||
if (!this.pendingChunkUpdates.isEmpty()) {
|
||||
@ -562,7 +562,7 @@ index cd81e7844c985d7d0f0930faa96478af6a7f6cd4..1744f4983b24a87f3861ebd5d68120cf
|
||||
// Paper end
|
||||
return true;
|
||||
} else {
|
||||
@@ -177,8 +181,10 @@ public abstract class DistanceManager {
|
||||
@@ -191,8 +195,10 @@ public abstract class DistanceManager {
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@ -573,7 +573,7 @@ index cd81e7844c985d7d0f0930faa96478af6a7f6cd4..1744f4983b24a87f3861ebd5d68120cf
|
||||
SortedArraySet<Ticket<?>> arraysetsorted = this.getTickets(i);
|
||||
int j = DistanceManager.getTicketLevelAt(arraysetsorted);
|
||||
Ticket<?> ticket1 = (Ticket) arraysetsorted.addOrGet(ticket);
|
||||
@@ -192,7 +198,9 @@ public abstract class DistanceManager {
|
||||
@@ -206,7 +212,9 @@ public abstract class DistanceManager {
|
||||
}
|
||||
|
||||
boolean removeTicket(long i, Ticket<?> ticket) { // CraftBukkit - void -> boolean
|
||||
@ -583,7 +583,7 @@ index cd81e7844c985d7d0f0930faa96478af6a7f6cd4..1744f4983b24a87f3861ebd5d68120cf
|
||||
|
||||
boolean removed = false; // CraftBukkit
|
||||
if (arraysetsorted.remove(ticket)) {
|
||||
@@ -224,7 +232,12 @@ public abstract class DistanceManager {
|
||||
@@ -238,7 +246,12 @@ public abstract class DistanceManager {
|
||||
this.tickets.remove(i);
|
||||
}
|
||||
|
||||
@ -597,7 +597,7 @@ index cd81e7844c985d7d0f0930faa96478af6a7f6cd4..1744f4983b24a87f3861ebd5d68120cf
|
||||
return removed; // CraftBukkit
|
||||
}
|
||||
|
||||
@@ -272,6 +285,112 @@ public abstract class DistanceManager {
|
||||
@@ -286,6 +299,112 @@ public abstract class DistanceManager {
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -36,10 +36,10 @@ scenario / path:
|
||||
Previously would have hopped to SERVER around 12+ times there extra.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 87271552aa85626f22f7f8569c8fb48fe4b30bf3..80aae4303e011dad13ce818136f0383e12ab5c41 100644
|
||||
index b62d7a85db012265dd4fae02cbed5363a41d536b..9810810467a9052f3362056e9372dd3d0f56b417 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -87,6 +87,13 @@ public class ChunkHolder {
|
||||
@@ -92,6 +92,13 @@ public class ChunkHolder {
|
||||
// Paper end - optimise anyPlayerCloseEnoughForSpawning
|
||||
long lastAutoSaveTime; // Paper - incremental autosave
|
||||
long inactiveTimeStart; // Paper - incremental autosave
|
||||
@ -54,7 +54,7 @@ index 87271552aa85626f22f7f8569c8fb48fe4b30bf3..80aae4303e011dad13ce818136f0383e
|
||||
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
|
||||
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 3e6cc16ff6f6c7993b15bd807257c0554afb6c77..a737fb56fef791f53ed3b0252e5a0369c22bcc7d 100644
|
||||
index aef2974ecec878a014ada9619d814ae333f4923a..f4a10bd3bbd421999b5ab2d5896b1aec57eb6a82 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -655,7 +655,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@ -66,7 +66,7 @@ index 3e6cc16ff6f6c7993b15bd807257c0554afb6c77..a737fb56fef791f53ed3b0252e5a0369
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1059,6 +1059,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1060,6 +1060,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
return "chunkGenerate " + requiredStatus.getName();
|
||||
});
|
||||
Executor executor = (runnable) -> {
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086)
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 80aae4303e011dad13ce818136f0383e12ab5c41..17a71e2fce455552c0e8af4073c516c21bc3e208 100644
|
||||
index 9810810467a9052f3362056e9372dd3d0f56b417..c2a040f735db091b5fb6017aa28a95f91ebcd9d3 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -229,6 +229,7 @@ public class ChunkHolder {
|
||||
@@ -234,6 +234,7 @@ public class ChunkHolder {
|
||||
}
|
||||
|
||||
public void blockChanged(BlockPos pos) {
|
||||
|
@ -8,10 +8,10 @@ cause a recursive call which would handle the increase but then
|
||||
the caller would think the chunk would be unloaded.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 17a71e2fce455552c0e8af4073c516c21bc3e208..6bfc705cbf3d8efdb0926df4e1bc6948f9052440 100644
|
||||
index c2a040f735db091b5fb6017aa28a95f91ebcd9d3..49247d12e743f987113524121e60a3e0ba4a825a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -438,8 +438,10 @@ public class ChunkHolder {
|
||||
@@ -443,8 +443,10 @@ public class ChunkHolder {
|
||||
playerchunkmap.onFullChunkStatusChange(this.pos, playerchunk_state);
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ index 17a71e2fce455552c0e8af4073c516c21bc3e208..6bfc705cbf3d8efdb0926df4e1bc6948
|
||||
ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel);
|
||||
ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel);
|
||||
boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE;
|
||||
@@ -481,6 +483,12 @@ public class ChunkHolder {
|
||||
@@ -486,6 +488,12 @@ public class ChunkHolder {
|
||||
|
||||
// Run callback right away if the future was already done
|
||||
chunkStorage.callbackExecutor.run();
|
||||
|
@ -10,10 +10,10 @@ chunk future to complete. We can simply schedule to the immediate
|
||||
executor to get this effect, rather than the main mailbox.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index ea0e86c3eb124a3ea10276776bfc9f32f4079792..01f95016dc8974db6d6fc09f54294673d83c2297 100644
|
||||
index 73cd4d12a4991a69adf3f19665bfb5672b7f2ecf..a7bc1d6ce7eebfe0b10f8c179b6a1441169d8fc1 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1272,9 +1272,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1273,9 +1273,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
return chunk;
|
||||
});
|
||||
|
@ -8,7 +8,7 @@ Sync loading the chunk at this stage would cause it to load
|
||||
older data, as well as screwing our region state.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 382532963a856478aa663d9b66e2169eaa36aefc..ba5dab2d3bc8325e5678ef58fedac5b2bc7e38d3 100644
|
||||
index a7bc1d6ce7eebfe0b10f8c179b6a1441169d8fc1..c773d6ca536389aac5efda6112440e1b0b85594d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -309,6 +309,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@ -27,7 +27,7 @@ index 382532963a856478aa663d9b66e2169eaa36aefc..ba5dab2d3bc8325e5678ef58fedac5b2
|
||||
if (k > ChunkMap.MAX_CHUNK_DISTANCE && level > ChunkMap.MAX_CHUNK_DISTANCE) {
|
||||
return holder;
|
||||
} else {
|
||||
@@ -883,6 +885,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -884,6 +886,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (completablefuture1 != completablefuture) {
|
||||
this.scheduleUnload(pos, holder);
|
||||
} else {
|
||||
@ -40,7 +40,7 @@ index 382532963a856478aa663d9b66e2169eaa36aefc..ba5dab2d3bc8325e5678ef58fedac5b2
|
||||
// Paper start
|
||||
boolean removed;
|
||||
if ((removed = this.pendingUnloads.remove(pos, holder)) && ichunkaccess != null) {
|
||||
@@ -919,6 +927,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -920,6 +928,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
|
||||
}
|
||||
} // Paper end
|
||||
@ -49,7 +49,7 @@ index 382532963a856478aa663d9b66e2169eaa36aefc..ba5dab2d3bc8325e5678ef58fedac5b2
|
||||
}
|
||||
};
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 55cc46fb065246ef9fc8332ecc1db75a20986c81..b3b10baad56bf14a31a11a3375000195ce84d4d3 100644
|
||||
index 9cb9bd439be0595e8c94bf128fecc2bd6c1647fc..fc404951b8a910594ffa42aee5ebb8bc3d9bbca4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -820,6 +820,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
@ -8,10 +8,10 @@ This WILL cause state corruption if it happens. So, don't
|
||||
allow it.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 6bfc705cbf3d8efdb0926df4e1bc6948f9052440..1f602d50f3212078490c0092ceefd3b17e0b1532 100644
|
||||
index 49247d12e743f987113524121e60a3e0ba4a825a..b473a0e3235405dde46d9d6cb300e88d6b1d121b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -418,7 +418,13 @@ public class ChunkHolder {
|
||||
@@ -423,7 +423,13 @@ public class ChunkHolder {
|
||||
CompletableFuture<Void> completablefuture1 = new CompletableFuture();
|
||||
|
||||
completablefuture1.thenRunAsync(() -> {
|
||||
@ -25,7 +25,7 @@ index 6bfc705cbf3d8efdb0926df4e1bc6948f9052440..1f602d50f3212078490c0092ceefd3b1
|
||||
}, executor);
|
||||
this.pendingFullStateConfirmation = completablefuture1;
|
||||
completablefuture.thenAccept((either) -> {
|
||||
@@ -435,7 +441,12 @@ public class ChunkHolder {
|
||||
@@ -440,7 +446,12 @@ public class ChunkHolder {
|
||||
|
||||
private void demoteFullChunk(ChunkMap playerchunkmap, ChunkHolder.FullChunkStatus playerchunk_state) {
|
||||
this.pendingFullStateConfirmation.cancel(false);
|
||||
|
@ -5,11 +5,95 @@ Subject: [PATCH] Optimise chunk tick iteration
|
||||
|
||||
Use a dedicated list of entity ticking chunks to reduce the cost
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index b473a0e3235405dde46d9d6cb300e88d6b1d121b..43f97571f0b837cbba5c3e889edbc5737a6e7b54 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -83,11 +83,21 @@ public class ChunkHolder {
|
||||
long key = net.minecraft.server.MCUtil.getCoordinateKey(this.pos);
|
||||
this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
|
||||
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ if (this.needsBroadcastChanges()) {
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
}
|
||||
|
||||
void onChunkRemove() {
|
||||
this.playersInMobSpawnRange = null;
|
||||
this.playersInChunkTickRange = null;
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ if (this.needsBroadcastChanges()) {
|
||||
+ this.chunkMap.needsChangeBroadcasting.remove(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
}
|
||||
// Paper end - optimise anyPlayerCloseEnoughForSpawning
|
||||
long lastAutoSaveTime; // Paper - incremental autosave
|
||||
@@ -242,7 +252,7 @@ public class ChunkHolder {
|
||||
|
||||
if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
||||
if (this.changedBlocksPerSection[i] == null) {
|
||||
- this.hasChangedSections = true;
|
||||
+ this.hasChangedSections = true; this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
|
||||
this.changedBlocksPerSection[i] = new ShortOpenHashSet();
|
||||
}
|
||||
|
||||
@@ -259,6 +269,7 @@ public class ChunkHolder {
|
||||
int k = this.lightEngine.getMaxLightSection();
|
||||
|
||||
if (y >= j && y <= k) {
|
||||
+ this.addToBroadcastMap(); // Paper - optimise chunk tick iteration
|
||||
int l = y - j;
|
||||
|
||||
if (lightType == LightLayer.SKY) {
|
||||
@@ -271,8 +282,19 @@ public class ChunkHolder {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ public final boolean needsBroadcastChanges() {
|
||||
+ return this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ private void addToBroadcastMap() {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("ChunkHolder update");
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(this);
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
+
|
||||
public void broadcastChanges(LevelChunk chunk) {
|
||||
- if (this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) {
|
||||
+ if (this.needsBroadcastChanges()) { // Paper - moved into above, other logic needs to call
|
||||
Level world = chunk.getLevel();
|
||||
int i = 0;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index c773d6ca536389aac5efda6112440e1b0b85594d..a7fcf3042e6d26739051ed37efbef4a722561c5a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -155,6 +155,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
private final Queue<Runnable> unloadQueue;
|
||||
int viewDistance;
|
||||
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper
|
||||
+ public final ReferenceOpenHashSet<ChunkHolder> needsChangeBroadcasting = new ReferenceOpenHashSet<>();
|
||||
|
||||
// CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
|
||||
public final CallbackExecutor callbackExecutor = new CallbackExecutor();
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 7c3a1622f161409e92c4ccfa13e8c1fc1d66c947..f7b2fa30eac4da6847d77fd3b2bdd73349b41822 100644
|
||||
index 59ebce5b9f4db5e48b4b46d68e7325f2d2820bd6..ab1b24820a5ec576f33095ad5688aaecd44910f4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -995,34 +995,46 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -50,6 +50,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper
|
||||
import java.util.function.Function; // Paper
|
||||
+import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper
|
||||
|
||||
public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
@@ -995,34 +996,42 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
this.lastSpawnState = spawnercreature_d;
|
||||
gameprofilerfiller.popPush("filteringLoadedChunks");
|
||||
@ -56,23 +140,19 @@ index 7c3a1622f161409e92c4ccfa13e8c1fc1d66c947..f7b2fa30eac4da6847d77fd3b2bdd733
|
||||
+ LevelChunk chunk1 = iterator1.next();
|
||||
+ ChunkHolder holder = chunk1.playerChunk;
|
||||
+ if (holder != null) {
|
||||
+ gameprofilerfiller.popPush("broadcast");
|
||||
+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
+ holder.broadcastChanges(chunk1);
|
||||
+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
+ gameprofilerfiller.pop();
|
||||
+ // Paper - move down
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
ChunkPos chunkcoordintpair = chunk1.getPos();
|
||||
|
||||
- if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ if ((true || this.level.isPositionEntityTicking(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
|
||||
+ if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
chunk1.incrementInhabitedTime(j);
|
||||
- if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
|
||||
}
|
||||
|
||||
@@ -1030,7 +1042,16 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -1030,7 +1039,16 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.level.tickChunk(chunk1, k);
|
||||
}
|
||||
}
|
||||
@ -89,18 +169,35 @@ index 7c3a1622f161409e92c4ccfa13e8c1fc1d66c947..f7b2fa30eac4da6847d77fd3b2bdd733
|
||||
this.level.timings.chunkTicks.stopTiming(); // Paper
|
||||
gameprofilerfiller.popPush("customSpawners");
|
||||
if (flag2) {
|
||||
@@ -1039,13 +1060,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -1038,15 +1056,24 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies);
|
||||
} // Paper - timings
|
||||
}
|
||||
|
||||
-
|
||||
- gameprofilerfiller.popPush("broadcast");
|
||||
- list.forEach((chunkproviderserver_a1) -> {
|
||||
- this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
- chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk);
|
||||
- this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
- });
|
||||
- gameprofilerfiller.pop();
|
||||
+ // Paper - no, iterating just ONCE is expensive enough! Don't do it TWICE! Code moved up
|
||||
gameprofilerfiller.pop();
|
||||
+ // Paper start - use set of chunks requiring updates, rather than iterating every single one loaded
|
||||
+ gameprofilerfiller.popPush("broadcast");
|
||||
+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
+ if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) {
|
||||
+ ReferenceOpenHashSet<ChunkHolder> copy = this.chunkMap.needsChangeBroadcasting.clone();
|
||||
+ this.chunkMap.needsChangeBroadcasting.clear();
|
||||
+ for (ChunkHolder holder : copy) {
|
||||
+ holder.broadcastChanges(holder.getFullChunkUnchecked()); // LevelChunks are NEVER unloaded
|
||||
+ if (holder.needsBroadcastChanges()) {
|
||||
+ // I DON'T want to KNOW what DUMB plugins might be doing.
|
||||
+ this.chunkMap.needsChangeBroadcasting.add(holder);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
gameprofilerfiller.pop();
|
||||
+ // Paper end - use set of chunks requiring updates, rather than iterating every single one loaded
|
||||
this.chunkMap.tick();
|
||||
}
|
||||
}
|
||||
|
@ -108,10 +108,10 @@ index 79e5b8a05828bbc07468d2deeb0f4dad51ca12a5..7be369cf60e45a551fb2d274b9514856
|
||||
} else {
|
||||
if (this.haveTime()) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 579b2ac31034082456de5ee91e3c6906c7199e32..4e7027d739f7d3c8586804fc053931b2dca1de59 100644
|
||||
index ab1b24820a5ec576f33095ad5688aaecd44910f4..264105bb8b806d64d1a108bb438a8623c502c990 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -1019,6 +1019,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -1020,6 +1020,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
iterator1 = shuffled.iterator();
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ index 579b2ac31034082456de5ee91e3c6906c7199e32..4e7027d739f7d3c8586804fc053931b2
|
||||
try {
|
||||
while (iterator1.hasNext()) {
|
||||
LevelChunk chunk1 = iterator1.next();
|
||||
@@ -1040,6 +1041,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -1037,6 +1038,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) {
|
||||
this.level.tickChunk(chunk1, k);
|
||||
@ -128,7 +128,7 @@ index 579b2ac31034082456de5ee91e3c6906c7199e32..4e7027d739f7d3c8586804fc053931b2
|
||||
}
|
||||
// Paper start - optimise chunk tick iteration
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 9362b39f4cc321bf0d4fc272bc3fb0463c47d4ce..cb327920cfa8d4eec626af1fe42ec1cc5e8953c7 100644
|
||||
index 3c2c326c974531eda95757893981a28fb52b4d16..b5e60bd6c023cfc9d48fe8c567feff24b00b3a0e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -201,7 +201,9 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
@ -35,7 +35,7 @@ index b3516862d796c2d9fcc1c67a6073445403d73088..b61abf227a04b4565c2525e5f469db30
|
||||
List<ChunkHolder> allChunks = new ArrayList<>(visibleChunks.values());
|
||||
List<ServerPlayer> players = world.players;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f245070e72 100644
|
||||
index a7fcf3042e6d26739051ed37efbef4a722561c5a..58dc590cf659cba84d7cb4f7205fdb0bdefded79 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -120,9 +120,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@ -52,7 +52,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
private final Long2ObjectLinkedOpenHashMap<ChunkHolder> pendingUnloads;
|
||||
public final LongSet entitiesInLevel;
|
||||
public final ServerLevel level;
|
||||
@@ -312,7 +314,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -313,7 +315,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
boolean unloadingPlayerChunk = false; // Paper - do not allow ticket level changes while unloading chunks
|
||||
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory, int viewDistance, boolean dsync) {
|
||||
super(session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync);
|
||||
@ -61,7 +61,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
this.pendingUnloads = new Long2ObjectLinkedOpenHashMap();
|
||||
this.entitiesInLevel = new LongOpenHashSet();
|
||||
this.toDrop = new LongOpenHashSet();
|
||||
@@ -535,12 +537,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -536,12 +538,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
@Nullable
|
||||
public ChunkHolder getUpdatingChunkIfPresent(long pos) {
|
||||
@ -81,7 +81,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
}
|
||||
|
||||
protected IntSupplier getChunkQueueLevel(long pos) {
|
||||
@@ -702,7 +709,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -703,7 +710,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
this.modified = true;
|
||||
}
|
||||
|
||||
@@ -782,7 +789,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -783,7 +790,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
protected void saveAllChunks(boolean flush) {
|
||||
if (flush) {
|
||||
@ -99,7 +99,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
MutableBoolean mutableboolean = new MutableBoolean();
|
||||
|
||||
do {
|
||||
@@ -813,7 +820,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -814,7 +821,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
//this.flushWorker(); // Paper - nuke IOWorker
|
||||
this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
|
||||
} else {
|
||||
@ -108,7 +108,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
}
|
||||
|
||||
}
|
||||
@@ -847,7 +854,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -848,7 +855,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
while (longiterator.hasNext()) { // Spigot
|
||||
long j = longiterator.nextLong();
|
||||
longiterator.remove(); // Spigot
|
||||
@ -116,8 +116,8 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
+ ChunkHolder playerchunk = this.updatingChunks.queueRemove(j); // Paper - Don't copy
|
||||
|
||||
if (playerchunk != null) {
|
||||
this.pendingUnloads.put(j, playerchunk);
|
||||
@@ -946,7 +953,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
playerchunk.onChunkRemove(); // Paper
|
||||
@@ -948,7 +955,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (!this.modified) {
|
||||
return false;
|
||||
} else {
|
||||
@ -131,7 +131,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
this.modified = false;
|
||||
return true;
|
||||
}
|
||||
@@ -1424,7 +1436,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1426,7 +1438,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
this.viewDistance = j;
|
||||
this.distanceManager.updatePlayerTickets(this.viewDistance + 1);
|
||||
@ -140,7 +140,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
|
||||
while (objectiterator.hasNext()) {
|
||||
ChunkHolder playerchunk = (ChunkHolder) objectiterator.next();
|
||||
@@ -1467,7 +1479,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1469,7 +1481,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public int size() {
|
||||
@ -149,7 +149,7 @@ index f9f1afb49c8dba14d8d9134e84c73fa2e1d13f02..2e11bedafe383242996aeb545d6612f2
|
||||
}
|
||||
|
||||
public DistanceManager getDistanceManager() {
|
||||
@@ -1475,13 +1487,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1477,13 +1489,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
protected Iterable<ChunkHolder> getChunks() {
|
||||
|
@ -19,10 +19,10 @@ index eada966d7f108a6081be7a848f5c1dfcb1eed676..a977f7483f37df473096b2234dc1308b
|
||||
public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks");
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 05f2fad85da8192d097c2349e630349f6c61754c..631eb52d646309cfbd5b4c7c0621c865967c08e7 100644
|
||||
index 264105bb8b806d64d1a108bb438a8623c502c990..5bd358983f4b501adb0433e10df320d06816e6e7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -834,6 +834,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -835,6 +835,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
public boolean runDistanceManagerUpdates() {
|
||||
if (distanceManager.delayDistanceManagerTick) return false; // Paper - Chunk priority
|
||||
if (this.chunkMap.unloadingPlayerChunk) { net.minecraft.server.MinecraftServer.LOGGER.fatal("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper
|
||||
@ -30,7 +30,7 @@ index 05f2fad85da8192d097c2349e630349f6c61754c..631eb52d646309cfbd5b4c7c0621c865
|
||||
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
|
||||
boolean flag1 = this.chunkMap.promoteChunkMap();
|
||||
|
||||
@@ -843,6 +844,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -844,6 +845,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.clearCache();
|
||||
return true;
|
||||
}
|
||||
|
@ -22,13 +22,13 @@ With this change I could get all 200 on at 0ms ping.
|
||||
So in general this patch should reduce Netty I/O thread load.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 631eb52d646309cfbd5b4c7c0621c865967c08e7..9a07ccbd12675e501a9aebf89ab85adf6fb658ba 100644
|
||||
index 5bd358983f4b501adb0433e10df320d06816e6e7..98be0ea366732695f76bc5b1a78e0a36060515bd 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -1066,7 +1066,24 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
// Paper - no, iterating just ONCE is expensive enough! Don't do it TWICE! Code moved up
|
||||
@@ -1078,7 +1078,24 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
gameprofilerfiller.pop();
|
||||
// Paper end - use set of chunks requiring updates, rather than iterating every single one loaded
|
||||
+ // Paper start - controlled flush for entity tracker packets
|
||||
+ List<net.minecraft.network.Connection> disabledFlushes = new java.util.ArrayList<>(this.level.players.size());
|
||||
+ for (ServerPlayer player : this.level.players) {
|
||||
|
@ -7,7 +7,7 @@ Reference2BooleanOpenHashMap is going to have
|
||||
better lookups than HashMap.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 7353b4e43503b371973c2de6a61e5ca91d613680..31a1a13887bda174181d926d83273a89b59ec789 100644
|
||||
index 58dc590cf659cba84d7cb4f7205fdb0bdefded79..72443ab38931a3774641bdc52999e7dcd2586de0 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -108,6 +108,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
@ -18,7 +18,7 @@ index 7353b4e43503b371973c2de6a61e5ca91d613680..31a1a13887bda174181d926d83273a89
|
||||
|
||||
public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider {
|
||||
|
||||
@@ -2114,7 +2115,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -2116,7 +2117,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
final Entity entity;
|
||||
private final int range;
|
||||
SectionPos lastSectionPos;
|
||||
|
@ -9,29 +9,42 @@ since the penalty of a map lookup could outweigh the benefits of
|
||||
searching less players (as it basically did in the outside range patch).
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 1f602d50f3212078490c0092ceefd3b17e0b1532..825fdb0336b0388dbbc54c8da99781900612031c 100644
|
||||
index 43f97571f0b837cbba5c3e889edbc5737a6e7b54..f5b6d0f69e727b8f5e425340f8c1381a82a24ce3 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -83,6 +83,12 @@ public class ChunkHolder {
|
||||
long key = net.minecraft.server.MCUtil.getCoordinateKey(this.pos);
|
||||
this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
|
||||
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
||||
@@ -88,6 +88,12 @@ public class ChunkHolder {
|
||||
this.chunkMap.needsChangeBroadcasting.add(this);
|
||||
}
|
||||
// Paper end - optimise chunk tick iteration
|
||||
+ // Paper start - optimise checkDespawn
|
||||
+ LevelChunk chunk = this.getFullChunkUnchecked();
|
||||
+ if (chunk != null) {
|
||||
+ chunk.updateGeneralAreaCache();
|
||||
+ }
|
||||
+ // Paper end - optimise checkDespawn
|
||||
}
|
||||
|
||||
void onChunkRemove() {
|
||||
@@ -98,6 +104,12 @@ public class ChunkHolder {
|
||||
this.chunkMap.needsChangeBroadcasting.remove(this);
|
||||
}
|
||||
// Paper end - optimise chunk tick iteration
|
||||
+ // Paper start - optimise checkDespawn
|
||||
+ LevelChunk chunk = this.getFullChunkUnchecked();
|
||||
+ if (chunk != null) {
|
||||
+ chunk.removeGeneralAreaCache();
|
||||
+ }
|
||||
+ // Paper end - optimise checkDespawn
|
||||
}
|
||||
// Paper end - optimise anyPlayerCloseEnoughForSpawning
|
||||
long lastAutoSaveTime; // Paper - incremental autosave
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index dd23e7110259574859a074c423312c452d533668..c56ccb8a6faba0be36b53038e723da5a4461ded1 100644
|
||||
index 72443ab38931a3774641bdc52999e7dcd2586de0..69533a1239f12c41a255bf9deeb5640695edfa13 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -159,6 +159,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
int viewDistance;
|
||||
@@ -160,6 +160,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper
|
||||
public final ReferenceOpenHashSet<ChunkHolder> needsChangeBroadcasting = new ReferenceOpenHashSet<>();
|
||||
|
||||
+ // Paper start - optimise checkDespawn
|
||||
+ public static final int GENERAL_AREA_MAP_SQUARE_RADIUS = 40;
|
||||
@ -43,7 +56,7 @@ index dd23e7110259574859a074c423312c452d533668..c56ccb8a6faba0be36b53038e723da5a
|
||||
// CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
|
||||
public final CallbackExecutor callbackExecutor = new CallbackExecutor();
|
||||
public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable {
|
||||
@@ -236,6 +243,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -237,6 +244,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper end - use distance map to optimise entity tracker
|
||||
// Note: players need to be explicitly added to distance maps before they can be updated
|
||||
this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); // Paper - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
||||
@ -51,7 +64,7 @@ index dd23e7110259574859a074c423312c452d533668..c56ccb8a6faba0be36b53038e723da5a
|
||||
// Paper start - per player mob spawning
|
||||
if (this.playerMobDistanceMap != null) {
|
||||
this.playerMobDistanceMap.add(player, chunkX, chunkZ, this.distanceManager.getSimulationDistance());
|
||||
@@ -254,6 +262,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -255,6 +263,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.playerMobSpawnMap.remove(player);
|
||||
this.playerChunkTickRangeMap.remove(player);
|
||||
// Paper end - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
||||
@ -59,7 +72,7 @@ index dd23e7110259574859a074c423312c452d533668..c56ccb8a6faba0be36b53038e723da5a
|
||||
// Paper start - per player mob spawning
|
||||
if (this.playerMobDistanceMap != null) {
|
||||
this.playerMobDistanceMap.remove(player);
|
||||
@@ -274,6 +283,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -275,6 +284,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
// Paper end - use distance map to optimise entity tracker
|
||||
this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); // Paper - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
||||
@ -67,7 +80,7 @@ index dd23e7110259574859a074c423312c452d533668..c56ccb8a6faba0be36b53038e723da5a
|
||||
// Paper start - per player mob spawning
|
||||
if (this.playerMobDistanceMap != null) {
|
||||
this.playerMobDistanceMap.update(player, chunkX, chunkZ, this.distanceManager.getSimulationDistance());
|
||||
@@ -434,6 +444,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -435,6 +445,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
});
|
||||
// Paper end - optimise ChunkMap#anyPlayerCloseEnoughForSpawning
|
||||
@ -92,7 +105,7 @@ index dd23e7110259574859a074c423312c452d533668..c56ccb8a6faba0be36b53038e723da5a
|
||||
|
||||
protected ChunkGenerator generator() {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index fe2e5eb72307f8f07987b12a1af9100348b86a82..94798e2715a16b43f11493b08fe342aeecf11cef 100644
|
||||
index 4b18dfbf559214dc511003bb3396acbcfb80fdda..9c73cb316522302bf88b671398ba53c0eb2d29d5 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -399,6 +399,83 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
@ -309,10 +322,10 @@ index 6dba117b4f5dc6c4e078a32037a4026b45bf2176..515e58e3db223fbdc01ca87607aca234
|
||||
|
||||
private static Boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { // Paper
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 8e03e63a00dd242791ba0d5a8a17922227b16165..4a9a1fef5603b073e6d2d12e3e8e5dca73a7bd1b 100644
|
||||
index 8e03e63a00dd242791ba0d5a8a17922227b16165..0746300e8c0a29bedb9ec02803c194c2d03b78fb 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -235,6 +235,93 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -235,6 +235,98 @@ public class LevelChunk extends ChunkAccess {
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
@ -331,6 +344,11 @@ index 8e03e63a00dd242791ba0d5a8a17922227b16165..4a9a1fef5603b073e6d2d12e3e8e5dca
|
||||
+ this.updateGeneralAreaCache(((ServerLevel)this.level).getChunkSource().chunkMap.playerGeneralAreaMap.getObjectsInRange(this.coordinateKey));
|
||||
+ }
|
||||
+
|
||||
+ public void removeGeneralAreaCache() {
|
||||
+ this.playerGeneralAreaCacheSet = false;
|
||||
+ this.playerGeneralAreaCache = null;
|
||||
+ }
|
||||
+
|
||||
+ public void updateGeneralAreaCache(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<net.minecraft.server.level.ServerPlayer> value) {
|
||||
+ this.playerGeneralAreaCacheSet = true;
|
||||
+ this.playerGeneralAreaCache = value;
|
||||
|
@ -8,10 +8,10 @@ Instead, only iterate over navigators in the current region that are
|
||||
eligible for repathing.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 60ae567fe76a643f6a363644bfc99eac2ef64835..634f8690ccce7cdcc524258a6f2844c60b9563b5 100644
|
||||
index 69533a1239f12c41a255bf9deeb5640695edfa13..3c90c6514dc856490da7fca5c8a42023493836d7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -296,15 +296,81 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -297,15 +297,81 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
public final io.papermc.paper.chunk.SingleThreadChunkRegionManager dataRegionManager;
|
||||
|
||||
public static final class DataRegionData implements io.papermc.paper.chunk.SingleThreadChunkRegionManager.RegionData {
|
||||
@ -93,7 +93,7 @@ index 60ae567fe76a643f6a363644bfc99eac2ef64835..634f8690ccce7cdcc524258a6f2844c6
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -314,6 +380,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -315,6 +381,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
final DataRegionSectionData sectionData = (DataRegionSectionData)section.sectionData;
|
||||
final DataRegionData oldRegionData = oldRegion == null ? null : (DataRegionData)oldRegion.regionData;
|
||||
final DataRegionData newRegionData = (DataRegionData)newRegion.regionData;
|
||||
@ -110,7 +110,7 @@ index 60ae567fe76a643f6a363644bfc99eac2ef64835..634f8690ccce7cdcc524258a6f2844c6
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 0918bb28fd058e6b79f45993a46738a50b05b60a..f17c0f501c89c07651a40673ad5ecfe6c7168fce 100644
|
||||
index 9c73cb316522302bf88b671398ba53c0eb2d29d5..9f1f55d457b1a99c12f7fc94aaf9005fb8df50e7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1093,6 +1093,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
@ -12,10 +12,10 @@ time to save, as flush saving performs a full flush at
|
||||
the end anyways.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 634f8690ccce7cdcc524258a6f2844c60b9563b5..b7a215c94e1ef021360dde5c4099ddd5b1f676b8 100644
|
||||
index 3c90c6514dc856490da7fca5c8a42023493836d7..8678640da7724283664e3f115230d6b2687967b1 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -891,6 +891,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -892,6 +892,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper end
|
||||
|
||||
protected void saveAllChunks(boolean flush) {
|
||||
@ -32,7 +32,7 @@ index 634f8690ccce7cdcc524258a6f2844c60b9563b5..b7a215c94e1ef021360dde5c4099ddd5
|
||||
if (flush) {
|
||||
List<ChunkHolder> list = (List) this.updatingChunks.getVisibleValuesCopy().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper
|
||||
MutableBoolean mutableboolean = new MutableBoolean();
|
||||
@@ -913,6 +923,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -914,6 +924,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}).filter((ichunkaccess) -> {
|
||||
return ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk;
|
||||
}).filter(this::save).forEach((ichunkaccess) -> {
|
||||
|
@ -4345,7 +4345,7 @@ index 0000000000000000000000000000000000000000..dd995e25ae620ae36cd5eecb2fe10ad0
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
index 315bd2408e4a45993c9b2572e0ab5260a70522ec..c0d123bff1825366c30aadd3ad8a7fde68ef74e4 100644
|
||||
index c57999061a7a9adb7b5207a13af3d693529a43cd..76d27205b2bd08ba2b3530b46f0d9b4e2315d82e 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
@@ -700,6 +700,46 @@ public class PaperCommand extends Command {
|
||||
@ -4419,7 +4419,7 @@ index 315bd2408e4a45993c9b2572e0ab5260a70522ec..c0d123bff1825366c30aadd3ad8a7fde
|
||||
Deque<ChunkPos> queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius));
|
||||
updateLight(sender, world, lightengine, queue);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 825fdb0336b0388dbbc54c8da99781900612031c..d271871563fa883efb77b35ec3b1dfbba87f0b62 100644
|
||||
index f5b6d0f69e727b8f5e425340f8c1381a82a24ce3..9c4e4ab16441555d7940863b6736a03ee4af545c 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -52,7 +52,7 @@ public class ChunkHolder {
|
||||
@ -4432,7 +4432,7 @@ index 825fdb0336b0388dbbc54c8da99781900612031c..d271871563fa883efb77b35ec3b1dfbb
|
||||
private final DebugBuffer<ChunkHolder.ChunkSaveDebug> chunkToSaveHistory;
|
||||
public int oldTicketLevel;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index b7a215c94e1ef021360dde5c4099ddd5b1f676b8..02bcffcdde33088e43a7771924b2d2bf47badd09 100644
|
||||
index 8678640da7724283664e3f115230d6b2687967b1..29fdc1b991c67006a13231abbbe50e201744b5c2 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -130,7 +130,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@ -4961,7 +4961,7 @@ index e15263a152c88371ebc65b47f0be938f7c19a8f2..59c053deb52c9307f1b4c1515384a7c6
|
||||
super(wrapped.getPos(), UpgradeData.EMPTY, wrapped.levelHeightAccessor, wrapped.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), wrapped.getBlendingData());
|
||||
this.wrapped = wrapped;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 4a9a1fef5603b073e6d2d12e3e8e5dca73a7bd1b..7567a8bf848c82b27383f084056cb43c41df6d0c 100644
|
||||
index 0746300e8c0a29bedb9ec02803c194c2d03b78fb..55c0e9655ded14e25b0f284ad0c1f99eb5d0b192 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -100,6 +100,10 @@ public class LevelChunk extends ChunkAccess {
|
||||
@ -4975,7 +4975,7 @@ index 4a9a1fef5603b073e6d2d12e3e8e5dca73a7bd1b..7567a8bf848c82b27383f084056cb43c
|
||||
this.tickersInLevel = Maps.newHashMap();
|
||||
this.clientLightReady = false;
|
||||
this.level = (ServerLevel) world; // CraftBukkit - type
|
||||
@@ -325,6 +329,12 @@ public class LevelChunk extends ChunkAccess {
|
||||
@@ -330,6 +334,12 @@ public class LevelChunk extends ChunkAccess {
|
||||
|
||||
public LevelChunk(ServerLevel world, ProtoChunk protoChunk, @Nullable LevelChunk.PostLoadProcessor entityLoader) {
|
||||
this(world, protoChunk.getPos(), protoChunk.getUpgradeData(), protoChunk.unpackBlockTicks(), protoChunk.unpackFluidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), entityLoader, protoChunk.getBlendingData());
|
||||
@ -5002,7 +5002,7 @@ index d850cae1ec024a557e62cd561fbca137dc2be96c..eef1b58cfaf3cfa90f3786785dd94d05
|
||||
return data.palette.valueFor(data.storage.get(index));
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
index 0dfa51c8826b9e984586a3e4e050a50a4fbb1bd3..e947a47dd8c6906bc36eca757c4b9f9f2ab3cedc 100644
|
||||
index acfd46c7035b4009d61bda8a7c8dd6953e4836e6..9e293afe94e85ecbc2a236b1b34df1a4926b83cb 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
|
||||
@@ -54,6 +54,12 @@ public class ProtoChunk extends ChunkAccess {
|
||||
|
@ -70,10 +70,10 @@ index be668387f65a633c6ac497fca632a4767a1bf3a2..e08f4e39db4ee3fed62e37364d17dcc5
|
||||
}
|
||||
diff --git a/src/main/java/io/papermc/paper/util/CollisionUtil.java b/src/main/java/io/papermc/paper/util/CollisionUtil.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde946135784a0d8bc
|
||||
index 0000000000000000000000000000000000000000..b25018ab6cff59e43652c953421f01b6d0bb0a85
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/CollisionUtil.java
|
||||
@@ -0,0 +1,639 @@
|
||||
@@ -0,0 +1,899 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import io.papermc.paper.voxel.AABBVoxelShape;
|
||||
@ -91,6 +91,7 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+import net.minecraft.world.level.border.WorldBorder;
|
||||
+import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
+import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
+import net.minecraft.world.level.chunk.PalettedContainer;
|
||||
+import net.minecraft.world.level.material.FlowingFluid;
|
||||
+import net.minecraft.world.level.material.FluidState;
|
||||
+import net.minecraft.world.phys.AABB;
|
||||
@ -101,7 +102,6 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+import net.minecraft.world.phys.shapes.Shapes;
|
||||
+import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
+import java.util.List;
|
||||
+import java.util.Optional;
|
||||
+import java.util.function.BiPredicate;
|
||||
+import java.util.function.Predicate;
|
||||
+
|
||||
@ -109,6 +109,15 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+
|
||||
+ public static final double COLLISION_EPSILON = 1.0E-7;
|
||||
+
|
||||
+ public static final long KNOWN_EMPTY_BLOCK = 0b00; // known to always have voxelshape of empty
|
||||
+ public static final long KNOWN_FULL_BLOCK = 0b01; // known to always have voxelshape of full cube
|
||||
+ public static final long KNOWN_UNKNOWN_BLOCK = 0b10; // must read the actual block state for info
|
||||
+ public static final long KNOWN_SPECIAL_BLOCK = 0b11; // caller must check this block for special collisions
|
||||
+
|
||||
+ public static boolean isSpecialCollidingBlock(final net.minecraft.world.level.block.state.BlockBehaviour.BlockStateBase block) {
|
||||
+ return block.shapeExceedsCube() || block.getBlock() == Blocks.MOVING_PISTON;
|
||||
+ }
|
||||
+
|
||||
+ public static boolean isEmpty(final AABB aabb) {
|
||||
+ return (aabb.maxX - aabb.minX) < COLLISION_EPSILON && (aabb.maxY - aabb.minY) < COLLISION_EPSILON && (aabb.maxZ - aabb.minZ) < COLLISION_EPSILON;
|
||||
+ }
|
||||
@ -486,21 +495,21 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ int minBlockX = Mth.floor(aabb.minX - COLLISION_EPSILON) - 1;
|
||||
+ int maxBlockX = Mth.floor(aabb.maxX + COLLISION_EPSILON) + 1;
|
||||
+ final int minBlockX = Mth.floor(aabb.minX - COLLISION_EPSILON) - 1;
|
||||
+ final int maxBlockX = Mth.floor(aabb.maxX + COLLISION_EPSILON) + 1;
|
||||
+
|
||||
+ int minBlockY = Mth.floor(aabb.minY - COLLISION_EPSILON) - 1;
|
||||
+ int maxBlockY = Mth.floor(aabb.maxY + COLLISION_EPSILON) + 1;
|
||||
+ final int minBlockY = Mth.floor(aabb.minY - COLLISION_EPSILON) - 1;
|
||||
+ final int maxBlockY = Mth.floor(aabb.maxY + COLLISION_EPSILON) + 1;
|
||||
+
|
||||
+ int minBlockZ = Mth.floor(aabb.minZ - COLLISION_EPSILON) - 1;
|
||||
+ int maxBlockZ = Mth.floor(aabb.maxZ + COLLISION_EPSILON) + 1;
|
||||
+ final int minBlockZ = Mth.floor(aabb.minZ - COLLISION_EPSILON) - 1;
|
||||
+ final int maxBlockZ = Mth.floor(aabb.maxZ + COLLISION_EPSILON) + 1;
|
||||
+
|
||||
+ final int minSection = WorldUtil.getMinSection(getter);
|
||||
+ final int maxSection = WorldUtil.getMaxSection(getter);
|
||||
+ final int minBlock = minSection << 4;
|
||||
+ final int maxBlock = (maxSection << 4) | 15;
|
||||
+
|
||||
+ BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
|
||||
+ final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
|
||||
+ CollisionContext collisionShape = null;
|
||||
+
|
||||
+ // special cases:
|
||||
@ -509,16 +518,22 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ int minYIterate = Math.max(minBlock, minBlockY);
|
||||
+ int maxYIterate = Math.min(maxBlock, maxBlockY);
|
||||
+ final int minYIterate = Math.max(minBlock, minBlockY);
|
||||
+ final int maxYIterate = Math.min(maxBlock, maxBlockY);
|
||||
+
|
||||
+ int minChunkX = minBlockX >> 4;
|
||||
+ int maxChunkX = maxBlockX >> 4;
|
||||
+ final int minChunkX = minBlockX >> 4;
|
||||
+ final int maxChunkX = maxBlockX >> 4;
|
||||
+
|
||||
+ int minChunkZ = minBlockZ >> 4;
|
||||
+ int maxChunkZ = maxBlockZ >> 4;
|
||||
+ final int minChunkY = minBlockY >> 4;
|
||||
+ final int maxChunkY = maxBlockY >> 4;
|
||||
+
|
||||
+ ServerChunkCache chunkProvider;
|
||||
+ final int minChunkYIterate = minYIterate >> 4;
|
||||
+ final int maxChunkYIterate = maxYIterate >> 4;
|
||||
+
|
||||
+ final int minChunkZ = minBlockZ >> 4;
|
||||
+ final int maxChunkZ = maxBlockZ >> 4;
|
||||
+
|
||||
+ final ServerChunkCache chunkProvider;
|
||||
+ if (getter instanceof WorldGenRegion) {
|
||||
+ chunkProvider = null;
|
||||
+ } else if (getter instanceof ServerLevel) {
|
||||
@ -526,26 +541,24 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+ } else {
|
||||
+ chunkProvider = null;
|
||||
+ }
|
||||
+ // TODO special case single chunk?
|
||||
+
|
||||
+ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) {
|
||||
+ int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk
|
||||
+ int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 15; // coordinate in chunk
|
||||
+ final int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk
|
||||
+ final int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 15; // coordinate in chunk
|
||||
+
|
||||
+ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) {
|
||||
+ int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk
|
||||
+ int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk
|
||||
+ final int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk
|
||||
+ final int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk
|
||||
+
|
||||
+ int chunkXGlobalPos = currChunkX << 4;
|
||||
+ int chunkZGlobalPos = currChunkZ << 4;
|
||||
+ ChunkAccess chunk;
|
||||
+ final int chunkXGlobalPos = currChunkX << 4;
|
||||
+ final int chunkZGlobalPos = currChunkZ << 4;
|
||||
+ final ChunkAccess chunk;
|
||||
+ if (chunkProvider == null) {
|
||||
+ chunk = (ChunkAccess)getter.getChunkForCollisions(currChunkX, currChunkZ);
|
||||
+ } else {
|
||||
+ chunk = loadChunks ? chunkProvider.getChunk(currChunkX, currChunkZ, true) : chunkProvider.getChunkAtIfLoadedImmediately(currChunkX, currChunkZ);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ if (chunk == null) {
|
||||
+ if (collidesWithUnloaded) {
|
||||
+ if (checkOnly) {
|
||||
@ -558,26 +571,116 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ LevelChunkSection[] sections = chunk.getSections();
|
||||
+ final LevelChunkSection[] sections = chunk.getSections();
|
||||
+
|
||||
+ // bound y
|
||||
+
|
||||
+ for (int currY = minYIterate; currY <= maxYIterate; ++currY) {
|
||||
+ LevelChunkSection section = sections[(currY >> 4) - minSection];
|
||||
+ if (section.hasOnlyAir()) {
|
||||
+ for (int currChunkY = minChunkYIterate; currChunkY <= maxChunkYIterate; ++currChunkY) {
|
||||
+ final LevelChunkSection section = sections[currChunkY - minSection];
|
||||
+ if (section == null || section.hasOnlyAir()) {
|
||||
+ // empty
|
||||
+ // skip to next section
|
||||
+ currY = (currY & ~(15)) + 15; // increment by 15: iterator loop increments by the extra one
|
||||
+ continue;
|
||||
+ }
|
||||
+ final PalettedContainer<BlockState> blocks = section.states;
|
||||
+
|
||||
+ net.minecraft.world.level.chunk.PalettedContainer<BlockState> blocks = section.states;
|
||||
+ final int minY = currChunkY == minChunkYIterate ? minYIterate & 15 : 0; // coordinate in chunk
|
||||
+ final int maxY = currChunkY == maxChunkYIterate ? maxYIterate & 15 : 15; // coordinate in chunk
|
||||
+ final int chunkYGlobalPos = currChunkY << 4;
|
||||
+
|
||||
+ final boolean sectionHasSpecial = section.hasSpecialCollidingBlocks();
|
||||
+
|
||||
+ final int minXIterate;
|
||||
+ final int maxXIterate;
|
||||
+ final int minZIterate;
|
||||
+ final int maxZIterate;
|
||||
+ final int minYIterateLocal;
|
||||
+ final int maxYIterateLocal;
|
||||
+
|
||||
+ if (!sectionHasSpecial) {
|
||||
+ minXIterate = currChunkX == minChunkX ? minX + 1 : minX;
|
||||
+ maxXIterate = currChunkX == maxChunkX ? maxX - 1 : maxX;
|
||||
+ minZIterate = currChunkZ == minChunkZ ? minZ + 1 : minZ;
|
||||
+ maxZIterate = currChunkZ == maxChunkZ ? maxZ - 1 : maxZ;
|
||||
+ minYIterateLocal = currChunkY == minChunkY ? minY + 1 : minY;
|
||||
+ maxYIterateLocal = currChunkY == maxChunkY ? maxY - 1 : maxY;
|
||||
+ if (minXIterate > maxXIterate || minZIterate > maxZIterate) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ } else {
|
||||
+ minXIterate = minX;
|
||||
+ maxXIterate = maxX;
|
||||
+ minZIterate = minZ;
|
||||
+ maxZIterate = maxZ;
|
||||
+ minYIterateLocal = minY;
|
||||
+ maxYIterateLocal = maxY;
|
||||
+ }
|
||||
+
|
||||
+ for (int currY = minYIterateLocal; currY <= maxYIterateLocal; ++currY) {
|
||||
+ long collisionForHorizontal = section.getKnownBlockInfoHorizontalRaw(currY, minZIterate & 15);
|
||||
+ for (int currZ = minZIterate; currZ <= maxZIterate; ++currZ,
|
||||
+ collisionForHorizontal = (currZ & 1) == 0 ? section.getKnownBlockInfoHorizontalRaw(currY, currZ & 15) : collisionForHorizontal) {
|
||||
+ // From getKnownBlockInfoHorizontalRaw:
|
||||
+ // important detail: this returns 32 values, one for localZ = localZ & (~1) and one for localZ = localZ | 1
|
||||
+ // the even localZ is the lower 32 bits, the odd is the upper 32 bits
|
||||
+ // We want to use a bitset to only iterate over non-empty blocks.
|
||||
+ // We need to build a bitset mask to and out the other collisions we just don't care at all about
|
||||
+ // First, we need to build a bitset from 0..n*2 where n is the number of blocks on the x axis
|
||||
+ // It's important to note that the iterate values can be outside [0, 15], but if they are,
|
||||
+ // then none of the x or z loops would meet their conditions. So we can assume they are never
|
||||
+ // out of bounds here
|
||||
+ final int xAxisBits = (maxXIterate - minXIterate + 1) << 1; // << 1 -> * 2 // Never > 32
|
||||
+ long bitset = (1L << xAxisBits) - 1;
|
||||
+ // Now we need to offset it by 32 bits if current Z is odd (lower 32 bits is 16 block infos for even z, upper is for odd)
|
||||
+ int shift = (currZ & 1) << 5; // this will be a LEFT shift
|
||||
+ // Now we need to offset shift so that the bitset first position is at minXIterate
|
||||
+ shift += (minXIterate << 1); // 0th pos -> 0th bit, 1st pos -> 2nd bit, ...
|
||||
+
|
||||
+ // all done
|
||||
+ bitset = bitset << shift;
|
||||
+ if ((collisionForHorizontal & bitset) == 0L) {
|
||||
+ // All empty
|
||||
+ continue;
|
||||
+ }
|
||||
+ for (int currX = minXIterate; currX <= maxXIterate; ++currX) {
|
||||
+ final int localBlockIndex = (currX) | (currZ << 4) | (currY << 8);
|
||||
+
|
||||
+ final int blockInfo = (int) LevelChunkSection.getKnownBlockInfo(localBlockIndex, collisionForHorizontal);
|
||||
+
|
||||
+ switch (blockInfo) {
|
||||
+ case (int) CollisionUtil.KNOWN_EMPTY_BLOCK: {
|
||||
+ continue;
|
||||
+ }
|
||||
+ case (int) CollisionUtil.KNOWN_FULL_BLOCK: {
|
||||
+ double blockX = (double)(currX | chunkXGlobalPos);
|
||||
+ double blockY = (double)(currY | chunkYGlobalPos);
|
||||
+ double blockZ = (double)(currZ | chunkZGlobalPos);
|
||||
+ final AABB blockBox = new AABB(
|
||||
+ blockX, blockY, blockZ,
|
||||
+ blockX + 1.0, blockY + 1.0, blockZ + 1.0,
|
||||
+ true
|
||||
+ );
|
||||
+ if (predicate != null) {
|
||||
+ if (!voxelShapeIntersect(aabb, blockBox)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // fall through to get the block for the predicate
|
||||
+ } else {
|
||||
+ if (voxelShapeIntersect(aabb, blockBox)) {
|
||||
+ if (checkOnly) {
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ into.add(blockBox);
|
||||
+ ret = true;
|
||||
+ }
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ // default: fall through to standard logic
|
||||
+ }
|
||||
+
|
||||
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
|
||||
+ for (int currX = minX; currX <= maxX; ++currX) {
|
||||
+ int localBlockIndex = (currX) | (currZ << 4) | ((currY & 15) << 8);
|
||||
+ int blockX = currX | chunkXGlobalPos;
|
||||
+ int blockY = currY;
|
||||
+ int blockY = currY | chunkYGlobalPos;
|
||||
+ int blockZ = currZ | chunkZGlobalPos;
|
||||
+
|
||||
+ int edgeCount = ((blockX == minBlockX || blockX == maxBlockX) ? 1 : 0) +
|
||||
@ -588,7 +691,163 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+ }
|
||||
+
|
||||
+ BlockState blockData = blocks.get(localBlockIndex);
|
||||
+ if (blockData.isAir()) {
|
||||
+
|
||||
+ if ((edgeCount != 1 || blockData.shapeExceedsCube()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON)) {
|
||||
+ mutablePos.set(blockX, blockY, blockZ);
|
||||
+ if (collisionShape == null) {
|
||||
+ collisionShape = new LazyEntityCollisionContext(entity);
|
||||
+ }
|
||||
+ VoxelShape voxelshape2 = blockData.getCollisionShape(getter, mutablePos, collisionShape);
|
||||
+ if (voxelshape2 != Shapes.empty()) {
|
||||
+ VoxelShape voxelshape3 = voxelshape2.move((double)blockX, (double)blockY, (double)blockZ);
|
||||
+
|
||||
+ if (predicate != null && !predicate.test(blockData, mutablePos)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (checkOnly) {
|
||||
+ if (voxelshape3.intersects(aabb)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ } else {
|
||||
+ ret |= addBoxesToIfIntersects(voxelshape3, aabb, into);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ public static boolean getCollisionsForBlocksOrWorldBorderReference(final CollisionGetter getter, final Entity entity, final AABB aabb,
|
||||
+ final List<AABB> into, final boolean loadChunks, final boolean collidesWithUnloaded,
|
||||
+ final boolean checkBorder, final boolean checkOnly, final BiPredicate<BlockState, BlockPos> predicate) {
|
||||
+ boolean ret = false;
|
||||
+
|
||||
+ if (checkBorder) {
|
||||
+ if (CollisionUtil.isAlmostCollidingOnBorder(getter.getWorldBorder(), aabb)) {
|
||||
+ if (checkOnly) {
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ CollisionUtil.addBoxesTo(getter.getWorldBorder().getCollisionShape(), into);
|
||||
+ ret = true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ final int minBlockX = Mth.floor(aabb.minX - COLLISION_EPSILON) - 1;
|
||||
+ final int maxBlockX = Mth.floor(aabb.maxX + COLLISION_EPSILON) + 1;
|
||||
+
|
||||
+ final int minBlockY = Mth.floor(aabb.minY - COLLISION_EPSILON) - 1;
|
||||
+ final int maxBlockY = Mth.floor(aabb.maxY + COLLISION_EPSILON) + 1;
|
||||
+
|
||||
+ final int minBlockZ = Mth.floor(aabb.minZ - COLLISION_EPSILON) - 1;
|
||||
+ final int maxBlockZ = Mth.floor(aabb.maxZ + COLLISION_EPSILON) + 1;
|
||||
+
|
||||
+ final int minSection = WorldUtil.getMinSection(getter);
|
||||
+ final int maxSection = WorldUtil.getMaxSection(getter);
|
||||
+ final int minBlock = minSection << 4;
|
||||
+ final int maxBlock = (maxSection << 4) | 15;
|
||||
+
|
||||
+ final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
|
||||
+ CollisionContext collisionShape = null;
|
||||
+
|
||||
+ // special cases:
|
||||
+ if (minBlockY > maxBlock || maxBlockY < minBlock) {
|
||||
+ // no point in checking
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ final int minYIterate = Math.max(minBlock, minBlockY);
|
||||
+ final int maxYIterate = Math.min(maxBlock, maxBlockY);
|
||||
+
|
||||
+ final int minChunkX = minBlockX >> 4;
|
||||
+ final int maxChunkX = maxBlockX >> 4;
|
||||
+
|
||||
+ final int minChunkY = minBlockY >> 4;
|
||||
+ final int maxChunkY = maxBlockY >> 4;
|
||||
+
|
||||
+ final int minChunkYIterate = minYIterate >> 4;
|
||||
+ final int maxChunkYIterate = maxYIterate >> 4;
|
||||
+
|
||||
+ final int minChunkZ = minBlockZ >> 4;
|
||||
+ final int maxChunkZ = maxBlockZ >> 4;
|
||||
+
|
||||
+ final ServerChunkCache chunkProvider;
|
||||
+ if (getter instanceof WorldGenRegion) {
|
||||
+ chunkProvider = null;
|
||||
+ } else if (getter instanceof ServerLevel) {
|
||||
+ chunkProvider = ((ServerLevel)getter).getChunkSource();
|
||||
+ } else {
|
||||
+ chunkProvider = null;
|
||||
+ }
|
||||
+
|
||||
+ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) {
|
||||
+ final int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk
|
||||
+ final int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 15; // coordinate in chunk
|
||||
+
|
||||
+ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) {
|
||||
+ final int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk
|
||||
+ final int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk
|
||||
+
|
||||
+ final int chunkXGlobalPos = currChunkX << 4;
|
||||
+ final int chunkZGlobalPos = currChunkZ << 4;
|
||||
+ final ChunkAccess chunk;
|
||||
+ if (chunkProvider == null) {
|
||||
+ chunk = (ChunkAccess)getter.getChunkForCollisions(currChunkX, currChunkZ);
|
||||
+ } else {
|
||||
+ chunk = loadChunks ? chunkProvider.getChunk(currChunkX, currChunkZ, true) : chunkProvider.getChunkAtIfLoadedImmediately(currChunkX, currChunkZ);
|
||||
+ }
|
||||
+
|
||||
+ if (chunk == null) {
|
||||
+ if (collidesWithUnloaded) {
|
||||
+ if (checkOnly) {
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ into.add(getBoxForChunk(currChunkX, currChunkZ));
|
||||
+ ret = true;
|
||||
+ }
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final LevelChunkSection[] sections = chunk.getSections();
|
||||
+
|
||||
+ // bound y
|
||||
+ for (int currChunkY = minChunkYIterate; currChunkY <= maxChunkYIterate; ++currChunkY) {
|
||||
+ final LevelChunkSection section = sections[currChunkY - minSection];
|
||||
+ if (section == null || section.hasOnlyAir()) {
|
||||
+ // empty
|
||||
+ continue;
|
||||
+ }
|
||||
+ final PalettedContainer<BlockState> blocks = section.states;
|
||||
+
|
||||
+ final int minY = currChunkY == minChunkYIterate ? minYIterate & 15 : 0; // coordinate in chunk
|
||||
+ final int maxY = currChunkY == maxChunkYIterate ? maxYIterate & 15 : 15; // coordinate in chunk
|
||||
+ final int chunkYGlobalPos = currChunkY << 4;
|
||||
+
|
||||
+ for (int currY = minY; currY <= maxY; ++currY) {
|
||||
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
|
||||
+ for (int currX = minX; currX <= maxX; ++currX) {
|
||||
+ int localBlockIndex = (currX) | (currZ << 4) | ((currY) << 8);
|
||||
+ int blockX = currX | chunkXGlobalPos;
|
||||
+ int blockY = currY | chunkYGlobalPos;
|
||||
+ int blockZ = currZ | chunkZGlobalPos;
|
||||
+
|
||||
+ int edgeCount = ((blockX == minBlockX || blockX == maxBlockX) ? 1 : 0) +
|
||||
+ ((blockY == minBlockY || blockY == maxBlockY) ? 1 : 0) +
|
||||
+ ((blockZ == minBlockZ || blockZ == maxBlockZ) ? 1 : 0);
|
||||
+ if (edgeCount == 3) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ BlockState blockData = blocks.get(localBlockIndex);
|
||||
+ if (blockData.getBlockCollisionBehavior() == CollisionUtil.KNOWN_EMPTY_BLOCK) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
@ -619,6 +878,7 @@ index 0000000000000000000000000000000000000000..58629451977c89db2fa895bde9461357
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
@ -955,7 +1215,7 @@ index 80888d5adf7d4377e17e6f530f35053cfcc9eed4..fe9810c3b908339ca050ed832c2e67d6
|
||||
}
|
||||
// CraftBukkit start
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 26546c030710685cdc1c75b8018462cd424b9ed6..2e61243b86ea1f21ec799a63badeae329e1ac3fa 100644
|
||||
index bf3bf6f359bfbef0fa2c6f872ec3ff35739a15fc..fe6f2ec41c521c8f1ac17aa3af8bb7f7375e5a02 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1082,9 +1082,44 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
|
||||
@ -1216,18 +1476,202 @@ index f9527d1d867f93b4e0e2758485cfa1f6efa0bf8b..1f4b72a0aca200b2e0860449c718e6e6
|
||||
return List.of();
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
index 1831588b275f11aff37573fead835f6ddabfece1..05c46f3b3bce5225b819d86e6e06729a5093e092 100644
|
||||
index 1831588b275f11aff37573fead835f6ddabfece1..eac017fc521bfd1391e75db8628f42b28329d681 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -726,7 +726,7 @@ public abstract class BlockBehaviour {
|
||||
@@ -717,6 +717,13 @@ public abstract class BlockBehaviour {
|
||||
return this.conditionallyFullOpaque;
|
||||
}
|
||||
// Paper end
|
||||
+ // Paper start
|
||||
+ private long blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_SPECIAL_BLOCK;
|
||||
+
|
||||
+ public final long getBlockCollisionBehavior() {
|
||||
+ return this.blockCollisionBehavior;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public void initCache() {
|
||||
this.fluid = this.getBlock().getFluidState(this.asState()); // Paper - moved from getFluid()
|
||||
@@ -726,7 +733,35 @@ public abstract class BlockBehaviour {
|
||||
}
|
||||
this.shapeExceedsCube = this.cache == null || this.cache.largeCollisionShape; // Paper - moved from actual method to here
|
||||
this.opacityIfCached = this.cache == null || this.isConditionallyFullOpaque() ? -1 : this.cache.lightBlock; // Paper - cache opacity for light
|
||||
-
|
||||
+ // TODO optimise light
|
||||
+ // Paper start
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(this)) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_SPECIAL_BLOCK;
|
||||
+ } else {
|
||||
+ try {
|
||||
+ // There is NOTHING HACKY ABOUT THIS AT ALLLLLLLLLLLLLLL
|
||||
+ VoxelShape constantShape = this.getCollisionShape(null, null, null);
|
||||
+ if (constantShape == null) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_UNKNOWN_BLOCK;
|
||||
+ } else {
|
||||
+ constantShape = constantShape.optimize();
|
||||
+ if (constantShape.isEmpty()) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_EMPTY_BLOCK;
|
||||
+ } else {
|
||||
+ final List<net.minecraft.world.phys.AABB> boxes = constantShape.toAabbs();
|
||||
+ if (constantShape == net.minecraft.world.phys.shapes.Shapes.getFullUnoptimisedCube() || (boxes.size() == 1 && boxes.get(0).equals(net.minecraft.world.phys.shapes.Shapes.BLOCK_OPTIMISED.aabb))) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_FULL_BLOCK;
|
||||
+ } else {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_UNKNOWN_BLOCK;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (final Error error) {
|
||||
+ throw error;
|
||||
+ } catch (final Throwable throwable) {
|
||||
+ this.blockCollisionBehavior = io.papermc.paper.util.CollisionUtil.KNOWN_UNKNOWN_BLOCK;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
index d5ceebee36885c6470917bc1d0952733e983f030..e962db693510dc261d6456706a459929369f2510 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -43,6 +43,110 @@ public class LevelChunkSection {
|
||||
this.biomes = new PalettedContainer<>(biomeRegistry, (Biome) biomeRegistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ protected int specialCollidingBlocks;
|
||||
+ // blockIndex = x | (z << 4) | (y << 8)
|
||||
+ private long[] knownBlockCollisionData;
|
||||
+
|
||||
+ private long[] initKnownDataField() {
|
||||
+ return this.knownBlockCollisionData = new long[16 * 16 * 16 * 2 / Long.SIZE];
|
||||
+ }
|
||||
+
|
||||
+ public final boolean hasSpecialCollidingBlocks() {
|
||||
+ return this.specialCollidingBlocks != 0;
|
||||
+ }
|
||||
+
|
||||
+ public static long getKnownBlockInfo(final int blockIndex, final long value) {
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1));
|
||||
+
|
||||
+ return (value >>> (valueShift << 1)) & 0b11L;
|
||||
+ }
|
||||
+
|
||||
+ public final long getKnownBlockInfo(final int blockIndex) {
|
||||
+ if (this.knownBlockCollisionData == null) {
|
||||
+ return 0L;
|
||||
+ }
|
||||
+
|
||||
+ final int arrayIndex = (blockIndex >>> (6 - 1)); // blockIndex / (64/2)
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1));
|
||||
+
|
||||
+ final long value = this.knownBlockCollisionData[arrayIndex];
|
||||
+
|
||||
+ return (value >>> (valueShift << 1)) & 0b11L;
|
||||
+ }
|
||||
+
|
||||
+ // important detail: this returns 32 values, one for localZ = localZ & (~1) and one for localZ = localZ | 1
|
||||
+ // the even localZ is the lower 32 bits, the odd is the upper 32 bits
|
||||
+ public final long getKnownBlockInfoHorizontalRaw(final int localY, final int localZ) {
|
||||
+ if (this.knownBlockCollisionData == null) {
|
||||
+ return 0L;
|
||||
+ }
|
||||
+
|
||||
+ final int horizontalIndex = (localZ << 4) | (localY << 8);
|
||||
+ return this.knownBlockCollisionData[horizontalIndex >>> (6 - 1)];
|
||||
+ }
|
||||
+
|
||||
+ private void initBlockCollisionData() {
|
||||
+ this.specialCollidingBlocks = 0;
|
||||
+ // In 1.18 all sections will be initialised, whether or not they have blocks (fucking stupid btw)
|
||||
+ // This means we can't aggressively initialise the backing long[], or else memory usage will just skyrocket.
|
||||
+ // So only init if we contain non-empty blocks.
|
||||
+ if (this.nonEmptyBlockCount == 0) {
|
||||
+ this.knownBlockCollisionData = null;
|
||||
+ return;
|
||||
+ }
|
||||
+ this.initKnownDataField();
|
||||
+ for (int index = 0; index < (16 * 16 * 16); ++index) {
|
||||
+ final BlockState state = this.states.get(index);
|
||||
+ this.setKnownBlockInfo(index, state);
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(state)) {
|
||||
+ ++this.specialCollidingBlocks;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // only use for initBlockCollisionData
|
||||
+ private void setKnownBlockInfo(final int blockIndex, final BlockState blockState) {
|
||||
+ final int arrayIndex = (blockIndex >>> (6 - 1)); // blockIndex / (64/2)
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1)) << 1;
|
||||
+
|
||||
+ long value = this.knownBlockCollisionData[arrayIndex];
|
||||
+
|
||||
+ value &= ~(0b11L << valueShift);
|
||||
+ value |= blockState.getBlockCollisionBehavior() << valueShift;
|
||||
+
|
||||
+ this.knownBlockCollisionData[arrayIndex] = value;
|
||||
+ }
|
||||
+
|
||||
+ public void updateKnownBlockInfo(final int blockIndex, final BlockState from, final BlockState to) {
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(from)) {
|
||||
+ --this.specialCollidingBlocks;
|
||||
+ }
|
||||
+ if (io.papermc.paper.util.CollisionUtil.isSpecialCollidingBlock(to)) {
|
||||
+ ++this.specialCollidingBlocks;
|
||||
+ }
|
||||
+
|
||||
+ if (this.nonEmptyBlockCount == 0) {
|
||||
+ this.knownBlockCollisionData = null;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (this.knownBlockCollisionData == null) {
|
||||
+ this.initKnownDataField();
|
||||
+ }
|
||||
+
|
||||
+ final int arrayIndex = (blockIndex >>> (6 - 1)); // blockIndex / (64/2)
|
||||
+ final int valueShift = (blockIndex & (Long.SIZE / 2 - 1)) << 1;
|
||||
+
|
||||
+ long value = this.knownBlockCollisionData[arrayIndex];
|
||||
+
|
||||
+ value &= ~(0b11L << valueShift);
|
||||
+ value |= to.getBlockCollisionBehavior() << valueShift;
|
||||
+
|
||||
+ this.knownBlockCollisionData[arrayIndex] = value;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static int getBottomBlockY(int chunkPos) {
|
||||
return chunkPos << 4;
|
||||
}
|
||||
@@ -67,8 +171,8 @@ public class LevelChunkSection {
|
||||
return this.setBlockState(x, y, z, state, true);
|
||||
}
|
||||
|
||||
- public BlockState setBlockState(int x, int y, int z, BlockState state, boolean lock) {
|
||||
- BlockState iblockdata1;
|
||||
+ public BlockState setBlockState(int x, int y, int z, BlockState state, boolean lock) { // Paper - state -> new state
|
||||
+ BlockState iblockdata1; // Paper - iblockdata1 -> oldState
|
||||
|
||||
if (lock) {
|
||||
iblockdata1 = (BlockState) this.states.getAndSet(x, y, z, state);
|
||||
@@ -107,6 +211,7 @@ public class LevelChunkSection {
|
||||
++this.tickingFluidCount;
|
||||
}
|
||||
|
||||
+ this.updateKnownBlockInfo(x | (z << 4) | (y << 8), iblockdata1, state); // Paper
|
||||
return iblockdata1;
|
||||
}
|
||||
|
||||
@@ -158,6 +263,7 @@ public class LevelChunkSection {
|
||||
}
|
||||
|
||||
});
|
||||
+ this.initBlockCollisionData(); // Paper
|
||||
}
|
||||
|
||||
public PalettedContainer<BlockState> getStates() {
|
||||
diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java
|
||||
index 120498a39b7ca7aee9763084507508d4a1c425aa..68cc6f2a78a06293a29317fda72ab3ee79b3533a 100644
|
||||
--- a/src/main/java/net/minecraft/world/phys/AABB.java
|
||||
|
@ -10,10 +10,10 @@ This patch also prevents the saving/unloading of POI data when
|
||||
world saving is disabled.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 02bcffcdde33088e43a7771924b2d2bf47badd09..e97e0dbc094963f0976590c2700686647f6dcc8a 100644
|
||||
index 29fdc1b991c67006a13231abbbe50e201744b5c2..79dbffe899dd7e31af648302c557e2993f170623 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -811,6 +811,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -812,6 +812,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
// Paper end
|
||||
}
|
||||
@ -21,7 +21,7 @@ index 02bcffcdde33088e43a7771924b2d2bf47badd09..e97e0dbc094963f0976590c270068664
|
||||
|
||||
this.updatingChunks.queueUpdate(pos, holder); // Paper - Don't copy
|
||||
this.modified = true;
|
||||
@@ -956,7 +957,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -957,7 +958,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
gameprofilerfiller.pop();
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ index 02bcffcdde33088e43a7771924b2d2bf47badd09..e97e0dbc094963f0976590c270068664
|
||||
|
||||
private void processUnloads(BooleanSupplier shouldKeepTicking) {
|
||||
LongIterator longiterator = this.toDrop.iterator();
|
||||
@@ -1019,6 +1020,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1021,6 +1022,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
|
||||
}
|
||||
// Paper end
|
||||
@ -38,7 +38,7 @@ index 02bcffcdde33088e43a7771924b2d2bf47badd09..e97e0dbc094963f0976590c270068664
|
||||
if (ichunkaccess instanceof LevelChunk) {
|
||||
((LevelChunk) ichunkaccess).setLoaded(false);
|
||||
}
|
||||
@@ -1047,6 +1049,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1049,6 +1051,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
|
||||
this.regionManagers.get(index).removeChunk(holder.pos.x, holder.pos.z);
|
||||
}
|
||||
@ -46,7 +46,7 @@ index 02bcffcdde33088e43a7771924b2d2bf47badd09..e97e0dbc094963f0976590c270068664
|
||||
} // Paper end
|
||||
} finally { this.unloadingPlayerChunk = unloadingBefore; } // Paper - do not allow ticket level changes while unloading chunks
|
||||
|
||||
@@ -1123,6 +1126,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -1125,6 +1128,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
this.poiManager.loadInData(pos, chunkHolder.poiData);
|
||||
chunkHolder.tasks.forEach(Runnable::run);
|
||||
|
@ -5,10 +5,10 @@ Subject: [PATCH] Fix int overflow in chunk range check
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 387b0e9b862621e7d0c1179f348e07c25f1ee9c0..2e6e86439173ebdb13b9cebd1e266e91335c1e2d 100644
|
||||
index 79dbffe899dd7e31af648302c557e2993f170623..6a035b173cf0d288b2912f568078fede45d138f2 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -621,9 +621,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
@@ -622,9 +622,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
public static boolean isChunkInRange(int x1, int z1, int x2, int z2, int distance) {
|
||||
int j1 = Math.max(0, Math.abs(x1 - x2) - 1);
|
||||
int k1 = Math.max(0, Math.abs(z1 - z2) - 1);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Tue, 28 Dec 2021 07:19:01 -0800
|
||||
Subject: [PATCH] Execute chunk tasks fairly for worlds while waiting for next
|
||||
tick
|
||||
|
||||
Currently, only the first world would have had tasks executed.
|
||||
This might result in chunks loading far slower in the nether,
|
||||
for example.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index eab93e1e3712c0a01cac187bf5944818c813d665..1674deebbeab0995ed7acacf8052e1daf4d2a7bc 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1392,6 +1392,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.executeMidTickTasks(); // Paper - execute chunk tasks mid tick
|
||||
return true;
|
||||
} else {
|
||||
+ boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
||||
if (this.haveTime()) {
|
||||
Iterator iterator = this.getAllLevels().iterator();
|
||||
|
||||
@@ -1399,12 +1400,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
ServerLevel worldserver = (ServerLevel) iterator.next();
|
||||
|
||||
if (worldserver.getChunkSource().pollTask()) {
|
||||
- return true;
|
||||
+ ret = true; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- return false;
|
||||
+ return ret; // Paper - force execution of all worlds, do not just bias the first
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ will be more effective, since more time will be allocated
|
||||
to actually processing chunk tasks vs the ticket level updates.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a602a44d5 100644
|
||||
index fd379155a67794288f7cdae3250767bc3615d421..d278e5b8b3386044e0fbc13add369794fd6f9cd7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
|
||||
@@ -36,6 +36,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
|
||||
@@ -37,6 +37,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@ -26,17 +26,17 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
public abstract class DistanceManager {
|
||||
|
||||
static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -44,7 +45,7 @@ public abstract class DistanceManager {
|
||||
private static final int INITIAL_TICKET_LIST_CAPACITY = 4;
|
||||
@@ -47,7 +48,7 @@ public abstract class DistanceManager {
|
||||
private static final int BLOCK_TICKING_LEVEL_THRESHOLD = 33;
|
||||
final Long2ObjectMap<ObjectSet<ServerPlayer>> playersPerChunk = new Long2ObjectOpenHashMap();
|
||||
public final Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> tickets = new Long2ObjectOpenHashMap();
|
||||
- private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker();
|
||||
+ //private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); // Paper - replace ticket level propagator
|
||||
public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used
|
||||
//private final TickingTracker tickingTicketsTracker = new TickingTracker(); // Paper - no longer used
|
||||
//private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); // Paper - no longer used
|
||||
// Paper start use a queue, but still keep unique requirement
|
||||
@@ -77,6 +78,46 @@ public abstract class DistanceManager {
|
||||
this.mainThreadExecutor = mainThreadExecutor;
|
||||
@@ -82,6 +83,46 @@ public abstract class DistanceManager {
|
||||
this.chunkMap = chunkMap; // Paper
|
||||
}
|
||||
|
||||
+ // Paper start - replace ticket level propagator
|
||||
@ -82,22 +82,23 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
protected void purgeStaleTickets() {
|
||||
++this.ticketTickCounter;
|
||||
ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().fastIterator();
|
||||
@@ -87,7 +128,7 @@ public abstract class DistanceManager {
|
||||
if ((entry.getValue()).removeIf((ticket) -> { // CraftBukkit - decompile error
|
||||
return ticket.timedOut(this.ticketTickCounter);
|
||||
})) {
|
||||
@@ -116,7 +157,7 @@ public abstract class DistanceManager {
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
- this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt((SortedArraySet) entry.getValue()), false);
|
||||
+ this.updateTicketLevel(entry.getLongKey(), getTicketLevelAt(entry.getValue())); // Paper - replace ticket level propagator
|
||||
}
|
||||
|
||||
if (((SortedArraySet) entry.getValue()).isEmpty()) {
|
||||
@@ -110,60 +151,93 @@ public abstract class DistanceManager {
|
||||
@@ -139,61 +180,94 @@ public abstract class DistanceManager {
|
||||
@Nullable
|
||||
protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k);
|
||||
|
||||
+ protected long ticketLevelUpdateCount; // Paper - replace ticket level propagator
|
||||
public boolean runAllUpdates(ChunkMap playerchunkmap) {
|
||||
public boolean runAllUpdates(ChunkMap chunkStorage) {
|
||||
//this.f.a(); // Paper - no longer used
|
||||
//this.tickingTicketsTracker.runAllUpdates(); // Paper - no longer used
|
||||
org.spigotmc.AsyncCatcher.catchOp("DistanceManagerTick"); // Paper
|
||||
//this.playerTicketManager.runAllUpdates(); // Paper - no longer used
|
||||
- int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE);
|
||||
@ -114,7 +115,7 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
- while(!this.pendingChunkUpdates.isEmpty()) {
|
||||
- ChunkHolder remove = this.pendingChunkUpdates.remove();
|
||||
- remove.isUpdateQueued = false;
|
||||
- remove.updateFutures(playerchunkmap, this.mainThreadExecutor);
|
||||
- remove.updateFutures(chunkStorage, this.mainThreadExecutor);
|
||||
- }
|
||||
- } finally { this.pollingPendingChunkUpdates = false; } // Paper - Chunk priority
|
||||
- // Paper end
|
||||
@ -142,23 +143,23 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
+ // not loaded and it shouldn't be loaded!
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ int currentLevel = chunk == null ? ChunkMap.MAX_CHUNK_DISTANCE + 1 : chunk.getTicketLevel();
|
||||
+
|
||||
+ if (currentLevel == newLevel) {
|
||||
+ // nothing to do
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- if (this.getTickets(j).stream().anyMatch((ticket) -> {
|
||||
- return ticket.getType() == TicketType.PLAYER;
|
||||
- })) {
|
||||
- ChunkHolder playerchunk = playerchunkmap.getUpdatingChunkIfPresent(j);
|
||||
+ this.updateChunkScheduling(key, newLevel, chunk, currentLevel);
|
||||
+ }
|
||||
- ChunkHolder playerchunk = chunkStorage.getUpdatingChunkIfPresent(j);
|
||||
+ int currentLevel = chunk == null ? ChunkMap.MAX_CHUNK_DISTANCE + 1 : chunk.getTicketLevel();
|
||||
|
||||
- if (playerchunk == null) {
|
||||
- throw new IllegalStateException();
|
||||
+ if (currentLevel == newLevel) {
|
||||
+ // nothing to do
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ this.updateChunkScheduling(key, newLevel, chunk, currentLevel);
|
||||
+ }
|
||||
+
|
||||
+ long recursiveCheck = ++this.ticketLevelUpdateCount;
|
||||
+ while (!this.ticketLevelUpdates.isEmpty()) {
|
||||
+ long key = this.ticketLevelUpdates.firstLongKey();
|
||||
@ -187,7 +188,7 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ chunk.updateFutures(playerchunkmap, this.mainThreadExecutor);
|
||||
+ chunk.updateFutures(chunkStorage, this.mainThreadExecutor);
|
||||
+ if (recursiveCheck != this.ticketLevelUpdateCount) {
|
||||
+ // back to the start, we must create player chunks and update the ticket level fields before
|
||||
+ // processing the actual level updates
|
||||
@ -207,7 +208,7 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
+ }
|
||||
|
||||
- return flag;
|
||||
+ pendingUpdate.updateFutures(playerchunkmap, this.mainThreadExecutor);
|
||||
+ pendingUpdate.updateFutures(chunkStorage, this.mainThreadExecutor);
|
||||
+ }
|
||||
+ } finally {
|
||||
+ this.pollingPendingChunkUpdates = oldPolling;
|
||||
@ -219,7 +220,7 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
}
|
||||
boolean pollingPendingChunkUpdates = false; // Paper - Chunk priority
|
||||
|
||||
@@ -175,7 +249,7 @@ public abstract class DistanceManager {
|
||||
@@ -205,7 +279,7 @@ public abstract class DistanceManager {
|
||||
|
||||
ticket1.setCreatedTick(this.ticketTickCounter);
|
||||
if (ticket.getTicketLevel() < j) {
|
||||
@ -228,7 +229,7 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
}
|
||||
|
||||
return ticket == ticket1; // CraftBukkit
|
||||
@@ -219,7 +293,7 @@ public abstract class DistanceManager {
|
||||
@@ -249,7 +323,7 @@ public abstract class DistanceManager {
|
||||
// Paper start - Chunk priority
|
||||
int newLevel = getTicketLevelAt(arraysetsorted);
|
||||
if (newLevel > oldLevel) {
|
||||
@ -237,7 +238,7 @@ index 0b34536cdffab31a717b613042d7098109846586..24fa3d847f7c0aec52133ffc658cd90a
|
||||
}
|
||||
// Paper end
|
||||
return removed; // CraftBukkit
|
||||
@@ -507,7 +581,7 @@ public abstract class DistanceManager {
|
||||
@@ -549,7 +623,7 @@ public abstract class DistanceManager {
|
||||
SortedArraySet<Ticket<?>> tickets = entry.getValue();
|
||||
if (tickets.remove(target)) {
|
||||
// copied from removeTicket
|
Loading…
Reference in New Issue
Block a user