From d01ba08f266d174e0719aa1799f3ae95055fcea1 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Sun, 30 Apr 2023 20:58:31 -0400 Subject: [PATCH] Fix double adding of avatar entities --- .../emu/grasscutter/game/player/TeamInfo.java | 190 +++++++++--------- .../grasscutter/game/player/TeamManager.java | 40 +++- .../send/PacketSceneTeamUpdateNotify.java | 3 +- 3 files changed, 127 insertions(+), 106 deletions(-) diff --git a/src/main/java/emu/grasscutter/game/player/TeamInfo.java b/src/main/java/emu/grasscutter/game/player/TeamInfo.java index 0edd3899a..ca29f66be 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamInfo.java +++ b/src/main/java/emu/grasscutter/game/player/TeamInfo.java @@ -1,95 +1,95 @@ -package emu.grasscutter.game.player; - -import static emu.grasscutter.config.Configuration.GAME_OPTIONS; - -import dev.morphia.annotations.Entity; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam; -import java.util.ArrayList; -import java.util.List; - -@Entity -public class TeamInfo { - private String name; - private final List avatars; - - public TeamInfo() { - this.name = ""; - this.avatars = new ArrayList<>(GAME_OPTIONS.avatarLimits.singlePlayerTeam); - } - - public TeamInfo(List avatars) { - this.name = ""; - this.avatars = avatars; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getAvatars() { - return avatars; - } - - public int size() { - return avatars.size(); - } - - public boolean contains(Avatar avatar) { - return getAvatars().contains(avatar.getAvatarId()); - } - - public boolean addAvatar(Avatar avatar) { - if (contains(avatar)) { - return false; - } - - getAvatars().add(avatar.getAvatarId()); - - return true; - } - - public boolean removeAvatar(int slot) { - if (size() <= 1) { - return false; - } - - getAvatars().remove(slot); - - return true; - } - - public void copyFrom(TeamInfo team) { - copyFrom(team, GAME_OPTIONS.avatarLimits.singlePlayerTeam); - } - - public void copyFrom(TeamInfo team, int maxTeamSize) { - // Clone avatar ids from team to copy from - List avatarIds = new ArrayList<>(team.getAvatars()); - - // Clear current avatar list first - this.getAvatars().clear(); - - // Copy from team - int len = Math.min(avatarIds.size(), maxTeamSize); - for (int i = 0; i < len; i++) { - int id = avatarIds.get(i); - this.getAvatars().add(id); - } - } - - public AvatarTeam toProto(Player player) { - AvatarTeam.Builder avatarTeam = AvatarTeam.newBuilder().setTeamName(this.getName()); - - for (int i = 0; i < this.getAvatars().size(); i++) { - Avatar avatar = player.getAvatars().getAvatarById(this.getAvatars().get(i)); - avatarTeam.addAvatarGuidList(avatar.getGuid()); - } - - return avatarTeam.build(); - } -} +package emu.grasscutter.game.player; + +import static emu.grasscutter.config.Configuration.GAME_OPTIONS; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam; +import java.util.ArrayList; +import java.util.List; + +@Entity +public final class TeamInfo { + private String name; + private final List avatars; + + public TeamInfo() { + this.name = ""; + this.avatars = new ArrayList<>(GAME_OPTIONS.avatarLimits.singlePlayerTeam); + } + + public TeamInfo(List avatars) { + this.name = ""; + this.avatars = avatars; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getAvatars() { + return avatars; + } + + public int size() { + return avatars.size(); + } + + public boolean contains(Avatar avatar) { + return getAvatars().contains(avatar.getAvatarId()); + } + + public boolean addAvatar(Avatar avatar) { + if (contains(avatar)) { + return false; + } + + getAvatars().add(avatar.getAvatarId()); + + return true; + } + + public boolean removeAvatar(int slot) { + if (size() <= 1) { + return false; + } + + getAvatars().remove(slot); + + return true; + } + + public void copyFrom(TeamInfo team) { + copyFrom(team, GAME_OPTIONS.avatarLimits.singlePlayerTeam); + } + + public void copyFrom(TeamInfo team, int maxTeamSize) { + // Clone avatar ids from team to copy from + List avatarIds = new ArrayList<>(team.getAvatars()); + + // Clear current avatar list first + this.getAvatars().clear(); + + // Copy from team + int len = Math.min(avatarIds.size(), maxTeamSize); + for (int i = 0; i < len; i++) { + int id = avatarIds.get(i); + this.getAvatars().add(id); + } + } + + public AvatarTeam toProto(Player player) { + AvatarTeam.Builder avatarTeam = AvatarTeam.newBuilder().setTeamName(this.getName()); + + for (int i = 0; i < this.getAvatars().size(); i++) { + Avatar avatar = player.getAvatars().getAvatarById(this.getAvatars().get(i)); + avatarTeam.addAvatarGuidList(avatar.getGuid()); + } + + return avatarTeam.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index 111478e18..009958e7d 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -131,6 +131,30 @@ public final class TeamManager extends BasePlayerDataManager { return avatars; } + /** + * Returns the active team. + * If there are errors with the team, they can be fixed. + * + * @param fix If true, the team will be fixed. + * @return The active team. + */ + public List getActiveTeam(boolean fix) { + if (!fix) return this.getActiveTeam(); + + // Remove duplicate avatars. + var avatars = this.getActiveTeam(); + var avatarIds = new HashSet(); + for (var entityAvatar : new ArrayList<>(avatars)) { + if (avatarIds.contains(entityAvatar.getAvatar().getGuid())) { + avatars.remove(entityAvatar); + } else { + avatarIds.add(entityAvatar.getAvatar().getGuid()); + } + } + + return avatars; // Return the fixed team. + } + public EntityAvatar getCurrentAvatarEntity() { if (this.currentCharacterIndex >= this.getActiveTeam().size()) { this.currentCharacterIndex = 0; // Reset to the first character. @@ -557,8 +581,6 @@ public final class TeamManager extends BasePlayerDataManager { } else { // Restores all avatars from the player's avatar storage. // If the avatar is already in the team, it will not be added. - // TODO: Fix order in which avatars are added. - // Currently, they are added from last to first. var avatars = this.getCurrentTeamInfo().getAvatars(); for (var index = 0; index < avatars.size(); index++) { var avatar = avatars.get(index); @@ -804,7 +826,7 @@ public final class TeamManager extends BasePlayerDataManager { // return; // } // } - player + this.getPlayer() .getStaminaManager() .stopSustainedStaminaHandler(); // prevent drowning immediately after respawn @@ -813,7 +835,7 @@ public final class TeamManager extends BasePlayerDataManager { entity.setFightProperty( FightProperty.FIGHT_PROP_CUR_HP, entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .4f); - player.getSatiationManager().removeSatiationDirectly(entity.getAvatar(), 15000); + this.getPlayer().getSatiationManager().removeSatiationDirectly(entity.getAvatar(), 15000); this.getPlayer() .sendPacket( new PacketAvatarFightPropUpdateNotify( @@ -829,10 +851,10 @@ public final class TeamManager extends BasePlayerDataManager { this.getPlayer(), EnterType.ENTER_TYPE_SELF, EnterReason.Revival, - player.getSceneId(), - getRespawnPosition())); - player.getPosition().set(getRespawnPosition()); - } catch (Exception e) { + this.getPlayer().getSceneId(), + this.getRespawnPosition())); + this.getPlayer().getPosition().set(this.getRespawnPosition()); + } catch (Exception ignored) { this.getPlayer() .sendPacket( new PacketPlayerEnterSceneNotify( @@ -841,7 +863,7 @@ public final class TeamManager extends BasePlayerDataManager { EnterReason.Revival, 3, GameConstants.START_POSITION)); - player + this.getPlayer() .getPosition() .set(GameConstants.START_POSITION); // If something goes wrong, the resurrection is here } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java index 198f5a46d..de6a8006e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTeamUpdateNotify.java @@ -8,7 +8,6 @@ import emu.grasscutter.net.proto.SceneTeamAvatarOuterClass.SceneTeamAvatar; import emu.grasscutter.net.proto.SceneTeamUpdateNotifyOuterClass.SceneTeamUpdateNotify; public class PacketSceneTeamUpdateNotify extends BasePacket { - public PacketSceneTeamUpdateNotify(Player player) { super(PacketOpcodes.SceneTeamUpdateNotify); @@ -16,7 +15,7 @@ public class PacketSceneTeamUpdateNotify extends BasePacket { .setIsInMp(player.getWorld().isMultiplayer()); for (var p : player.getWorld().getPlayers()) { - for (var entityAvatar : p.getTeamManager().getActiveTeam()) { + for (var entityAvatar : p.getTeamManager().getActiveTeam(true)) { var avatarProto = SceneTeamAvatar.newBuilder() .setPlayerUid(p.getUid())