mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-15 16:34:56 +01:00
Custom Teams (#1731)
* Add support for creating and deleting custom teams. * Add support for creating and deleting custom teams. * Move some logic to TeamInfo::toProto
This commit is contained in:
@@ -8,7 +8,8 @@ import emu.grasscutter.utils.Utils;
|
||||
public final class GameConstants {
|
||||
public static String VERSION = "3.0.0";
|
||||
|
||||
public static final int MAX_TEAMS = 4;
|
||||
public static final int DEFAULT_TEAMS = 4;
|
||||
public static final int MAX_TEAMS = 10;
|
||||
public static final int MAIN_CHARACTER_MALE = 10000005;
|
||||
public static final int MAIN_CHARACTER_FEMALE = 10000007;
|
||||
public static final Position START_POSITION = new Position(2747, 194, -1719);
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam;
|
||||
|
||||
@Entity
|
||||
public class TeamInfo {
|
||||
@@ -81,4 +82,16 @@ public class TeamInfo {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,20 @@ import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
|
||||
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
|
||||
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType;
|
||||
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
|
||||
import emu.grasscutter.server.event.player.PlayerTeamDeathEvent;
|
||||
import emu.grasscutter.server.packet.send.PacketAddCustomTeamRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarDieAnimationEndRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarSkillInfoNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarTeamUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketChangeAvatarRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketChangeTeamNameRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketChooseCurAvatarTeamRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketCustomTeamListNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketRemoveCustomTeamRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneTeamUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSetUpAvatarTeamRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketWorldPlayerDieNotify;
|
||||
@@ -44,7 +47,8 @@ import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
public class TeamManager extends BasePlayerDataManager {
|
||||
@Getter private Map<Integer, TeamInfo> teams;
|
||||
// This needs to be a LinkedHashMap to guarantee insertion order.
|
||||
@Getter private LinkedHashMap<Integer, TeamInfo> teams;
|
||||
private int currentTeamIndex;
|
||||
@Getter @Setter private int currentCharacterIndex;
|
||||
|
||||
@@ -70,9 +74,9 @@ public class TeamManager extends BasePlayerDataManager {
|
||||
this();
|
||||
this.setPlayer(player);
|
||||
|
||||
this.teams = new HashMap<>();
|
||||
this.teams = new LinkedHashMap<>();
|
||||
this.currentTeamIndex = 1;
|
||||
for (int i = 1; i <= GameConstants.MAX_TEAMS; i++) {
|
||||
for (int i = 1; i <= GameConstants.DEFAULT_TEAMS; i++) {
|
||||
this.teams.put(i, new TeamInfo());
|
||||
}
|
||||
}
|
||||
@@ -640,4 +644,42 @@ public class TeamManager extends BasePlayerDataManager {
|
||||
public void onPlayerLogin() { // Hack for now to fix resonances on login
|
||||
this.updateTeamResonances();
|
||||
}
|
||||
|
||||
public synchronized void addNewCustomTeam() {
|
||||
// Sanity check - max number of teams.
|
||||
if (this.teams.size() == GameConstants.MAX_TEAMS) {
|
||||
player.sendPacket(new PacketAddCustomTeamRsp(Retcode.RET_FAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
// The id of the new custom team is the lowest id in [5,MAX_TEAMS] that is not yet taken.
|
||||
int id = -1;
|
||||
for (int i = 5; i <= GameConstants.MAX_TEAMS; i++) {
|
||||
if (!this.teams.keySet().contains(i)) {
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the new team.
|
||||
this.teams.put(id, new TeamInfo());
|
||||
|
||||
// Send packets.
|
||||
player.sendPacket(new PacketCustomTeamListNotify(player));
|
||||
player.sendPacket(new PacketAddCustomTeamRsp());
|
||||
}
|
||||
|
||||
public synchronized void removeCustomTeam(int id) {
|
||||
// Check if the target id exists.
|
||||
if (!this.teams.containsKey(id)) {
|
||||
player.sendPacket(new PacketRemoveCustomTeamRsp(Retcode.RET_FAIL, id));
|
||||
}
|
||||
|
||||
// Remove team.
|
||||
this.teams.remove(id);
|
||||
|
||||
// Send packets.
|
||||
player.sendPacket(new PacketCustomTeamListNotify(player));
|
||||
player.sendPacket(new PacketRemoveCustomTeamRsp(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1784,9 +1784,9 @@ public class PacketOpcodes {
|
||||
public static final int Unk3000_CPCMICDDBCH = 20011;
|
||||
public static final int Unk3000_DCAHJINNNDM = 23107;
|
||||
public static final int Unk3000_DCLAGIJJEHB = 402;
|
||||
public static final int Unk3000_DFIIBIGPHGE = 1731;
|
||||
public static final int RemoveCustomTeamReq = 1731;
|
||||
public static final int Unk3000_DHEOMDCCMMC = 429;
|
||||
public static final int Unk3000_DHOFMKPKFMF = 1749;
|
||||
public static final int CustomTeamListNotify = 1749;
|
||||
public static final int Unk3000_DJNBNBMIECP = 5588;
|
||||
public static final int Unk3000_DLCDJPKNGBD = 185;
|
||||
public static final int Unk3000_DPEJONKFONL = 21750;
|
||||
@@ -1807,9 +1807,9 @@ public class PacketOpcodes {
|
||||
public static final int Unk3000_HIJKNFBBCFC = 23948;
|
||||
public static final int Unk3000_HPFGNOIGNAG = 21961;
|
||||
public static final int Unk3000_IBMFJMGHCNC = 6060;
|
||||
public static final int Unk3000_IBNIGBFIEEF = 1735;
|
||||
public static final int AddCustomTeamRsp = 1735;
|
||||
public static final int Unk3000_IGCECHKNKOO = 21804;
|
||||
public static final int Unk3000_IMLAPBGLBFF = 1687;
|
||||
public static final int AddCustomTeamReq = 1687;
|
||||
public static final int Unk3000_IPAKLDNKDAO = 6275;
|
||||
public static final int Unk3000_JDCOHPBDPED = 125;
|
||||
public static final int Unk3000_JIEPEGAHDNH = 24152;
|
||||
@@ -1817,7 +1817,7 @@ public class PacketOpcodes {
|
||||
public static final int Unk3000_KEJGDDMMBLP = 6376;
|
||||
public static final int Unk3000_KGDKKLOOIPG = 457;
|
||||
public static final int Unk3000_KHFMBKILMMD = 24081;
|
||||
public static final int Unk3000_KIDDGDPKBEN = 1729;
|
||||
public static final int RemoveCustomTeamRsp = 1729;
|
||||
public static final int Unk3000_KJNIKBPKAED = 461;
|
||||
public static final int Unk3000_KKHPGFINACH = 24602;
|
||||
public static final int Unk3000_KOKEHAPLNHF = 6190;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
|
||||
@Opcodes(PacketOpcodes.AddCustomTeamReq)
|
||||
public class HandlerAddCustomTeamReq extends PacketHandler {
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
session.getPlayer().getTeamManager().addNewCustomTeam();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.RemoveCustomTeamReqOuterClass.RemoveCustomTeamReq;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
|
||||
@Opcodes(PacketOpcodes.RemoveCustomTeamReq)
|
||||
public class HandlerRemoveCustomTeamReq extends PacketHandler {
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
RemoveCustomTeamReq req = RemoveCustomTeamReq.parseFrom(payload);
|
||||
session.getPlayer().getTeamManager().removeCustomTeam(req.getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
|
||||
import emu.grasscutter.net.proto.AddCustomTeamRspOuterClass.AddCustomTeamRsp;
|
||||
|
||||
public class PacketAddCustomTeamRsp extends BasePacket {
|
||||
public PacketAddCustomTeamRsp(Retcode retcode) {
|
||||
super(PacketOpcodes.AddCustomTeamRsp);
|
||||
|
||||
AddCustomTeamRsp proto = AddCustomTeamRsp.newBuilder()
|
||||
.setRetcode(retcode.getNumber())
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
|
||||
public PacketAddCustomTeamRsp() {
|
||||
this(Retcode.RET_SUCC);
|
||||
}
|
||||
}
|
||||
@@ -25,17 +25,16 @@ public class PacketAvatarDataNotify extends BasePacket {
|
||||
proto.addAvatarList(avatar.toProto());
|
||||
}
|
||||
|
||||
// Add the id list for custom teams.
|
||||
for (int id : player.getTeamManager().getTeams().keySet()) {
|
||||
if (id > 4) {
|
||||
proto.addCustomTeamIds(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<Integer, TeamInfo> entry : player.getTeamManager().getTeams().entrySet()) {
|
||||
TeamInfo teamInfo = entry.getValue();
|
||||
AvatarTeam.Builder avatarTeam = AvatarTeam.newBuilder()
|
||||
.setTeamName(teamInfo.getName());
|
||||
|
||||
for (int i = 0; i < teamInfo.getAvatars().size(); i++) {
|
||||
Avatar avatar = player.getAvatars().getAvatarById(teamInfo.getAvatars().get(i));
|
||||
avatarTeam.addAvatarGuidList(avatar.getGuid());
|
||||
}
|
||||
|
||||
proto.putAvatarTeamMap(entry.getKey(), avatarTeam.build());
|
||||
proto.putAvatarTeamMap(entry.getKey(), teamInfo.toProto(player));
|
||||
}
|
||||
|
||||
// Set main character
|
||||
|
||||
@@ -19,15 +19,7 @@ public class PacketAvatarTeamUpdateNotify extends BasePacket {
|
||||
|
||||
for (Entry<Integer, TeamInfo> entry : player.getTeamManager().getTeams().entrySet()) {
|
||||
TeamInfo teamInfo = entry.getValue();
|
||||
AvatarTeam.Builder avatarTeam = AvatarTeam.newBuilder()
|
||||
.setTeamName(teamInfo.getName());
|
||||
|
||||
for (int i = 0; i < teamInfo.getAvatars().size(); i++) {
|
||||
Avatar avatar = player.getAvatars().getAvatarById(teamInfo.getAvatars().get(i));
|
||||
avatarTeam.addAvatarGuidList(avatar.getGuid());
|
||||
}
|
||||
|
||||
proto.putAvatarTeamMap(entry.getKey(), avatarTeam.build());
|
||||
proto.putAvatarTeamMap(entry.getKey(), teamInfo.toProto(player));
|
||||
}
|
||||
|
||||
this.setData(proto);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.player.TeamInfo;
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam;
|
||||
import emu.grasscutter.net.proto.CustomTeamListNotifyOuterClass.CustomTeamListNotify;
|
||||
|
||||
public class PacketCustomTeamListNotify extends BasePacket {
|
||||
public PacketCustomTeamListNotify(Player player) {
|
||||
super(PacketOpcodes.CustomTeamListNotify);
|
||||
|
||||
CustomTeamListNotify.Builder proto = CustomTeamListNotify.newBuilder();
|
||||
|
||||
// Add the id list for custom teams.
|
||||
for (int id : player.getTeamManager().getTeams().keySet()) {
|
||||
if (id > 4) {
|
||||
proto.addCustomTeamIds(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the avatar lists for all the teams the player has.
|
||||
for (Entry<Integer, TeamInfo> entry : player.getTeamManager().getTeams().entrySet()) {
|
||||
TeamInfo teamInfo = entry.getValue();
|
||||
proto.putAvatarTeamMap(entry.getKey(), teamInfo.toProto(player));
|
||||
}
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
|
||||
import emu.grasscutter.net.proto.RemoveCustomTeamRspOuterClass.RemoveCustomTeamRsp;
|
||||
|
||||
public class PacketRemoveCustomTeamRsp extends BasePacket {
|
||||
public PacketRemoveCustomTeamRsp(Retcode retcode, int id) {
|
||||
super(PacketOpcodes.RemoveCustomTeamRsp);
|
||||
|
||||
RemoveCustomTeamRsp proto = RemoveCustomTeamRsp.newBuilder()
|
||||
.setRetcode(retcode.getNumber())
|
||||
.setId(id)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
|
||||
public PacketRemoveCustomTeamRsp(int id) {
|
||||
this(Retcode.RET_SUCC, id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user