Skip to main content

bevy_networker_multiplayer/
replicated.rs

1// SPDX-License-Identifier: MIT
2//! Replicated entity marker and plugin wiring.
3use bevy::prelude::*;
4use std::collections::HashMap;
5
6use crate::{netres::NetResource, sync};
7
8/// Marker component for entities that should exist on every peer.
9#[derive(Component, Default)]
10pub struct Replicated;
11
12/// Internal mapping between a Bevy entity and its network identity.
13#[derive(Component, Clone, Copy, Debug, Eq, Hash, PartialEq)]
14#[doc(hidden)]
15pub struct NetworkId(pub u64);
16
17/// Monotonic counter used to assign fresh network IDs on the server.
18#[derive(Resource, Default)]
19#[doc(hidden)]
20pub struct NextNetworkId(pub u64);
21
22/// Bidirectional index between network IDs and local entities.
23#[derive(Resource, Default)]
24#[doc(hidden)]
25pub struct EntityIndex {
26    by_network: HashMap<NetworkId, Entity>,
27    by_entity: HashMap<Entity, NetworkId>,
28}
29
30impl EntityIndex {
31    /// Stores the mapping in both directions.
32    pub fn insert(&mut self, network_id: NetworkId, entity: Entity) {
33        self.by_network.insert(network_id, entity);
34        self.by_entity.insert(entity, network_id);
35    }
36
37    /// Looks up the local entity for a network ID.
38    pub fn entity(&self, network_id: NetworkId) -> Option<Entity> {
39        self.by_network.get(&network_id).copied()
40    }
41
42    /// Looks up the network ID for a local entity.
43    pub fn network_id(&self, entity: Entity) -> Option<NetworkId> {
44        self.by_entity.get(&entity).copied()
45    }
46
47    /// Removes an entity from the index and returns its previous network ID.
48    pub fn remove_entity(&mut self, entity: Entity) -> Option<NetworkId> {
49        let network_id = self.by_entity.remove(&entity)?;
50        self.by_network.remove(&network_id);
51        Some(network_id)
52    }
53}
54
55/// Bevy plugin that wires replication resources and systems together.
56pub struct ReplicatedPlugin;
57
58impl Plugin for ReplicatedPlugin {
59    /// Initializes replication state and installs the replication pipeline.
60    fn build(&self, app: &mut App) {
61        app.init_resource::<NetResource>()
62            .init_resource::<NextNetworkId>()
63            .init_resource::<EntityIndex>();
64
65        sync::register_sync_components(app);
66
67        app.add_systems(PreUpdate, sync::poll_network_incoming)
68            .add_systems(
69                Update,
70                (
71                    sync::assign_prefab_ids,
72                    sync::assign_network_ids,
73                    sync::replicate_removals,
74                    sync::sync_new_connections,
75                    sync::apply_incoming_packets,
76                )
77                    .chain(),
78            )
79            .add_systems(PostUpdate, sync::flush_network_outbox);
80    }
81}