Server and Client on one instance of a game

Hello,
this topic might be more appropriate to be put in the library category, but this is not suposed to be a question about any library.

In Minecraft in some very early update, offline singleplayer worlds were given multiplayer features. If you’re playing on a singleplayer world, you basically have a server and a client connected to the server without an internet connection in the same instance of the game and you’re controlling that client.

My question is how to do this exact thing.
I am working on a sequel to my game DubTank, which I didn’t have a chance to release in time, because like a week before my planned release a game called Diep.io came out, which is pretty much DubTank with a different look.
Right now I want to have a working LAN-based server; I don’t care about a global server right now as me and my friends are going to test it and we won’t have a 24/7 online server to connect to.
Also, I’d like to have 2 or more offline clients connected to the server (for splitscreen);

1 Like

From a programming perspective, there isn’t a huge difference between a local server and a global server. The only difference is that you run a local server on your own computer, and you run a global server on a service like AWS or Google Cloud.

(You can also set your computer up as a global server, but that’s not really what you’re asking about.)

Start looking into server-side development, and start with a local server. That’s how you should start whether you’re planning on eventually implementing a global server or not.

What you can do is have two separate projects together, one is the server, one is the client, the server handles the logic and the client draws whatever’s supposed to be drawn. When you start a new singleplayer session on the client, start the server and connect to localhost:9001 (or whatever your port is). This way you can have a singleplayer session backed by the server.
The main advantage of such a session is that you can now allow other players on your LAN to connect to your computer and play locally.

So basically, I have to make:
A server, that handles calculations, data and incoming input.
Client, that handles drawing, interactions with mouse, screen, keyboard etc. and sending user input.

Then I can make multi-platform game, that will differ in controls and have the same features. This is useful, because I have to make the game code only for the server.

Also, question:
Can I have a client connected to a server on the same device?

Yes, you can. You can have even one server and multiple clients in the same machine. The code from this should be a good starting points. You can check the library documentation and see if it suits your needs.

Kf

Of course you can! Just connect to localhost under your game server’s port (for example, if the server’s port is 1234 you connect to the IP address localhost:1234. To do so, you use the Client class, with the constructor new Client(this, "localhost", 1234)).

If I ran the server and the client separatelly on Android one of them wouldn’t work on older versions. Can I do that from a single sketch?

I tried having the “client” interact with the server by calling methods. That is difficult and I still need to implement network clients, so I have two different things that will tell the server to do one thing two different ways.

Also, I haven’t touched the networking since the start of the topic. I am implenenting kind of command-based interaction system.
Basically I send the server a string “shoot” and the server processes it and calls shoot(int playerID). Is it a good approach?

What do you mean by “it wouldn’t run on older versions”?

That approach where you send the server a string like ‘shoot’ is pretty OK, until you start having problems with either a) performance, b) string lengths.
If I were you, I’d probably just send the server a byte signifying a player just shot. I’d do this, because bytes have a constant size (1 byte), and I don’t have to worry about lengths. If I have to pass some arguments with my bytes, I send that argument to the server in bytes aswell, eg. an int = 4 bytes, and then the server would receive those based on the first one of the sequence. Creating the data to send could be done with the java.nio.ByteBuffer. ByteBuffer has functions to deal with converting bytes to arrays, you can use it like so:

// we allocate 5 bytes, because our instruction is (byte, int) for (command, someIntegerArgument), adding the byte numbers of byte (1) and int (4) gives us 5
// then we put a byte of value 2, and an int of value 32
// you can read more about the ByteBuffer here:
// https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html
ByteBuffer.allocate(5).put(2).putInt(32).array();

This will create an array with a byte 2 and your int converted to bytes. Remember that:

  • byte = 1 byte (duh) (8-bit)
  • short = 2 bytes (16-bit)
  • char = 2 bytes (16-bit)
  • int = 4 bytes (32-bit)
  • float = 4 bytes (32-bit)
  • long = 8 bytes (64-bit)
  • double = 8 bytes (64-bit)
    Good luck!
1 Like

I suggest you create a small version testing a server-client setup and convince yourself how it works. You can use the net library in Processing. Not sure if it will work on Android though. Another alternative is oscP5 which works on supported mobile devices.

How many clients will your server manage?

Kf

@kfrajer I can’t use any libraries in APDE, because of a bug I’ve reported. I can still use Android version in desktop PDE. Though I wish the APDE libraries were fixed. I write code mostly on my phone. I am currently testing it on a game of Pong (because it’s easy to write). I want to have a working network on something simple before I implement it to DubTank 2. With friends we’ve been able to run 6 clients at once (4 being spectators) without any lag. Not sure, how DubTank 2 will handle things. It’s way more complicated game with more data to send to clients.

@Iqdev I thought that might be the way to go, but I wasn’t sure. It might be more useful to use bits.
In Pong I use only these commands:

Pong Command List

Bots don’t have clients. They’re there just so that the game works. However bots use commands as well, because why make things complicated?
By default all players can use commands (like admins), because the game is for testing only.

  • goto int:playerID float:position set a position to move towards
    (If a player doesn’t control a paddle, nothing happens)
  • restartround restarts current round (duh)
  • restartgame restarts whole game (duuuuh)
  • spectator become a spectator
  • paddle int:playerid int:paddleID Gain control of a paddle
    (If no player has control of a paddle, a bot takes over)
    (If a paddle is taken, nothing happens)
  • swappaddles Swap paddles between players (or bots)
  • **disconnect int:playerID disconnects a player
  • **set String:property float:value Set a value to something in game (i.e. set paddle0size 200)
  • timescale float:timescale Slows down a game or speeds it up. (Mainly so I can )
    For bot movement:
  • paddlegoto int:paddleID float:position sets a position to move towards for a paddle

That works just fine. There’s not much delay, because it is a simple game running on LAN.
On Android, I still haven’t decided between

  • Tap to target and move
  • Use a controler to move and the rest of the screen to aim and shoot
    Depends on how efective the nework will be…
    Maybe I’ll do both, toggle in settings in server creation.
DubTank 2 Command List

An admin (also the creator of the server) can control other palyers like this. Also I plan to use those commands to control the players character by sending them from their client. I can even control a bot by sending commands.
However this aproach has a big flaw. It can be used for cheating.

So I need 1 byte for command type and the rest as parameters. Chat is fine, because unless someone spams messages, there will be at most 1 message per second. And even if that’s the case, I can limit the amount of messages sent.

Well, I’ll have to learn to work with just bytes.