Tons of fixes
Added movement updates Updated how entities are checked Events sending between packet service all the way to the logic service
This commit is contained in:
@@ -1,21 +1,32 @@
|
||||
pub mod components;
|
||||
mod entity_factory;
|
||||
mod entity_system;
|
||||
mod id_manager;
|
||||
mod loader;
|
||||
mod random;
|
||||
mod game_logic_service;
|
||||
mod game_service;
|
||||
mod world_client;
|
||||
mod spatial_grid;
|
||||
|
||||
use dotenv::dotenv;
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use hecs::World;
|
||||
use tracing::{debug, error, info};
|
||||
use tokio::time::{timeout, Duration};
|
||||
use tokio::sync::oneshot;
|
||||
use tonic::transport::Server;
|
||||
use tracing::{debug, error, info, warn};
|
||||
use utils::service_discovery::{get_kube_service_endpoints_by_dns, get_service_endpoints_by_dns};
|
||||
use utils::{health_check, logging};
|
||||
|
||||
use loader::load_zone_for_map;
|
||||
use crate::components::position::Position;
|
||||
use crate::entity_factory::EntityFactory;
|
||||
use crate::entity_system::EntitySystem;
|
||||
use crate::world_client::{WorldGameLogicServiceImpl, WorldGameLogicServiceServer};
|
||||
use crate::game_logic_service::{MyGameLogicService, game_logic::game_logic_service_server::GameLogicServiceServer};
|
||||
use crate::game_service::{MyGameService};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
@@ -45,18 +56,65 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
// Create world service first
|
||||
let world_game_logic_service_impl = WorldGameLogicServiceImpl::new(map_id);
|
||||
let world_game_logic_service_arc = Arc::new(world_game_logic_service_impl);
|
||||
|
||||
// Create shared entity system with world service
|
||||
let entity_system = Arc::new(EntitySystem::new().with_world_service(world_game_logic_service_arc.clone()));
|
||||
|
||||
// Create world service with entity system for the gRPC server
|
||||
let world_game_logic_service = WorldGameLogicServiceImpl::new(map_id).with_entity_system(entity_system.clone());
|
||||
|
||||
// Create gRPC services
|
||||
let game_logic_service = MyGameLogicService {
|
||||
map_id,
|
||||
entity_system: entity_system.clone(),
|
||||
};
|
||||
let game_service = MyGameService {};
|
||||
|
||||
// Start gRPC server with graceful shutdown support
|
||||
let grpc_addr = format!("{}:{}", addr, port).parse()?;
|
||||
info!("Starting Game Logic Service gRPC server on {}", grpc_addr);
|
||||
|
||||
// Create shutdown signal channels
|
||||
let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
|
||||
let (game_logic_shutdown_tx, mut game_logic_shutdown_rx) = oneshot::channel::<()>();
|
||||
|
||||
let server_task = tokio::spawn(async move {
|
||||
let server = Server::builder()
|
||||
.add_service(GameLogicServiceServer::new(game_logic_service))
|
||||
.add_service(game_service.into_service())
|
||||
.add_service(WorldGameLogicServiceServer::new(world_game_logic_service))
|
||||
.serve_with_shutdown(grpc_addr, async {
|
||||
shutdown_rx.await.ok();
|
||||
info!("gRPC server shutdown signal received");
|
||||
});
|
||||
|
||||
if let Err(e) = server.await {
|
||||
error!("gRPC server error: {}", e);
|
||||
} else {
|
||||
info!("gRPC server shut down gracefully");
|
||||
}
|
||||
});
|
||||
|
||||
let entity_system_clone = entity_system.clone();
|
||||
let game_logic_task = tokio::spawn(async move {
|
||||
let mut loading = true;
|
||||
let mut world = World::new();
|
||||
let mut factory = EntityFactory::new(&mut world);
|
||||
|
||||
loop {
|
||||
// Check for shutdown signal
|
||||
if let Ok(_) = game_logic_shutdown_rx.try_recv() {
|
||||
info!("Game logic task received shutdown signal");
|
||||
break;
|
||||
}
|
||||
|
||||
// Load the map
|
||||
if loading {
|
||||
match load_zone_for_map(file_path, map_id) {
|
||||
Ok(Some(zone)) => {
|
||||
info!("Zone with Map Id {} found:", map_id);
|
||||
factory.load_map(zone);
|
||||
entity_system_clone.load_map(zone);
|
||||
loading = false;
|
||||
}
|
||||
Ok(None) => {
|
||||
@@ -72,14 +130,66 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Update the world
|
||||
if !loading {
|
||||
factory.run();
|
||||
entity_system_clone.run();
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000/30));
|
||||
}
|
||||
info!("Game logic task shut down gracefully");
|
||||
});
|
||||
|
||||
// Register service with Consul
|
||||
// health_check::start_health_check(addr.as_str()).await?;
|
||||
|
||||
// Wait for shutdown signal
|
||||
info!("Game Logic service is running. Waiting for shutdown signal...");
|
||||
utils::signal_handler::wait_for_signal().await;
|
||||
|
||||
info!("Shutdown signal received. Beginning graceful shutdown...");
|
||||
|
||||
// Step 1: Signal the game logic task to stop
|
||||
if let Err(_) = game_logic_shutdown_tx.send(()) {
|
||||
warn!("Failed to send shutdown signal to game logic task (receiver may have been dropped)");
|
||||
}
|
||||
|
||||
// Step 2: Signal the gRPC server to stop accepting new connections
|
||||
if let Err(_) = shutdown_tx.send(()) {
|
||||
warn!("Failed to send shutdown signal to gRPC server (receiver may have been dropped)");
|
||||
}
|
||||
|
||||
// Step 3: Wait for both tasks to finish with timeouts
|
||||
let mut shutdown_errors = Vec::new();
|
||||
|
||||
match timeout(Duration::from_secs(10), game_logic_task).await {
|
||||
Ok(result) => {
|
||||
if let Err(e) = result {
|
||||
error!("Game logic task failed: {}", e);
|
||||
shutdown_errors.push(format!("Game logic task: {}", e));
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
error!("Game logic task shutdown timed out after 10 seconds");
|
||||
shutdown_errors.push("Game logic task: timeout".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
match timeout(Duration::from_secs(30), server_task).await {
|
||||
Ok(result) => {
|
||||
if let Err(e) = result {
|
||||
error!("gRPC server task failed: {}", e);
|
||||
shutdown_errors.push(format!("gRPC server task: {}", e));
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
error!("gRPC server shutdown timed out after 30 seconds");
|
||||
shutdown_errors.push("gRPC server task: timeout".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if shutdown_errors.is_empty() {
|
||||
info!("All components shut down successfully");
|
||||
} else {
|
||||
warn!("Some components failed to shut down cleanly: {:?}", shutdown_errors);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user