游戏跨服开发笔记

服务器管理入口


@Component
@SocketClass
public class ServerFacade {

    // 所有游戏服连接时,合服事件
    @ReceiverAnno
    public void onAllGameServerConnected(EventMergeServer  eventMergeServer) {
        serverGroupManager.mergeServerExitGroup(eventMergeServer.getGameServer(), eventMergeServer.getChildServerIds());
    }

    // 所有游戏服连接时,所有游戏服连接事件
    @ReceiverAnno
    public void onAllGameServerConnected() {
        serverGroupManager.forceRefresh();
    }

    // 注册
    @SocketMethod
    public void register(Wsession wsessoin, G2cGameServerRegister g2cGameServerRegister) {
        gameServerManager.register(wsession, g2cGameServerRegister);
    }

    // 游戏服心跳事件
    @SocketMethod
    public void register(GameSerever gameServer, G2cGameServerRegist g2cGameServerHeartbeat) {
         gameServerManager.register(wsession,  g2cGameServerHeartbeat);
    }
    // 战斗服心跳事件
    @SocketMethod
    public void transferHeartbeat(Wsession wsession, T2cTeansferHeartbeat) {
        transferServerManger.heartbeat(wsession, heartbeat);
    }
    // 接受分组参数
    @SocketMethod
    public void receiveGroupParam(GameServer gameServer, G2cGroupParamUpload paramUpload) {
        serverGroupManager.uploadGroupParam(gameServer, paramUpload);
    }
    // 重新分组
    @SocketMethod
    public void reServerGroup(GameServer gameServer, G2cCommandReServerGroup commandReServerGroup) {
        serverGroupManager.commandReGroup();
    }
    // 接受分组
    @SocketMethod
    public void assignServerGroup(GameServer gameServer, G2cCommandAssignServerGroupResp cCommandAssignServerGroupResp) {
        serverGroupManager.commandAssignGroup(gameServer.getEntity(), cCommandAssignServerGroupResp.getGroupType());
    }

}



// 游戏服 - 跨服处理相关入口
//  注意:Wsession不是玩家会话,是游戏服与中心服的会话

```java
@Componet
@SocketClass
public class GameServerFacade {

    // 开服连接
    @ReceiverAnno
    public void onGameServerOpen(ServerOpenEvent event) {
        if(serverManager.getOpenDay().isOpen()) {
            centerManager.connect();
        }
    }

    // 开服了,注册到中心服
    @ReceiverAnno
    public void onServerDayBegin(ServerDayBeginEvent event) {
        centerManager.connect();
    }

    // 连接成功了,尝试注册,如果这时候服务器未达成开服条件,不注册
    @ReceiverAnno
    public void onConnerctCenter(EventCenterC) {
        if(ServerType.isGameServer()) {
            gameServerService.tryRegisterGameServer2Center();
        }
    }

    // 玩家断开连接,检测是否需要退出跨服
    @ReceiverAnno
    public void onPlayerLogout(LogoutEvent event) {
        Player player = event.getPlayer();
        gameServerService.onPlayerOffine(player);
    }

    // 收到门票,开始前往跨服
    @SocketMethod
    public void receiverTicketFormCenter() {
        gamServerService.beginEnter(ticketResp.getPlayerId(), ticketResp.getTransferIp(),
        ticketResp.getTransferPort(), ticketResp.getTicket());
    }

    // 确认退出跨服
    @SocketMethod
    public void confirmExitTransfer(Player player, T2gTransferExitConfirmResp resp) {
        gameServerService.exitTransferConfirm(player, resp);
    }

    // 中心服发送给玩家的通知信息
    @SocketMethod
    public void sendMessage(Wsession wsession, C2GMessagePacket, c2GMessagePacket) {
        gameServerService.sendMessagePacket(c2GMessagePacket);
    }

    // 确认进入跨服
    @SocketMethod
    public void enterTransfer(Player player, T2gTransferEnteredResp resp) {
        player.submitEvent(TeansgerEnteredEvent.valueOf(resp.getTransferType()));
    }

    // 收到中心返回的所有跨服地图门票信息
    // 中心服会在启动完成初始化之后,主动推送到游戏服
    @SocketMethod
    public void receiveTransportTicketFromCenter(Wsesion wsession, C2gTransportTicketsResp c2TransportTicketsResp) {

    }

    // 收到中心服返回的分组信息
    @SocketMethod
    public void receiveServerGroupInfoFromCneter(Wsession wsession, C2gServerGroupType2ServerIds c2gServerGroupType2ServerIds) {

    }

    // 收到战斗服回传的玩家事件
    @SocketMethod(coustomPacketId = CrossPacketId.GLOBAL_EVENT_RESP)
    @IRunInNioThread
    public void transferPlayerEvent(Wsession wsession, IEvent eventPacket) {
        // 异步提交事件
        String simpleName = eventPacket.getClass().getSimpleName();
        EventBusManager.getInstance().sumbmit(eventPacket, "globalEvent_"+SimpleName, simpleName.hashCode());
    }

    // 跨服发奖
    @SocketMethod
    public void gainReward(Player player, T2gGainRewardResp t2gGainRewardResp) {
        palyer.gainReward(t2gGainRewardResp.getReward(), t2gGainRewardResp.getModuleInfo());
    }

    // 战斗服 -> 游戏服 跨服事务
    @SocketMethod
    public T2gTransactionResp transaction(Player player, T2gTransactioReq) {

    }

    // 分组销毁
    @SocketMethod
    public void receiveServerGroupDestroy(Wsession wsession, C2gTicketsDetroyPacket c2gTicketsDestroyPacket) {
        centerManger.onServerGroupDestroy(c2gTicketDestroyPacket.getServerGroupType());
    }
}



服务器管理逻辑处理

跨服类型

    @Desc("跨服3V3")
    transfer_t3v3,
    @Desc("跨服地图")
    transfer_land,
    @Desc("跨服灭神塔")
    transfer_godKillTower,
    @Desc("跨服灭神塔全服")
    transfer_godKillTowerServer,
    @Desc("跨服沙巴克")
    shabake,

    // ...

服务器分组类型

@Desc("服务器哦分组类型")
public enum ServerGroupType {
    @Desc("3v3")
    t3v3(false, false),
    @Desc("第四大陆")
    land4(true, true),
    @Desc("第五大陆")
    land5(true, true),
    @Desc("公会秘境争霸")
    secretArea(false,false)


    // 该战区是否预分配战斗服
    private boolean groupOnServerOpen;

    // 预分配战斗服之后,是否通知战斗服,检测该战区下面的地图是否需要预创建地图, ps:只判断是否发送检测通知
    // 具体某一张地图是否预创建,是检测地图配置MapType枚举里面的initTrandferMap字段
    private boolean initMapAfterGroupTransfer;
}

跨服门票

@ProtobufClass
public class Ticket {
    @Protobuf(description = "跨服类型")
    private TransferType type;
    @Protobuf(description = "门票id,同一")
    private long ticketId;
     @Protobuf(description = "分组类型(战区)")
    private ServerGroupType groupType;
     @Protobuf(description = "组号")
    private int groupIndex;

    // 其他额外信息

    @Protobuf(description = "阵营类型")
    private CampType campType;
    @Protobuf(description = "前往的跨服地图ID")
    private int mapId;
    @Protobuf(description = "x")
    private int x;
    @Protobuf(description = "y")
    private int y;

    // 创建一张门票 ...

}


中心服通用业务处理

@Component
public class CenterManager {
    // ...

    // 创建一个唯一的门票id
    public long createTicketId() {
        return idGen.getAndIncrement();
    }
1
    // 发送门票到游戏服
    public void sendTicket(TransferType transferType, long playerId, int gameServerId, TransferServer transferServer, Ticket ticket) {
        GameServer gameServer = gameServerManager.getSreverIfRegister(gameServerId);
        if(gameServer == null) {
            return;
        }
        C2gTransferTicketResp resp = C2gTransferTicketResp.valueOf(
            transferServer.getIp(),
            transferServer.getPort(),
            playerId,
            ticket
        );
        // 通知游戏服
        gameServer.send(resp);
    }
}