图 4-1 客户端已连接至服务器。请注意游戏策划,其中一个客户端已与服务器建立了多个连接。
4.1.2 Rooms 房间是socket服务器领域的一个常见概念,指的是用户的集合(如图4-2所示)。在ElectroServer中,房间是作为一个用户和多个用户相互查看和交互的媒介。如果一个用户在一个房间中,他可以向房间中的所有用户发送聊天消息,然后该消息会被广播给房间中的所有用户。这只是房间的一种简单用法。单个用户可以同时在不同的房间中。
图 4-2 各种房间
ElectroServer 中有两种类型的房间。 · 持久房间。即使没有用户,房间也会继续存在。 · 动态房间。为一次性用途而创建的房间。如果房间中的用户数降至 0,表明所有用户都已离开房间,则系统会销毁该房间。这也是最常见的房间类型。 房间有很多用途,其中最常见的两种是方便聊天和聚集人们玩多人游戏。我们将在后面的章节中详细探讨这些常见用途。 4.1.3 区域 区域是房间的集合。区域是非常有用的概念,主要用于组织和管理服务器上大量的房间。区域中的每个房间都必须有一个唯一的名称。区域内的每个房间用户都可以获取该区域内的房间列表。每当房间列表发生变化时,用户可以自动订阅更新的房间列表。 如果房间列表非常大或非常活跃(服务器上不断创建和删除许多房间),则连接的用户每秒将收到大量更新,以至于他们无法跟上房间列表。使用更多区域可以帮助解决此问题(图 4-3)。请注意,可以在不同区域中使用相同的房间名称。
图 4-3
4.1.4 聊天 聊天是连接到套接字服务器的用户之间进行交互的主要方式。聊天消息是用户向其他用户发送的文本。与其他套接字服务器解决方案一样,ElectroServer 中也有公共聊天消息和私人聊天消息。公共聊天消息是用户向其所属房间内的所有用户发送的聊天消息。通常公共消息最终会显示在客户端的文本字段中,如图 4-4 所示。
图 4-4
请注意,我们将在第 5 章中更详细地讨论“聊天”这一主题。私人聊天消息是直接由一个用户发送给一个或多个其他用户的消息(图 4-5)。与公开聊天消息不同,目标用户不需要与发送者在同一个房间,甚至不需要在任何房间。私人聊天消息通常由一个用户发送给另一个用户,例如聊天室中用户之间的私人对话或游戏中同一团队的玩家之间的秘密通信。在大多数多人游戏和虚拟世界中,私人消息仅在朋友之间发送。
图 4-5
4.1.5 好友社交网络是典型多人游戏体验的重要组成部分。除了一起玩游戏和竞争之外,玩家还喜欢建立超越娱乐的友谊。他们会很乐意将对方的在线身份标记为“好友”,并将其添加到好友列表中。当用户稍后返回多人互动程序时,她只需查看好友列表,即可查看哪些好友在线,哪些好友不在线(见图 4-6)。用户可以向当前在线的好友发送消息,甚至邀请他们一起玩游戏。
图 4-6
在一些虚拟世界或社交网络平台中,即使用户当前处于离线状态,也可以向他的某个好友发送聊天消息。当这些离线用户返回网络时,他们可以收到其他人发送给他们的延迟消息。 4.1.6 EsObject 这是我们介绍的第一个真正的 ElectroServer 特定概念。乍一看,EsObject 似乎有点奇怪,但一旦熟悉它,就会发现它非常有用。EsObject 是一个在服务器和客户端上以相同结构存在的类。首先,创建此类的新实例,然后将数据存储在对象上。EsObject 对象可以在客户端和服务器之间轻松交换,因为事务层知道如何序列化和反序列化对象。 序列化和反序列化 对象被序列化,这意味着它的数据以另一种结构表示,以便存储或传输。例如,以下对象:var person:Object = new Object();person.name = "Jobe";person.age = 33;此对象可以像下面这样在 XML 中表示:
乔布33
这种将数据对象转换成 XML 表示的字符串的操作称为“序列化”。数据对象也可能被转换成二进制或其他格式,而将序列化的数据转换回原始数据对象的过程称为“反序列化”。注意,事务层是指客户端和服务器 API 部分,它解析和格式化客户端和服务器之间交换的数据。它读取数据并格式化,然后通过 Socket 服务器发送格式化的数据,然后它通过 Socket 服务器接收数据,解析并加载到可用的对象中,最后调度一个可被特定应用程序代码捕获的事件。从头到尾,客户端和服务器通过 API 进行通信时都使用 EsObject 对象。 下面是一个使用ActionScript创建EsObject对象的例子:var esob:EsObject = new EsObject();esob.setString("name", "Jobe");esob.setInteger("age", 33);esob.setStringArray("petNames", ["elfie", "bosley", "clyde"]);上面的例子中,我们首先创建了一个EsObject类的新实例网页游戏开发,然后向其中添加数据。
添加到 EsObject 对象的每个属性值都对应着一种严格的数据类型。上面的例子介绍了 String、Integer 和 String Array 数据类型。下面的列表完整列出了 EsObject 支持的数据类型。· String/String Array · Integer/Integer Array · Number/Number Array · Boolean/Boolean Array · Byte/Byte Array · Character/Character Array · Double/Double Array · EsObject/EsObject Array · Float/Float Array · Long/Long Array · Short/Short Array 请注意,最常用的数据类型是 String、Integer、Boolean、Byte 和 String。您可能一开始会想:为什么要将所有数据放入 EsObject 对象?这是个好主意吗?这似乎需要编写大量代码,并且必须确认看似过于严格的数据类型。然而,它实际上可以为您节省以后的时间和麻烦。 通过使用 EsObject 和严格的数据类型,您可以减少代码中的歧义,并最终使代码更易于管理。
使用 EsObject 的另一个优势(显而易见但容易被忽视)是带宽。EsObject 对象序列化过程产生的数据包大小(您无法看到)极小,因此带宽也保持在最低限度。 4.1.7 扩展 除了提供高度可扩展的连接层之外,大多数实用的套接字服务器将首先提供基本级别的开箱即用功能,例如房间、聊天、好友等功能。但是网页游戏开发,如果多人游戏或虚拟世界需要一些特殊功能或特性,而这些功能或特性未包含在您现在使用的服务器的核心功能集中,该怎么办?好的套接字服务器将为您提供自己添加这些功能的方法。通过使用自定义代码扩展服务器的功能,您可以实现任何您想要的功能。 ElectroServer 和许多其他服务器都支持一种称为扩展的程序。扩展是运行在服务器上的自定义代码,提供服务器中未内置的功能和特性。扩展可以包含一种或多种类型的对象,这些对象扩展了 ElectroServer 的某些功能。它支持 3 种类型的 EsObject 对象。 扩展和增强 ElectroServer:事件处理程序、插件和管理对象工厂。
每个对象都可以包含变量,这些变量定义在创建对象时应该分配给它的值。 1. 事件处理程序 事件处理程序允许开发人员将一些自定义逻辑应用为事件的结果。它们通常用 Java 编写,尽管也可以使用 ActionScript 1。ElectroServer 目前允许为以下事件类型创建事件处理程序: · 登录 - 用户登录到 ElectroServer; · 注销 - 用户注销 ElectroServer; · 用户变量 - 用户已更新附加到用户对象的 EsObject 对象; · 房间变量 - 用户已更新附加到房间对象的 EsObject 对象; · 好友列表 - 用户已更新其好友列表(添加/编辑/删除); · Private/PublicMessaging - 用户已向另一个实体(房间/用户)发送消息。 让我们以登录事件处理程序为例。客户端连接到 ElectroServer 并提供其登录凭据,通过对照数据库检查其名称和密码,然后事件处理程序决定是接受还是拒绝用户的连接。 请注意硬件设备,几乎所有使用 ElectroServer 的大型应用程序最终都会使用自定义编写的登录事件处理程序来根据数据库验证用户凭据。
2. 插件 插件(通常用 Java 编写)提供核心功能未提供的基本可扩展功能。客户端可以与插件通信,插件之间也可以相互通信。ElectroServer 提供两种类型的插件:房间级插件和服务器级插件。房间级插件负责管理可能需要附加到特定房间的任何功能。它们通常用于处理游戏逻辑和其他房间功能。房间级插件的一个很好的例子是纸牌游戏:该插件处理发牌的所有规则、哪个玩家获得牌、计算分数以及确定谁是赢家。房间级插件被创建并限定在一个房间内,因此它成为一个实例。客户端只能与任何限定在其当前所在房间内的房间级插件通信。服务器级插件扩展了 ElectroServer 的执行能力。这些扩展包括从全局增强房间功能到为想要更改游戏某些方面的功能公开外部接口。 与需要时创建的房间级插件不同,服务器级插件仅创建一次并会持续存在。客户端可以与任何服务器级插件通信。服务器级插件的一个很好的例子是访问远程 RSS 源。如果您的虚拟世界需要在某些方面显示新闻项目,那么服务器需要加载新闻。在这种情况下,明智的做法是让服务器级插件加载和管理最新新闻,以便任何其他插件都可以在需要时访问它。
3. 托管对象工厂 托管对象工厂允许创建需要长时间保持活动状态的对象实例。我们使用这种类型的工厂创建的常见对象是数据库连接。它允许定义其属性和数据库类型以连接到插件并从中检索数据。让我们看一下以下基于 MySQL 的托管对象的创建过程,该对象是为基于 Java 的插件编写的。EsObject esDB = new EsObject();esDB.setString("poolname","mysqlpool");Connection c = (Connection)getApi().acquireManagedObject("ManagedDBConnection", esDB);