From badcd288ad5cf44659df71b0d27632735603d925 Mon Sep 17 00:00:00 2001 From: CaptainRexPL Date: Mon, 15 Jan 2024 10:41:33 +0100 Subject: [PATCH] fix issues with NEARBY groups --- .../client/api/location/LocationApi.java | 2 +- .../server/services/groups/GroupService.java | 9 ++- .../services/location/NearbyGroups.java | 63 ++++++++++--------- .../location/PlayerLocationService.java | 2 +- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/client/src/main/java/com/collarmc/client/api/location/LocationApi.java b/client/src/main/java/com/collarmc/client/api/location/LocationApi.java index c74b02e2..5b9fdcb3 100644 --- a/client/src/main/java/com/collarmc/client/api/location/LocationApi.java +++ b/client/src/main/java/com/collarmc/client/api/location/LocationApi.java @@ -278,7 +278,7 @@ public boolean handleResponse(ProtocolResponse resp) { // Update the location playerLocations.put(response.sender, location.get()); } else { - // Remove if stooped sharing + // Remove if stopped sharing playerLocations.remove(response.sender); } collar.configuration.eventBus.dispatch(new LocationUpdatedEvent(collar, response.sender, location.orElse(Location.UNKNOWN))); diff --git a/server/src/main/java/com/collarmc/server/services/groups/GroupService.java b/server/src/main/java/com/collarmc/server/services/groups/GroupService.java index d516dad3..315053a4 100644 --- a/server/src/main/java/com/collarmc/server/services/groups/GroupService.java +++ b/server/src/main/java/com/collarmc/server/services/groups/GroupService.java @@ -160,7 +160,11 @@ public Optional playerIsOffline(Player player) { BatchProtocolResponse response = new BatchProtocolResponse(); store.findGroupsContaining(player.identity.id()).forEach(group -> { PublicProfile profile = profiles.getById(player.identity.id()).orElseThrow(() -> new IllegalStateException("could not load profile " + player.identity.id())).toPublic(); - group = group.updatePlayer(new MemberSource(player, profile)); + if (group.type == GroupType.NEARBY) { + group = group.removeMember(player); + } else { + group = group.updatePlayer(new MemberSource(player, profile)); + } // Let everyone else in the group know that this identity has gone offline Group finalGroup = group; BatchProtocolResponse updates = createMemberMessages( @@ -341,6 +345,7 @@ public Optional updateNearbyGroups(NearbyGroups.Result re group = group.removeMember(source.player); } store.delete(group.id); + LOGGER.info("[GroupService] deleted " + group.type + " group: " + group.id); })); return response.optional(); } @@ -414,7 +419,7 @@ public Optional transferOwnership(ClientIdentity identity, Tra } private void updateState(Group group) { - if (group != null && group.members.isEmpty()) { + if (group != null && (group.members.isEmpty() || (group.type == GroupType.NEARBY && group.members.size() == 1))) { LOGGER.info("Removed group " + group.id + " as it has no members."); store.delete(group.id); } diff --git a/server/src/main/java/com/collarmc/server/services/location/NearbyGroups.java b/server/src/main/java/com/collarmc/server/services/location/NearbyGroups.java index 3290d02a..bf6378d9 100644 --- a/server/src/main/java/com/collarmc/server/services/location/NearbyGroups.java +++ b/server/src/main/java/com/collarmc/server/services/location/NearbyGroups.java @@ -9,12 +9,17 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + /** * State machine for managing dynamically created {@link Group}'s based on hashing * every players player entity list and comparing them. */ public final class NearbyGroups { + private static final Logger LOGGER = LogManager.getLogger(NearbyGroups.class.getName()); + private final ConcurrentMap> playerHashes = new ConcurrentHashMap<>(); private final ConcurrentMap nearbyGroups = new ConcurrentHashMap<>(); private final ConcurrentMap> playerToGroups = new ConcurrentHashMap<>(); @@ -33,37 +38,39 @@ public Result updateNearbyGroups(MemberSource source, Set hashes) { playerHashes.keySet().stream() .filter(anotherSource -> anotherSource.player.minecraftPlayer != null && - source.player.minecraftPlayer != null && - anotherSource.player.minecraftPlayer.inServerWith(source.player.minecraftPlayer) - && !anotherSource.equals(source) + source.player.minecraftPlayer != null && + anotherSource.player.minecraftPlayer.inServerWith(source.player.minecraftPlayer) + && !anotherSource.equals(source) ).forEach(anotherPlayer -> { - Set otherPlayersHashes = playerHashes.get(anotherPlayer); - NearbyGroup group = new NearbyGroup(Set.of(source, anotherPlayer)); - if (Sets.difference(hashes, otherPlayersHashes).isEmpty()) { - nearbyGroups.compute(group, (nearbyGroup, uuid) -> { - if (uuid == null) { - uuid = UUID.randomUUID(); - add.put(uuid, group); + Set otherPlayersHashes = playerHashes.get(anotherPlayer); + NearbyGroup group = new NearbyGroup(Set.of(source, anotherPlayer)); + if (Sets.difference(hashes, otherPlayersHashes).isEmpty()) { + nearbyGroups.compute(group, (nearbyGroup, uuid) -> { + if (uuid == null) { + uuid = UUID.randomUUID(); + add.put(uuid, group); + } + return uuid; + }); + playerToGroups.compute(source, (thePlayer, playersGroups) -> { + playersGroups = playersGroups == null ? new HashSet<>() : playersGroups; + playersGroups.add(group); + return playersGroups; + }); + } else { + UUID groupId = nearbyGroups.get(group); + nearbyGroups.remove(group); + if (groupId != null) { + remove.put(groupId, group); + playerToGroups.compute(source, (thePlayer, playersGroups) -> { + playersGroups = playersGroups == null ? new HashSet<>() : playersGroups; + playersGroups.remove(group); + return nearbyGroups.isEmpty() ? null : playersGroups; + }); + } } - return uuid; - }); - playerToGroups.compute(source, (thePlayer, playersGroups) -> { - playersGroups = playersGroups == null ? new HashSet<>() : playersGroups; - playersGroups.add(group); - return playersGroups; }); - } else { - UUID groupId = nearbyGroups.get(group); - if (groupId != null) { - remove.put(groupId, group); - playerToGroups.compute(source, (thePlayer, playersGroups) -> { - playersGroups = playersGroups == null ? new HashSet<>() : playersGroups; - playersGroups.remove(group); - return nearbyGroups.isEmpty() ? null : playersGroups; - }); - } - } - }); + nearbyGroups.entrySet().removeIf(entry -> entry.getKey().players.size() < 2); return new Result(add, remove); } diff --git a/server/src/main/java/com/collarmc/server/services/location/PlayerLocationService.java b/server/src/main/java/com/collarmc/server/services/location/PlayerLocationService.java index 361b15bd..0350237d 100644 --- a/server/src/main/java/com/collarmc/server/services/location/PlayerLocationService.java +++ b/server/src/main/java/com/collarmc/server/services/location/PlayerLocationService.java @@ -78,7 +78,7 @@ public Optional updateLocation(ClientIdentity identity, U } private Optional stopSharing(UUID groupId, Player player) { - LOGGER.info("Player " + player + " started sharing location with group " + groupId); + LOGGER.info("Player " + player + " stopped sharing location with group " + groupId); LocationUpdatedResponse locationUpdatedResponse = new LocationUpdatedResponse(groupId, player, null); Optional responses = createLocationResponses(player, locationUpdatedResponse); playersSharing.compute(groupId, (uuid, players) -> {