-
Notifications
You must be signed in to change notification settings - Fork 12
GameServer
crazyjohn edited this page Jan 14, 2016
·
5 revisions
如何用stupidbird写一个游戏服务器
- Facada门面/入口代码
/**
* 游戏服;
*
* @author crazyjohn
*
*/
public class GameServer {
static Logger logger = LoggerFactory.getLogger("Server");
/**
* 入口
*
* @param args
* @throws Exception
*/
public static void main(String[] args) {
try {
GameServerConfig config = ConfigUtil.loadConfig(GameServerConfig.class, "game_server.cfg.js");
Node node = new Commander();
// 加载配置
node.configure(config);
// 全局模块初始化
Injector globalInjector = Guice.createInjector(new GlobalModules(config, node));
// io处理器
GameIoHandler ioHandler = globalInjector.getInstance(GameIoHandler.class);
node.setIoHandler(ioHandler);
// 设置注入器
ioHandler.setGlobalInjector(globalInjector);
// 启动
node.startup();
// dump
logger.info("Dump executor info: " + node.executor().dump());
} catch (Exception e) {
GameMonitor.catchException(e);
System.exit(0);
}
}
}
- 整体结构
- 切入点
游戏Io处理器
public class GameIoHandler extends NodeIoHandler<PlayerSession> {
@Inject
private EntityDBService dbService;
@Inject
private UUIDGenerator uuidService;
private Injector globalInjector;
@Inject
public GameIoHandler(NodeDispatcher dispatcher) {
super(dispatcher);
}
@Override
protected SessionMessage<PlayerSession> createSessionOpenMessage(PlayerSession sessionInfo) {
Open msg = new Open();
msg.setSession(sessionInfo);
return msg;
}
@Override
protected SessionMessage<PlayerSession> createSessionCloseMessage(PlayerSession sessionInfo) {
Close msg = new Close();
msg.setSession(sessionInfo);
return msg;
}
@Override
protected PlayerSession createSessionInfo(IoSession session) {
PlayerSession sessionInfo = new PlayerSession(session, dbService, uuidService, globalInjector);
return sessionInfo;
}
public void setGlobalInjector(Injector injector) {
this.globalInjector = injector;
}
}
在网络会话创建的时候创建一个PlayerSession
,再看看玩家会话的内部:
public class PlayerSession extends NodeBindableSession<Player> {
private final Player player;
public PlayerSession(IoSession session, EntityDBService dbService, UUIDGenerator uuidService,
Injector globalInjector) {
super(session);
// 构建玩家对象
player = new Player(this, dbService, uuidService, globalInjector);
}
@Override
public Player object() {
return player;
}
@Override
public String toString() {
return this.session.toString();
}
}
内部注入了Player
玩家对象,以此展开业务。
- 玩家业务模块结构
HumanModule
- 全局管理器结构
ManagerActor
- 数据层交互
Save机制
引擎开发到2016.1.6这天,我准备在其中加入di的东西。其实之前在生产中用过类似的东西,用的是spring来托管,但是进入上线后期发现spring在di这里的效率堪忧,所以去掉了大部分依赖,说以可以说之前对di是一次不愉快的使用(其实很大程度源于时间问题以及对spring di的不了解)。
这次我准备使用guice作为di驱动。原因是看了一个项目使用这个还挺简单方便的,而且据说它的效率是spring的100倍。而且主要这里的思路是源于业务层的架构:
-
业务层有Module模块的概念,用来管理玩家指定模块的数据。
-
模块之前的交互通过对对指定模块抽象出交互接口。
/** * 玩家物品模块; * * @author crazyjohn * */ public class HumanItemModule extends BaseHumanModule implements ItemModule { protected List<HumanItemEntity> items = new ArrayList<HumanItemEntity>(); @Inject protected EquipModule itemModule; private Logger logger = LoggerFactory.getLogger("Action"); @Inject public HumanItemModule(Human human) { super(human); } @Override public void onLogin(HumanEntity entity) { items = entity.getItems(); }
如上,物品模块和装备模块交互的时候,通过注入EquipFronter
接口来实现。
public interface EquipFronter {
public void addEquip(HumanEquipEntity equipEntity);
}
- 通过guice来进行方便的di注入管理。
- 以上就是整体的思路,或许后面发现有问题(效率?),还会再次去掉。
- 目前不爽的地方就是guice尼玛还需要引入javax.inject和aopalliance这两个包,让整体体积又变大了。