[][src]Trait specs::saveload::Marker

pub trait Marker: Clone + Component + Debug + Eq + Hash + DeserializeOwned + Serialize {
    type Identifier;
    type Allocator: MarkerAllocator<Self>;
    fn id(&self) -> Self::Identifier;

    fn update(&mut self, new_revision: Self) { ... }
}

This trait should be implemented by a component which is going to be used as marker. This marker should be set to entity that should be serialized. If serialization strategy needs to set marker to some entity then it should use newly allocated marker from Marker::Allocator.

Example

extern crate specs;
#[macro_use]
extern crate serde;
use std::{collections::HashMap, ops::Range};

use specs::{
    prelude::*,
    saveload::{MarkedBuilder, Marker, MarkerAllocator},
    world::EntitiesRes,
};

// Marker for entities that should be synced over network
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
struct NetMarker {
    id: u64,
    seq: u64,
}

impl Component for NetMarker {
    type Storage = DenseVecStorage<Self>;
}

impl Marker for NetMarker {
    type Allocator = NetNode;
    type Identifier = u64;

    fn id(&self) -> u64 {
        self.id
    }

    // Updates sequence id.
    // Entities with too old sequence id get deleted.
    fn update(&mut self, update: Self) {
        assert_eq!(self.id, update.id);
        self.seq = update.seq;
    }
}

// Each client and server has one
// Contains id range and `NetMarker -> Entity` mapping
struct NetNode {
    range: Range<u64>,
    mapping: HashMap<u64, Entity>,
}

impl MarkerAllocator<NetMarker> for NetNode {
    fn allocate(&mut self, entity: Entity, id: Option<u64>) -> NetMarker {
        let id = id.unwrap_or_else(|| {
            self.range
                .next()
                .expect("Id range must be virtually endless")
        });
        let marker = NetMarker { id, seq: 0 };
        self.mapping.insert(id, entity);
        marker
    }

    fn retrieve_entity_internal(&self, id: u64) -> Option<Entity> {
        self.mapping.get(&id).cloned()
    }

    fn maintain(&mut self, entities: &EntitiesRes, storage: &ReadStorage<NetMarker>) {
        self.mapping = (entities, storage)
            .join()
            .map(|(e, m)| (m.id(), e))
            .collect();
    }
}

fn main() {
    let mut world = World::new();
    world.register::<NetMarker>();

    world.insert(NetNode {
        range: 0..100,
        mapping: HashMap::new(),
    });

    let entity = world.create_entity().marked::<NetMarker>().build();
    let storage = &mut world.write_storage::<NetMarker>();
    let marker = storage.get(entity).unwrap().clone();
    assert_eq!(
        world
            .write_resource::<NetNode>()
            .retrieve_entity(marker, storage, &world.entities()),
        entity
    );
}

Associated Types

type Identifier

Id of the marker

type Allocator: MarkerAllocator<Self>

Allocator for this Marker

Loading content...

Required methods

fn id(&self) -> Self::Identifier

Get this marker internal id. The value of this method should be constant.

Loading content...

Provided methods

fn update(&mut self, new_revision: Self)

This gets called when an entity is deserialized by DeserializeComponents. It can be used to update internal data that is not used for identification.

Contract

This function may assume that self.id() == new_revision.id(). However, it must not exhibit undefined behavior in such a case.

Panics

May panic if self.id() != new_revision.id().

Default implementation

The default implementation just sets self to new_revision.

Examples

This example is not tested
#[derive(Clone, Debug, Deserialize, Eq, Hash, Serialize)]
struct MyMarker {
    id: u64,
    last_modified: String,
}

impl Marker for MyMarker {
    type Identifier = u64;

    fn id(&self) -> u64 {
        self.id
    }

    fn update(&self, new: Self) {
        self.last_modified = new.last_modified;
    }
}

Now, the marker always contains the name of the client who updated the entity associated with this marker.

Loading content...

Implementors

impl Marker for UuidMarker[src]

impl<T: ?Sized> Marker for SimpleMarker<T> where
    T: 'static + Send + Sync
[src]

Loading content...