diff --git a/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-waypoint-command-bar.patch b/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-waypoint-command-bar.patch index c1db4d5..68ab30e 100644 --- a/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-waypoint-command-bar.patch +++ b/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-waypoint-command-bar.patch @@ -3,6 +3,7 @@ From: Helvetica Volubi Date: Mon, 7 Jul 2025 18:19:00 +0800 Subject: [PATCH] Add config to enable waypoint command & bar +use concurrent method to fix it (now, they are thread safe) diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java index 1fb359073342a657e9e493403263b56be5b3393f..451a685782da46f5683ea6707289bbaf3193771f 100644 @@ -22,10 +23,19 @@ index 1fb359073342a657e9e493403263b56be5b3393f..451a685782da46f5683ea6707289bbaf WorldBorderCommand.register(this.dispatcher); if (JvmProfiler.INSTANCE.isAvailable()) { diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java -index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..52fd730998535ea071bfc99b7cc2c254b9b656d7 100644 +index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..73b69b0d93c17ab8bd3a7c0226d210760b607d7f 100644 --- a/net/minecraft/server/waypoints/ServerWaypointManager.java +++ b/net/minecraft/server/waypoints/ServerWaypointManager.java -@@ -22,7 +22,14 @@ public class ServerWaypointManager implements WaypointManager { +- private final Set waypoints = new HashSet<>(); +- private final Set players = new HashSet<>(); +- private final Table connections = HashBasedTable.create(); ++ private final Set waypoints = new java.util.concurrent.CopyOnWriteArraySet<>(); // Lophine - concurrent ++ private final Set players = new java.util.concurrent.CopyOnWriteArraySet<>(); // Lophine - concurrent ++ private final fun.bm.lophine.utils.concurrent.ConcurrentTable connections = new fun.bm.lophine.utils.concurrent.ConcurrentTable<>(); // Lophine - concurrent @Override public void trackWaypoint(WaypointTransmitter waypoint) { @@ -41,7 +51,23 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..52fd730998535ea071bfc99b7cc2c254 } @Override -@@ -50,14 +57,48 @@ public class ServerWaypointManager implements WaypointManager map = Tables.transpose(this.connections).row(waypoint); ++ Map map = this.connections.getXZ(waypoint); // Lophine - concurrent + SetView set = Sets.difference(this.players, map.keySet()); + + for (Entry entry : ImmutableSet.copyOf(map.entrySet())) { +@@ -43,26 +50,58 @@ public class ServerWaypointManager implements WaypointManager connection.disconnect()); +- Tables.transpose(this.connections).row(waypoint).clear(); ++ this.connections.getXZ(waypoint).forEach((serverPlayer, connection) -> connection.disconnect()); // Lophine - concurrent ++ this.connections.clearXZ(waypoint); // Lophine - concurrent + this.waypoints.remove(waypoint); + } public void addPlayer(ServerPlayer player) { // Folia - region threading @@ -63,7 +89,7 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..52fd730998535ea071bfc99b7cc2c254 // Folia - region threading + // Lophine start - unsafe waypoint bar + if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return; -+ Map map = this.connections.row(player); ++ Map map = this.connections.getYZ(player); // Lophine - concurrent + SetView set = Sets.difference(this.waypoints, map.keySet()); + + for (Entry entry : ImmutableSet.copyOf(map.entrySet())) { @@ -80,13 +106,38 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..52fd730998535ea071bfc99b7cc2c254 // Folia - region threading + // Lophine start - unsafe waypoint bar + if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return; -+ this.connections.row(player).values().removeIf(connection -> { -+ connection.disconnect(); -+ return true; -+ }); ++ this.connections.getYZ(player).values().forEach(WaypointTransmitter.Connection::disconnect); // Lophine - concurrent ++ this.connections.clearYZ(player); // Lophine - concurrent + this.untrackWaypoint((WaypointTransmitter)player); + this.players.remove(player); + // Lophine end - unsafe waypoint bar } public void breakAllConnections() { +- this.connections.values().forEach(WaypointTransmitter.Connection::disconnect); +- this.connections.clear(); ++ this.connections.getAllZ().forEach(WaypointTransmitter.Connection::disconnect); // Lophine - concurrent ++ this.connections.clearAll(); // Lophine - concurrent + } + + public void remakeConnections(WaypointTransmitter waypoint) { +@@ -86,7 +125,8 @@ public class ServerWaypointManager implements WaypointManager { +- WaypointTransmitter.Connection connection = this.connections.remove(player, waypoint); ++ WaypointTransmitter.Connection connection = this.connections.getZ(player, waypoint); // Lophine - concurrent ++ this.connections.remove(player, waypoint, connection); // Lophine - concurrent + if (connection != null) { + connection.disconnect(); + } +@@ -106,7 +146,8 @@ public class ServerWaypointManager implements WaypointManager { + connection.disconnect(); +- this.connections.remove(player, waypoint); ++ WaypointTransmitter.Connection c = this.connections.getZ(player, waypoint); // Lophine - concurrent ++ this.connections.remove(player, waypoint, c); // Lophine - concurrent + }); + } + } diff --git a/lophine-server/src/main/java/fun/bm/lophine/utils/concurrent/ConcurrentTable.java b/lophine-server/src/main/java/fun/bm/lophine/utils/concurrent/ConcurrentTable.java new file mode 100644 index 0000000..a6fc8ca --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/utils/concurrent/ConcurrentTable.java @@ -0,0 +1,116 @@ +package fun.bm.lophine.utils.concurrent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentLinkedDeque; + +public class ConcurrentTable { + ConcurrentLinkedDeque> data = new ConcurrentLinkedDeque<>(); + + public void put(X x, Y y, Z z) { + data.add(new TableEntry<>(x, y, z)); + } + + public void remove(X x, Y y, Z z) { + data.removeIf(entry -> entry.getX().equals(x) && entry.getY().equals(y) && entry.getZ().equals(z)); + } + + public Z getZ(X x, Y y) { + for (TableEntry entry : data) { + if (entry.getX().equals(x) && entry.getY().equals(y)) { + return entry.getZ(); + } + } + return null; + } + + public Y getY(X x, Z z) { + for (TableEntry entry : data) { + if (entry.getX().equals(x) && entry.getZ().equals(z)) { + return entry.getY(); + } + } + return null; + } + + public X getX(Y y, Z z) { + for (TableEntry entry : data) { + if (entry.getY().equals(y) && entry.getZ().equals(z)) { + return entry.getX(); + } + } + return null; + } + + public Map getXY(Z z) { + HashMap map = new HashMap<>(); + for (TableEntry entry : data) { + if (entry.getZ().equals(z)) { + map.put(entry.getX(), entry.getY()); + } + } + return map; + } + + public Map getYZ(X x) { + HashMap map = new HashMap<>(); + for (TableEntry entry : data) { + if (entry.getX().equals(x)) { + map.put(entry.getY(), entry.getZ()); + } + } + return map; + } + + public Map getXZ(Y y) { + HashMap map = new HashMap<>(); + for (TableEntry entry : data) { + if (entry.getY().equals(y)) { + map.put(entry.getX(), entry.getZ()); + } + } + return map; + } + + public List getAllX() { + List xList = new ArrayList<>(); + for (TableEntry entry : data) { + xList.add(entry.getX()); + } + return xList; + } + + public List getAllY() { + List yList = new ArrayList<>(); + for (TableEntry entry : data) { + yList.add(entry.getY()); + } + return yList; + } + + public List getAllZ() { + List zList = new ArrayList<>(); + for (TableEntry entry : data) { + zList.add(entry.getZ()); + } + return zList; + } + + public void clearXY(Z z) { + data.removeIf(entry -> entry.getZ().equals(z)); + } + + public void clearYZ(X x) { + data.removeIf(entry -> entry.getX().equals(x)); + } + + public void clearXZ(Y y) { + data.removeIf(entry -> entry.getY().equals(y)); + } + + public void clearAll() { + data.clear(); + } +} diff --git a/lophine-server/src/main/java/fun/bm/lophine/utils/concurrent/TableEntry.java b/lophine-server/src/main/java/fun/bm/lophine/utils/concurrent/TableEntry.java new file mode 100644 index 0000000..391ee37 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/utils/concurrent/TableEntry.java @@ -0,0 +1,25 @@ +package fun.bm.lophine.utils.concurrent; + +public class TableEntry { + private final X x; + private final Y y; + private final Z z; + + public TableEntry(X x, Y y, Z z) { + this.x = x; + this.y = y; + this.z = z; + } + + public X getX() { + return x; + } + + public Y getY() { + return y; + } + + public Z getZ() { + return z; + } +}