Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add serialiable and flatbufferable representations of World and Tank #27

Merged
merged 5 commits into from
May 15, 2020

Conversation

mluogh
Copy link
Collaborator

@mluogh mluogh commented May 14, 2020

This adds native Rust structs for World and Tank, as well as useful Serializable and Flatbufferable traits.

This allows us to easily manipulate structs on the backend while easily being able to wire information the client.

Test Plan:
covered in serialization.rs . cargo test will test serialization and flatbuffering.

use crate::world::{Tank, World};

pub trait Serializable {
fn serialize(&self, builder: &mut FlatBufferBuilder, config: &Config) -> Vec<u8>;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Serializable takes a flatbuffer because we allocating a new FlatbufferBuilder every time we call this function is extremely inefficient.

I know this is not the API we discussed, but I think this is a valid price to pay.

server/src/serialization.rs Outdated Show resolved Hide resolved
server/src/serialization.rs Outdated Show resolved Hide resolved
server/src/main.rs Outdated Show resolved Hide resolved
server/src/serialization.rs Outdated Show resolved Hide resolved
server/src/serialization.rs Outdated Show resolved Hide resolved
use crate::world::{Tank, World};

pub trait Serializable {
fn serialize(&self, builder: &mut FlatBufferBuilder, config: &Config) -> Vec<u8>;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not take in a builder. You clear the builder anyway, and the caller of the API should not need to construct a builder

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reset() does not clear owned buffer from FlatBufferBuilder. It will reuse this buffer.

google/flatbuffers#5135


let recovered_tank = get_root::<world_generated::Tank>(builder.finished_data());

assert_eq!(recovered_tank.pos().unwrap().x(), tank.pos_ref().x);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use results instead of unwrap

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pos() returns an Option, not Result.

At any rate, an unwrap() in a test is not a big deal, crashing will cause an error which is what we want.

use crate::math::Position;

pub struct World {
tanks: Vec<Tank>,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this not have dimensions

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary for v0.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite necessary @yizzlez

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? There are no boundaries restricting movement in v0.

server/src/world.rs Outdated Show resolved Hide resolved
server/src/world.rs Outdated Show resolved Hide resolved
world.add_tank(Tank::new(1, Position { x: 23.0, y: 54.0 }));
world.add_tank(Tank::new(2, Position { x: 84.0, y: 34.0 }));

let world = Arc::new(world.serialize(&mut builder, &Config::new(0)));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The maintained state should be the rust WOrld struct, not the Buffer itself. We modify the World struct during processing and only serialize into message when we broadcast to clients

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this to interoperate into the existing code as easily as possible. We can start using a real World in a future pr.

}

trait Flatbufferable<'a> {
type Buffer;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump

}
}

impl<'a> Flatbufferable<'a> for Tank {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump

server/src/serialization.rs Outdated Show resolved Hide resolved
player.len(),
config.player_id
);
return Err(anyhow!(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a TODO to use thiserror for error handling since we can treat this serialization module as its own library not application

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like treating serialization module as own library because it directly interfaces with our game logic.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sire you misunderstand. anyhow is the preference for application code, and thiserror is the preference for library code. Here, you have written a nice serialization library.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can table this, it's interfering with velocity. But if the server ever needs different handling for each serialization error type, then we will need to define error types.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See second comment. The serialization module is not much of a library since it will have a lot of game logic (e.g. sorting between teammates and enemies when serializing tank).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No other application can use our serialization "library" other than ours.

server/src/serialization.rs Outdated Show resolved Hide resolved
server/src/serialization.rs Outdated Show resolved Hide resolved
use crate::math::Position;

pub struct World {
tanks: Vec<Tank>,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite necessary @yizzlez

@mluogh mluogh merged commit 95818b6 into master May 15, 2020
@mluogh mluogh deleted the mluogh/game branch May 15, 2020 02:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants