Skip to content

Commit

Permalink
Custom Teams (Grasscutters#1731)
Browse files Browse the repository at this point in the history
* Add support for creating and deleting custom teams.

* Add support for creating and deleting custom teams.

* Move some logic to TeamInfo::toProto
  • Loading branch information
GanyusLeftHorn authored Sep 1, 2022
1 parent 4f015c1 commit 712d176
Show file tree
Hide file tree
Showing 17 changed files with 3,678 additions and 125 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/main/java/emu/grasscutter/GameConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
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);
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/emu/grasscutter/game/player/TeamInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import dev.morphia.annotations.Entity;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam;

@Entity
public class TeamInfo {
Expand Down Expand Up @@ -81,4 +82,16 @@ public void copyFrom(TeamInfo team, int maxTeamSize) {
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();
}
}
50 changes: 46 additions & 4 deletions src/main/java/emu/grasscutter/game/player/TeamManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,20 @@
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;
Expand All @@ -44,7 +47,8 @@

@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;

Expand All @@ -70,9 +74,9 @@ public TeamManager(Player player) {
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());
}
}
Expand Down Expand Up @@ -640,4 +644,42 @@ public void saveAvatars() {
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));
}
}
10 changes: 5 additions & 5 deletions src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -1807,17 +1807,17 @@ 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;
public static final int Unk3000_JIMGCFDPFCK = 20754;
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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,16 @@ public PacketAvatarDataNotify(Player player) {
proto.addAvatarList(avatar.toProto());
}

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());
// Add the id list for custom teams.
for (int id : player.getTeamManager().getTeams().keySet()) {
if (id > 4) {
proto.addCustomTeamIds(id);
}
}

proto.putAvatarTeamMap(entry.getKey(), avatarTeam.build());
for (Entry<Integer, TeamInfo> entry : player.getTeamManager().getTeams().entrySet()) {
TeamInfo teamInfo = entry.getValue();
proto.putAvatarTeamMap(entry.getKey(), teamInfo.toProto(player));
}

// Set main character
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@ public PacketAvatarTeamUpdateNotify(Player player) {

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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit 712d176

Please sign in to comment.