Skip to content
This repository was archived by the owner on May 8, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/game/faction.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use actix_web::{get, web, HttpResponse};
use serde::{Serialize, Deserialize};
use crate::{
AppState,
game::global::AppState,
game::{
game::game::GameID,
},
Expand Down Expand Up @@ -119,7 +119,7 @@ impl GameFaction {
}

#[get("/")]
pub async fn get_factions(state: web::Data<AppState>) -> Result<HttpResponse> {
pub async fn get_factions(state: &AppState) -> Result<HttpResponse> {
Ok(HttpResponse::Ok().json(Faction::find_all(&state.db_pool).await?))
}

Expand Down
46 changes: 28 additions & 18 deletions src/game/fleet/combat/battle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::{HashSet, HashMap};
use crate::{
game::global::state,
task,
lib::{
error::{ServerError, InternalError},
Expand All @@ -9,7 +10,7 @@ use crate::{
},
game::{
faction::FactionID,
game::server::GameServer,
game::{game::GameID, server::GameServer},
fleet::{
combat::{
conquest::Conquest,
Expand All @@ -23,12 +24,12 @@ use crate::{
},
ws::protocol,
};
use actix::prelude::*;
use serde::{Deserialize, Serialize};
use sqlx::{PgPool, PgConnection, pool::PoolConnection, postgres::{PgRow, PgQueryAs}, FromRow, Executor, Transaction, Postgres, Error, types::Json};
use sqlx_core::row::Row;
use rand::prelude::*;
use uuid::Uuid;
use futures::executor::block_on;

#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq, Copy)]
pub struct BattleID(pub Uuid);
Expand Down Expand Up @@ -180,24 +181,31 @@ impl Battle {
Err(InternalError::NotFound.into())
}

pub async fn engage(arriver: &Fleet, orbiting_fleets: &HashMap<FleetID, Fleet>, system: &System, defender_faction: Option<FactionID>, server: &GameServer) -> Result<()> {
Conquest::stop(&system, &server).await?;
pub async fn engage(arriver: &Fleet, orbiting_fleets: &HashMap<FleetID, Fleet>, system: &System, defender_faction: Option<FactionID>, gid: GameID) -> Result<()> {
let state = state();
Conquest::stop(&system, gid).await?;

let mut fleets = orbiting_fleets.clone();
fleets.insert(arriver.id.clone(), arriver.clone());

let battle = init_battle(arriver, system, fleets, defender_faction, &server.state.db_pool).await?;
let battle = init_battle(arriver, system, fleets, defender_faction, &state.db_pool).await?;

server.ws_broadcast(&protocol::Message::new(protocol::Action::BattleStarted, &battle, None)).await?;
GameServer::ws_broadcast(gid, protocol::Message::new(protocol::Action::BattleStarted, &battle, None)).await?;

let mut round = Round::new(battle.id, 1);
server.state.games().get(&server.id).unwrap().do_send(task!(round -> move |gs| block_on(round.execute(gs))));
state.games().get(&gid).unwrap().do_send(task!(round -> move |gs, ctx| {
let gid = gs.id;
ctx.wait(actix::fut::wrap_future(async move {
round.execute(gid).await;
}));
Ok(())
}));

log(gelf::Level::Informational, "Battle started", "A new battle has started", vec![
("battle_id", battle.id.0.to_string()),
("system_id", system.id.0.to_string()),
("fleet_id", arriver.id.0.to_string()),
], &server.state.logger);
], &state.logger);

Ok(())
}
Expand All @@ -207,12 +215,13 @@ impl Battle {
2 > self.fleets.keys().len()
}

pub async fn end(&mut self, server: &GameServer) -> Result<()> {
pub async fn end(&mut self, gid: GameID) -> Result<()> {
let state = state();
self.victor = Some(self.process_victor()?);
self.ended_at = Some(Time::now());
self.update(&mut &server.state.db_pool).await?;
self.update(&mut &state.db_pool).await?;

server.ws_broadcast(&protocol::Message::new(
GameServer::ws_broadcast(gid, protocol::Message::new(
protocol::Action::BattleEnded,
self.clone(),
None
Expand All @@ -222,16 +231,16 @@ impl Battle {
return Ok(());
}

let fleet = Fleet::find(&self.attacker, &server.state.db_pool).await?;
let system = System::find(self.system, &server.state.db_pool).await?;
let fleet = Fleet::find(&self.attacker, &state.db_pool).await?;
let system = System::find(self.system, &state.db_pool).await?;

log(gelf::Level::Informational, "Battle ended", "A battle has finished", vec![
("battle_id", self.id.0.to_string()),
("victor_id", self.victor.unwrap().0.to_string()),
("system_id", self.system.0.to_string())
], &server.state.logger);
], &state.logger);

Conquest::resume(&fleet, &system, self.victor, &server).await
Conquest::resume(&fleet, &system, self.victor, gid).await
}
}

Expand Down Expand Up @@ -292,8 +301,9 @@ async fn init_battle(attacker: &Fleet, system: &System, fleets: HashMap<FleetID,
Ok(battle)
}

pub async fn update_fleets(battle: &Battle, server: &GameServer) -> Result<HashMap<FactionID, HashMap<FleetID, Fleet>>> {
let mut tx = server.state.db_pool.begin().await?;
pub async fn update_fleets(battle: &Battle) -> Result<HashMap<FactionID, HashMap<FleetID, Fleet>>> {
let state = state();
let mut tx = state.db_pool.begin().await?;
let mut remaining_fleets = HashMap::new();

for (faction_id, fleets) in battle.fleets.iter() {
Expand All @@ -304,7 +314,7 @@ pub async fn update_fleets(battle: &Battle, server: &GameServer) -> Result<HashM
log(gelf::Level::Informational, "Fleet destroyed", "A fleet has been destroyed in combat", vec![
("fleet_id", fleet.id.0.to_string()),
("battle_id", battle.id.0.to_string()),
], &server.state.logger);
], &state.logger);
} else {
faction_remaining_fleets.insert(*fleet_id, fleet.clone());
}
Expand Down
111 changes: 67 additions & 44 deletions src/game/fleet/combat/conquest.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use actix_web::web;
use actix::prelude::*;
use crate::{
task,
cancel_task,
Expand All @@ -21,11 +21,10 @@ use crate::{
player::{Player, PlayerID},
system::system::{SystemID, System},
},
AppState,
game::global::{state, AppState},
ws::protocol,
};
use chrono::{DateTime, Utc};
use futures::executor::block_on;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use sqlx::{PgPool, PgConnection, pool::PoolConnection, postgres::{PgRow, PgQueryAs}, FromRow, Executor, Error, Transaction, Postgres, types::Json};
Expand Down Expand Up @@ -139,19 +138,26 @@ impl Conquest {
.fetch_optional(db_pool).await.map_err(ServerError::from)
}

pub async fn remove_fleet(&mut self, system: &System, fleet: &Fleet, server: &GameServer) -> Result<()> {
let mut fleets = system.retrieve_orbiting_fleets(&server.state.db_pool).await?;
let game = Game::find(system.game, &server.state.db_pool).await?;
pub async fn remove_fleet(&mut self, system: &System, fleet: &Fleet, gid: GameID) -> Result<()> {
let state = state();
let mut fleets = system.retrieve_orbiting_fleets(&state.db_pool).await?;
let game = Game::find(system.game, &state.db_pool).await?;
fleets.retain(|&fid, _| fid != fleet.id);
// If the current fleet is the only one, the conquest is cancelled
if fleets.len() < 1 {
return self.cancel(&server).await;
return self.cancel(gid).await;
}
server.state.games().get(&server.id).unwrap().do_send(cancel_task!(self));
self.update_time(fleets.values().collect(), game.game_speed, &server.state.db_pool).await?;
state.games().get(&gid).unwrap().do_send(cancel_task!(self));
self.update_time(fleets.values().collect(), game.game_speed, &state.db_pool).await?;

let mut conquest = self.clone();
server.state.games().get(&server.id).unwrap().do_send(task!(conquest -> move |server| block_on(conquest.end(&server))));
state.games().get(&gid).unwrap().do_send(task!(conquest -> move |server, ctx| {
let gid = server.id;
ctx.wait(actix::fut::wrap_future(async move {
conquest.end(gid).await;
}));
Ok(())
}));

Ok(())
}
Expand All @@ -169,37 +175,39 @@ impl Conquest {
Ok(())
}

pub async fn cancel(&mut self, server: &GameServer) -> Result<()> {
pub async fn cancel(&mut self, gid: GameID) -> Result<()> {
let state = state();
self.ended_at = Time::now();
self.is_over = true;
self.update(&mut &server.state.db_pool).await?;
self.update(&mut &state.db_pool).await?;

let conquest = self.clone();
server.ws_broadcast(&protocol::Message::new(
GameServer::ws_broadcast(gid, protocol::Message::new(
protocol::Action::ConquestCancelled,
conquest.clone(),
None
)).await?;
server.state.games().get(&server.id).unwrap().do_send(cancel_task!(conquest));
state.games().get(&gid).unwrap().do_send(cancel_task!(conquest));

log(gelf::Level::Informational, "Conquest cancelled", "The last fleet executing the conquest has travelled elsewhere", vec![
("conquest_id", conquest.id.0.to_string()),
("system_id", conquest.system.0.to_string()),
], &server.state.logger);
], &state.logger);

Ok(())
}

pub async fn stop(system: &System, server: &GameServer) -> Result<()> {
let c = Self::find_current_by_system(&system.id, &server.state.db_pool).await?;
pub async fn stop(system: &System, gid: GameID) -> Result<()> {
let state = state();
let c = Self::find_current_by_system(&system.id, &state.db_pool).await?;

if let Some(mut conquest) = c {
conquest.halt(&server.state, &server.id).await?;
conquest.halt(&state, gid).await?;
}
Ok(())
}

pub async fn halt(&mut self, state: &web::Data<AppState>, game_id: &GameID) -> Result<()> {
pub async fn halt(&mut self, state: &AppState, game_id: GameID) -> Result<()> {
self.is_stopped = true;
self.percent = self.calculate_progress();
self.update(&mut &state.db_pool).await?;
Expand All @@ -219,21 +227,22 @@ impl Conquest {
self.percent + (consumed_ms / total_ms)
}

pub async fn resume(fleet: &Fleet, system: &System, victor_faction: Option<FactionID>, server: &GameServer) -> Result<()> {
let c = Self::find_current_by_system(&system.id, &server.state.db_pool).await?;
let game = Game::find(system.game, &server.state.db_pool).await?;
let fleets_data = system.retrieve_orbiting_fleets(&server.state.db_pool).await?;
pub async fn resume(fleet: &Fleet, system: &System, victor_faction: Option<FactionID>, gid: GameID) -> Result<()> {
let state = state();
let c = Self::find_current_by_system(&system.id, &state.db_pool).await?;
let game = Game::find(system.game, &state.db_pool).await?;
let fleets_data = system.retrieve_orbiting_fleets(&state.db_pool).await?;
let fleets = fleets_data.values().collect();

if let Some(mut conquest) = c {
let conquest_player = Player::find(conquest.player, &server.state.db_pool).await?;
let games = server.state.games();
let game_server = games.get(&server.id).unwrap();
let conquest_player = Player::find(conquest.player, &state.db_pool).await?;
let games = state.games();
let game_server = games.get(&gid).unwrap();

if victor_faction.is_some() && victor_faction != conquest_player.faction {
conquest.cancel(&server).await?;
conquest.cancel(gid).await?;

return Self::new(fleet, fleets, system, game.game_speed, &server).await;
return Self::new(fleet, fleets, system, game.game_speed, gid).await;
}

// This case means the fleet is reinforcing a current conquest
Expand All @@ -245,21 +254,28 @@ impl Conquest {
None,
));
}
conquest.update_time(fleets, game.game_speed, &server.state.db_pool).await?;
conquest.update_time(fleets, game.game_speed, &state.db_pool).await?;

game_server.do_send(protocol::Message::new(
protocol::Action::ConquestUpdated,
conquest.clone(),
None
));
game_server.do_send(task!(conquest -> move |server| block_on(conquest.end(&server))));
game_server.do_send(task!(conquest -> move |server, ctx| {
let gid = server.id;
ctx.wait(actix::fut::wrap_future(async move {
conquest.end(gid).await;
}));
Ok(())
}));

return Ok(());
}
Self::new(fleet, fleets, system, game.game_speed, &server).await
Self::new(fleet, fleets, system, game.game_speed, gid).await
}

pub async fn new(fleet: &Fleet, fleets: Vec<&Fleet>, system: &System, game_speed: GameOptionSpeed, server: &GameServer) -> Result<()> {
pub async fn new(fleet: &Fleet, fleets: Vec<&Fleet>, system: &System, game_speed: GameOptionSpeed, gid: GameID) -> Result<()> {
let state = state();
let conquest_id = ConquestID(Uuid::new_v4());
let mut conquest = Conquest{
id: conquest_id,
Expand All @@ -274,37 +290,44 @@ impl Conquest {
is_successful: false,
is_over: false,
};
conquest.insert(&mut &server.state.db_pool).await?;
conquest.insert(&mut &state.db_pool).await?;

log(gelf::Level::Informational, "New conquest", "A new conquest has started", vec![
("conquest_id", conquest_id.0.to_string()),
("player_id", fleets[0].player.0.to_string()),
("fleet_id", fleets[0].id.0.to_string()),
("system_id", system.id.0.to_string())
], &server.state.logger);
], &state.logger);

server.ws_broadcast(&protocol::Message::new(
GameServer::ws_broadcast(gid, protocol::Message::new(
protocol::Action::ConquestStarted,
conquest.clone(),
None
)).await?;

server.state.games().get(&server.id).unwrap().do_send(task!(conquest -> move |server| block_on(conquest.end(&server))));
state.games().get(&gid).unwrap().do_send(task!(conquest -> move |server, ctx| {
let gid = server.id;
ctx.wait(actix::fut::wrap_future(async move {
conquest.end(gid).await;
}));
Ok(())
}));

Ok(())
}

pub async fn end(&mut self, server: &GameServer) -> Result<()> {
let mut system = System::find(self.system.clone(), &server.state.db_pool).await?;
let fleets = system.retrieve_orbiting_fleets(&server.state.db_pool).await?.values().cloned().collect();
pub async fn end(&mut self, gid: GameID) -> Result<()> {
let state = state();
let mut system = System::find(self.system.clone(), &state.db_pool).await?;
let fleets = system.retrieve_orbiting_fleets(&state.db_pool).await?.values().cloned().collect();

self.is_over = true;
self.update(&mut &server.state.db_pool).await?;
self.update(&mut &state.db_pool).await?;

system.player = Some(self.player.clone());
system.update(&mut &server.state.db_pool).await?;
system.update(&mut &state.db_pool).await?;

server.ws_broadcast(&protocol::Message::new(
GameServer::ws_broadcast(gid, protocol::Message::new(
protocol::Action::SystemConquerred,
ConquestData{ system, fleets },
None
Expand All @@ -314,7 +337,7 @@ impl Conquest {
("conquest_id", self.id.0.to_string()),
("player_id", self.player.0.to_string()),
("system_id", self.system.0.to_string())
], &server.state.logger);
], &state.logger);

Ok(())
}
Expand Down Expand Up @@ -423,4 +446,4 @@ mod tests
category,
}
}
}
}
Loading