package net.minecraft.server.waypoints; import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.common.collect.Table; import com.google.common.collect.Tables; import com.google.common.collect.Sets.SetView; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.GameRules; import net.minecraft.world.waypoints.WaypointManager; import net.minecraft.world.waypoints.WaypointTransmitter; public class ServerWaypointManager implements WaypointManager { private final Set waypoints = new HashSet(); private final Set players = new HashSet(); private final Table connections = HashBasedTable.create(); public void trackWaypoint(WaypointTransmitter waypoint) { this.waypoints.add(waypoint); for (ServerPlayer serverPlayer : this.players) { this.createConnection(serverPlayer, waypoint); } } public void updateWaypoint(WaypointTransmitter waypoint) { if (this.waypoints.contains(waypoint)) { Map map = Tables.transpose(this.connections).row(waypoint); SetView setView = Sets.difference(this.players, map.keySet()); for (Entry entry : ImmutableSet.copyOf(map.entrySet())) { this.updateConnection((ServerPlayer)entry.getKey(), waypoint, (WaypointTransmitter.Connection)entry.getValue()); } for (ServerPlayer serverPlayer : setView) { this.createConnection(serverPlayer, waypoint); } } } public void untrackWaypoint(WaypointTransmitter waypoint) { this.connections.column(waypoint).forEach((serverPlayer, connection) -> connection.disconnect()); Tables.transpose(this.connections).row(waypoint).clear(); this.waypoints.remove(waypoint); } public void addPlayer(ServerPlayer player) { this.players.add(player); for (WaypointTransmitter waypointTransmitter : this.waypoints) { this.createConnection(player, waypointTransmitter); } if (player.isTransmittingWaypoint()) { this.trackWaypoint((WaypointTransmitter)player); } } public void updatePlayer(ServerPlayer player) { Map map = this.connections.row(player); SetView setView = Sets.difference(this.waypoints, map.keySet()); for (Entry entry : ImmutableSet.copyOf(map.entrySet())) { this.updateConnection(player, (WaypointTransmitter)entry.getKey(), (WaypointTransmitter.Connection)entry.getValue()); } for (WaypointTransmitter waypointTransmitter : setView) { this.createConnection(player, waypointTransmitter); } } public void removePlayer(ServerPlayer player) { this.connections.row(player).values().removeIf(connection -> { connection.disconnect(); return true; }); this.untrackWaypoint((WaypointTransmitter)player); this.players.remove(player); } public void breakAllConnections() { this.connections.values().forEach(WaypointTransmitter.Connection::disconnect); this.connections.clear(); } public void remakeConnections(WaypointTransmitter waypoint) { for (ServerPlayer serverPlayer : this.players) { this.createConnection(serverPlayer, waypoint); } } public Set transmitters() { return this.waypoints; } private static boolean isLocatorBarEnabledFor(ServerPlayer player) { return player.level().getServer().getGameRules().getBoolean(GameRules.RULE_LOCATOR_BAR); } private void createConnection(ServerPlayer player, WaypointTransmitter waypoint) { if (player != waypoint) { if (isLocatorBarEnabledFor(player)) { waypoint.makeWaypointConnectionWith(player).ifPresentOrElse(connection -> { this.connections.put(player, waypoint, connection); connection.connect(); }, () -> { WaypointTransmitter.Connection connection = this.connections.remove(player, waypoint); if (connection != null) { connection.disconnect(); } }); } } } private void updateConnection(ServerPlayer player, WaypointTransmitter waypoint, WaypointTransmitter.Connection connection) { if (player != waypoint) { if (isLocatorBarEnabledFor(player)) { if (!connection.isBroken()) { connection.update(); } else { waypoint.makeWaypointConnectionWith(player).ifPresentOrElse(connectionx -> { connectionx.connect(); this.connections.put(player, waypoint, connectionx); }, () -> { connection.disconnect(); this.connections.remove(player, waypoint); }); } } } } }