处理
Proxy Server处理与传递消息到其他服务器的客户端的通信。代理服务器由atavism.server.plugins.ProxyPlugin类实现。
当代理服务器从客户端获取登录请求消息(消息ID 1)时,它:
- 在atavism.server.plugins.PlayerManager类中添加一个条目以跟踪玩家。
- 调用ObjectManagerPlugin从数据库加载玩家对象。播放器的子对象状态由相关插件加载。
- 向客户端返回登录“成功”或“失败”指示。 (LoginResponse消息ID 4)。 从WorldManager请求地形信息并将其传递给客户端。
- 请求有关玩家对象的基本信息,例如名称,位置,方向,比例和对象类型。将此信息中继到客户端。 (NewObjectMessage ID 8)。
- 请求从WorldManagerPlugin显示(预制),并中继到客户端。
- 将玩家添加到代理的PerceptionFilter
- 通过WorldManagerPlugin将玩家发布到世界各地。
- 发送updateObject消息,要求其他插件通过任何相关信息发送。 (例如,动画插件将发送玩家的当前动画)。
剩下的大部分工作都是将玩家带入世界的副作用。世界经理确定玩家可以感知哪些对象并生成PerceptionMessage。这包括基本对象信息,例如位置和显示上下文。对于每个可感知对象,代理发送updateObject消息以从其他插件收集信息。来自世界经理和其他插件的信息由代理收集并转发给客户端。
脚本
除了脚本和文件之外,它还会读取消息传递配置,它会读取以下脚本:
- atavism_server/bin/proxy.py
- atavism_server/config/common/events.py
- atavism_server/config/common/proxy.py
- atavism_server/config/world/extensions_proxy.py
一般配置
代理服务器配置了来自proxy.py的设置。使用以下语句设置服务器ID。
Engine.setServerID( server_id );
服务器ID在代理服务器和世界服务器中必须是唯一的。设置世界ID和端口号,如下所示,其中值是与先前定义的世界ID和端口匹配的整数。
Engine.setWorldID( world_id ); Engine.setPort( portNumber );
以下设置控制代理服务器的一般行为:Engine.setNetworkThrottle() – 指定允许未完成的未确认数据包的数量。 Engine.EventServerThreadPoolSize – 必须始终为一(1)。您可以定义多个世界服务器。定义每个世界服务器如下:
wsMgr = Engine.getWSManager(); wsMgr.addWorldServer(new WorldServer("localhost", 5090, 0));
如果世界服务器在其他主机上运行,请将“localhost”替换为主机名。为每个世界服务器指定不同的端口。
消息
登录和登出消息
代理服务器在玩家登录时发送登录消息,在玩家注销时发送登出消息。它使用广播RPC发送消息,因此所有订户都必须响应。代理服务器在继续登录或注销之前等待所有响应。代理服务器在加载播放器对象之后但在产生之前发送登录消息。
- 消息类:atavism.server.messages.LoginMessage。该消息是以玩家OID为主题的SubjectMessage。该消息还包含玩家名称和玩家将生成的instanceOid。
- 消息类型:LoginMessage.MSG_TYPE_LOGIN
代理服务器在发送玩家之后但在卸载之前发送登出消息。
- 消息类:atavism.server.messages.LogoutMessage。该消息是以玩家OID为主题的SubjectMessage。该消息还包含玩家名称。 消息类型:LogoutMessage.MSG_TYPE_LOGOUT
例如:
// Hooks to process login/logout messages getHookManager().addHook(LoginMessage.MSG_TYPE_LOGIN, new LoginHook()); getHookManager().addHook(LogoutMessage.MSG_TYPE_LOGOUT, new LogoutHook());
// Create responder subscription MessageTypeFilter filter = new MessageTypeFilter(); filter.addType(LoginMessage.MSG_TYPE_LOGIN); filter.addType(LogoutMessage.MSG_TYPE_LOGOUT); Engine.getAgent().createSubscription(filter, this, MessageAgent.RESPONDER);
// Log the login information and send a response class LoginHook implements Hook { public boolean processMessage(Message msg, int flags) { LoginMessage message = (LoginMessage) msg; Long playerOid = message.getSubject(); Long instanceOid = message.getInstanceOid(); Log.debug("LoginHook: playerOid=" + playerOid + " instanceOid=" + instanceOid); // Do something Engine.getAgent().sendResponse(new ResponseMessage(message)); return true; } }
// Log the logout information and send a response class LogoutHook implements Hook { public boolean processMessage(Message msg, int flags) { LogoutMessage message = (LogoutMessage) msg; Long playerOid = message.getSubject(); Log.debug("LogoutHook: playerOid=" + playerOid); // Do something Engine.getAgent().sendResponse(new ResponseMessage(message)); return true; } }
代理扩展挂钩
代理服务器包括为来自客户端的扩展消息注册处理程序的机制。注册扩展消息子类型的处理程序,以使代理服务器在从客户端接收到具有该子类型的扩展消息时运行处理函数。
编写代理扩展钩子
代理扩展钩子实现接口atavism.server.objects.ProxyExtensionHook。该接口具有代理调用以处理扩展消息的单个方法。该方法接收atavism.server.events.ExtensionMessageEvent和atavism.server.objects.Player对象。客户端设置的属性可从ExtensionMessageEvent获得。你可以通过player.getOid()获得玩家oid。
public class MyProxyHook implements ProxyExtensionHook { public void processExtensionEvent(ExtensionMessageEvent event, Player player, ProxyPlugin proxy) { Map<String,Serializable> props = event.getPropertyMap(); if (Log.loggingDebug) Log.debug("MyProxyHook: received "+event.getExtensionType()+" from playerOid="+player.getOid()); // Log the extension message properties if (Log.loggingDebug) { String propStr = ""; for (Map.Entry<String,Serializable> entry : props.entrySet()) { propStr += entry.getKey() + "=" + entry.getValue() + " "; } Log.debug("MyProxyHook: "+propStr); } } }
请注意,来自客户端的消息将按顺序处理。在processExtensionEvent()返回之前,不会处理后续消息。
注册代理扩展挂钩
要注册代理扩展挂钩,请在ProxyPlugin上使用以下方法。 proxyPlugin.addProxyExtensionHook(“proxy.GENERATE_OBJECT”,GenerateObjectProxyHook())/atavism/config/world-name/extensions_proxy.py脚本是放置此代码的好地方。
InstanceEntryProxyHook
GenerateObjectProxyHook
此挂钩将在玩家的当前位置或标记处生成一个对象。钩子需要以下扩展消息属性:
- template – 已注册的对象模板名称。模板必须在世界管理器命名空间中具有属性,否则它将不会生成。
- marker – 当前实例中的标记名称。如果未指定,则使用播放器的当前位置和方向。
- persistent – 如果此整数不为0,则该对象将是持久的。
对象的位置和方向是从标记或当前玩家位置设置的。如果对象创建成功,那么它将立即生成。此挂钩在演示中注册到扩展子类型
“proxy.GENERATE_OBJECT”。示例资产包括StandardCommands脚本中发送此扩展消息的客户端“/ generate”命令。