I have been running my bot and I’ve noticed that the deserializer does not map to my GameStateDto object correctly, ticks and timeStamp are always correctly mapped but the lists of animals, cells and zookeepers are not, for instance the AnimalDto and ZookeeperDto have their spawn points correctly mapped and for the cells nothing is mapped , I’ve only changed the Number of bots to 1 in the game settings and I’m not sure how to proceed from here.
At first i thought the mapper was case-sensitive and changed all the fields for my Dto classes to match those from the payload…nothing changed
I tried to map the payload to a string instead of the GameStateDto to see the raw data from the server but this throws an error since the payload is a Json object instead of a string and Gson cannot map json to a string.
I am running the engine locally not through a container, any suggestions
P.S I’ve also tried running the engine image on docker but it always returns before my bot can connect to it ,even when i run it in detached mode
With JavaScript I use JSON.stringify(var) to console.log and debug my variables,
Dont know if your language has a similar function that you can maybe add temporarily?
I am using java , the problem is that I don’t have access to the raw payload, I can only access the payload from the “GameState” callback function and by that time it’s already too late since gson has already deserialized the payload into a GamestateDto( GameState in JS) object.
Using a debugger i was able to look at the returned game state, that’s where i saw that some of the instances where missing values and I overrode the toString function in each of my classes, so i can easily call the toString on each class instance to see whats going on.
I looked at the starter JS bot, the state variable from the code below is already deserialized so i can’t do much with it connection.on("GameState", (state) => { console.log("Game state received"); });
The only reasonable way forward would be to parse a custom Gson deserializer to the hubconnectionbuilder which I’m still trying to figure out.
Do you by any chance know a way to intercept the game state before it can be deserialized?
You can do:
connection.on(“GameState”, (state) => {
console.log(“Game state received”);
console.log(JSON.stringify(state)); // Full state as JSON string
console.log(JSON.stringify(state.cells)); // Just the ‘cells’ portion
});
Or store the variables
A small example, In JS I do the following to store my own animal in variable ma:
an=state.animals;
ma=an.find(animal => animal.id === token);
mx = ma.x;
my = ma.y;
console.log(“Score:”+JSON.stringify(ma.score));
Id expect in Java youd take a similar approach.
But I use Javascript because of its opensource nature.
I remap the received state and then manipulate my own variables.
So fellow Java coder here. I know your pain. It’s just that I kinda know what to change from past challenges over the years. Can’t really remember what I did in the past exactly to print out the raw payload but probably had something to do with playing around with the Gson libraries or what @WillieTheron stated.
But to answer more directly on your issue, you were correct on making sure that the variable naming is correct and case sensitive to what’s being sent (you can also check on the game engine’s side if you can’t log the payload to see the variable naming of the Dto classes). Personally, I use int over Enum for the mapping part (I convert back to Enums internally - but there might be better ways of doing that. I just do what works.)
Below is a sample of the changes I made to help map the CellDto class. Hope it’s a good starting point. Maybe the correct way would be to submit a pull request to Entelect to fix the Java starter bot Dto classes.
package Models.Dtos;
import Enums.CellContent;
public class CellDto {
public int x;
public int y;
public int content;
public int getX() {
return x;
}
public void setX(int x) {
x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
y = y;
}
public CellContent getContent() {
return CellContent.values()[content];
}
public void setContent(CellContent cellContent) {
this.content = cellContent.ordinal();
}
}
Gson is not case-sensitive by default when matching Java field names to JSON property names during deserialization, but it is case-sensitive for the JSON keys themselves
so alot of the fields that where provided in the java classes matched(in some cases) the JSON keys of the payload but that should not be the case, they should however follow a camel case naming convention on the client side
Sometimes the default representation is not what you want. This is often the case when dealing with library classes (DateTime, etc.)
And for fields such your Id and timestamp you would need to change their types( to strings) to allow for easier mapping you can always internally convert them back to which ever type you desire.
Lastly you would need to convert the command/ action field from Enum to an int since the BotCommand expects an int representing the value of the move instead on an Enum something like {"Action" : 1} instead of {"Action" : "UP"}