Move sync and net processing to physics_process

This commit is contained in:
Sofia 2026-07-21 22:53:14 +03:00
parent 1622acf0c1
commit d1282693da
4 changed files with 340 additions and 357 deletions

View File

@ -106,7 +106,7 @@ pub struct Game {
#[godot_api]
impl INode for Game {
fn process(&mut self, delta: f64) {
fn physics_process(&mut self, delta: f64) {
self.since_last_sync += delta;
if self.since_last_sync > (1. / 60.) {
self.since_last_sync = 0.;

View File

@ -1,3 +1,4 @@
pub mod net_stats;
pub mod network_manager;
pub mod protocol;
pub mod util;

View File

@ -6,7 +6,7 @@ use std::{
use godot::{prelude::*, tools::get_autoload_by_name};
use serde::{Deserialize, Serialize};
use teanet::{Peer, PeerConfig};
use teanet::{Peer, PeerConfig, PeerMessage};
use crate::{
game_manager::{Game, GameManager, NetPlayer},
@ -66,10 +66,8 @@ impl INode for NetworkManager {
.connect_other(self, |s| s.disconnect());
}
fn process(&mut self, _delta: f64) {
fn physics_process(&mut self, _delta: f64) {
if let Some(peer) = &mut self.peer {
let mut cli = CommandLinePanel::singleton();
let now = Instant::now();
if now - self.last_netstat_update > Duration::from_millis(1000) {
Stats::singleton().bind_mut().update_stats(match peer {
@ -112,363 +110,37 @@ impl INode for NetworkManager {
}
}
match peer {
PeerKind::Client(peer, _) => match peer.poll() {
Ok(message) => {
if let Some(message) = message {
match message {
teanet::PeerMessage::NewConnection(connection) => {
cli.bind_mut().publish_message(
format!("Connected to: {}", connection.address),
CliColor::Info,
);
self.swap_to_lobby(false);
}
teanet::PeerMessage::Disconnected(connection, connection_error) => {
cli.bind_mut().publish_message(
format!("Disconnected from: {}", connection.address),
CliColor::Info,
);
if let Some(err) = &connection_error {
cli.bind_mut().publish_message(
format!("Error with connection: {}", err),
CliColor::Error,
);
}
peer.close();
}
teanet::PeerMessage::Closed => {
self.peer = None;
GameManager::singleton().bind_mut().game = None;
}
teanet::PeerMessage::Message(_, msg) => match msg {
Package::Hello => {
cli.bind_mut().publish_message(
format!("Got \"Hello\"!"),
CliColor::Info,
);
}
Package::Players(players, self_id) => {
cli.bind_mut().publish_message(
format!("Got players"),
CliColor::Info,
);
if let Some(game) = &mut Game::singleton() {
game.bind_mut().set_players(
players
.into_iter()
.map(|p| p.clone().into())
.collect(),
);
game.bind_mut().set_self(self_id);
}
}
Package::SetNick(id, nick) => {
if let Some(game) = &mut Game::singleton() {
if game.bind().self_id != Some(id) {
game.bind_mut().update_player_nick(id, nick);
}
}
}
Package::UpdatePings(pings) => {
if let Some(game) = &mut Game::singleton() {
for (player_id, ping) in pings {
game.bind_mut().update_player_ping(player_id, ping);
}
}
}
Package::NewPlayer(player) => {
if let Some(game) = &mut Game::singleton() {
if player.id != game.bind().self_id.unwrap_or(u16::MAX)
{
game.bind_mut().new_player(
SocketAddr::from(([0, 0, 0, 0], 0)),
player.name,
Some(player.id),
);
}
}
}
Package::PlayerLeft(player) => {
if let Some(game) = &mut Game::singleton() {
if player.id != game.bind().self_id.unwrap_or(u16::MAX)
{
game.bind_mut().remove_player(player.id);
}
}
}
Package::SetReady(player_id, is_ready) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut()
.update_player_ready(player_id, is_ready);
}
}
Package::SelectMap(map_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().change_map_selection(map_id, true);
}
}
Package::GameStarted => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().start_game();
}
}
Package::SpawnPlayer(id, transform) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().spawn_player_client(id, transform);
}
}
Package::Sync(sync_data, ball_sync) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_sync(sync_data, ball_sync);
}
}
Package::Jump(player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_jump(player_id);
}
}
Package::Shoot(player_id, to, transform, look_up) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_shoot(
player_id,
to.into(),
transform,
look_up,
false,
);
}
}
Package::TakeDamage(
source_player_id,
target_player_id,
damage,
) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_take_damage(
source_player_id,
target_player_id,
damage,
);
}
}
Package::Kill(source_player_id, target_player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut()
.handle_kill(source_player_id, target_player_id);
}
}
Package::SpawnBall(transform, velocity, player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().spawn_ball(
Some(transform),
Some(velocity),
player_id,
);
}
}
Package::DespawnBall => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().despawn_ball();
}
}
Package::SwapWeapon(id, weapon_type) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_swap_weapon(
id,
weapon_type,
true,
);
}
}
_ => {}
},
}
}
}
Err(err) => {
cli.bind_mut()
.publish_message(format!("Error: {}", err), CliColor::Info);
}
},
PeerKind::Server(peer, _) => match peer.poll() {
Ok(message) => {
if let Some(message) = message {
match message {
teanet::PeerMessage::NewConnection(connection) => {
cli.bind_mut().publish_message(
format!("Client connected from: {}", connection.address),
CliColor::Info,
);
if let Some(game) = &mut Game::singleton() {
let self_id = game.bind_mut().new_player(
connection.address,
String::new(),
None,
);
peer.send_reliable(
&connection.address,
Package::Players(
game.bind()
.players
.clone()
.into_iter()
.map(|p| p.into())
.collect(),
self_id,
),
);
peer.broadcast_reliable(Package::NewPlayer(
game.bind()
.find_player(self_id)
.unwrap()
.clone()
.into(),
));
peer.send_reliable(
&connection.address,
Package::SelectMap(game.bind().selected_map_idx),
);
}
}
teanet::PeerMessage::Disconnected(connection, connection_error) => {
cli.bind_mut().publish_message(
format!("Client disconnected: {}", connection.address),
CliColor::Info,
);
if let Some(err) = &connection_error {
cli.bind_mut().publish_message(
format!("Error with connection: {}", err),
CliColor::Error,
);
}
if let Some(game) = &mut Game::singleton() {
let player_id = game
.bind()
.find_player_by_addr(&connection.address)
.map(|p| p.id);
if let Some(player_id) = player_id {
peer.broadcast_reliable(Package::PlayerLeft(
game.bind()
.find_player(player_id)
.unwrap()
.clone()
.into(),
));
game.bind_mut().remove_player(player_id);
}
}
}
teanet::PeerMessage::Closed => {
cli.bind_mut()
.publish_message(format!("Server closed"), CliColor::Info);
self.peer = None;
GameManager::singleton().bind_mut().game = None;
}
teanet::PeerMessage::Message(conn, msg) => match msg {
Package::SetSelfNick(nick) => {
if let Some(game) = &mut Game::singleton() {
let player = game
.bind()
.find_player_by_addr(&conn.address)
.cloned();
if let Some(player) = player {
peer.broadcast_reliable(Package::SetNick(
player.id,
nick.clone(),
));
game.bind_mut().update_player_nick(player.id, nick);
}
}
}
Package::SetReady(_, is_ready) => {
if let Some(game) = &mut Game::singleton() {
let player = game
.bind()
.find_player_by_addr(&conn.address)
.cloned();
if let Some(player) = player {
game.bind_mut()
.update_player_ready(player.id, is_ready);
peer.broadcast_reliable(Package::SetReady(
player.id, is_ready,
));
}
}
}
Package::MapLoaded => {
if let Some(game) = Game::singleton() {
for player in &game.bind().players {
if let Some(transform) = player.get_transform() {
peer.send_reliable(
&conn.address,
Package::SpawnPlayer(player.id, transform),
);
}
}
}
}
Package::SelfSync(sync_data) => {
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(sync_data);
}
}
}
Package::Jump(_) => {
if let Some(game) = &mut Game::singleton() {
let player = game
.bind()
.find_player_by_addr(&conn.address)
.cloned();
if let Some(player) = player {
game.bind_mut().handle_jump(player.id);
peer.broadcast_reliable(Package::Jump(player.id));
}
}
}
Package::Shoot(_, to, transform, look_up) => {
if let Some(game) = &mut Game::singleton() {
let player = game
.bind()
.find_player_by_addr(&conn.address)
.cloned();
if let Some(player) = player {
if game.bind_mut().handle_shoot(
player.id,
to.into(),
transform,
look_up,
true,
) {
peer.broadcast_reliable(Package::Shoot(
player.id, to, transform, look_up,
));
}
}
}
}
_ => {}
},
}
}
}
Err(err) => {
cli.bind_mut()
.publish_message(format!("Error: {}", err), CliColor::Error);
}
},
while let Some(message) = self.poll() {
self.handle_message(message);
}
}
}
}
impl NetworkManager {
fn poll(&mut self) -> Option<PeerMessage<Package>> {
let mut cli = CommandLinePanel::singleton();
if let Some(peer) = &mut self.peer {
let peer = match peer {
PeerKind::Client(peer, _) => peer,
PeerKind::Server(peer, _) => peer,
};
let result = peer.poll();
match result {
Ok(msg) => msg,
Err(err) => {
cli.bind_mut()
.publish_message(format!("Error: {}", err), CliColor::Error);
None
}
}
} else {
None
}
}
pub fn singleton() -> Gd<NetworkManager> {
get_autoload_by_name::<NetworkManager>(NETWORK_SINGLETON_NAME)
}
@ -546,7 +218,7 @@ impl NetworkManager {
}
}
fn swap_to_lobby(&self, is_host: bool) {
pub fn swap_to_lobby(&self, is_host: bool) {
if let Some(scene) = &self.lobby_scene {
self.base().get_tree().change_scene_to_packed(scene);
GameManager::singleton().bind_mut().init_game(is_host);

310
rust/src/net/protocol.rs Normal file
View File

@ -0,0 +1,310 @@
use std::net::SocketAddr;
use teanet::{Peer, PeerMessage};
use crate::{
game_manager::{Game, GameManager},
net::network_manager::{NetworkManager, Package, PeerKind},
ui::cli::{CliColor, CommandLinePanel},
};
impl NetworkManager {
pub fn handle_message(&mut self, message: PeerMessage<Package>) {
let mut cli = CommandLinePanel::singleton();
if let Some(peer) = &mut self.peer {
match peer {
PeerKind::Client(peer, _) => match message {
teanet::PeerMessage::NewConnection(connection) => {
cli.bind_mut().publish_message(
format!("Connected to: {}", connection.address),
CliColor::Info,
);
self.swap_to_lobby(false);
}
teanet::PeerMessage::Disconnected(connection, connection_error) => {
cli.bind_mut().publish_message(
format!("Disconnected from: {}", connection.address),
CliColor::Info,
);
if let Some(err) = &connection_error {
cli.bind_mut().publish_message(
format!("Error with connection: {}", err),
CliColor::Error,
);
}
peer.close();
}
teanet::PeerMessage::Closed => {
self.peer = None;
GameManager::singleton().bind_mut().game = None;
}
teanet::PeerMessage::Message(_, msg) => match msg {
Package::Hello => {
cli.bind_mut()
.publish_message(format!("Got \"Hello\"!"), CliColor::Info);
}
Package::Players(players, self_id) => {
cli.bind_mut()
.publish_message(format!("Got players"), CliColor::Info);
if let Some(game) = &mut Game::singleton() {
game.bind_mut().set_players(
players.into_iter().map(|p| p.clone().into()).collect(),
);
game.bind_mut().set_self(self_id);
}
}
Package::SetNick(id, nick) => {
if let Some(game) = &mut Game::singleton() {
if game.bind().self_id != Some(id) {
game.bind_mut().update_player_nick(id, nick);
}
}
}
Package::UpdatePings(pings) => {
if let Some(game) = &mut Game::singleton() {
for (player_id, ping) in pings {
game.bind_mut().update_player_ping(player_id, ping);
}
}
}
Package::NewPlayer(player) => {
if let Some(game) = &mut Game::singleton() {
if player.id != game.bind().self_id.unwrap_or(u16::MAX) {
game.bind_mut().new_player(
SocketAddr::from(([0, 0, 0, 0], 0)),
player.name,
Some(player.id),
);
}
}
}
Package::PlayerLeft(player) => {
if let Some(game) = &mut Game::singleton() {
if player.id != game.bind().self_id.unwrap_or(u16::MAX) {
game.bind_mut().remove_player(player.id);
}
}
}
Package::SetReady(player_id, is_ready) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().update_player_ready(player_id, is_ready);
}
}
Package::SelectMap(map_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().change_map_selection(map_id, true);
}
}
Package::GameStarted => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().start_game();
}
}
Package::SpawnPlayer(id, transform) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().spawn_player_client(id, transform);
}
}
Package::Sync(sync_data, ball_sync) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_sync(sync_data, ball_sync);
}
}
Package::Jump(player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_jump(player_id);
}
}
Package::Shoot(player_id, to, transform, look_up) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_shoot(
player_id,
to.into(),
transform,
look_up,
false,
);
}
}
Package::TakeDamage(source_player_id, target_player_id, damage) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_take_damage(
source_player_id,
target_player_id,
damage,
);
}
}
Package::Kill(source_player_id, target_player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut()
.handle_kill(source_player_id, target_player_id);
}
}
Package::SpawnBall(transform, velocity, player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().spawn_ball(
Some(transform),
Some(velocity),
player_id,
);
}
}
Package::DespawnBall => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().despawn_ball();
}
}
Package::SwapWeapon(id, weapon_type) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_swap_weapon(id, weapon_type, true);
}
}
_ => {}
},
},
PeerKind::Server(peer, _) => match message {
teanet::PeerMessage::NewConnection(connection) => {
cli.bind_mut().publish_message(
format!("Client connected from: {}", connection.address),
CliColor::Info,
);
if let Some(game) = &mut Game::singleton() {
let self_id =
game.bind_mut()
.new_player(connection.address, String::new(), None);
peer.send_reliable(
&connection.address,
Package::Players(
game.bind()
.players
.clone()
.into_iter()
.map(|p| p.into())
.collect(),
self_id,
),
);
peer.broadcast_reliable(Package::NewPlayer(
game.bind().find_player(self_id).unwrap().clone().into(),
));
peer.send_reliable(
&connection.address,
Package::SelectMap(game.bind().selected_map_idx),
);
}
}
teanet::PeerMessage::Disconnected(connection, connection_error) => {
cli.bind_mut().publish_message(
format!("Client disconnected: {}", connection.address),
CliColor::Info,
);
if let Some(err) = &connection_error {
cli.bind_mut().publish_message(
format!("Error with connection: {}", err),
CliColor::Error,
);
}
if let Some(game) = &mut Game::singleton() {
let player_id = game
.bind()
.find_player_by_addr(&connection.address)
.map(|p| p.id);
if let Some(player_id) = player_id {
peer.broadcast_reliable(Package::PlayerLeft(
game.bind().find_player(player_id).unwrap().clone().into(),
));
game.bind_mut().remove_player(player_id);
}
}
}
teanet::PeerMessage::Closed => {
cli.bind_mut()
.publish_message(format!("Server closed"), CliColor::Info);
self.peer = None;
GameManager::singleton().bind_mut().game = None;
}
teanet::PeerMessage::Message(conn, msg) => match msg {
Package::SetSelfNick(nick) => {
if let Some(game) = &mut Game::singleton() {
let player =
game.bind().find_player_by_addr(&conn.address).cloned();
if let Some(player) = player {
peer.broadcast_reliable(Package::SetNick(
player.id,
nick.clone(),
));
game.bind_mut().update_player_nick(player.id, nick);
}
}
}
Package::SetReady(_, is_ready) => {
if let Some(game) = &mut Game::singleton() {
let player =
game.bind().find_player_by_addr(&conn.address).cloned();
if let Some(player) = player {
game.bind_mut().update_player_ready(player.id, is_ready);
peer.broadcast_reliable(Package::SetReady(player.id, is_ready));
}
}
}
Package::MapLoaded => {
if let Some(game) = Game::singleton() {
for player in &game.bind().players {
if let Some(transform) = player.get_transform() {
peer.send_reliable(
&conn.address,
Package::SpawnPlayer(player.id, transform),
);
}
}
}
}
Package::SelfSync(sync_data) => {
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(sync_data);
}
}
}
Package::Jump(_) => {
if let Some(game) = &mut Game::singleton() {
let player =
game.bind().find_player_by_addr(&conn.address).cloned();
if let Some(player) = player {
game.bind_mut().handle_jump(player.id);
peer.broadcast_reliable(Package::Jump(player.id));
}
}
}
Package::Shoot(_, to, transform, look_up) => {
if let Some(game) = &mut Game::singleton() {
let player =
game.bind().find_player_by_addr(&conn.address).cloned();
if let Some(player) = player {
if game.bind_mut().handle_shoot(
player.id,
to.into(),
transform,
look_up,
true,
) {
peer.broadcast_reliable(Package::Shoot(
player.id, to, transform, look_up,
));
}
}
}
}
_ => {}
},
},
}
}
}
}