Compare commits

..

No commits in common. "f45f15b3bfbeacbb9ecce9019188f00569a0c6da" and "6284c49bb9436b0e63d52d18ef90746e14990fa5" have entirely different histories.

31 changed files with 184 additions and 210 deletions

View File

@ -4,7 +4,7 @@ use godot::{
tools::get_autoload_by_name, tools::get_autoload_by_name,
}; };
use crate::game::GameManager; use crate::game_manager::GameManager;
pub const MUSIC_MANAGER_GLOBAL: &str = "MusicManagerGlobal"; pub const MUSIC_MANAGER_GLOBAL: &str = "MusicManagerGlobal";

View File

@ -2,7 +2,7 @@ use godot::{classes::RichTextLabel, prelude::*};
use crate::{ use crate::{
announcer::Announcement, announcer::Announcement,
game::{Game, Player}, game_manager::{Game, Player},
player::DamageSource, player::DamageSource,
}; };

View File

@ -3,7 +3,7 @@ use std::net::SocketAddr;
use godot::{classes::Os, prelude::*}; use godot::{classes::Os, prelude::*};
use crate::{ use crate::{
game::{Game, GameManager}, game_manager::{Game, GameManager},
net::network_manager::NetworkManager, net::network_manager::NetworkManager,
}; };

View File

@ -1,74 +0,0 @@
use godot::classes::class_macros::private::virtuals::Xrvrs::Gd;
use crate::{
game::Game,
ui::cli::{CliColor, Command, CommandLinePanel},
};
pub fn register_commands(cli: &mut Gd<CommandLinePanel>) {
cli.bind_mut()
.register_command("respawn_ball".to_string(), Box::new(RespawnBallCommand));
cli.bind_mut()
.register_command("players".to_string(), Box::new(ListPlayersCommand));
cli.bind_mut()
.register_command("kill".to_string(), Box::new(KillCommand));
}
pub fn unregister_commands(cli: &mut Gd<CommandLinePanel>) {
cli.bind_mut()
.unregister_command("respawn_ball".to_string());
cli.bind_mut().unregister_command("players".to_string());
cli.bind_mut().unregister_command("kill".to_string());
}
pub struct RespawnBallCommand;
impl Command for RespawnBallCommand {
fn execute(&self, _: &mut CommandLinePanel, _: &[&str]) {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().respawn_ball();
}
}
fn help(&self) -> &str {
"respawns the ball"
}
}
pub struct ListPlayersCommand;
impl Command for ListPlayersCommand {
fn execute(&self, cli: &mut CommandLinePanel, _: &[&str]) {
if let Some(game) = &mut Game::singleton() {
for player in &game.bind().players {
cli.publish_message(
format!(" - {} ({})", player.data.name, player.id()),
CliColor::Info,
);
}
}
}
fn help(&self) -> &str {
"lists all players"
}
}
pub struct KillCommand;
impl Command for KillCommand {
fn execute(&self, cli: &mut CommandLinePanel, args: &[&str]) {
if let Some(player_str) = args.first() {
if let Ok(player_id) = player_str.parse() {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().kill_player(player_id);
}
} else {
cli.publish_message("Invalid player id".to_string(), CliColor::Error);
}
} else {
cli.publish_message("Usage: kill [player_id]".to_string(), CliColor::Error);
}
}
fn help(&self) -> &str {
"kills given player"
}
}

View File

@ -1,86 +0,0 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub struct GameOptions {
pub values: HashMap<GameOption, GameOptionValue>,
}
impl Default for GameOptions {
fn default() -> Self {
let mut opts = HashMap::new();
opts.insert(GameOption::AllowAnyMap, GameOptionValue::Boolean(false));
opts.insert(GameOption::AllowAnyTeam, GameOptionValue::Boolean(false));
opts.insert(GameOption::FriendlyFire, GameOptionValue::Boolean(true));
opts.insert(GameOption::GoalsNeededToWin, GameOptionValue::Number(5.));
opts.insert(GameOption::RespawnTimer, GameOptionValue::Number(5.));
opts.insert(
GameOption::TelegrenadesAllowed,
GameOptionValue::Boolean(true),
);
Self { values: opts }
}
}
impl GameOptions {
pub fn is_true(&self, opt: GameOption) -> bool {
let opt = self
.values
.get(&opt)
.copied()
.unwrap_or(GameOptionValue::Boolean(false));
match opt {
GameOptionValue::Boolean(value) => value,
_ => false,
}
}
pub fn get_float(&self, opt: GameOption) -> f64 {
let opt = self
.values
.get(&opt)
.copied()
.unwrap_or(GameOptionValue::Number(0.));
match opt {
GameOptionValue::Number(value) => value,
_ => 0.,
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Hash, Copy, Clone, Serialize, Deserialize)]
pub enum GameOption {
/// Allow anyone to select a map, not just the host
AllowAnyMap,
/// Allow anyone to select anyone's team, not just themselves and the host
AllowAnyTeam,
/// Allow anyone to shoot anyone, not just other team's members
FriendlyFire,
/// The number of goals needed to win a match
GoalsNeededToWin,
/// Whether telegrenades are allowed or not.
TelegrenadesAllowed,
/// How long in seconds does it take for a player to respawn
RespawnTimer,
}
impl ToString for GameOption {
fn to_string(&self) -> String {
match self {
GameOption::AllowAnyMap => "Allow anyone to select the map",
GameOption::AllowAnyTeam => "Allow anyone to select any teams",
GameOption::FriendlyFire => "Friendly fire",
GameOption::GoalsNeededToWin => "Goals needed to win",
GameOption::TelegrenadesAllowed => "Telegrenades allowed",
GameOption::RespawnTimer => "Respawn Time (seconds)",
}
.to_owned()
}
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum GameOptionValue {
Boolean(bool),
Number(f64),
}

View File

@ -10,10 +10,6 @@ use crate::{
}, },
bgm::{Music, MusicManager}, bgm::{Music, MusicManager},
chat::{Chat, ChatMessage}, chat::{Chat, ChatMessage},
game::{
commands::{register_commands, unregister_commands},
opts::{GameOption, GameOptionValue, GameOptions},
},
map::Map, map::Map,
map_resource::MapResource, map_resource::MapResource,
net::{ net::{
@ -33,12 +29,9 @@ use crate::{
}, },
replay::{ReplayEvent, ReplayPlayback, ReplayRecorder}, replay::{ReplayEvent, ReplayPlayback, ReplayRecorder},
team_resource::TeamResource, team_resource::TeamResource,
ui::cli::CommandLinePanel, ui::cli::{CliColor, Command, CommandLinePanel},
}; };
pub mod commands;
pub mod opts;
pub const GAME_MANAGER_GLOBAL: &str = "GameManagerGlobal"; pub const GAME_MANAGER_GLOBAL: &str = "GameManagerGlobal";
#[derive(GodotClass)] #[derive(GodotClass)]
@ -159,6 +152,141 @@ impl GameManager {
} }
} }
#[derive(Debug)]
pub struct GameOptions {
pub values: HashMap<GameOption, GameOptionValue>,
}
impl Default for GameOptions {
fn default() -> Self {
let mut opts = HashMap::new();
opts.insert(GameOption::AllowAnyMap, GameOptionValue::Boolean(false));
opts.insert(GameOption::AllowAnyTeam, GameOptionValue::Boolean(false));
opts.insert(GameOption::FriendlyFire, GameOptionValue::Boolean(true));
opts.insert(GameOption::GoalsNeededToWin, GameOptionValue::Number(5.));
opts.insert(GameOption::RespawnTimer, GameOptionValue::Number(5.));
opts.insert(
GameOption::TelegrenadesAllowed,
GameOptionValue::Boolean(true),
);
Self { values: opts }
}
}
impl GameOptions {
pub fn is_true(&self, opt: GameOption) -> bool {
let opt = self
.values
.get(&opt)
.copied()
.unwrap_or(GameOptionValue::Boolean(false));
match opt {
GameOptionValue::Boolean(value) => value,
_ => false,
}
}
pub fn get_float(&self, opt: GameOption) -> f64 {
let opt = self
.values
.get(&opt)
.copied()
.unwrap_or(GameOptionValue::Number(0.));
match opt {
GameOptionValue::Number(value) => value,
_ => 0.,
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Hash, Copy, Clone, Serialize, Deserialize)]
pub enum GameOption {
/// Allow anyone to select a map, not just the host
AllowAnyMap,
/// Allow anyone to select anyone's team, not just themselves and the host
AllowAnyTeam,
/// Allow anyone to shoot anyone, not just other team's members
FriendlyFire,
/// The number of goals needed to win a match
GoalsNeededToWin,
/// Whether telegrenades are allowed or not.
TelegrenadesAllowed,
/// How long in seconds does it take for a player to respawn
RespawnTimer,
}
impl ToString for GameOption {
fn to_string(&self) -> String {
match self {
GameOption::AllowAnyMap => "Allow anyone to select the map",
GameOption::AllowAnyTeam => "Allow anyone to select any teams",
GameOption::FriendlyFire => "Friendly fire",
GameOption::GoalsNeededToWin => "Goals needed to win",
GameOption::TelegrenadesAllowed => "Telegrenades allowed",
GameOption::RespawnTimer => "Respawn Time (seconds)",
}
.to_owned()
}
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum GameOptionValue {
Boolean(bool),
Number(f64),
}
pub struct RespawnBallCommand;
impl Command for RespawnBallCommand {
fn execute(&self, _: &mut CommandLinePanel, _: &[&str]) {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().respawn_ball();
}
}
fn help(&self) -> &str {
"respawns the ball"
}
}
pub struct ListPlayersCommand;
impl Command for ListPlayersCommand {
fn execute(&self, cli: &mut CommandLinePanel, _: &[&str]) {
if let Some(game) = &mut Game::singleton() {
for player in &game.bind().players {
cli.publish_message(
format!(" - {} ({})", player.data.name, player.id()),
CliColor::Info,
);
}
}
}
fn help(&self) -> &str {
"lists all players"
}
}
pub struct KillCommand;
impl Command for KillCommand {
fn execute(&self, cli: &mut CommandLinePanel, args: &[&str]) {
if let Some(player_str) = args.first() {
if let Ok(player_id) = player_str.parse() {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().kill_player(player_id);
}
} else {
cli.publish_message("Invalid player id".to_string(), CliColor::Error);
}
} else {
cli.publish_message("Usage: kill [player_id]".to_string(), CliColor::Error);
}
}
fn help(&self) -> &str {
"kills given player"
}
}
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=Node, init)] #[class(base=Node, init)]
pub struct Game { pub struct Game {
@ -392,7 +520,12 @@ impl Game {
peer.set_accepting_connections(false); peer.set_accepting_connections(false);
let mut cli = CommandLinePanel::singleton(); let mut cli = CommandLinePanel::singleton();
register_commands(&mut cli); cli.bind_mut()
.register_command("respawn_ball".to_string(), Box::new(RespawnBallCommand));
cli.bind_mut()
.register_command("players".to_string(), Box::new(ListPlayersCommand));
cli.bind_mut()
.register_command("kill".to_string(), Box::new(KillCommand));
} }
} }
}); });
@ -461,7 +594,10 @@ impl Game {
}); });
let mut cli = CommandLinePanel::singleton(); let mut cli = CommandLinePanel::singleton();
unregister_commands(&mut cli); cli.bind_mut()
.unregister_command("respawn_ball".to_string());
cli.bind_mut().unregister_command("players".to_string());
cli.bind_mut().unregister_command("kill".to_string());
} }
pub fn change_option(&mut self, opt: GameOption, value: GameOptionValue) { pub fn change_option(&mut self, opt: GameOption, value: GameOptionValue) {

View File

@ -1,9 +1,12 @@
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::{
net::SocketAddr,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use godot::{ use godot::{
classes::{ classes::{
AudioServer, DisplayServer, FileAccess, InputEvent, InputEventKey, InputEventMouseButton, AudioServer, DisplayServer, FileAccess, InputEvent, InputEventKey, InputEventMouseButton,
InputMap, display_server::WindowMode, file_access::ModeFlags, InputMap, display_server::WindowMode, file_access::ModeFlags, window::Mode,
}, },
global::{Key, MouseButton}, global::{Key, MouseButton},
prelude::*, prelude::*,

View File

@ -3,7 +3,7 @@ use godot::{
prelude::*, prelude::*,
}; };
use crate::{game::Game, net::network_manager::NetworkManager, player::ball::Ball}; use crate::{game_manager::Game, net::network_manager::NetworkManager, player::ball::Ball};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=Area3D, init)] #[class(base=Area3D, init)]

View File

@ -5,7 +5,7 @@ use godot::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
game::Game, game_manager::Game,
net::network_manager::NetworkManager, net::network_manager::NetworkManager,
player::{DamageSource, IPlayer, ball::Ball}, player::{DamageSource, IPlayer, ball::Ball},
}; };

View File

@ -5,7 +5,7 @@ pub mod bgm;
pub mod chat; pub mod chat;
pub mod cli_parser; pub mod cli_parser;
pub mod credits; pub mod credits;
pub mod game; pub mod game_manager;
pub mod game_settings; pub mod game_settings;
pub mod goal; pub mod goal;
pub mod killbox; pub mod killbox;

View File

@ -2,7 +2,7 @@ use std::{collections::HashMap, f32::consts::PI};
use godot::{classes::RandomNumberGenerator, prelude::*}; use godot::{classes::RandomNumberGenerator, prelude::*};
use crate::{game::Game, ui::menu_player::MenuPlayer}; use crate::{game_manager::Game, ui::menu_player::MenuPlayer};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=Node3D, init)] #[class(base=Node3D, init)]

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use godot::{classes::CharacterBody3D, prelude::*}; use godot::{classes::CharacterBody3D, prelude::*};
use crate::{ use crate::{
game::{Game, GameManager}, game_manager::{Game, GameManager},
net::util::NetVector3, net::util::NetVector3,
pickup::Pickup, pickup::Pickup,
player::{ player::{

View File

@ -10,10 +10,7 @@ use teanet::{Peer, PeerConfig, PeerMessage};
use crate::{ use crate::{
announcer::Announcement, announcer::Announcement,
game::{ game_manager::{Game, GameManager, GameOption, GameOptionValue, NetPlayer},
Game, GameManager, NetPlayer,
opts::{GameOption, GameOptionValue},
},
game_settings::GameSettingsManager, game_settings::GameSettingsManager,
net::{net_stats::Stats, util::NetVector3}, net::{net_stats::Stats, util::NetVector3},
player::{DamageSource, NetTransform, weapon::WeaponType}, player::{DamageSource, NetTransform, weapon::WeaponType},

View File

@ -4,7 +4,7 @@ use godot::obj::Singleton;
use teanet::PeerMessage; use teanet::PeerMessage;
use crate::{ use crate::{
game::{Game, GameManager, opts::GameOption}, game_manager::{Game, GameManager, GameOption},
game_settings::GameSettingsManager, game_settings::GameSettingsManager,
net::network_manager::{NetworkManager, Package, PeerKind}, net::network_manager::{NetworkManager, Package, PeerKind},
popup_queue::{Popup, PopupQueue}, popup_queue::{Popup, PopupQueue},
@ -17,7 +17,7 @@ impl NetworkManager {
if let Some(peer) = &mut self.peer { if let Some(peer) = &mut self.peer {
match peer { match peer {
PeerKind::Client(peer, _) => match message { PeerKind::Client(peer, addr) => match message {
teanet::PeerMessage::NewConnection(connection) => { teanet::PeerMessage::NewConnection(connection) => {
cli.bind_mut().publish_message( cli.bind_mut().publish_message(
format!("Connected to: {}", connection.address), format!("Connected to: {}", connection.address),

View File

@ -2,7 +2,7 @@ use godot::{classes::Area3D, prelude::*};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
game::Game, map::Map, net::network_manager::NetworkManager, player::IPlayer, game_manager::Game, map::Map, net::network_manager::NetworkManager, player::IPlayer,
replay::StandaloneReplayManager, replay::StandaloneReplayManager,
}; };

View File

@ -10,7 +10,7 @@ use godot::{
}; };
use crate::{ use crate::{
game::{Game, GameManager, opts::GameOption}, game_manager::{Game, GameManager, GameOption},
game_settings::{GameSettings, GameSettingsManager}, game_settings::{GameSettings, GameSettingsManager},
killbox::KillboxKind, killbox::KillboxKind,
net::{ net::{

View File

@ -8,7 +8,7 @@ use godot::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
game::{Game, opts::GameOption}, game_manager::{Game, GameOption},
killbox::KillboxKind, killbox::KillboxKind,
net::{ net::{
network_manager::NetworkManager, network_manager::NetworkManager,

View File

@ -8,7 +8,7 @@ use godot::{
}; };
use crate::{ use crate::{
game::{Game, opts::GameOption}, game_manager::{Game, GameOption},
killbox::KillboxKind, killbox::KillboxKind,
pickup::PickupKind, pickup::PickupKind,
player::{ player::{

View File

@ -7,7 +7,7 @@ use godot::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
game::Game, game_manager::Game,
net::util::{cast_ray, shotgun_ray}, net::util::{cast_ray, shotgun_ray},
player::{DamageSource, shootable::Shootable}, player::{DamageSource, shootable::Shootable},
replay::StandaloneReplayManager, replay::StandaloneReplayManager,

View File

@ -9,7 +9,7 @@ use godot::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
game::{Game, GameManager, Player}, game_manager::{Game, GameManager, Player},
game_settings::GameSettingsManager, game_settings::GameSettingsManager,
map::Map, map::Map,
net::{network_manager::BallSync, util::NetVector3}, net::{network_manager::BallSync, util::NetVector3},
@ -362,7 +362,9 @@ impl INode for ReplayPlayback {
} }
self.telegrenades.remove(player_id); self.telegrenades.remove(player_id);
if let Some(map) = &mut self.current_map { if let Some(map) = &mut self.current_map
&& let Some(player) = self.replay.players.get(player_id)
{
if let Some(telegrenade) = map.bind_mut().spawn_replay_telegrenade( if let Some(telegrenade) = map.bind_mut().spawn_replay_telegrenade(
(*location).into(), (*location).into(),
(*velocity).into(), (*velocity).into(),

View File

@ -10,7 +10,7 @@ use godot::{
use crate::{ use crate::{
chat::Chat, chat::Chat,
game::Game, game_manager::Game,
net::network_manager::{NetworkManager, Package, PeerKind}, net::network_manager::{NetworkManager, Package, PeerKind},
ui::cli::CommandLinePanel, ui::cli::CommandLinePanel,
}; };

View File

@ -4,7 +4,7 @@ use godot::{
}; };
use crate::{ use crate::{
game::{Game, GameManager}, game_manager::{Game, GameManager},
ui::player_listings::PlayerListings, ui::player_listings::PlayerListings,
}; };

View File

@ -7,7 +7,7 @@ use godot::{
}; };
use crate::{ use crate::{
game::Game, game_manager::Game,
net::network_manager::NetworkManager, net::network_manager::NetworkManager,
ui::{chatbox::ChatBox, cli::CommandLinePanel, settings::SettingsPanel}, ui::{chatbox::ChatBox, cli::CommandLinePanel, settings::SettingsPanel},
}; };

View File

@ -10,10 +10,7 @@ use godot::{
use crate::{ use crate::{
bgm::{Music, MusicManager}, bgm::{Music, MusicManager},
game::{ game_manager::{Game, GameManager, GameOption, GameOptionValue, GameOptions},
Game, GameManager,
opts::{GameOption, GameOptionValue, GameOptions},
},
net::network_manager::{NetworkManager, Package, PeerKind}, net::network_manager::{NetworkManager, Package, PeerKind},
ui::lobby_player_listing::LobbyPlayerListing, ui::lobby_player_listing::LobbyPlayerListing,
}; };

View File

@ -4,10 +4,7 @@ use godot::{
}; };
use crate::{ use crate::{
game::{ game_manager::{Game, GameOption, GameOptions},
Game,
opts::{GameOption, GameOptions},
},
net::network_manager::NetworkManager, net::network_manager::NetworkManager,
team_resource::TeamResource, team_resource::TeamResource,
}; };

View File

@ -3,7 +3,7 @@ use godot::{
prelude::*, prelude::*,
}; };
use crate::{game::Game, player::soldier_mesh::SoldierMesh}; use crate::{game_manager::Game, player::soldier_mesh::SoldierMesh};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=CharacterBody3D, init)] #[class(base=CharacterBody3D, init)]

View File

@ -3,7 +3,7 @@ use godot::{
prelude::*, prelude::*,
}; };
use crate::{game::Game, replay::StandaloneReplayManager}; use crate::{game_manager::Game, replay::StandaloneReplayManager};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=HBoxContainer, init)] #[class(base=HBoxContainer, init)]

View File

@ -4,7 +4,9 @@ use godot::{
prelude::*, prelude::*,
}; };
use crate::{game::Game, replay::StandaloneReplayManager, ui::player_listing::PlayerListing}; use crate::{
game_manager::Game, replay::StandaloneReplayManager, ui::player_listing::PlayerListing,
};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=HBoxContainer, init)] #[class(base=HBoxContainer, init)]

View File

@ -4,7 +4,7 @@ use godot::{
}; };
use crate::{ use crate::{
game::{Game, GameManager}, game_manager::{Game, GameManager},
replay::StandaloneReplayManager, replay::StandaloneReplayManager,
ui::player_listings::PlayerListings, ui::player_listings::PlayerListings,
}; };

View File

@ -1,5 +1,5 @@
use godot::{ use godot::{
classes::{Control, IControl, Label, Slider}, classes::{Control, IControl, InputEvent, Label, Slider},
prelude::*, prelude::*,
}; };

View File

@ -5,7 +5,7 @@ use godot::{
prelude::*, prelude::*,
}; };
use crate::{game::Game, replay::StandaloneReplayManager}; use crate::{game_manager::Game, replay::StandaloneReplayManager};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=HBoxContainer, init)] #[class(base=HBoxContainer, init)]