Player#
见于 src/server/user 。需要动态创建和释放。生命周期受Room限制。
Player持有 unique_ptr<Router> ,间接持有 shared_ptr<ClientSocket> 。
对象创建者#
对象通过 std::make_shared 创建,创建者:
UserManager:当一个ClientSocket通过认证后,为其创建一个Player管理其时
UserManager:创建机器人时
Room:玩家逃跑时,创建新Player用来接管逃跑玩家的ClientSocket时
对象管理者#
由UserManager中两个 std::unordered_map<int, std::shared_ptr<Player>> 管理。
不需要时,通过 UserManager::deletePlayer 释放。
基于UserManager中的方法从id查询Player时均返回weak_ptr,但要注意lock后会创建新shared_ptr。
使用场景#
作为ClientSocket的包装,进行服务端客户端之间的数据传输。
提供了管理连接状态的接口(踢出玩家)
当socket状态异常时,修改自己的连接状态
释放时机#
不被Lua需要,且也没有需要自己管理的ClientSocket时。
不被Lua需要:处于大厅;处于不被Lua需要的房间;是个旁观者
不存在受管理的ClientSocket:本来就不管理socket(人机),或者因掉线导致socket被设为nullptr。
例外的时,若人机玩家处于创建了自己的房间,则暂时不受这两条约束,释放条件改为:
当游戏开始后,顺应以上两点约束
即将进入大厅时(被踢出房间)
实现详情#
掉线#
从网络编程的角度考虑,当TCP连接断开时,需要回收socket的资源。 Player作为Socket的封装,其释放的时机基本上就是断线时。 为了便于思考,将逃跑也并入掉线中(逃跑的话会把原玩家的socket移动到新创建的玩家, 原玩家改为走人机的逻辑,可以认为是掉线的情况之一)。
当掉线时,第一件事是把socket设为nullptr,这样必定满足不存在受自己管理的ClientSocket。
然后,若不被Lua需要:
从所处房内删除
释放
否则:
将网络状态改为断线
试图唤醒Lua,提示玩家掉线
网络状态变更#
需要告诉房间其他玩家自己的网络状态变了,此外需要告诉Lua。
考虑到掉线本身也唤醒Lua,因此向Lua通知网络异常必须发生在实际唤醒之前。
断线重连当然也是变更。其代码基本上满足这两点。
待处理
由于pushRequest的异步性,存在在Lua游戏结束时触发重连的极端情况,此时C++中玩家的
socket已经正常所以不会释放,但是Lua的 ServerPlayer:reconnect 触发不了,
导致重连玩家的客户端不断转圈圈。修复应该不难。
待处理
上面对重连的叙述也适用于旁观。