Implement syncing

This commit is contained in:
Sofia 2026-07-18 02:55:41 +03:00
parent 4b0a90be0e
commit 1402b10180
3 changed files with 130 additions and 3 deletions

View File

@ -1,4 +1,4 @@
use std::net::SocketAddr; use std::{collections::HashMap, net::SocketAddr};
use godot::{classes::CharacterBody3D, prelude::*, tools::get_autoload_by_name}; use godot::{classes::CharacterBody3D, prelude::*, tools::get_autoload_by_name};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -6,7 +6,14 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
map::Map, map::Map,
map_resource::MapResource, map_resource::MapResource,
net::network_manager::{NetworkManager, Package, PeerKind}, net::{
network_manager::{
NetworkManager,
Package::{self, SelfSync},
PeerKind,
},
util::NetVector3,
},
player::{IPlayer, NetPlayerTransform}, player::{IPlayer, NetPlayerTransform},
}; };
@ -82,10 +89,52 @@ pub struct Game {
game_started: bool, game_started: bool,
pub current_map: Option<Gd<Map>>, pub current_map: Option<Gd<Map>>,
since_last_sync: f64,
base: Base<Node>, base: Base<Node>,
} }
#[godot_api]
impl INode for Game {
fn process(&mut self, delta: f64) {
self.since_last_sync += delta;
if self.since_last_sync > (1. / 30.) {
self.since_last_sync = 0.;
if let Some(_) = self.current_map {
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
match peer {
PeerKind::Client(peer, socket_addr) => {
if let Some(player) = self
.players
.iter()
.find(|p| p.id == self.self_id.unwrap_or(0))
{
if let Some((dir, rot)) = &player.get_self_sync() {
peer.send_unreliable(
socket_addr,
SelfSync(dir.clone(), rot.clone()),
);
}
}
}
PeerKind::Server(peer, _) => {
let mut sync_data = HashMap::new();
for player in &self.players {
if let (Some(dir), Some(transform)) =
(player.get_move_dir(), player.get_transform())
{
sync_data.insert(player.id, (dir, transform));
}
}
peer.broadcast_unreliable(Package::Sync(sync_data));
}
}
}
}
}
}
}
#[godot_api] #[godot_api]
impl Game { impl Game {
#[signal] #[signal]
@ -166,6 +215,10 @@ impl Game {
self.players.iter().find(|p| p.connection_addr == *addr) self.players.iter().find(|p| p.connection_addr == *addr)
} }
pub fn find_player_by_addr_mut(&mut self, addr: &SocketAddr) -> Option<&mut Player> {
self.players.iter_mut().find(|p| p.connection_addr == *addr)
}
pub fn find_player(&self, player_id: u16) -> Option<&Player> { pub fn find_player(&self, player_id: u16) -> Option<&Player> {
self.players.iter().find(|p| p.id == player_id) self.players.iter().find(|p| p.id == player_id)
} }
@ -234,6 +287,17 @@ impl Game {
} }
} }
} }
pub fn handle_sync(&mut self, sync_data: HashMap<u16, (NetVector3, NetPlayerTransform)>) {
for (player_id, (dir, transform)) in sync_data {
if let Some(player) = self.players.iter_mut().find(|p| p.id == player_id) {
if player.id != self.self_id.unwrap_or(0) {
player.set_transform(transform);
player.set_move_dir(dir);
}
}
}
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -260,6 +324,38 @@ impl Player {
character.dyn_bind_mut().apply_transform(transform); character.dyn_bind_mut().apply_transform(transform);
} }
} }
pub fn get_move_dir(&self) -> Option<NetVector3> {
if let Some(character) = &self.character {
Some(character.dyn_bind().get_movement_dir().into())
} else {
None
}
}
pub fn set_move_dir(&mut self, dir: NetVector3) {
if let Some(character) = &mut self.character {
character.dyn_bind_mut().set_movement_dir(dir.into());
}
}
pub fn get_self_sync(&self) -> Option<(NetVector3, NetVector3)> {
if let Some(character) = &self.character {
Some((
character.dyn_bind().get_movement_dir().into(),
character.dyn_bind().get_transform().rotation,
))
} else {
None
}
}
pub fn apply_self_sync(&mut self, dir: NetVector3, rot: NetVector3) {
if let Some(character) = &mut self.character {
character.dyn_bind_mut().set_movement_dir(dir.into());
character.dyn_bind_mut().apply_rotation(rot.into());
}
}
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]

View File

@ -10,7 +10,7 @@ use teanet::{Peer, PeerConfig, PeerMessage, connections::Connection};
use crate::{ use crate::{
game_manager::{Game, GameManager, NetPlayer, Player}, game_manager::{Game, GameManager, NetPlayer, Player},
net::net_stats::Stats, net::{net_stats::Stats, util::NetVector3},
player::NetPlayerTransform, player::NetPlayerTransform,
ui::cli::{CliColor, CommandLinePanel}, ui::cli::{CliColor, CommandLinePanel},
}; };
@ -217,6 +217,11 @@ impl INode for NetworkManager {
game.bind_mut().spawn_player(id, transform); game.bind_mut().spawn_player(id, transform);
} }
} }
Package::Sync(sync_data) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_sync(sync_data);
}
}
_ => {} _ => {}
}, },
} }
@ -346,6 +351,16 @@ impl INode for NetworkManager {
} }
} }
} }
Package::SelfSync(dir, rot) => {
if let Some(game) = &mut Game::singleton() {
if let Some(player) = &mut game
.bind_mut()
.find_player_by_addr_mut(&conn.address)
{
player.apply_self_sync(dir, rot);
}
}
}
_ => {} _ => {}
}, },
} }
@ -466,6 +481,8 @@ pub enum Package {
SelectMap(u8), SelectMap(u8),
GameStarted, GameStarted,
SpawnPlayer(u16, NetPlayerTransform), SpawnPlayer(u16, NetPlayerTransform),
Sync(HashMap<u16, (NetVector3, NetPlayerTransform)>),
SelfSync(NetVector3, NetVector3),
MapLoaded, MapLoaded,
} }

View File

@ -23,8 +23,10 @@ pub trait IPlayer {
fn get_y_speed(&self) -> f32; fn get_y_speed(&self) -> f32;
fn set_y_speed(&mut self, speed: f32); fn set_y_speed(&mut self, speed: f32);
fn get_movement_dir(&self) -> Vector3; fn get_movement_dir(&self) -> Vector3;
fn set_movement_dir(&mut self, dir: Vector3);
fn get_move_speed(&self) -> f32; fn get_move_speed(&self) -> f32;
fn apply_transform(&mut self, transform: NetPlayerTransform); fn apply_transform(&mut self, transform: NetPlayerTransform);
fn apply_rotation(&mut self, rot: Vector3);
fn get_transform(&self) -> NetPlayerTransform; fn get_transform(&self) -> NetPlayerTransform;
} }
@ -95,6 +97,8 @@ impl IPlayer for LocalPlayer {
self.movement_dir self.movement_dir
} }
fn set_movement_dir(&mut self, _dir: Vector3) {}
fn get_move_speed(&self) -> f32 { fn get_move_speed(&self) -> f32 {
self.move_speed self.move_speed
} }
@ -106,6 +110,8 @@ impl IPlayer for LocalPlayer {
.set_global_rotation(transform.rotation.into()); .set_global_rotation(transform.rotation.into());
} }
fn apply_rotation(&mut self, _rot: Vector3) {}
fn get_transform(&self) -> NetPlayerTransform { fn get_transform(&self) -> NetPlayerTransform {
NetPlayerTransform { NetPlayerTransform {
location: self.base().get_global_position().into(), location: self.base().get_global_position().into(),
@ -212,6 +218,10 @@ impl IPlayer for RemotePlayer {
self.movement_dir self.movement_dir
} }
fn set_movement_dir(&mut self, dir: Vector3) {
self.movement_dir = dir.into();
}
fn get_move_speed(&self) -> f32 { fn get_move_speed(&self) -> f32 {
self.move_speed self.move_speed
} }
@ -227,6 +237,10 @@ impl IPlayer for RemotePlayer {
.set_global_rotation(transform.rotation.into()); .set_global_rotation(transform.rotation.into());
} }
fn apply_rotation(&mut self, rot: Vector3) {
self.base_mut().set_global_rotation(rot);
}
fn get_transform(&self) -> NetPlayerTransform { fn get_transform(&self) -> NetPlayerTransform {
NetPlayerTransform { NetPlayerTransform {
location: self.base().get_global_position().into(), location: self.base().get_global_position().into(),