Kryonet - Passing players

Hello!

I have an ArrayList on my gameserver. I need to transfer this to all clients, to show the players and set their locations.
However, as far as i’ve been able to read, Kryonet doesn’t accept objects with constructors (Player obviously have that) so i can’t just send the ArrayList.

How can i get the ArrayList to the clients? :slight_smile:

Trying just to pass it with the constructor gives this:


Exception in thread "Client" com.esotericsoftware.kryonet.KryoNetException: Error during deserialization.
	at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:141)
	at com.esotericsoftware.kryonet.Client.update(Client.java:239)
	at com.esotericsoftware.kryonet.Client.run(Client.java:317)
	at java.lang.Thread.run(Thread.java:680)
Caused by: com.esotericsoftware.kryo.KryoException: Class cannot be created (missing no-arg constructor): NFT.Player
Serialization trace:
playerList (NFT.Network$PlayerList)
	at com.esotericsoftware.kryo.Kryo.newInstantiator(Kryo.java:1048)
	at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:1060)
	at com.esotericsoftware.kryo.serializers.FieldSerializer.create(FieldSerializer.java:228)
	at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:217)
	at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:735)
	at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:109)
	at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:18)
	at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:654)
	at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.read(FieldSerializer.java:605)
	at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:221)
	at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:735)
	at com.esotericsoftware.kryonet.KryoSerialization.read(KryoSerialization.java:57)
	at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:139)
	... 3 more

And my Player class:


public class Player {
    
    private int playerId;
    private String name;
    private int playerX;
    private int playerY;
    private String figure;
    
    public Player(String name, int positionX, int positionY, int playerId) {
        this.name = name;
        this.playerX = positionX;
        this.playerY = positionY;
        figure = "NFT/player.png";
        //setRandomPosition();
    }
    
    public int getX() {
        return playerX;
    }
    
    public int getY() {
        return playerY;
    }
    
    public void setPosition(int x, int y) {
        this.playerX = x;
        this.playerY = y;
    }
    
    public String getFigure() {
        return figure;
    }
    
    public int getId() {
        return playerId;
    }
    
    public String getName() {
        return this.name;
    }
    
    public void setRandomPosition() {
        int randomX = 5 + (int)(Math.random() * ((768 - 5) + 1));
        int randomY = 5 + (int)(Math.random() * ((512 - 5) + 1));
        int newX = Math.round(randomX / 50) * 50 + 25;
        int newY = Math.round(randomY / 50) * 50 + 25;

        int tileCoordY = newY - (newY % 50);
        
        int finalX;
        int finalY = newY;
        if (tileCoordY % 2 == 1) {
            finalX = newX + 25;
        }
        else {
            finalX = newX;
        }
        
        setPosition(finalX, finalY);
    }
}

You just recreated the same topic for the same problem that I believe should be fixed.

Packet class


public class PlayerPacket(){
public ArrayList<Player> otherPlayers;
}

How your going to be sending the packet from the server to the client? im guessing?


PlayerPacket packet = new PlayerPacket();

//where players is the arraylist of players that the server contains.
packet.otherPlayers = players;

server.sendToAllTCP(packet);

You could of posted in your old topic, did not work, or better explanation instead of creating a whole new topic for the same question by the same person.

This is how I send packets through my server. the PlayerPacket should be pretty much the only code needed in the class.

edit: commented one line of code.

edit 2:
The only problem I had with ArrayLists for entities to be sent the size that is being sent can easily be to big, Im not sure if their is away to allow for bigger packet sizes.

That’s what i’m doing already, and that’s what’s causing the error.

Packet class:


        static public class PlayerList {
            public ArrayList<Player> playerList;
        }

Server sending the packet:


                        PlayerList toClient = new PlayerList();
                        toClient.playerList = playerList;
                        server.sendToAllTCP(toClient);

Hmm ok, Im getting the same thing for ArrayLists now.

I guess its definitely pass what I know, so I will be reading to find out how this is fixed. I have an Idea but I think it may be unecessary to recreate every entity via the client, and only sending required info to the client to create the entity (like username/id, x and y pos etc)

I’m not very familiar with “Kryonet” but it seems like it assumes a no args constructor exists since there’s no way for the library itself to distinguish parameters from each other (x, y, etc., conflicting types with no runtime information other than their order in the constructor.) You should add a default constructor to the class and see if that solves your problem.


public Player() {
    this("name", 0, 0, "img.png");
}