[wpdreams_ajaxsearchlite]

客户端到服务器消息


从客户端向服务器发送消息

从客户端向服务器发送消息是三个消息发送系统中最复杂的,因为它涉及一些额外的步骤以使服务器知道传入消息。为了使其更容易,将通过以下步骤使用现有示例,其中概述了需要执行的操作。此示例用于从客户端向服务器发送Place Claim Object消息。


1)创建MessageType

MessageTypes在插件包中的Client.java文件的AGIS代码中定义。它们是一个简单的字符串查找,如VoxelClient.java中的此示例所示:

  public static final MessageType MSG_TYPE_PLACE_CLAIM_OBJECT = MessageType.intern("voxel.PLACE_CLAIM_OBJECT");

实习生字符串必须是唯一的。您只需复制现有的MessageType条目并粘贴它,重命名变量名称和实习生名称。


2)创建MessageHook类


MessageHook是一个将接收消息并用它做事的类。它需要在* Plugin.java文件中创建(用相关的插件类型替换*)。 在提供的示例中,它将获取场所声明对象消息,并检查用户是否可以在将声明对象添加到指定位置的声明之前放置声明对象。

Hook类必须实现Hook接口并具有processMessage()函数,如下面VoxelPlugin.java中给出的示例所示:

  class PlaceClaimObjectHook implements Hook {
      public boolean processMessage(Message msg, int flags) {
          ExtensionMessage gridMsg = (ExtensionMessage)msg;
          OID playerOid = gridMsg.getSubject();
          Log.debug("CLAIM: got place object");
          // Get the claim ID property from the message - change this to get your own properties
          int claimID = (Integer)gridMsg.getProperty("claim");
      
          ...
      
          return true;
      }
  }

您将需要在…区域中添加自己的代码,以及更改getProperty()代码行。


3)将MessageType添加到插件过滤器并注册Hook类

在每个Plugin类的顶部有一个MessageFilter和一堆Hook注册。需要这些来告诉插件从客户端(或服务器的其他区域)侦听指定的消息,然后告诉它在获取该类型的消息时应该运行哪个Hook。


在VoxelPlugin中,您将在onActivate()函数中看到:

  getHookManager().addHook(VoxelClient.MSG_TYPE_PLACE_CLAIM_OBJECT,
              new PlaceClaimObjectHook());

以及下面的一点:

  filter.addType(VoxelClient.MSG_TYPE_PLACE_CLAIM_OBJECT);

您需要更改这些以使用新的MessageType和MessageHook。

您现在可以根据需要构建AGIS代码。

4)将MessageType和intern添加到服务器python脚本中


要使代理服务器能够从客户端接收这些消息,现在需要在worldmessages.py和extensions_proxy.py脚本中定义MessageType。这些都在config / world文件夹中找到。


worldmessages.py:

  MessageCatalog.addMsgTypeTranslation(aoMessageCatalog, VoxelClient.MSG_TYPE_PLACE_CLAIM_OBJECT)
  Add your MessageType like above making sure you get the Client type correct.

extensions_proxy.py:

  proxyPlugin.registerExtensionSubtype("voxel.PLACE_CLAIM_OBJECT", VoxelClient.MSG_TYPE_PLACE_CLAIM_OBJECT)

这与您定义MessageType时的反向相反。您将在文件底部找到所有这些内容。


5)从客户端发送消息


现在我们终于完成了服务器,我们需要从客户端发送消息。最简单的方法是复制现有示例。来自WorldBuilderUI.cs:


  // Need a dictionary to store all the props in
  Dictionary<string, object> props = new Dictionary<string, object>();
  // Now add the properties to be sent to the server. Send as many as you want (within reason)
  props.Add("claim", activeClaim.id);
  props.Add("gameObject", itemBeingPlaced.itemEffectValues[effectPositions[0]]);
  props.Add("loc", currentReticle.transform.position);
  props.Add("orient", currentReticle.transform.rotation);
  props.Add("itemID", itemBeingPlaced.templateId);
  props.Add("itemOID", itemBeingPlaced.ItemId);
  // The actual command to send the message
  NetworkAPI.SendExtensionMessage(ClientAPI.GetPlayerOid(), false, "voxel.PLACE_CLAIM_OBJECT", props);
  

格式很简单,创建一个Dictionary来存储道具,添加道具然后发送消息。在发送道具的命令中要注意的一件事是MessageType实习生被用作第二个最后一个参数。

大多数变量类型都可以在props消息中发送。所有简单类型(例如bool,int,float)都可以与一些对象类型(String,OID)一起发送。可以发送一些列表和词典,但它们可能有点问题,因此通常最好尽可能避免。

请注意,NetworkAPI.SendExtensionMessage中的第一个参数(在本例中为ClientAPI.GetPlayerOid())将作为邮件的主题发送。然后可以使用OID playerOid = msg.getSubject();从服务器上的消息中检索主题。

Final Notes

  • 在MessageHook的开头附近发出调试消息以确认消息是否发送到服务器是非常有帮助的。
  • 如果邮件发送到服务器但似乎没有运行其余代码,请检查要发送的属性和类型。如果服务器获得属性类型,它不会期望它可能会停止运行。
  • 在Unity脚本中的行上放置一个断点,发送扩展消息以确保它被发送,或者在它之后的调试消息。
  • 检查服务器errors.out日志文件,以帮助调试您的消息可能没有成功的原因。有时可能会说您的消息需要添加到-ads文件中。这些可以在config / world文件夹中找到。只需添加错误消息所说的内容。