| @@ -1510,6 +1510,7 @@ dependencies = [ | |||
| "glc", | |||
| "glutin", | |||
| "glyph_brush", | |||
| "lazy_static", | |||
| "log", | |||
| "log4rs", | |||
| "ordered-float 2.0.1", | |||
| @@ -9,6 +9,7 @@ gl = { version = "0.1", features = [ "use_log_crate" ] } | |||
| glc = "0.1" | |||
| glutin = { version = "0.25", features = [ "serde" ] } | |||
| glyph_brush = "0.7" | |||
| lazy_static = "1.4" | |||
| log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] } | |||
| log4rs = "0.13" | |||
| ordered-float = "2.0" | |||
| @@ -4,6 +4,7 @@ | |||
| #pragma include ../misc/glow.glsl | |||
| #pragma include ../misc/global.glsl | |||
| const float GLOW_ALPHA = 0.20; | |||
| const GlowArgs GLOW_ARGS = { | |||
| /* step0 */ 0.100, | |||
| /* step1 */ 1.900, | |||
| @@ -21,7 +22,7 @@ out vec4 outColor; | |||
| void main() { | |||
| float alpha = glow(GLOW_ARGS, fragmentData.texCoords - vec2(0.5), uGlobal.time); | |||
| vec4 glow = vec4(uGlowColor.rgb, uGlowColor.a * alpha); | |||
| vec4 glow = vec4(uGlowColor.rgb, uGlowColor.a * alpha * GLOW_ALPHA); | |||
| vec4 tex = texture(uTexture, fragmentData.texCoords); | |||
| outColor = tex * tex.a + glow * (1.0 - tex.a); | |||
| @@ -13,6 +13,13 @@ | |||
| }, | |||
| null, | |||
| {}, | |||
| null, | |||
| { | |||
| "owner": [ | |||
| 4 | |||
| ] | |||
| }, | |||
| null, | |||
| null | |||
| ] | |||
| }, | |||
| @@ -38,7 +45,14 @@ | |||
| null, | |||
| { | |||
| "type_": "Fighter" | |||
| } | |||
| }, | |||
| { | |||
| "owner": [ | |||
| 4 | |||
| ] | |||
| }, | |||
| null, | |||
| null | |||
| ] | |||
| }, | |||
| { | |||
| @@ -63,7 +77,14 @@ | |||
| null, | |||
| { | |||
| "type_": "Bomber" | |||
| } | |||
| }, | |||
| { | |||
| "owner": [ | |||
| 4 | |||
| ] | |||
| }, | |||
| null, | |||
| null | |||
| ] | |||
| }, | |||
| { | |||
| @@ -88,6 +109,34 @@ | |||
| null, | |||
| { | |||
| "type_": "Transporter" | |||
| }, | |||
| { | |||
| "owner": [ | |||
| 4 | |||
| ] | |||
| }, | |||
| null, | |||
| null | |||
| ] | |||
| }, | |||
| { | |||
| "marker": [ | |||
| 4 | |||
| ], | |||
| "components": [ | |||
| null, | |||
| null, | |||
| null, | |||
| null, | |||
| null, | |||
| {}, | |||
| { | |||
| "color": [ | |||
| 0.0, | |||
| 0.5, | |||
| 1.0, | |||
| 0.1 | |||
| ] | |||
| } | |||
| ] | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| mod player_visual; | |||
| pub use player_visual::PlayerVisual; | |||
| @@ -0,0 +1,12 @@ | |||
| use glc::vector::Vector4f; | |||
| use serde::{Deserialize, Serialize}; | |||
| use specs::{Component, HashMapStorage}; | |||
| #[derive(Clone, Debug, Serialize, Deserialize)] | |||
| pub struct PlayerVisual { | |||
| pub color: Vector4f, | |||
| } | |||
| impl Component for PlayerVisual { | |||
| type Storage = HashMapStorage<Self>; | |||
| } | |||
| @@ -1,2 +1,9 @@ | |||
| use glc::vector::Vector4f; | |||
| use lazy_static::lazy_static; | |||
| pub const UNIFORM_BUFFER_INDEX_CAMERA: gl::GLuint = 0; | |||
| pub const UNIFORM_BUFFER_INDEX_UNIFORM: gl::GLuint = 1; | |||
| lazy_static! { | |||
| pub static ref PLAYER_COLOR_DEFAULT: Vector4f = Vector4f::new(1.0, 1.0, 1.0, 0.1); | |||
| } | |||
| @@ -1,9 +1,10 @@ | |||
| mod constants; | |||
| mod error; | |||
| mod misc; | |||
| mod render; | |||
| mod resources; | |||
| mod systems; | |||
| pub mod components; | |||
| pub mod constants; | |||
| pub mod error; | |||
| pub mod misc; | |||
| pub mod render; | |||
| pub mod resources; | |||
| pub mod systems; | |||
| use specs::{Dispatcher, DispatcherBuilder, World}; | |||
| @@ -50,16 +50,26 @@ fn run(vfs: Vfs) -> Result<(), Error> { | |||
| } | |||
| fn create_world(world: &mut World) { | |||
| use glc::vector::Vector2f; | |||
| use glc::vector::{Vector2f, Vector4f}; | |||
| use space_crush_app::{components::PlayerVisual, misc::PersistWorld}; | |||
| use space_crush_common::{ | |||
| components::{Planet, Position, Ship, ShipType, Velocity}, | |||
| misc::{PersistWorld, Persistence}, | |||
| components::{Owned, Planet, Player, Position, Ship, ShipType, Velocity}, | |||
| misc::Persistence, | |||
| }; | |||
| use specs::{saveload::MarkedBuilder, Builder}; | |||
| let player1 = world | |||
| .create_entity() | |||
| .with(Player {}) | |||
| .with(PlayerVisual { | |||
| color: Vector4f::new(0.0, 0.5, 1.0, 0.1), | |||
| }) | |||
| .build(); | |||
| world | |||
| .create_entity() | |||
| .marked::<<PersistWorld as Persistence>::Marker>() | |||
| .with(Owned { owner: player1 }) | |||
| .with(Position { | |||
| pos: Vector2f::default(), | |||
| size: 500.0, | |||
| @@ -74,9 +84,10 @@ fn create_world(world: &mut World) { | |||
| world | |||
| .create_entity() | |||
| .marked::<<PersistWorld as Persistence>::Marker>() | |||
| .with(Owned { owner: player1 }) | |||
| .with(Position { | |||
| pos: Vector2f::new(250.0 * x, 250.0 * y), | |||
| size: 100.0, | |||
| size: 30.0, | |||
| }) | |||
| .with(Velocity { | |||
| dir: Vector2f::new(i as f32 - 1.0, 1.0).normalize(), | |||
| @@ -96,7 +107,8 @@ fn create_world(world: &mut World) { | |||
| fn load_world(world: &mut World, path: &str) -> Result<bool, Error> { | |||
| use serde_json::de::{Deserializer, IoRead}; | |||
| use space_crush_common::misc::{PersistWorld, Persistence, WorldHelper}; | |||
| use space_crush_app::misc::PersistWorld; | |||
| use space_crush_common::misc::{Persistence, WorldHelper}; | |||
| PersistWorld::setup(world); | |||
| @@ -116,7 +128,8 @@ fn load_world(world: &mut World, path: &str) -> Result<bool, Error> { | |||
| fn save_world(world: &mut World, path: &str) -> Result<(), Error> { | |||
| use serde_json::Serializer; | |||
| use space_crush_common::misc::{PersistWorld, WorldHelper}; | |||
| use space_crush_app::misc::PersistWorld; | |||
| use space_crush_common::misc::WorldHelper; | |||
| let vfs = world.resource::<Vfs>()?; | |||
| let mut file = vfs.join(path)?.create_file()?; | |||
| @@ -6,4 +6,4 @@ mod world; | |||
| pub use events::{Events, KeyboardEvent, MouseButton, MouseEvent, VirtualKeyCode, WindowEvent}; | |||
| pub use text::{Text, TextCache, TextManager}; | |||
| pub use window::Window; | |||
| pub use world::WorldHelper; | |||
| pub use world::{PersistWorld, WorldHelper}; | |||
| @@ -5,10 +5,33 @@ use glc::{ | |||
| shader::{Program, Shader, Type}, | |||
| texture::{Data, FilterMag, FilterMin, Target, Texture, Wrap}, | |||
| }; | |||
| use space_crush_common::misc::Vfs; | |||
| use specs::World; | |||
| use space_crush_common::{ | |||
| components::{Owned, Planet, Player, Position, Ship, Velocity}, | |||
| misc::{Persistence, Vfs}, | |||
| }; | |||
| use specs::{saveload::SimpleMarker, World}; | |||
| use crate::{components::PlayerVisual, Error}; | |||
| /* PersistWorld */ | |||
| pub struct PersistWorld; | |||
| pub struct PersistWorldMarker; | |||
| impl Persistence for PersistWorld { | |||
| type Marker = SimpleMarker<PersistWorldMarker>; | |||
| type Components = ( | |||
| Position, | |||
| Velocity, | |||
| Planet, | |||
| Ship, | |||
| Owned, | |||
| Player, | |||
| PlayerVisual, | |||
| ); | |||
| } | |||
| use crate::Error; | |||
| /* WorldHelper */ | |||
| pub trait WorldHelper { | |||
| fn load_program<I>(&self, iter: I) -> Result<Program, Error> | |||
| @@ -1,16 +1,17 @@ | |||
| use glc::{ | |||
| matrix::Matrix4f, | |||
| misc::Bindable, | |||
| misc::{BindGuard, Bindable}, | |||
| shader::{Program, Type, Uniform}, | |||
| texture::Texture, | |||
| vector::Vector4f, | |||
| }; | |||
| use log::error; | |||
| use space_crush_common::components::{Planet, Position}; | |||
| use space_crush_common::components::{Owned, Planet, Position}; | |||
| use specs::{prelude::*, ReadExpect, ReadStorage, System, World}; | |||
| use crate::{ | |||
| constants::{UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||
| components::PlayerVisual, | |||
| constants::{PLAYER_COLOR_DEFAULT, UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||
| misc::WorldHelper, | |||
| resources::Geometry, | |||
| Error, | |||
| @@ -19,7 +20,8 @@ use crate::{ | |||
| pub struct Planets { | |||
| program: Program, | |||
| texture: Texture, | |||
| model_location: gl::GLint, | |||
| location_model: gl::GLint, | |||
| location_glow_color: gl::GLint, | |||
| } | |||
| impl Planets { | |||
| @@ -32,13 +34,11 @@ impl Planets { | |||
| program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?; | |||
| program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?; | |||
| let glow_color = Vector4f::new(1.0, 1.0, 1.0, 0.1); | |||
| let glow_color = Uniform::Vector4f(&glow_color); | |||
| let model_location = program.uniform_location("uModel")?; | |||
| let location_model = program.uniform_location("uModel")?; | |||
| let location_glow_color = program.uniform_location("uGlowColor")?; | |||
| program.bind(); | |||
| program.uniform("uTexture", Uniform::Texture(0))?; | |||
| program.uniform("uGlowColor", glow_color)?; | |||
| program.unbind(); | |||
| let texture = world.load_texture("resources/textures/planet01.png")?; | |||
| @@ -46,7 +46,8 @@ impl Planets { | |||
| Ok(Self { | |||
| program, | |||
| texture, | |||
| model_location, | |||
| location_model, | |||
| location_glow_color, | |||
| }) | |||
| } | |||
| } | |||
| @@ -56,6 +57,8 @@ pub struct PlanetsData<'a> { | |||
| geometry: ReadExpect<'a, Geometry>, | |||
| position: ReadStorage<'a, Position>, | |||
| planet: ReadStorage<'a, Planet>, | |||
| owned: ReadStorage<'a, Owned>, | |||
| player_visual: ReadStorage<'a, PlayerVisual>, | |||
| } | |||
| impl<'a> System<'a> for Planets { | |||
| @@ -66,29 +69,43 @@ impl<'a> System<'a> for Planets { | |||
| geometry, | |||
| position, | |||
| planet, | |||
| owned, | |||
| player_visual, | |||
| } = data; | |||
| gl::enable(gl::BLEND); | |||
| gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); | |||
| self.texture.bind(); | |||
| self.program.bind(); | |||
| let _guard = BindGuard::new(&self.program); | |||
| let _guard = BindGuard::new(&self.texture); | |||
| for (p, _) in (&position, &planet).join() { | |||
| let x = p.pos.x; | |||
| let y = p.pos.y; | |||
| for (p, _, owned) in (&position, &planet, owned.maybe()).join() { | |||
| let p_x = p.pos.x; | |||
| let p_y = p.pos.y; | |||
| let s = p.size; | |||
| let c = match owned.and_then(|owned| player_visual.get(owned.owner)) { | |||
| Some(pv) => &pv.color, | |||
| None => &*PLAYER_COLOR_DEFAULT, | |||
| }; | |||
| let m = Matrix4f::new( | |||
| Vector4f::new(s, 0.0, 0.0, 0.0), | |||
| Vector4f::new(0.0, s, 0.0, 0.0), | |||
| Vector4f::new(0.0, 0.0, s, 0.0), | |||
| Vector4f::new(x, y, 0.0, 1.0), | |||
| Vector4f::new(p_x, p_y, 0.0, 1.0), | |||
| ); | |||
| if let Err(err) = self | |||
| .program | |||
| .uniform(self.model_location, Uniform::Matrix4f(&m)) | |||
| .uniform(self.location_glow_color, Uniform::Vector4f(&c)) | |||
| { | |||
| error!("Error while updating glow color: {}", err); | |||
| } | |||
| if let Err(err) = self | |||
| .program | |||
| .uniform(self.location_model, Uniform::Matrix4f(&m)) | |||
| { | |||
| error!("Error while updating model matrix: {}", err); | |||
| } | |||
| @@ -96,9 +113,6 @@ impl<'a> System<'a> for Planets { | |||
| geometry.render_quad(); | |||
| } | |||
| self.program.unbind(); | |||
| self.texture.unbind(); | |||
| gl::disable(gl::BLEND); | |||
| } | |||
| } | |||
| @@ -6,11 +6,12 @@ use glc::{ | |||
| vector::Vector4f, | |||
| }; | |||
| use log::error; | |||
| use space_crush_common::components::{Position, Ship, ShipType, Velocity}; | |||
| use space_crush_common::components::{Owned, Position, Ship, ShipType, Velocity}; | |||
| use specs::{prelude::*, ReadExpect, ReadStorage, System, World}; | |||
| use crate::{ | |||
| constants::{UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||
| components::PlayerVisual, | |||
| constants::{PLAYER_COLOR_DEFAULT, UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||
| misc::WorldHelper, | |||
| resources::Geometry, | |||
| Error, | |||
| @@ -18,10 +19,11 @@ use crate::{ | |||
| pub struct Ships { | |||
| program: Program, | |||
| texture_fighter: Texture, | |||
| texture_bomber: Texture, | |||
| texture_fighter: Texture, | |||
| texture_transporter: Texture, | |||
| model_location: gl::GLint, | |||
| location_model: gl::GLint, | |||
| location_glow_color: gl::GLint, | |||
| } | |||
| impl Ships { | |||
| @@ -34,25 +36,24 @@ impl Ships { | |||
| program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?; | |||
| program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?; | |||
| let glow_color = Vector4f::new(1.0, 1.0, 1.0, 0.02); | |||
| let glow_color = Uniform::Vector4f(&glow_color); | |||
| let model_location = program.uniform_location("uModel")?; | |||
| let location_model = program.uniform_location("uModel")?; | |||
| let location_glow_color = program.uniform_location("uGlowColor")?; | |||
| program.bind(); | |||
| program.uniform("uTexture", Uniform::Texture(0))?; | |||
| program.uniform("uGlowColor", glow_color)?; | |||
| program.unbind(); | |||
| let texture_fighter = world.load_texture("resources/textures/ship_fighter.png")?; | |||
| let texture_bomber = world.load_texture("resources/textures/ship_bomber.png")?; | |||
| let texture_fighter = world.load_texture("resources/textures/ship_fighter.png")?; | |||
| let texture_transporter = world.load_texture("resources/textures/ship_transporter.png")?; | |||
| Ok(Self { | |||
| program, | |||
| texture_fighter, | |||
| texture_bomber, | |||
| texture_fighter, | |||
| texture_transporter, | |||
| model_location, | |||
| location_model, | |||
| location_glow_color, | |||
| }) | |||
| } | |||
| } | |||
| @@ -63,6 +64,8 @@ pub struct ShipsData<'a> { | |||
| position: ReadStorage<'a, Position>, | |||
| velocity: ReadStorage<'a, Velocity>, | |||
| ship: ReadStorage<'a, Ship>, | |||
| owned: ReadStorage<'a, Owned>, | |||
| player_visual: ReadStorage<'a, PlayerVisual>, | |||
| } | |||
| impl<'a> System<'a> for Ships { | |||
| @@ -74,6 +77,8 @@ impl<'a> System<'a> for Ships { | |||
| position, | |||
| velocity, | |||
| ship, | |||
| owned, | |||
| player_visual, | |||
| } = data; | |||
| gl::enable(gl::BLEND); | |||
| @@ -81,13 +86,18 @@ impl<'a> System<'a> for Ships { | |||
| let _guard = BindGuard::new(&self.program); | |||
| for (p, v, ship) in (&position, &velocity, &ship).join() { | |||
| for (p, v, ship, owned) in (&position, &velocity, &ship, owned.maybe()).join() { | |||
| let _guard = match ship.type_ { | |||
| ShipType::Fighter => BindGuard::new(&self.texture_fighter), | |||
| ShipType::Bomber => BindGuard::new(&self.texture_bomber), | |||
| ShipType::Transporter => BindGuard::new(&self.texture_transporter), | |||
| }; | |||
| let c = match owned.and_then(|owned| player_visual.get(owned.owner)) { | |||
| Some(pv) => &pv.color, | |||
| None => &*PLAYER_COLOR_DEFAULT, | |||
| }; | |||
| let p_x = p.pos.x; | |||
| let p_y = p.pos.y; | |||
| let d_x = v.dir.x; | |||
| @@ -103,7 +113,14 @@ impl<'a> System<'a> for Ships { | |||
| if let Err(err) = self | |||
| .program | |||
| .uniform(self.model_location, Uniform::Matrix4f(&m)) | |||
| .uniform(self.location_glow_color, Uniform::Vector4f(&c)) | |||
| { | |||
| error!("Error while updating glow color: {}", err); | |||
| } | |||
| if let Err(err) = self | |||
| .program | |||
| .uniform(self.location_model, Uniform::Matrix4f(&m)) | |||
| { | |||
| error!("Error while updating model matrix: {}", err); | |||
| } | |||
| @@ -1,9 +1,13 @@ | |||
| mod owned; | |||
| mod planet; | |||
| mod player; | |||
| mod position; | |||
| mod ship; | |||
| mod velocity; | |||
| pub use owned::Owned; | |||
| pub use planet::Planet; | |||
| pub use player::Player; | |||
| pub use position::Position; | |||
| pub use ship::{Ship, Type as ShipType}; | |||
| pub use velocity::Velocity; | |||
| @@ -0,0 +1,46 @@ | |||
| use serde::{Deserialize, Serialize}; | |||
| use specs::{ | |||
| error::NoError, | |||
| saveload::{ConvertSaveload, Marker}, | |||
| Component, Entity, VecStorage, | |||
| }; | |||
| #[derive(Clone, Debug)] | |||
| pub struct Owned { | |||
| pub owner: Entity, | |||
| } | |||
| #[derive(Serialize, Deserialize)] | |||
| pub struct OwnedData<M> { | |||
| pub owner: M, | |||
| } | |||
| impl Component for Owned { | |||
| type Storage = VecStorage<Self>; | |||
| } | |||
| impl<M> ConvertSaveload<M> for Owned | |||
| where | |||
| for<'de> M: Marker + Serialize + Deserialize<'de>, | |||
| { | |||
| type Data = OwnedData<M>; | |||
| type Error = NoError; | |||
| fn convert_into<F>(&self, mut ids: F) -> Result<Self::Data, Self::Error> | |||
| where | |||
| F: FnMut(Entity) -> Option<M>, | |||
| { | |||
| let owner = ids(self.owner).unwrap(); | |||
| Ok(OwnedData { owner }) | |||
| } | |||
| fn convert_from<F>(data: Self::Data, mut ids: F) -> Result<Self, Self::Error> | |||
| where | |||
| F: FnMut(M) -> Option<Entity>, | |||
| { | |||
| let owner = ids(data.owner).unwrap(); | |||
| Ok(Owned { owner }) | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| use serde::{Deserialize, Serialize}; | |||
| use specs::{Component, NullStorage}; | |||
| #[derive(Clone, Debug, Default, Serialize, Deserialize)] | |||
| pub struct Player {} | |||
| impl Component for Player { | |||
| type Storage = NullStorage<Self>; | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| use specs::{Dispatcher as Inner, DispatcherBuilder, World}; | |||
| use specs::{Dispatcher as Inner, DispatcherBuilder, World, WorldExt}; | |||
| use crate::{ | |||
| components::Player, | |||
| resources::Global, | |||
| systems::{Movement, Process}, | |||
| }; | |||
| @@ -13,6 +14,8 @@ impl<'a, 'b> Dispatcher<'a, 'b> { | |||
| pub fn new(world: &mut World) -> Self { | |||
| world.insert(Global::default()); | |||
| world.register::<Player>(); | |||
| let mut dispatcher = DispatcherBuilder::new() | |||
| .with(Process::default(), "process", &[]) | |||
| .with(Movement::default(), "movement", &[]) | |||
| @@ -1,9 +1,7 @@ | |||
| mod log; | |||
| mod persistence; | |||
| mod vfs; | |||
| mod world; | |||
| pub use self::log::init as init_logger; | |||
| pub use self::vfs::{Vfs, VfsError}; | |||
| pub use persistence::PersistWorld; | |||
| pub use world::{Persistence, WorldHelper}; | |||
| @@ -1,13 +0,0 @@ | |||
| use specs::saveload::SimpleMarker; | |||
| use crate::components::{Planet, Position, Ship, Velocity}; | |||
| use super::Persistence; | |||
| pub struct PersistWorld; | |||
| pub struct PersistWorldMarker; | |||
| impl Persistence for PersistWorld { | |||
| type Marker = SimpleMarker<PersistWorldMarker>; | |||
| type Components = (Position, Velocity, Planet, Ship); | |||
| } | |||
| @@ -1,14 +1,11 @@ | |||
| use std::any::type_name; | |||
| use serde::{ | |||
| de::{DeserializeOwned, Deserializer}, | |||
| ser::{Serialize, Serializer}, | |||
| }; | |||
| use serde::{de::Deserializer, ser::Serializer}; | |||
| use shred::{Fetch, FetchMut, Resource}; | |||
| use shrev::{Event, EventChannel, ReaderId}; | |||
| use specs::{ | |||
| error::NoError, | |||
| saveload::{DeserializeComponents, Marker, SerializeComponents}, | |||
| saveload::{ConvertSaveload, DeserializeComponents, Marker, SerializeComponents}, | |||
| Component, Entities, ReadStorage, World, WorldExt, Write, WriteStorage, | |||
| }; | |||
| @@ -133,16 +130,31 @@ macro_rules! define_persistence_components { | |||
| where | |||
| M: Marker, | |||
| M::Allocator: Default, | |||
| $($T: Component + Serialize + DeserializeOwned + Clone,)+ | |||
| $($T: Component + ConvertSaveload<M, Error = NoError>,)+ | |||
| { | |||
| fn serialize<S>(world: &World, serializer: S) -> Result<(), S::Error> | |||
| where | |||
| S: Serializer, | |||
| { | |||
| let (entities, marker, $($T,)+) = | |||
| world.system_data::<(Entities, ReadStorage<M>, $(ReadStorage<$T>,)+)>(); | |||
| let ( | |||
| entities, | |||
| mut marker, | |||
| mut allocator, | |||
| $($T,)+ | |||
| ) = world.system_data::<( | |||
| Entities, | |||
| WriteStorage<M>, | |||
| Write<M::Allocator>, | |||
| $(ReadStorage<$T>, | |||
| )+)>(); | |||
| SerializeComponents::<NoError, M>::serialize(&($($T,)+), &entities, &marker, serializer)?; | |||
| SerializeComponents::<NoError, M>::serialize_recursive | |||
| (&($($T,)+), | |||
| &entities, | |||
| &mut marker, | |||
| &mut allocator, | |||
| serializer, | |||
| )?; | |||
| Ok(()) | |||
| } | |||
| @@ -151,7 +163,12 @@ macro_rules! define_persistence_components { | |||
| where | |||
| D: Deserializer<'de>, | |||
| { | |||
| let (entities, mut marker, mut allocator, $($T,)+) = world.system_data::<( | |||
| let ( | |||
| entities, | |||
| mut marker, | |||
| mut allocator, | |||
| $($T,)+ | |||
| ) = world.system_data::<( | |||
| Entities, | |||
| WriteStorage<M>, | |||
| Write<M::Allocator>, | |||