📜 ⬆️ ⬇️

Reddwarf on the example of the online game "Stone-Scissors-Paper": Client

In the Reddwarf article for creating a Java server using the example of the online game Stone-Scissors-Paper: The server described how to make a server. But playing on such a server without a client is impossible. Therefore, in this article we will try to write the simplest client and experiment with the server.


Preparation for work


To develop a client, download the Reddwarf client libraries in the sgs-client-dist-0.10.2.zip archive from here .
Create a project and connect to it all the libraries from the lib directory of the downloaded archive.

Shortly about the client


Strangely enough, but an attempt to write a command line client led to more cumbersome and confusing code, so the client will be doing a graphic on Swing.
The client part of our game will consist of two classes - the client and the GUI.
The client implements the SimpleClientListener interface - it receives connect / disconnect events and messages from the server. In response to incoming messages, the client will notify the GUI. In addition, all information about the protocol will be contained only in this class, so he will be in charge of sending messages.
')

Connection and Authentication


Connect to the specified server on port 62964 - this is the default port for Reddwarf.
For authentication, we will use the simplest (and, probably, the most frequently used in Reddwarf) authentication method - PasswordAuthentication. Since our server does not verify the password, the password is left blank.

Client.java code in full
public class Client implements SimpleClientListener { private SimpleClient simpleClient; private final String host; private final String username; public static final String DEFAULT_PORT = "62964"; private final ClientFrame frame; public Client(String host, String username, ClientFrame frame) { this.host = host; this.username = username; this.frame = frame; simpleClient = new SimpleClient(this); } @Override public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, new char[]{}); } @Override public void loggedIn() { frame.loggedIn(); } @Override public void loginFailed(String s) { frame.setStatus("login failed " + username+": "+s); } @Override public void receivedMessage(ByteBuffer packet) { String text = Messages.decodeString(packet); if (text.startsWith("SCORE")) { frame.setScore(text); } else if (text.startsWith("BATTLE")) { frame.startBattle(text); } else if (text.startsWith("DRAW")) { frame.setBattleResult(text); } else if (text.startsWith("WON")) { frame.setBattleResult(text); } else if (text.startsWith("LOST")) { frame.setBattleResult(text); } else if (text.startsWith("ERROR")) { frame.setStatus(text); } } public void login() { try { Properties connectProps = new Properties(); connectProps.put("host", host); connectProps.put("port", DEFAULT_PORT); simpleClient.login(connectProps); } catch (Exception e) { e.printStackTrace(); disconnected(false, e.getMessage()); } } public void play() { try { simpleClient.send(Messages.encodeString("PLAY")); } catch (IOException e) { e.printStackTrace(); } } public void answer(String text) { try { simpleClient.send(Messages.encodeString(text)); } catch (IOException e) { e.printStackTrace(); } } } 


User interface


GUI is a simple form with input fields and buttons:


The source code of the ClientFrame.java form can be viewed here.

The code of the Messages.java class is similar to the same file from the previous article.

Hurray, run!


The code is ready, you can start the server and clients and see what happens.
We start the server.
  03, 2012 6:53:29 PM com.sun.sgs.impl.kernel.Kernel <init> INFO: The Kernel is ready, version: 0.10.2.1  03, 2012 6:53:29 PM com.sun.sgs.impl.service.data.store.DataStoreImpl <init> INFO: Creating database directory : C:\sgs-server-dist-0.10.2.1\data\dsdb  03, 2012 6:53:29 PM com.sun.sgs.impl.service.watchdog.WatchdogServerImpl registerNode INFO: node:com.sun.sgs.impl.service.watchdog.NodeImpl[1,health:GREEN,backup:(none)]@black registered  03, 2012 6:53:30 PM hello.reddwarf.server.Server initialize INFO: Starting new Rock-Paper-Scissors Server. Initialized database.  03, 2012 6:53:30 PM com.sun.sgs.impl.kernel.Kernel startApplication INFO: RockPaperScissors: application is ready  03, 2012 6:53:30 PM hello.reddwarf.server.OnlineLoggerTask run INFO: Online: 0 

We launch two clients:


Login with one and the other client:

As we see, both players have 0 points in the account.

The server log does not keep you waiting: since we started the server for the first time, there are no players in the database, player1 and player2 players are automatically registered.
  03, 2012 6:53:47 PM hello.reddwarf.server.Server loggedIn INFO: Client login: player2  03, 2012 6:53:47 PM hello.reddwarf.server.Server loadOrRegister INFO: Registering new player player2  03, 2012 6:53:48 PM hello.reddwarf.server.Server loggedIn INFO: Client login: player1  03, 2012 6:53:48 PM hello.reddwarf.server.Server loadOrRegister INFO: Registering new player player1  03, 2012 6:53:50 PM hello.reddwarf.server.OnlineLoggerTask run INFO: Online: 2 


We press one of the players on the Play - the server automatically selects the second player as an opponent and the battle begins:


The log shows that the server has created a new battle. The server is waiting for players to answer
  03, 2012 6:53:54 PM hello.reddwarf.server.Player play INFO: Choosing enemy for player1  03, 2012 6:53:54 PM hello.reddwarf.server.Battle <init> INFO: Created Battle{2} for {player1} and {player2}  03, 2012 6:53:54 PM hello.reddwarf.server.Battle start INFO: Started Battle{2} 


Players respond:

  03, 2012 6:53:56 PM hello.reddwarf.server.Battle answer INFO: Battle{2} Player {player1} answer ROCK  03, 2012 6:53:57 PM hello.reddwarf.server.Battle answer INFO: Battle{2} Player {player2} answer PAPER 


The server waits for the end of the battle time and sums up:

  03, 2012 6:53:59 PM hello.reddwarf.server.Battle finish INFO: Battle{2} finished. Answers: {player1}->ROCK {player2}->PAPER 


On the client, you can see the results of the battle and how the number of points changed: the winner won 2 points, the loser got zero.


In order to make sure that the data is saved - disconnect the client, restart the server and reconnect player Player2.
 java -jar bin/sgs-stop.jar java -jar bin/sgs-boot.jar 


We are connected by the client: honestly earned 2 points are preserved.


During the restart, the following messages may appear in the log (with the glass trace):
 WARNING: Task has been retried 25 times: com.sun.sgs.impl.service.session.ClientSessionServiceImpl$RemoveNodeSpecificDataTask[owner:app:RockPaperScissors] WARNING: Task has been retried 25 times: com.sun.sgs.impl.service.channel.ChannelServiceImpl$RemoveChannelServerProxyTask[owner:app:RockPaperScissors] WARNING: Task has been retried 50 times: com.sun.sgs.impl.service.session.ClientSessionServiceImpl$RemoveNodeSpecificDataTask[owner:app:RockPaperScissors] WARNING: Task has been retried 50 times: com.sun.sgs.impl.service.channel.ChannelServiceImpl$RemoveChannelServerProxyTask[owner:app:RockPaperScissors] WARNING: Task has been retried 75 times: com.sun.sgs.impl.service.session.ClientSessionServiceImpl$RemoveNodeSpecificDataTask[owner:app:RockPaperScissors] WARNING: Task has been retried 75 times: com.sun.sgs.impl.service.channel.ChannelServiceImpl$RemoveChannelServerProxyTask[owner:app:RockPaperScissors] 


They appear due to the fact that when the server starts there are many simultaneous calls to common server objects. Since multithreading in Reddwarf is based on non-blocking synchronization, conflicting transactions are refused and a second attempt is made to perform actions. The platform is configured in such a way that with a large number of rollbacks of the same transaction, a message is displayed in the log. When starting the server, these messages should not cause concern, but the appearance of such messages while the server is running speaks of bottlenecks in the server logic code.

The source code of the client and server is laid out on code.google.com , it can be downloaded from SVN:
  svn checkout http://reddwarf-rock-paper-scissors-example.googlecode.com/svn/trunk/ reddwarf-rock-paper-scissors-example-read-only 

And if you do not want to mess with the source, then the compiled versions of the client and server can be found here: code.google.com/p/reddwarf-rock-paper-scissors-example/downloads/list
The client is started with the command
  java -jar HelloReddwarfClient.jar 

To start the server, the deploy.jar file must be copied to the sgs-server-dist-0.10.2.1 / deploy / directory and execute the server start command:
  java -jar bin / sgs-boot.jar 


Thanks for attention. I will be glad to any constructive criticism.

Source: https://habr.com/ru/post/138039/


All Articles