|
@@ -8,7 +8,7 @@
|
|
<table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33.3333%;"><col style="width: 33.3333%;"><col style="width: 33.3334%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Seen from the Client</th><th class="tableblock halign-left valign-top"></th><th class="tableblock halign-left valign-top">Seen from the Server</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>com.jme3.network.Client</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>==</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>com.jme3.network.HostedConnection</p></div></div></td></tr></tbody></table>
|
|
<table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33.3333%;"><col style="width: 33.3333%;"><col style="width: 33.3334%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Seen from the Client</th><th class="tableblock halign-left valign-top"></th><th class="tableblock halign-left valign-top">Seen from the Server</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>com.jme3.network.Client</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>==</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>com.jme3.network.HostedConnection</p></div></div></td></tr></tbody></table>
|
|
<div class="paragraph"><p>You can register several types of listeners to be notified of changes.</p></div>
|
|
<div class="paragraph"><p>You can register several types of listeners to be notified of changes.</p></div>
|
|
<div class="ulist"><ul><li><p>MessageListeners on both the Client and the Server are notified when new messages arrive. You can use MessageListeners to be notified about only specific types of messages.</p></li><li><p>ClientStateListeners inform the Client of changes in its connection state, e.g. when the client gets kicked from the server.</p></li><li><p>ConnectionListeners inform the Server about HostedConnection arrivals and removals, e.g. if a client joins or quits.</p></li><li><p>ErrorListeners inform the Client about network exceptions that have happened, e.g. if the server crashes, the client throws a ConnectorException, this can be picked up so that the application can do something about it.</p></li></ul></div></div></div>
|
|
<div class="ulist"><ul><li><p>MessageListeners on both the Client and the Server are notified when new messages arrive. You can use MessageListeners to be notified about only specific types of messages.</p></li><li><p>ClientStateListeners inform the Client of changes in its connection state, e.g. when the client gets kicked from the server.</p></li><li><p>ConnectionListeners inform the Server about HostedConnection arrivals and removals, e.g. if a client joins or quits.</p></li><li><p>ErrorListeners inform the Client about network exceptions that have happened, e.g. if the server crashes, the client throws a ConnectorException, this can be picked up so that the application can do something about it.</p></li></ul></div></div></div>
|
|
-<div class="sect2"><h3 id="client-and-server">Client and Server</h3><div class="sect2"><h3 id="creating-a-server">Creating a Server</h3><div class="paragraph"><p>The game server is a “headless com.jme3.app.SimpleApplication:</p></div>
|
|
|
|
|
|
+<div class="sect2"><h3 id="client-and-server">Client and Server</h3><div class="sect2"><h3 id="creating-a-server">Creating a Server</h3><div class="paragraph"><p>The game server is a “headless” com.jme3.app.SimpleApplication:</p></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ServerMain</span> <span class="directive">extends</span> SimpleApplication {
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ServerMain</span> <span class="directive">extends</span> SimpleApplication {
|
|
<span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) {
|
|
<span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) {
|
|
ServerMain app = <span class="keyword">new</span> ServerMain();
|
|
ServerMain app = <span class="keyword">new</span> ServerMain();
|
|
@@ -37,13 +37,14 @@
|
|
...
|
|
...
|
|
Client myClient = Network.connectToServer(<span class="string"><span class="delimiter">"</span><span class="content">localhost</span><span class="delimiter">"</span></span>, <span class="integer">6143</span>);
|
|
Client myClient = Network.connectToServer(<span class="string"><span class="delimiter">"</span><span class="content">localhost</span><span class="delimiter">"</span></span>, <span class="integer">6143</span>);
|
|
myClient.start();
|
|
myClient.start();
|
|
- ...</code></pre></div></div>
|
|
|
|
-<div class="paragraph"><p>The server address can be in the format “localhost or “127.0.0.1 (for local testing), or an IP address of a remote host in the format “123.456.78.9”. In this example, we assume the server is running on the localhost.</p></div>
|
|
|
|
|
|
+ ...
|
|
|
|
+}</code></pre></div></div>
|
|
|
|
+<div class="paragraph"><p>The server address can be in the format “localhost” or “127.0.0.1” (for local testing), or an IP address of a remote host in the format “123.456.78.9”. In this example, we assume the server is running on the localhost.</p></div>
|
|
<div class="paragraph"><p>When you run this client, it connects to the server.</p></div></div>
|
|
<div class="paragraph"><p>When you run this client, it connects to the server.</p></div></div>
|
|
<div class="sect2"><h3 id="getting-info-about-a-client">Getting Info About a Client</h3><div class="paragraph"><p>The server refers to a connected client as com.jme3.network.HostedConnection objects. The server can get info about clients as follows:</p></div>
|
|
<div class="sect2"><h3 id="getting-info-about-a-client">Getting Info About a Client</h3><div class="paragraph"><p>The server refers to a connected client as com.jme3.network.HostedConnection objects. The server can get info about clients as follows:</p></div>
|
|
<table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Accessor</th><th class="tableblock halign-left valign-top">Purpose</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>myServer.getConnections()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server gets a collection of all connected HostedConnection objects (all connected clients).</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>myServer.getConnections().size()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server gets the number of all connected HostedConnection objects (number of clients).</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>myServer.getConnection(0)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server gets the first (0), second (1), etc, connected HostedConnection object (one client).</p></div></div></td></tr></tbody></table>
|
|
<table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Accessor</th><th class="tableblock halign-left valign-top">Purpose</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>myServer.getConnections()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server gets a collection of all connected HostedConnection objects (all connected clients).</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>myServer.getConnections().size()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server gets the number of all connected HostedConnection objects (number of clients).</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>myServer.getConnection(0)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server gets the first (0), second (1), etc, connected HostedConnection object (one client).</p></div></div></td></tr></tbody></table>
|
|
<div class="paragraph"><p>Your game can define its own game data based on whatever criteria you want, typically these include player ID and state. If the server needs to look up player/client-specific information, you can store this information directly on the HostedConnection object. The following examples read and write a custom Java object <code>MyState</code> in the HostedConnection object <code>conn</code>:</p></div>
|
|
<div class="paragraph"><p>Your game can define its own game data based on whatever criteria you want, typically these include player ID and state. If the server needs to look up player/client-specific information, you can store this information directly on the HostedConnection object. The following examples read and write a custom Java object <code>MyState</code> in the HostedConnection object <code>conn</code>:</p></div>
|
|
-<table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Accessor</th><th class="tableblock halign-left valign-top">Purpose</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>conn.setAttribute(“MyState, new MyState());</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server can change an attribute of the HostedConnection.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>MyState state = conn.getAttribute(“MyState)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server can read an attribute of the HostedConnection.</p></div></div></td></tr></tbody></table></div></div>
|
|
|
|
|
|
+<table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Accessor</th><th class="tableblock halign-left valign-top">Purpose</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>conn.setAttribute( "MyState", new MyState());</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server can change an attribute of the HostedConnection.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>MyState state = conn.getAttribute("MyState");</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Server can read an attribute of the HostedConnection.</p></div></div></td></tr></tbody></table></div></div>
|
|
<div class="sect2"><h3 id="messaging">Messaging</h3><div class="sect2"><h3 id="creating-message-types">Creating Message Types</h3><div class="paragraph"><p>Each message represents data that you want to transmit between client and server. Common message examples include transformation updates or game actions. For each message type, create a message class that extends com.jme3.network.AbstractMessage. Use the @Serializable annotation from com.jme3.network.serializing.Serializable and create an empty default constructor. Custom constructors, fields, and methods are up to you and depend on the message data that you want to transmit.</p></div>
|
|
<div class="sect2"><h3 id="messaging">Messaging</h3><div class="sect2"><h3 id="creating-message-types">Creating Message Types</h3><div class="paragraph"><p>Each message represents data that you want to transmit between client and server. Common message examples include transformation updates or game actions. For each message type, create a message class that extends com.jme3.network.AbstractMessage. Use the @Serializable annotation from com.jme3.network.serializing.Serializable and create an empty default constructor. Custom constructors, fields, and methods are up to you and depend on the message data that you want to transmit.</p></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Serializable</span>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Serializable</span>
|
|
<span class="directive">public</span> <span class="type">class</span> <span class="class">HelloMessage</span> <span class="directive">extends</span> AbstractMessage {
|
|
<span class="directive">public</span> <span class="type">class</span> <span class="class">HelloMessage</span> <span class="directive">extends</span> AbstractMessage {
|
|
@@ -51,7 +52,8 @@
|
|
<span class="directive">public</span> HelloMessage() {} <span class="comment">// empty constructor</span>
|
|
<span class="directive">public</span> HelloMessage() {} <span class="comment">// empty constructor</span>
|
|
<span class="directive">public</span> HelloMessage(<span class="predefined-type">String</span> s) { hello = s; } <span class="comment">// custom constructor</span>
|
|
<span class="directive">public</span> HelloMessage(<span class="predefined-type">String</span> s) { hello = s; } <span class="comment">// custom constructor</span>
|
|
}</code></pre></div></div>
|
|
}</code></pre></div></div>
|
|
-<div class="paragraph"><p>You must register each message type to the com.jme3.network.serializing.Serializer, in both server and client!</p></div>
|
|
|
|
|
|
+<div class="paragraph"><p>You register message types to the com.jme3.network.serializing.Serializer only on the server! SpiderMonkey has an automatic registering mechanism that will register the messages on the client the first time it connects to the server.</p></div>
|
|
|
|
+<div class="admonitionblock warning"><table><tr><td class="icon"><i class="fa icon-warning" title="Warning"></i></td><td class="content"><div class="paragraph"><p>Messages must be registered after server creation, and before it is started. NOT before the server is created.</p></div></td></tr></table></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">Serializer.registerClass(HelloMessage.class);</code></pre></div></div></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">Serializer.registerClass(HelloMessage.class);</code></pre></div></div></div>
|
|
<div class="sect2"><h3 id="responding-to-messages">Responding to Messages</h3><div class="paragraph"><p>After a Message was received, a Listener responds to it. The listener can access fields of the message, and send messages back, start new threads, etc. There are two listeners, one on the server, one on the client. For each message type, you implement the responses in either Listeners’ <code>messageReceived()</code> method.</p></div>
|
|
<div class="sect2"><h3 id="responding-to-messages">Responding to Messages</h3><div class="paragraph"><p>After a Message was received, a Listener responds to it. The listener can access fields of the message, and send messages back, start new threads, etc. There are two listeners, one on the server, one on the client. For each message type, you implement the responses in either Listeners’ <code>messageReceived()</code> method.</p></div>
|
|
<div class="sect3"><h4 id="clientlistener-java">ClientListener.java</h4><div class="paragraph"><p>Create one ClientListener.java and make it extend <code>com.jme3.network.MessageListener</code>.</p></div>
|
|
<div class="sect3"><h4 id="clientlistener-java">ClientListener.java</h4><div class="paragraph"><p>Create one ClientListener.java and make it extend <code>com.jme3.network.MessageListener</code>.</p></div>
|
|
@@ -62,7 +64,8 @@
|
|
HelloMessage helloMessage = (HelloMessage) message;
|
|
HelloMessage helloMessage = (HelloMessage) message;
|
|
<span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Client #</span><span class="delimiter">"</span></span>+source.getId()+<span class="string"><span class="delimiter">"</span><span class="content"> received: '</span><span class="delimiter">"</span></span>+helloMessage.getSomething()+<span class="string"><span class="delimiter">"</span><span class="content">'</span><span class="delimiter">"</span></span>);
|
|
<span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Client #</span><span class="delimiter">"</span></span>+source.getId()+<span class="string"><span class="delimiter">"</span><span class="content"> received: '</span><span class="delimiter">"</span></span>+helloMessage.getSomething()+<span class="string"><span class="delimiter">"</span><span class="content">'</span><span class="delimiter">"</span></span>);
|
|
} <span class="comment">// else...</span>
|
|
} <span class="comment">// else...</span>
|
|
- }</code></pre></div></div>
|
|
|
|
|
|
+ }
|
|
|
|
+}</code></pre></div></div>
|
|
<div class="paragraph"><p>For each message type, register a client listener to the client.</p></div>
|
|
<div class="paragraph"><p>For each message type, register a client listener to the client.</p></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">myClient.addMessageListener(<span class="keyword">new</span> ClientListener(), HelloMessage.class);</code></pre></div></div></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">myClient.addMessageListener(<span class="keyword">new</span> ClientListener(), HelloMessage.class);</code></pre></div></div></div>
|
|
<div class="sect3"><h4 id="serverlistener-java">ServerListener.java</h4><div class="paragraph"><p>Create one ServerListener.java and make it extend <code>com.jme3.network.MessageListener</code>.</p></div>
|
|
<div class="sect3"><h4 id="serverlistener-java">ServerListener.java</h4><div class="paragraph"><p>Create one ServerListener.java and make it extend <code>com.jme3.network.MessageListener</code>.</p></div>
|
|
@@ -71,9 +74,10 @@
|
|
<span class="keyword">if</span> (message <span class="keyword">instanceof</span> HelloMessage) {
|
|
<span class="keyword">if</span> (message <span class="keyword">instanceof</span> HelloMessage) {
|
|
<span class="comment">// do something with the message</span>
|
|
<span class="comment">// do something with the message</span>
|
|
HelloMessage helloMessage = (HelloMessage) message;
|
|
HelloMessage helloMessage = (HelloMessage) message;
|
|
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Server received '</span><span class="delimiter">"</span></span> +helloMessage.getSomething() +<span class="string"><span class="delimiter">"</span><span class="content">' from client #</span><span class="delimiter">"</span></span>+source.getId() );
|
|
|
|
|
|
+ <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Server received '</span><span class="delimiter">"</span></span> +helloMessage.getSomething() +<span class="string"><span class="delimiter">"</span><span class="content">' from client #</span><span class="delimiter">"</span></span>+source.getId());
|
|
} <span class="comment">// else....</span>
|
|
} <span class="comment">// else....</span>
|
|
- }</code></pre></div></div>
|
|
|
|
|
|
+ }
|
|
|
|
+}</code></pre></div></div>
|
|
<div class="paragraph"><p>For each message type, register a server listener to the server:</p></div>
|
|
<div class="paragraph"><p>For each message type, register a server listener to the server:</p></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">myServer.addMessageListener(<span class="keyword">new</span> ServerListener(), HelloMessage.class);</code></pre></div></div></div></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">myServer.addMessageListener(<span class="keyword">new</span> ServerListener(), HelloMessage.class);</code></pre></div></div></div></div>
|
|
<div class="sect2"><h3 id="creating-and-sending-messages">Creating and Sending Messages</h3><div class="paragraph"><p>Let’s create a new message of type HelloMessage:</p></div>
|
|
<div class="sect2"><h3 id="creating-and-sending-messages">Creating and Sending Messages</h3><div class="paragraph"><p>Let’s create a new message of type HelloMessage:</p></div>
|
|
@@ -106,7 +110,7 @@ myServer.broadcast(message);</code></pre></div></div>
|
|
myServer.close();
|
|
myServer.close();
|
|
<span class="local-variable">super</span>.destroy();
|
|
<span class="local-variable">super</span>.destroy();
|
|
}</code></pre></div></div></div>
|
|
}</code></pre></div></div></div>
|
|
-<div class="sect2"><h3 id="kicking-a-client">Kicking a Client</h3><div class="paragraph"><p>The server can kick a HostedConnection to make it disconnect. You should provide a String with further info (an explanation to the user what happened, e.g. “Shutting down for maintenance) for the server to send along. This info message can be used (displayed to the user) by a ClientStateListener. (See below)</p></div>
|
|
|
|
|
|
+<div class="sect2"><h3 id="kicking-a-client">Kicking a Client</h3><div class="paragraph"><p>The server can kick a HostedConnection to make it disconnect. You should provide a String with further info (an explanation to the user what happened, e.g. “Shutting” down for maintenance) for the server to send along. This info message can be used (displayed to the user) by a ClientStateListener. (See below)</p></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">conn.close(<span class="string"><span class="delimiter">"</span><span class="content">We kick cheaters.</span><span class="delimiter">"</span></span>);</code></pre></div></div></div></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">conn.close(<span class="string"><span class="delimiter">"</span><span class="content">We kick cheaters.</span><span class="delimiter">"</span></span>);</code></pre></div></div></div></div>
|
|
<div class="sect2"><h3 id="listening-to-connection-notification">Listening to Connection Notification</h3><div class="paragraph"><p>The server and clients are notified about connection changes.</p></div>
|
|
<div class="sect2"><h3 id="listening-to-connection-notification">Listening to Connection Notification</h3><div class="paragraph"><p>The server and clients are notified about connection changes.</p></div>
|
|
<div class="sect2"><h3 id="clientstatelistener">ClientStateListener</h3><div class="paragraph"><p>The com.jme3.network.ClientStateListener notifies the Client when the Client has fully connected to the server (including any internal handshaking), and when the Client is kicked (disconnected) from the server.</p></div>
|
|
<div class="sect2"><h3 id="clientstatelistener">ClientStateListener</h3><div class="paragraph"><p>The com.jme3.network.ClientStateListener notifies the Client when the Client has fully connected to the server (including any internal handshaking), and when the Client is kicked (disconnected) from the server.</p></div>
|
|
@@ -133,13 +137,13 @@ If you do override this, make sure you add a mechanic that can close the client
|
|
<div class="sect1"><h2 id="udp-versus-tcp">UDP versus TCP</h2><div class="sectionbody"><div class="paragraph"><p>SpiderMonkey supports both UDP (unreliable, fast) and TCP (reliable, slow) transport of messages.</p></div>
|
|
<div class="sect1"><h2 id="udp-versus-tcp">UDP versus TCP</h2><div class="sectionbody"><div class="paragraph"><p>SpiderMonkey supports both UDP (unreliable, fast) and TCP (reliable, slow) transport of messages.</p></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">message1.setReliable(<span class="predefined-constant">true</span>); <span class="comment">// TCP</span>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">message1.setReliable(<span class="predefined-constant">true</span>); <span class="comment">// TCP</span>
|
|
message2.setReliable(<span class="predefined-constant">false</span>); <span class="comment">// UDP</span></code></pre></div></div>
|
|
message2.setReliable(<span class="predefined-constant">false</span>); <span class="comment">// UDP</span></code></pre></div></div>
|
|
-<div class="ulist"><ul><li><p>Choose reliable and slow transport for messages, if you want to make certain the message is delivered (resent) when lost, and if the order of a series of messages is relevant. E.g. game actions such as “1. wield weapon, 2. attack, 3. dodge.</p></li><li><p>Choose unreliable and fast transport for messages if the next message makes any previously delayed or lost message obsolete and synchronizes the state again. E.g. a series of new locations while walking.</p></li></ul></div></div></div>
|
|
|
|
|
|
+<div class="ulist"><ul><li><p>Choose reliable and slow transport for messages, if you want to make certain the message is delivered (resent) when lost, and if the order of a series of messages is relevant. E.g. game actions such as “1”. wield weapon, 2. attack, 3. dodge.</p></li><li><p>Choose unreliable and fast transport for messages if the next message makes any previously delayed or lost message obsolete and synchronizes the state again. E.g. a series of new locations while walking.</p></li></ul></div></div></div>
|
|
<div class="sect1"><h2 id="important-use-multi-threading">Important: Use Multi-Threading</h2><div class="sectionbody"><div class="admonitionblock important"><table><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content"><div class="paragraph"><p><strong>You cannot modify the scenegraph directly from the network thread.</strong> A common example for such a modification is when you synchronize the player’s position in the scene. You have to use Java Multithreading.</p></div></td></tr></table></div>
|
|
<div class="sect1"><h2 id="important-use-multi-threading">Important: Use Multi-Threading</h2><div class="sectionbody"><div class="admonitionblock important"><table><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content"><div class="paragraph"><p><strong>You cannot modify the scenegraph directly from the network thread.</strong> A common example for such a modification is when you synchronize the player’s position in the scene. You have to use Java Multithreading.</p></div></td></tr></table></div>
|
|
<div class="paragraph"><p>Multithreading means that you create a Callable. A Callable is a Java class representing any (possibly time-intensive) self-contained task that has an impact on the scene graph (such as positioning the player). You enqueue the Callable in the Executor of the client’s OpenGL thread. The Callable ensures to executes the modification in sync with the update loop.</p></div>
|
|
<div class="paragraph"><p>Multithreading means that you create a Callable. A Callable is a Java class representing any (possibly time-intensive) self-contained task that has an impact on the scene graph (such as positioning the player). You enqueue the Callable in the Executor of the client’s OpenGL thread. The Callable ensures to executes the modification in sync with the update loop.</p></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">app.enqueue(callable);</code></pre></div></div>
|
|
<div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">app.enqueue(callable);</code></pre></div></div>
|
|
<div class="paragraph"><p>Learn more about using <a href="../../jme3/advanced/multithreading.html">multithreading</a> in jME3 here.</p></div>
|
|
<div class="paragraph"><p>Learn more about using <a href="../../jme3/advanced/multithreading.html">multithreading</a> in jME3 here.</p></div>
|
|
<div class="paragraph"><p>For general advice, see the articles <a href="https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking">MultiPlayer Networking</a> and <a href="https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization">Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization</a> by the Valve Developer Community.</p></div></div></div>
|
|
<div class="paragraph"><p>For general advice, see the articles <a href="https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking">MultiPlayer Networking</a> and <a href="https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization">Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization</a> by the Valve Developer Community.</p></div></div></div>
|
|
-<div class="sect1"><h2 id="troubleshooting">Troubleshooting</h2><div class="sectionbody"><div class="paragraph"><p>If you have set up a server in your home network, and the game clients cannot reach the server from the outside, it’s time to learn about <a href="http://portforward.com/">port forwarding</a>.</p></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2019-12-23 13:36:15 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
|
|
|
|
|
|
+<div class="sect1"><h2 id="troubleshooting">Troubleshooting</h2><div class="sectionbody"><div class="paragraph"><p>If you have set up a server in your home network, and the game clients cannot reach the server from the outside, it’s time to learn about <a href="http://portforward.com/">port forwarding</a>.</p></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2020-01-20 22:16:07 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
|
|
apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
|
|
apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
|
|
indexName: 'jmonkeyengine',
|
|
indexName: 'jmonkeyengine',
|
|
inputSelector: '#doc-search',
|
|
inputSelector: '#doc-search',
|