<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://game.etao.net/w/index.php?action=history&amp;feed=atom&amp;title=Marauroa_Chat_Tutorial%2FText_Client</id>
	<title>Marauroa Chat Tutorial/Text Client - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://game.etao.net/w/index.php?action=history&amp;feed=atom&amp;title=Marauroa_Chat_Tutorial%2FText_Client"/>
	<link rel="alternate" type="text/html" href="https://game.etao.net/w/index.php?title=Marauroa_Chat_Tutorial/Text_Client&amp;action=history"/>
	<updated>2026-05-05T16:01:15Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://game.etao.net/w/index.php?title=Marauroa_Chat_Tutorial/Text_Client&amp;diff=138&amp;oldid=prev</id>
		<title>2020年4月27日 (一) 13:02 imported&gt;朱志凌</title>
		<link rel="alternate" type="text/html" href="https://game.etao.net/w/index.php?title=Marauroa_Chat_Tutorial/Text_Client&amp;diff=138&amp;oldid=prev"/>
		<updated>2020-04-27T13:02:39Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Navigation for Marauroa Top|Using}}&lt;br /&gt;
{{Navigation for Marauroa Users}}&lt;br /&gt;
{{Marauroa Chat Tutorial}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 编码 ==&lt;br /&gt;
为了使用Marauroa框架字创建客户端，您应该使用您的逻辑扩展marauroa.client.ClientFramework类。 这是聊天客户端的源代码&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import java.util.Map;&lt;br /&gt;
import java.util.HashMap;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
import java.util.LinkedList;&lt;br /&gt;
&lt;br /&gt;
import marauroa.client.ClientFramework;&lt;br /&gt;
import marauroa.client.net.IPerceptionListener;&lt;br /&gt;
import marauroa.client.net.PerceptionHandler;&lt;br /&gt;
import marauroa.common.game.RPAction;&lt;br /&gt;
import marauroa.common.game.RPObject;&lt;br /&gt;
import marauroa.common.net.message.MessageS2CPerception;&lt;br /&gt;
import marauroa.common.net.message.TransferContent;&lt;br /&gt;
&lt;br /&gt;
public class Client extends ClientFramework {&lt;br /&gt;
  private PerceptionHandler handler;&lt;br /&gt;
  private static Client client;&lt;br /&gt;
  private Map&amp;lt;RPObject.ID, RPObject&amp;gt; worldObjects;&lt;br /&gt;
  private String[] availableCharacters;&lt;br /&gt;
  private LinkedList&amp;lt;String&amp;gt; quotes = new LinkedList&amp;lt;String&amp;gt;();&lt;br /&gt;
  &lt;br /&gt;
  public static Client get() {&lt;br /&gt;
    if (client == null) {&lt;br /&gt;
      client = new Client();&lt;br /&gt;
    }&lt;br /&gt;
    return client;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  protected Client() {&lt;br /&gt;
    super(&amp;quot;log4j.properties&amp;quot;);&lt;br /&gt;
    worldObjects = new HashMap&amp;lt;RPObject.ID, RPObject&amp;gt;();&lt;br /&gt;
    handler = new PerceptionHandler(new PerceptionListener());&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String[] getAvailableCharacters() {&lt;br /&gt;
    return availableCharacters;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public String popQuote() {&lt;br /&gt;
    if (quotes.isEmpty()) {&lt;br /&gt;
      return null;&lt;br /&gt;
    }&lt;br /&gt;
    return quotes.pop();&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  public void sendMessage(String text) {&lt;br /&gt;
    RPAction action;&lt;br /&gt;
    action = new RPAction();&lt;br /&gt;
    action.put(&amp;quot;type&amp;quot;, &amp;quot;chat&amp;quot;);&lt;br /&gt;
    action.put(&amp;quot;text&amp;quot;, text);&lt;br /&gt;
    send(action);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  @Override&lt;br /&gt;
  protected void onPerception(MessageS2CPerception message) {&lt;br /&gt;
    try {&lt;br /&gt;
      handler.apply(message, worldObjects);&lt;br /&gt;
    } catch (java.lang.Exception e) {&lt;br /&gt;
      // Something weird happened while applying perception&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected List&amp;lt;TransferContent&amp;gt; onTransferREQ(List&amp;lt;TransferContent&amp;gt; items) {&lt;br /&gt;
    return items;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected void onTransfer(List&amp;lt;TransferContent&amp;gt; items) {&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected void onAvailableCharacters(String[] characters) {&lt;br /&gt;
    availableCharacters = characters;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected void onServerInfo(String[] info) {&lt;br /&gt;
    for (String s : info) {&lt;br /&gt;
      quotes.add(s);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected String getGameName() {&lt;br /&gt;
    return &amp;quot;Chat&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected String getVersionNumber() {&lt;br /&gt;
    return &amp;quot;0.5&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  @Override&lt;br /&gt;
  protected void onPreviousLogins(List&amp;lt;String&amp;gt; previousLogins) {&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  class PerceptionListener implements IPerceptionListener {&lt;br /&gt;
    @Override&lt;br /&gt;
    public boolean onAdded(RPObject object) {&lt;br /&gt;
      if (object.has(&amp;quot;text&amp;quot;)) {&lt;br /&gt;
        quotes.add(&amp;quot;*&amp;quot; + object.get(&amp;quot;from&amp;quot;) + &amp;quot;* : &amp;quot; + object.get(&amp;quot;text&amp;quot;));&lt;br /&gt;
      }&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public boolean onModifiedAdded(RPObject object, RPObject changes) {&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public boolean onModifiedDeleted(RPObject object, RPObject changes) {&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public boolean onDeleted(RPObject object) {&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public boolean onMyRPObject(RPObject added, RPObject deleted) {&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onSynced() {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onUnsynced() {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onException(Exception e, MessageS2CPerception perception) {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      System.exit(-1);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public boolean onClear() {&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onPerceptionBegin(byte type, int timestamp) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onPerceptionEnd(byte type, int timestamp) {&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这主要是样板代码。 我们声称我们是“聊天”客户端，版本为“ 0.5”。您还记得，我们的服务器将接受任何“聊天”客户端，而没有版本限制。&lt;br /&gt;
&lt;br /&gt;
您应该注意的是，我们使用了Marauroa提供的感知处理程序，请参见onPerception。 我们仍然引入了自己的感知侦听器，以便在添加，修改或删除对象时能够采取措施。 &lt;br /&gt;
&lt;br /&gt;
PerceptionListener是我们的实现。 我们仅使用onAdded处理程序，该处理程序允许我们在出现新对象时做出反应，即将新的聊天消息添加到消息列表中。 在其他处理程序中返回的假值非常重要，因为它们向Marauroa表示您要继续当前操作（例如添加对象）。&lt;br /&gt;
&lt;br /&gt;
收到的所有消息都存储在消息列表中。 一个人可以使用popQuote（）方法一一访问存储的消息.&lt;br /&gt;
&lt;br /&gt;
最后，您可以使用SendMessage方法发送消息。 它构造服务器可理解的RPAction并将其发送。&lt;br /&gt;
&lt;br /&gt;
Marauroa框架为服务器提供了主要方法，因此您无需关心执行循环。 对于客户端而言并非如此，因此我们还需要实现客户端的主要模块。 这是一个非常简单的解决方案&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import marauroa.common.game.RPObject;&lt;br /&gt;
&lt;br /&gt;
public class Test {&lt;br /&gt;
  public static void main(String[] args) {&lt;br /&gt;
    boolean runClient = true;&lt;br /&gt;
    Client client = Client.get();&lt;br /&gt;
    try {&lt;br /&gt;
      client.connect(&amp;quot;localhost&amp;quot;, 5555);&lt;br /&gt;
      if (args.length == 3) {&lt;br /&gt;
        client.createAccount(args[0], args[1], args[2]);&lt;br /&gt;
      }&lt;br /&gt;
      client.login(args[0], args[1]);&lt;br /&gt;
      if (client.getAvailableCharacters().length == 0) {&lt;br /&gt;
        RPObject character = new RPObject();&lt;br /&gt;
        client.createCharacter(args[0], character);&lt;br /&gt;
      }&lt;br /&gt;
      client.chooseCharacter(args[0]);&lt;br /&gt;
    } catch (Exception e) {&lt;br /&gt;
      runClient = false;&lt;br /&gt;
    }&lt;br /&gt;
    int i = 0;&lt;br /&gt;
    while (runClient) {&lt;br /&gt;
      i++;&lt;br /&gt;
      client.loop(0);&lt;br /&gt;
      if (i % 100 == 50) {&lt;br /&gt;
        client.sendMessage(&amp;quot;test&amp;quot; + i);&lt;br /&gt;
      }&lt;br /&gt;
      String s = client.popQuote();&lt;br /&gt;
      while (s != null) {&lt;br /&gt;
        System.out.println(s);&lt;br /&gt;
        s = client.popQuote();&lt;br /&gt;
      }&lt;br /&gt;
      try {&lt;br /&gt;
        Thread.sleep(100);&lt;br /&gt;
      } catch (InterruptedException e) {&lt;br /&gt;
        runClient = false;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
我们的main方法做两件事。 首先，如果提供了三个命令行参数（登录，密码，电子邮件），我们将创建一个新帐户。 否则，我们仅使用指定的登录名和密码登录。&lt;br /&gt;
&lt;br /&gt;
然后是时候选择一个角色了。 如果服务器报告该帐户没有可用的角色，那么我们将创建一个新名称，该名称与帐户名称相同。 请注意，不可能直接在Client类的onAvailableCharacters处理程序中选择角色。&lt;br /&gt;
&lt;br /&gt;
随后开始心跳循环。 在每一步中，我们都调用loop（0），其中浮点参数在这一点上没有任何意义。 每100步，我们就会向服务器发送一条消息。 没有互动的方式来控制消息，但是看到您自己的客户端创建的聊天仍然令人赞叹。&lt;br /&gt;
&lt;br /&gt;
== 部署 ==&lt;br /&gt;
运行客户端非常简单，您只需要一堆jar（客户端不需要数据库）和已编译的客户端代码。 我使用以下行进行编译&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
javac -cp marauroa.jar;log4j.jar;. *.java&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
确保所需的jar位于当前目录中。 运行使用&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java -cp marauroa.jar;log4j.jar;h2.jar;. Test login password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
同样，在Linux和MacOSX上，所有“;” 必须替换为“：”。&lt;br /&gt;
&lt;br /&gt;
不要忘记用实际的登录名和密码替换。 要创建一个新帐户，只需添加第三个命令行参数（应该是电子邮件，但目前尚无验证）。.&lt;br /&gt;
&lt;br /&gt;
== 输出 ==&lt;br /&gt;
理想情况下，您应该会看到类似&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt;java -cp marauroa.jar;log4j.jar;h2.jar;. Test test1 test1&lt;br /&gt;
Cannot find log4j.properties in classpath. Using default properties.&lt;br /&gt;
*test1* : test50&lt;br /&gt;
*test1* : test150&lt;br /&gt;
*test1* : test250&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
请注意有关log4j.properties的消息：您可以创建该文件以便在Marauroa框架内配置Log4J用法.&lt;br /&gt;
&lt;br /&gt;
== 下一步 ==&lt;br /&gt;
&lt;br /&gt;
在本教程的下一部分中，我们将编写一个 &amp;#039;&amp;#039;&amp;#039;[[Marauroa Chat Tutorial/Swing Client|Swing 客户端]]&amp;#039;&amp;#039;&amp;#039; 它带有图形用户接口.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Marauroa]]&lt;br /&gt;
{{#breadcrumbs: [[Marauroa]] | [[Navigation for Marauroa Users|使用]] | [[Marauroa Chat Tutorial|教程]] | [[Marauroa Chat Tutorial/Text Client|文本客户端]]}}&lt;/div&gt;</summary>
		<author><name>imported&gt;朱志凌</name></author>
	</entry>
</feed>