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 serde::{Deserialize, Serialize};
@ -6,7 +6,14 @@ use serde::{Deserialize, Serialize};
use crate::{
map::Map,
map_resource::MapResource,
net::network_manager::{NetworkManager, Package, PeerKind},
net::{
network_manager::{
NetworkManager,
Package::{self, SelfSync},
PeerKind,
},
util::NetVector3,
},
player::{IPlayer, NetPlayerTransform},
};
@ -82,10 +89,52 @@ pub struct Game {
game_started: bool,
pub current_map: Option<Gd<Map>>,
since_last_sync: f64,
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]
impl Game {
#[signal]
@ -166,6 +215,10 @@ impl Game {
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> {
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)]
@ -260,6 +324,38 @@ impl Player {
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)]

View File

@ -10,7 +10,7 @@ use teanet::{Peer, PeerConfig, PeerMessage, connections::Connection};
use crate::{
game_manager::{Game, GameManager, NetPlayer, Player},
net::net_stats::Stats,
net::{net_stats::Stats, util::NetVector3},
player::NetPlayerTransform,
ui::cli::{CliColor, CommandLinePanel},
};
@ -217,6 +217,11 @@ impl INode for NetworkManager {
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),
GameStarted,
SpawnPlayer(u16, NetPlayerTransform),
Sync(HashMap<u16, (NetVector3, NetPlayerTransform)>),
SelfSync(NetVector3, NetVector3),
MapLoaded,
}

View File

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