Fix double adding of avatar entities

This commit is contained in:
KingRainbow44
2023-04-30 20:58:31 -04:00
parent 3f51db47c4
commit d01ba08f26
3 changed files with 127 additions and 106 deletions

View File

@@ -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<Integer> avatars;
public TeamInfo() {
this.name = "";
this.avatars = new ArrayList<>(GAME_OPTIONS.avatarLimits.singlePlayerTeam);
}
public TeamInfo(List<Integer> avatars) {
this.name = "";
this.avatars = avatars;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Integer> 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<Integer> 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<Integer> avatars;
public TeamInfo() {
this.name = "";
this.avatars = new ArrayList<>(GAME_OPTIONS.avatarLimits.singlePlayerTeam);
}
public TeamInfo(List<Integer> avatars) {
this.name = "";
this.avatars = avatars;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Integer> 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<Integer> 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();
}
}

View File

@@ -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<EntityAvatar> getActiveTeam(boolean fix) {
if (!fix) return this.getActiveTeam();
// Remove duplicate avatars.
var avatars = this.getActiveTeam();
var avatarIds = new HashSet<Long>();
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
}

View File

@@ -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())