From ba0bb5a827947151b1dbaa5a9669dc623697c0b4 Mon Sep 17 00:00:00 2001 From: tovjemam Date: Sat, 21 Mar 2026 16:24:22 +0100 Subject: [PATCH] Move player character creation to EnterableWorld & route player events via Game --- CMakeLists.txt | 2 + src/game/enterable_world.cpp | 97 +++++++++++++++++++++++++++++++++++ src/game/enterable_world.hpp | 34 ++++++++++++ src/game/game.cpp | 61 +++++++++++++++++----- src/game/game.hpp | 24 +++++++-- src/game/openworld.cpp | 83 +----------------------------- src/game/openworld.hpp | 29 ++--------- src/game/player.cpp | 18 ++----- src/game/player.hpp | 7 ++- src/game/player_character.cpp | 2 +- src/game/player_character.hpp | 3 +- src/game/world.cpp | 10 ++++ src/game/world.hpp | 8 +-- src/server/server.cpp | 2 + 14 files changed, 227 insertions(+), 153 deletions(-) create mode 100644 src/game/enterable_world.cpp create mode 100644 src/game/enterable_world.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 427e38e..42bebfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,6 +130,8 @@ set(SERVER_ONLY_SOURCES "src/game/destroyed_object.cpp" "src/game/drivable_vehicle.hpp" "src/game/drivable_vehicle.cpp" + "src/game/enterable_world.hpp" + "src/game/enterable_world.cpp" "src/game/entity.hpp" "src/game/entity.cpp" "src/game/game.hpp" diff --git a/src/game/enterable_world.cpp b/src/game/enterable_world.cpp new file mode 100644 index 0000000..4de45d8 --- /dev/null +++ b/src/game/enterable_world.cpp @@ -0,0 +1,97 @@ +#include "enterable_world.hpp" +#include "player_character.hpp" + +static glm::vec3 GetRandomColor() +{ + glm::vec3 color; + // shittiest way to do it + for (int i = 0; i < 3; ++i) + { + net::ColorQ qcol; + qcol.value = rand() % 256; + color[i] = qcol.Decode(); + } + + return color; +} + +game::EnterableWorld::EnterableWorld(std::string mapname) : World(std::move(mapname)) {} + +void game::EnterableWorld::InsertPlayer(Player& player, const glm::vec3& pos, float yaw) +{ + CreatePlayerCharacter(player, pos, yaw); +} + +void game::EnterableWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled) +{ + auto it = player_characters_.find(&player); + if (it == player_characters_.end()) + return; + + auto character = it->second; + + switch (type) + { + case IN_DEBUG1: + if (enabled) + { + if (character->GetVehicle()) + character->GetVehicle()->SetPosition({100.0f, 100.0f, 5.0f}); + else + character->SetPosition({100.0f, 100.0f, 5.0f}); + } + break; + + case IN_DEBUG2: + if (enabled) + CreatePlayerCharacter(player, glm::vec3(100.0f, 100.0f, 5.0f), 0.0f); + break; + + default: + character->ProcessInput(type, enabled); + break; + } + +} + +void game::EnterableWorld::PlayerViewAnglesChanged(Player& player, float yaw, float pitch) +{ + auto it = player_characters_.find(&player); + if (it == player_characters_.end()) + return; + + auto character = it->second; + + character->SetForwardYaw(yaw); +} + +void game::EnterableWorld::RemovePlayer(Player& player) +{ + RemovePlayerCharacter(player); +} + +game::PlayerCharacter& game::EnterableWorld::CreatePlayerCharacter(Player& player, const glm::vec3& position, float yaw) +{ + RemovePlayerCharacter(player); + + auto& character = Spawn(player); + character.AddClothes("tshirt", GetRandomColor()); + character.AddClothes("shorts", GetRandomColor()); + + // character.SetNametag("player (" + std::to_string(character.GetEntNum()) + ")"); + character.SetPosition(position); + character.SetYaw(yaw); + + player_characters_[&player] = &character; + return character; +} + +void game::EnterableWorld::RemovePlayerCharacter(Player& player) +{ + auto it = player_characters_.find(&player); + if (it != player_characters_.end()) + { + it->second->Remove(); + player_characters_.erase(it); + } +} diff --git a/src/game/enterable_world.hpp b/src/game/enterable_world.hpp new file mode 100644 index 0000000..f3a805b --- /dev/null +++ b/src/game/enterable_world.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "world.hpp" +#include "drivable_vehicle.hpp" + +namespace game +{ + +class Player; +class PlayerCharacter; + +class EnterableWorld : public World +{ +public: + EnterableWorld(std::string mapname); + + // events + virtual void InsertPlayer(Player& player, const glm::vec3& pos, float yaw); + virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled); + virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch); + virtual void RemovePlayer(Player& player); + +private: + PlayerCharacter& CreatePlayerCharacter(Player& player, const glm::vec3& position, float yaw); + void RemovePlayerCharacter(Player& player); + +private: + std::map player_characters_; + + +}; + + +} \ No newline at end of file diff --git a/src/game/game.cpp b/src/game/game.cpp index 754033d..0855b63 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -5,43 +5,76 @@ game::Game::Game() { - default_world_ = std::make_shared(); - + openworld_ = std::make_shared(); + all_worlds_.push_back(openworld_.get()); } void game::Game::Update() { - default_world_->Update(40); + for (auto world : all_worlds_) + { + world->Update(40); + } } void game::Game::FinishFrame() { - default_world_->FinishFrame(); + for (auto world : all_worlds_) + { + world->FinishFrame(); + } } void game::Game::PlayerJoined(Player& player) { - player.SetWorld(default_world_); - - players_.insert(&player); BroadcastChat(player.GetName() + "^r se připoojil jupí jupí jupííí"); + + players_.insert({ &player, PlayerGameInfo(player) }); + auto& player_info = players_.at(&player); + player_info.world = openworld_.get(); + player.SetWorld(openworld_); + + openworld_->InsertPlayer(player, glm::vec3(100.0f, 100.0f, 5.0f), 0.0f); +} + +void game::Game::PlayerViewAnglesChanged(Player& player, float yaw, float pitch) +{ + auto world = FindPlayerWorld(player); + if (world) + world->PlayerViewAnglesChanged(player, yaw, pitch); +} + +void game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled) +{ + auto world = FindPlayerWorld(player); + if (world) + world->PlayerInput(player, type, enabled); } void game::Game::PlayerLeft(Player& player) { - players_.erase(&player); - BroadcastChat(player.GetName() + "^r se vodpojil zmrd"); -} + auto world = FindPlayerWorld(player); + if (world) + world->RemovePlayer(player); -bool game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled) -{ - return false; // not handled here + players_.erase(&player); + + BroadcastChat(player.GetName() + "^r se vodpojil zmrd"); } void game::Game::BroadcastChat(const std::string& text) { - for (auto player : players_) + for (auto& [player, info] : players_) { player->SendChat(text); } } + +game::EnterableWorld* game::Game::FindPlayerWorld(Player& player) const +{ + auto it = players_.find(&player); + if (it == players_.end()) + return nullptr; + + return it->second.world; +} diff --git a/src/game/game.hpp b/src/game/game.hpp index 1e492ec..1f6184c 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -1,15 +1,23 @@ #pragma once #include -#include -#include "world.hpp" +#include "enterable_world.hpp" +#include "openworld.hpp" namespace game { class Player; +struct PlayerGameInfo +{ + Player& player; + EnterableWorld* world = nullptr; + + PlayerGameInfo(Player& player) : player(player) {} +}; + class Game { public: @@ -19,15 +27,21 @@ public: void FinishFrame(); void PlayerJoined(Player& player); + void PlayerViewAnglesChanged(Player& player, float yaw, float pitch); + void PlayerInput(Player& player, PlayerInputType type, bool enabled); void PlayerLeft(Player& player); - bool PlayerInput(Player& player, PlayerInputType type, bool enabled); private: void BroadcastChat(const std::string& text); + EnterableWorld* FindPlayerWorld(Player& player) const; + private: - std::shared_ptr default_world_; - std::set players_; + std::shared_ptr openworld_; + + + std::vector all_worlds_; // for common update etc. + std::map players_; }; diff --git a/src/game/openworld.cpp b/src/game/openworld.cpp index 2272f5f..b8dcd65 100644 --- a/src/game/openworld.cpp +++ b/src/game/openworld.cpp @@ -45,10 +45,8 @@ static uint32_t GetRandomColor24() return (b << 16) | (g << 8) | r; } -game::OpenWorld::OpenWorld() : World("openworld") +game::OpenWorld::OpenWorld() : EnterableWorld("openworld") { - srand(time(NULL)); - // spawn bots for (size_t i = 0; i < 100; ++i) { @@ -81,64 +79,6 @@ game::OpenWorld::OpenWorld() : World("openworld") } -void game::OpenWorld::Update(int64_t delta_time) -{ - World::Update(delta_time); - -} - -void game::OpenWorld::PlayerJoined(Player& player) -{ - CreatePlayerCharacter(player); -} - -void game::OpenWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled) -{ - auto character = player_characters_.at(&player); - - switch (type) - { - case IN_DEBUG1: - if (enabled) - { - if (character->GetVehicle()) - character->GetVehicle()->SetPosition({100.0f, 100.0f, 5.0f}); - else - character->SetPosition({100.0f, 100.0f, 5.0f}); - } - break; - - case IN_DEBUG2: - if (enabled) - CreatePlayerCharacter(player); - break; - - default: - character->ProcessInput(type, enabled); - break; - } -} - -void game::OpenWorld::PlayerViewAnglesChanged(Player& player, float yaw, float pitch) -{ - auto character = player_characters_.at(&player); - character->SetForwardYaw(yaw); -} - -void game::OpenWorld::PlayerLeft(Player& player) -{ - RemovePlayerCharacter(player); -} - -void game::OpenWorld::DestructibleDestroyed(net::ObjNum num, std::unique_ptr col) -{ - auto& destroyed_obj = Spawn(std::move(col)); - - Schedule(120000, [this, num] { - RespawnObj(num); - }); -} - template static T& SpawnRandomCharacter(game::OpenWorld& world, TArgs&&... args) { @@ -151,27 +91,6 @@ static T& SpawnRandomCharacter(game::OpenWorld& world, TArgs&&... args) return character; } -void game::OpenWorld::CreatePlayerCharacter(Player& player) -{ - RemovePlayerCharacter(player); - - auto& character = SpawnRandomCharacter(*this, player); - // character.SetNametag("player (" + std::to_string(character.GetEntNum()) + ")"); - character.SetPosition({100.0f, 100.0f, 5.0f}); - - player_characters_[&player] = &character; -} - -void game::OpenWorld::RemovePlayerCharacter(Player& player) -{ - auto it = player_characters_.find(&player); - if (it != player_characters_.end()) - { - it->second->Remove(); - player_characters_.erase(it); - } -} - game::DrivableVehicle& game::OpenWorld::SpawnRandomVehicle() { game::VehicleTuning tuning; diff --git a/src/game/openworld.hpp b/src/game/openworld.hpp index a00a4d0..7d33316 100644 --- a/src/game/openworld.hpp +++ b/src/game/openworld.hpp @@ -1,42 +1,21 @@ #pragma once -#include "world.hpp" -#include "vehicle.hpp" -#include "character.hpp" -#include "usable.hpp" -#include "drivable_vehicle.hpp" - -#include +#include "enterable_world.hpp" +#include "npc_character.hpp" namespace game { -class PlayerCharacter; -class NpcCharacter; - -class OpenWorld : public World +class OpenWorld : public EnterableWorld { public: OpenWorld(); - virtual void Update(int64_t delta_time) override; - - virtual void PlayerJoined(Player& player) override; - virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) override; - virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch) override; - virtual void PlayerLeft(Player& player) override; - - virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr col) override; - -private: - void CreatePlayerCharacter(Player& player); - void RemovePlayerCharacter(Player& player); - +private: game::DrivableVehicle& SpawnRandomVehicle(); void SpawnBot(); private: - std::map player_characters_; std::vector npcs_; }; diff --git a/src/game/player.cpp b/src/game/player.cpp index de4e9b6..cc4b4d9 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -6,6 +6,7 @@ #include #include "world.hpp" +#include "game.hpp" game::Player::Player(Game& game, std::string name) : game_(game), name_(std::move(name)) { @@ -48,13 +49,7 @@ void game::Player::SetWorld(std::shared_ptr world) if (world == world_) return; - if (world_) - world_->PlayerLeft(*this); - world_ = std::move(world); - - if (world_) - world_->PlayerJoined(*this); } void game::Player::SetCamera(net::EntNum entnum) @@ -74,7 +69,6 @@ void game::Player::SendChat(const std::string& text) game::Player::~Player() { - SetWorld(nullptr); game_.PlayerLeft(*this); } @@ -247,9 +241,7 @@ bool game::Player::ProcessViewAnglesMsg(net::InMessage& msg) view_yaw_ = yaw_q.Decode(); view_pitch_ = pitch_q.Decode(); - if (world_) - world_->PlayerViewAnglesChanged(*this, view_yaw_, view_pitch_); - + game_.PlayerViewAnglesChanged(*this, view_yaw_, view_pitch_); return true; } @@ -260,10 +252,6 @@ void game::Player::Input(PlayerInputType type, bool enabled) else in_ &= ~(1 << type); - if (!game_.PlayerInput(*this, type, enabled)) - { - if (world_) - world_->PlayerInput(*this, type, enabled); - } + game_.PlayerInput(*this, type, enabled); } diff --git a/src/game/player.hpp b/src/game/player.hpp index 501d9a5..05435cc 100644 --- a/src/game/player.hpp +++ b/src/game/player.hpp @@ -1,20 +1,23 @@ #pragma once #include +#include + +#include #include "net/defs.hpp" #include "net/inmessage.hpp" #include "net/msg_producer.hpp" +#include "utils/defs.hpp" #include "player_input.hpp" -#include "game.hpp" namespace game { +class Game; class World; class Entity; -class Vehicle; class Player : public net::MsgProducer { diff --git a/src/game/player_character.cpp b/src/game/player_character.cpp index 93f15c1..6eb25b3 100644 --- a/src/game/player_character.cpp +++ b/src/game/player_character.cpp @@ -1,5 +1,5 @@ #include "player_character.hpp" -#include "openworld.hpp" +#include "world.hpp" game::PlayerCharacter::PlayerCharacter(World& world, Player& player) : Super(world), player_(player) { diff --git a/src/game/player_character.hpp b/src/game/player_character.hpp index efb665f..85aa003 100644 --- a/src/game/player_character.hpp +++ b/src/game/player_character.hpp @@ -2,12 +2,11 @@ #include "drivable_vehicle.hpp" #include "player.hpp" +#include "world.hpp" namespace game { -class OpenWorld; - class PlayerCharacter : public ControllableCharacter { public: diff --git a/src/game/world.cpp b/src/game/world.cpp index d14e397..a94fcef 100644 --- a/src/game/world.cpp +++ b/src/game/world.cpp @@ -6,6 +6,7 @@ #include "assets/cache.hpp" #include "utils/allocnum.hpp" #include "collision/object_info.hpp" +#include "destroyed_object.hpp" game::World::World(std::string mapname) : Scheduler(time_ms_), map_(*this, std::move(mapname)) { @@ -78,6 +79,15 @@ void game::World::FinishFrame() } +void game::World::DestructibleDestroyed(net::ObjNum num, std::unique_ptr col) +{ + auto& destroyed_obj = Spawn(std::move(col)); + + Schedule(120000, [this, num] { + RespawnObj(num); + }); +} + game::Entity* game::World::GetEntity(net::EntNum entnum) { auto it = ents_.find(entnum); diff --git a/src/game/world.hpp b/src/game/world.hpp index 311916c..82d1e6a 100644 --- a/src/game/world.hpp +++ b/src/game/world.hpp @@ -37,13 +37,7 @@ public: virtual void Update(int64_t delta_time); void FinishFrame(); - // events - virtual void PlayerJoined(Player& player) {} - virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) {} - virtual void PlayerViewAnglesChanged(Player& player, float yaw, float pitch) {} - virtual void PlayerLeft(Player& player) {} - - virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr col) {} + virtual void DestructibleDestroyed(net::ObjNum num, std::unique_ptr col); Entity* GetEntity(net::EntNum entnum); diff --git a/src/server/server.cpp b/src/server/server.cpp index 253079f..d5aa0f4 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -17,6 +17,8 @@ void sv::Server::Run() { using namespace std::chrono_literals; + srand(time(NULL)); + auto t_start = std::chrono::steady_clock::now(); auto t_next = t_start; auto t_prev = t_start;