implement player id allocation (#90)

* implement player id allocation

* move `bevy/debug` to `dbg`
This commit is contained in:
PROMETHIA-27
2025-12-19 17:41:16 -05:00
committed by GitHub
parent a4488cc072
commit f6fa9ce1e4
6 changed files with 42 additions and 12 deletions

View File

@@ -20,7 +20,7 @@ client = [
"bevy_replicon_renet/client", "bevy_replicon_renet/client",
"bevy_trenchbroom/client", "bevy_trenchbroom/client",
] ]
dbg = ["avian3d/debug-plugin", "dep:bevy-inspector-egui"] dbg = ["avian3d/debug-plugin", "bevy/debug", "dep:bevy-inspector-egui"]
[dependencies] [dependencies]
avian3d = { workspace = true } avian3d = { workspace = true }

View File

@@ -36,7 +36,7 @@ pub mod water;
use crate::{ use crate::{
config::NetworkingConfig, config::NetworkingConfig,
heads_database::{HeadDatabaseAsset, HeadsDatabase}, heads_database::{HeadDatabaseAsset, HeadsDatabase},
protocol::{PlayerId, messages::AssignClientPlayer}, protocol::{PlayerIdCounter, messages::AssignClientPlayer},
tb_entities::SpawnPoint, tb_entities::SpawnPoint,
}; };
use avian3d::{PhysicsPlugins, prelude::TransformInterpolation}; use avian3d::{PhysicsPlugins, prelude::TransformInterpolation};
@@ -198,12 +198,16 @@ fn start_solo_client(
query: Query<&Transform, With<SpawnPoint>>, query: Query<&Transform, With<SpawnPoint>>,
heads_db: Res<HeadsDatabase>, heads_db: Res<HeadsDatabase>,
mut assign_player_id: MessageWriter<AssignClientPlayer>, mut assign_player_id: MessageWriter<AssignClientPlayer>,
mut ids: ResMut<PlayerIdCounter>,
) { ) {
next.set(GameState::Playing); next.set(GameState::Playing);
player::spawn(commands, ClientId::Server, query, heads_db); ids.reset();
let id = ids.alloc();
assign_player_id.write(AssignClientPlayer(PlayerId { id: 0 })); player::spawn(commands, ClientId::Server, id, query, heads_db);
assign_player_id.write(AssignClientPlayer(id));
} }
fn start_listen_server( fn start_listen_server(
@@ -212,12 +216,16 @@ fn start_listen_server(
query: Query<&Transform, With<SpawnPoint>>, query: Query<&Transform, With<SpawnPoint>>,
heads_db: Res<HeadsDatabase>, heads_db: Res<HeadsDatabase>,
mut assign_player_id: MessageWriter<AssignClientPlayer>, mut assign_player_id: MessageWriter<AssignClientPlayer>,
mut ids: ResMut<PlayerIdCounter>,
) { ) {
next.set(GameState::Hosting); next.set(GameState::Hosting);
player::spawn(commands, ClientId::Server, query, heads_db); ids.reset();
let id = ids.alloc();
assign_player_id.write(AssignClientPlayer(PlayerId { id: 0 })); player::spawn(commands, ClientId::Server, id, query, heads_db);
assign_player_id.write(AssignClientPlayer(id));
} }
fn start_client(mut next: ResMut<NextState<GameState>>) { fn start_client(mut next: ResMut<NextState<GameState>>) {

View File

@@ -65,6 +65,7 @@ pub fn plugin(app: &mut App) {
pub fn spawn( pub fn spawn(
mut commands: Commands, mut commands: Commands,
owner: ClientId, owner: ClientId,
id: PlayerId,
query: Query<&Transform, With<SpawnPoint>>, query: Query<&Transform, With<SpawnPoint>>,
heads_db: Res<HeadsDatabase>, heads_db: Res<HeadsDatabase>,
) -> Option<Entity> { ) -> Option<Entity> {
@@ -91,7 +92,7 @@ pub fn spawn(
transform, transform,
Visibility::default(), Visibility::default(),
PlayerCharacterController, PlayerCharacterController,
PlayerId { id: 0 }, id,
), ),
Backpack::default(), Backpack::default(),
BackpackUiState::default(), BackpackUiState::default(),

View File

@@ -76,6 +76,23 @@ impl From<NetworkedCollider> for Collider {
} }
} }
#[derive(Resource, Default)]
pub struct PlayerIdCounter {
next: u8,
}
impl PlayerIdCounter {
pub fn reset(&mut self) {
self.next = 0;
}
pub fn alloc(&mut self) -> PlayerId {
let id = PlayerId { id: self.next };
self.next += 1;
id
}
}
/// An ID, unique per player, inserted on the character controller. The `PlayerIdMap` maintains a mapping of ID -> controller entity /// An ID, unique per player, inserted on the character controller. The `PlayerIdMap` maintains a mapping of ID -> controller entity
/// on the server /// on the server
#[derive(Clone, Copy, Component, Hash, Reflect, Serialize, Deserialize, PartialEq, Eq)] #[derive(Clone, Copy, Component, Hash, Reflect, Serialize, Deserialize, PartialEq, Eq)]

View File

@@ -74,6 +74,7 @@ pub fn plugin(app: &mut App) {
app.register_type::<TbMapIdCounter>(); app.register_type::<TbMapIdCounter>();
app.register_type::<TbMapEntityMapping>(); app.register_type::<TbMapEntityMapping>();
app.init_resource::<PlayerIdCounter>();
app.init_resource::<PlayerIdMap>(); app.init_resource::<PlayerIdMap>();
app.init_resource::<TbMapIdCounter>(); app.init_resource::<TbMapIdCounter>();
app.init_resource::<TbMapEntityMapping>(); app.init_resource::<TbMapEntityMapping>();

View File

@@ -2,7 +2,7 @@ use crate::{
GameState, global_observer, GameState, global_observer,
heads_database::HeadsDatabase, heads_database::HeadsDatabase,
player::ClientPlayerId, player::ClientPlayerId,
protocol::{ClientEnteredPlaying, PlayerId, SetGameTick, messages::AssignClientPlayer}, protocol::{ClientEnteredPlaying, PlayerIdCounter, SetGameTick, messages::AssignClientPlayer},
tb_entities::SpawnPoint, tb_entities::SpawnPoint,
tick::GameTick, tick::GameTick,
}; };
@@ -38,12 +38,14 @@ pub fn plugin(app: &mut App) {
fn on_client_playing( fn on_client_playing(
trigger: On<FromClient<ClientEnteredPlaying>>, trigger: On<FromClient<ClientEnteredPlaying>>,
commands: Commands, commands: Commands,
clients: Query<&ClientPlayerId>,
query: Query<&Transform, With<SpawnPoint>>, query: Query<&Transform, With<SpawnPoint>>,
heads_db: Res<HeadsDatabase>, heads_db: Res<HeadsDatabase>,
) -> Result { ) -> Result {
info!("client has entered playing gamestate"); info!("client has entered playing gamestate");
crate::player::spawn(commands, trigger.client_id, query, heads_db) let id = clients.get(trigger.client_id.entity().unwrap()).unwrap();
crate::player::spawn(commands, trigger.client_id, id.0, query, heads_db)
.ok_or("failed to spawn player")?; .ok_or("failed to spawn player")?;
Ok(()) Ok(())
@@ -100,16 +102,17 @@ fn on_connected(
game_tick: Res<GameTick>, game_tick: Res<GameTick>,
mut commands: Commands, mut commands: Commands,
mut assign_id: MessageWriter<ToClients<AssignClientPlayer>>, mut assign_id: MessageWriter<ToClients<AssignClientPlayer>>,
mut ids: ResMut<PlayerIdCounter>,
) { ) {
let client = trigger.event_target(); let client = trigger.event_target();
info!("{client} connected to server!"); info!("{client} connected to server!");
let id = ClientPlayerId(PlayerId { id: 0 }); let id = ids.alloc();
commands.entity(client).insert(id); commands.entity(client).insert(ClientPlayerId(id));
assign_id.write(ToClients { assign_id.write(ToClients {
mode: SendMode::Direct(ClientId::Client(trigger.entity)), mode: SendMode::Direct(ClientId::Client(trigger.entity)),
message: AssignClientPlayer(id.0), message: AssignClientPlayer(id),
}); });
commands.server_trigger(ToClients { commands.server_trigger(ToClients {