Zay-ES-Net tutorials and references?

I saw that post before and was definitely interested but was still worrying about zay-es-net at the time. Now that it seems like I am putting that part of the game off, I will be happy to participate :smiley:.

Oh I’m very glad to read that :slight_smile: please tell me if you meet issues !

Note: when JME alpha 2 is released (any time now), I will put together a self-contained small zay-es-net test that can be run from command line with gradle.

2 Likes

The error went away with alpha2 :smiley: is there anything I have to do in the client side to update the EntityData instance? Im generating a new position of a cube on the server but still only getting the original position (also set by server). Im sending out the position every second.

EDIT: I think this is an error on my side as entities.applyChanges() evaluates true every second.

EDIT2: So it turns out to add the entity on the client side, the Model.class name is correct but the Vector3fs always come as (0, 0, 0) which im still trying to figure out why.

EDIT3: So it seems to be sending the empty constructer version of each of the EntityComponents, and I never call the empty constructer myself. Otherwise it updates on schedule and the client knows when something has added/removed/or updated.

Client Side: Visual App State

 @Override
public void initialize(AppStateManager stateManager, Application app){
    this.app = (SimpleApplication)app;
    this.edcs = stateManager.getState(ClientState.class).getClientService(); //might have to do this per update
    this.ed = this.edcs.getEntityData();
    this.entities = ed.getEntities(Position.class, Model.class);
    ...
}
@Override
public void update(float tpf) {
    if (entities.applyChanges()) { //this is pretty much the same as the tutorial that someone just
        removeModels(entities.getRemovedEntities());  posted
        addModels(entities.getAddedEntities());
        updateModels(entities.getChangedEntities());
    }
}

Server Side: Game App State

@Override
public void update(float tpf) {
    Vector3f position = new Vector3f(randomRangedFloat(),randomRangedFloat(), 0);
    System.out.println(position);
    shipSet.applyChanges();
    shipSet.stream().findFirst().ifPresent(e -> {
        System.out.println("Found");
        e.set(new Position(position));
    });  
}

Server Side: Server App State

@Override
public void update(float tpf){
    System.out.println("Sending Updates");
    edhs.sendUpdates();
}

Yes, serialization must instantiate the empty constructor version and then it sets the fields.

So is it working now or not? That wasn’t clear.

If it’s not working then I also need to see your other classes like Model, etc.

Sorry! no it is not working, the client only receives the empty constructor version of the component only and I cannot seem to get any updated components (although it knows when they are updated).

My Model Component:

@Serializable
public class Model implements EntityComponent {
    private final String name;
    public final static String SpaceShip = "SpaceShip";
    public final static String BasicInvader = "BasicInvader";
    public final static String Bullet = "Bullet";

public Model(){
    this.name = SpaceShip;
}

public Model(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

@Override
public String toString() {
    return "Model[" + name + "]";
}

My Position Component:

@Serializable
public class Position implements EntityComponent{

private final Vector3f location;
private final Vector3f rotation;

public Position(Vector3f location, Vector3f rotation) {
    this.location = location;
    this.rotation = rotation;
}

public Position(Vector3f location) {
    this (location, new Vector3f(0, 0, 0));
}

public Position(){
    this(new Vector3f(0, 0, 0), new Vector3f(0, 0, 0));
}

public Vector3f getLocation() {
    return location;
}

public Vector3f getRotation() {
    return rotation;
}

@Override
public String toString() {
    return getClass().getSimpleName() + "[" + location + ", " + rotation + "]";
 }
}

The Input and Update are not components and not really used now.

Here is the initialization of the Game App State:

@Override
public void initialize(AppStateManager stateManager, Application app) {

    this.app = (SimpleApplication) app;
    this.ed = this.app.getStateManager().getState(EntityDataState.class).getEntityData();

    EntityId ship = ed.createEntity();
    this.ed.setComponents(ship,
            new Position(new Vector3f(0f, -20f, 0f)),
            new Model(Model.SpaceShip));
    
    shipSet = ed.getEntities(
            Filters.fieldEquals(Model.class, "name", Model.SpaceShip),
            Model.class,
            Position.class
    );
}

Let me know if I need to add more.

Remove the ‘final’.

Also, this constructor should do nothing… and now you can even make it protected and SpiderMonkey won’t care.

I mean, if you really want to have a public no-arg constructor then I guess keep it. It just means you needlessly create an extra two vector3f objects every time the object is unserialized.

It works!!! So I am asumming if you use zay-es-net you lose some of the advantages to having immutable data that is recommended in just plain zay-es?

If you want I can put this example on github after I clean it up so other people do not get as stuck as me :slight_smile: (im pretty sure there is not even a small example that is anywhere?)

With fasterXML and many other serialization frameworks, you have to write a constructor with anotated parameters for the serializer to know which param is which field. This allow final fields. Maybe there is something similiar in jme.network.serializing.

Not really. Those field values weren’t really immutable anyway (like you can set the x,y,z of the vector3fs, for example)… so ‘immutability’ is largely a developer restraint.

Just because those fields aren’t final, doesn’t mean that users of your class can set them. Don’t provide setters… then they can’t set them.

Nah, nothing like that was ever added. It’s a bit cumbersome anyway and cannot detect properly whether the final fields types are really final classes and stuff. I mean, it could work but it would be a lot of potentially buggy code to little effect.

General advice: follow the few rules. Use a little discipline to make immutable objects.

If you really really really want to use final fields, you can also write your own serializer for your object. Personally, I think convenience far trumps ‘pure correctness’ in this case.

If anyone is interested the full example is here GitHub - allenj12/zay-es-net-example: a very brief example of zay-es-net . its very basic but should be everything you need to get started,

Nice. I’ve started one last night also. I have a basic server and just have to write a basic client.

I will post back when it’s done.

It will live here when I commit it: GitHub - Simsilica/Examples: Example applications for various Simsilica libraries, singly or in combination.

Full basic Zay-ES-Net example and documentation here:

1 Like

+1
That is super cool. I will study it. Can I maybe - after I understood it - make a wiki case study out of it? With some explain?

Sure. If you like.