Best way to manage entities in a client-server model

Hey JGO,

Just started porting my game to multiplayer (No, I don’t know why I’m putting myself through this either), and I’m wondering how you guys think the best way to go about entity creation and removal management would be.

Obviously I can’t just send the entire Entity class from the server to the client with all the render data attached, but my issue is what system must I then use to differentiate between types of entities.

Is the only way to send a byte or integer code unique to each entity and then have a massive selection statement client-side that instantiates a render-only instance of each entity?

Interested to hear how you guys have solved this problem if you’ve come across it!

Thanks!

I didn’t do something like that so far, but isn’t the server supposed
to just do the logic and inform about updates? Normally the client
knows about every entity and what it can do, while the server orders
it to do something. If this couldn’t help you can you tell more precisely
what exactly you want to do? Or show your project?

If you want to send whole classes over maybe check out KryoNet.

Greetings

The issue is the world is dynamic and entities will be added and removed server-side. When the server say spawns a pig (for example) what’s the best way of communicating to the client that it was a pig entity that was spawned and how can the client differentiate between a pig and a sheep (for example)

Well… the easiest way would be to give each entity an ID. Then send
a packet like:

spawn::x,y,z

As an easy example. You could also use IDs for commands to save more bandwidth.

Yes, that’s the method I am considering using at the moment, but the limitation of this would be I would need a massive selection statement in the client program like this :


if (id == 0)
//Entity is a pig
if (id == 1)
//Entity is a sheep
//etc....

meaning I need to add to this every time I add new entities to the game. I was wondering if there were any cleaner solutions to this issue?

You declare each entity like:

public static final Entity PIG = new Entity(0);

then you store each entity in an array by using the ID as index:

entity[0] would contain PIG
entity[1] contains SHEEP

and so on…

Yeah, that seems like a bit better than my way, still has the issue of having to be done for each new entity however. Maybe that’s just the way I’ll have to do it

Its better if you handle the rendering part outside the entity class. You just have one single instance of each entity in that array and check with the id what type it is. Then just copy the saved instance and work with it a copy.

Another way:

Create a class EntityPig or EntitySheep which extends the basic entity and store those inside the array like:

entity[0] = EntityPig.class;

Now you can instantiate a new entity from this class object by calling newInstance() (if you need parameters look into getDeclaredConstructor())

In my multiplayer sandbox game, I send entire entities only when creating. Each entity has a UUID (normally supposed to be 128 bits but I used 64 because it’s just a long and easier to work with). When removing it’ll send the UUID of the to-be-removed entity (if the entity with the UUID doesn’t exist for some reason the client will ignore the packet). Updating entities’ positions is merely an array of UUIDs and another array of floats that correspond for each entity’s position.

If you are using Kryonet, the below will be a breeze because Kryonet can serialize and deserialize object graphs over the network extremely efficiently. If not, I suggest you do try it and see how you like it.

As for render data, that’s client-side only. I can mark fields as not-needed to be sent over the network by using the transient keyword. Of course, in order for Kryonet to create objects they will need an empty constructor where it can be instantiated and then the rest of the information can be filled in.

You won’t need to assign IDs for each entity. IDs for that are really a pain because if you remove a type then you have an annoying gap in your sequence of numbers. With Kryonet you can merely register the entity’s class and it’ll tell the serializers how to work with that type of object.

Kryonet was designed to be really fast and efficient, so it’s perfect for games. The only time you’re sending an entire entity’s worth of data is when it’s being created. Anything else merely uses the UUID to look up the entity.

I hope that helps!