diff --git a/CMakeLists.txt b/CMakeLists.txt index fd76b61..e540c27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,8 @@ set(CLIENT_ONLY_SOURCES "src/gameview/entityview.cpp" "src/gameview/mapinstanceview.hpp" "src/gameview/mapinstanceview.cpp" + "src/gameview/markerview.hpp" + "src/gameview/markerview.cpp" "src/gameview/remote_menu_view.hpp" "src/gameview/remote_menu_view.cpp" "src/gameview/simple_entity_view.hpp" @@ -142,6 +144,8 @@ set(SERVER_ONLY_SOURCES "src/game/game.cpp" "src/game/mapinstance.hpp" "src/game/mapinstance.cpp" + "src/game/marker.hpp" + "src/game/marker.cpp" "src/game/npc_character.hpp" "src/game/npc_character.cpp" "src/game/openworld.hpp" diff --git a/src/game/entity.cpp b/src/game/entity.cpp index e424f8e..141c4ca 100644 --- a/src/game/entity.cpp +++ b/src/game/entity.cpp @@ -1,8 +1,20 @@ #include "entity.hpp" #include "world.hpp" +#include "player.hpp" -game::Entity::Entity(World& world, net::EntType viewtype) : Scheduler(world.GetTime()), world_(world), entnum_(world.GetNewEntnum()), viewtype_(viewtype) {} +#define GLM_ENABLE_EXPERIMENTAL +#include + + +game::Entity::Entity(World& world, net::EntType viewtype) : Scheduler(world.GetTime()), world_(world), entnum_(world.GetNewEntnum()), viewtype_(viewtype) +{ + if (viewtype == net::ET_NONE) + { + visible_ = false; + } + +} void game::Entity::SendInitData(Player& player, net::OutMessage& msg) const { @@ -69,6 +81,18 @@ void game::Entity::PlaySound(const std::string& name, float volume, float pitch) msg.Write(pitch); } +bool game::Entity::IsVisibleTo(const Player& player) const +{ + if (!visible_) + return false; + + // max distance check + if (glm::distance2(root_.GetGlobalPosition(), player.GetCullPos()) > (max_distance_ * max_distance_)) + return false; + + return true; +} + void game::Entity::WriteNametag(net::OutMessage& msg) const { msg.Write(net::NameTag{nametag_}); diff --git a/src/game/entity.hpp b/src/game/entity.hpp index 436e9a7..348d234 100644 --- a/src/game/entity.hpp +++ b/src/game/entity.hpp @@ -49,6 +49,7 @@ public: const TransformNode& GetRoot() const { return root_; } const Transform& GetRootTransform() const { return root_.local; } + bool IsVisibleTo(const Player& player) const; float GetMaxDistance() const { return max_distance_; } virtual ~Entity() = default; @@ -73,6 +74,7 @@ protected: TransformNode root_; Entity* parent_ = nullptr; + bool visible_ = true; float max_distance_ = 700.0f; bool removed_ = false; diff --git a/src/game/game.cpp b/src/game/game.cpp index ea6a2da..21ac07e 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -18,14 +18,8 @@ static uint32_t GetRandomColor24() game::Game::Game() { - openworld_ = std::make_shared(); - all_worlds_.push_back(openworld_.get()); - - testworld_ = std::make_shared("testarena"); - all_worlds_.push_back(testworld_.get()); - - garage_ = std::make_shared(*this, *openworld_, glm::vec3(0.0f), 0.0f, "garage"); - all_worlds_.push_back(garage_.get()); + openworld_ = std::make_shared(*this); + AddWorld(openworld_.get()); } void game::Game::Update() @@ -44,6 +38,11 @@ void game::Game::FinishFrame() } } +void game::Game::AddWorld(World* world) +{ + all_worlds_.push_back(world); +} + void game::Game::PlayerJoined(Player& player) { BroadcastChat(player.GetName() + "^r se připoojil jupí jupí jupííí"); @@ -71,29 +70,29 @@ void game::Game::PlayerInput(Player& player, PlayerInputType type, bool enabled) { switch (type) { - case IN_DEBUG2: { - if (!enabled) - return; + // case IN_DEBUG2: { + // if (!enabled) + // return; - // auto& player_info = players_.at(&player); + // // auto& player_info = players_.at(&player); - // if (player_info.world == openworld_.get()) - // { - // MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f, true); - // } - // else - // { - // MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f, true); - // } + // // if (player_info.world == openworld_.get()) + // // { + // // MovePlayerToWorld(player_info, testworld_.get(), test_spawn, 0.0f, true); + // // } + // // else + // // { + // // MovePlayerToWorld(player_info, openworld_.get(), openworld_spawn, 0.0f, true); + // // } - MovePlayerToTuning(player); + // MovePlayerToTuning(player); - break; - } + // break; + // } - case IN_DEBUG3: - DisplayTestMenu(player); - break; + // case IN_DEBUG3: + // // DisplayTestMenu(player); + // break; default: { auto world = FindPlayerWorld(player); @@ -224,69 +223,3 @@ game::EnterableWorld* game::Game::FindPlayerWorld(Player& player) const return it->second.world; } - -void game::Game::DisplayTestMenu(Player& player) -{ - if (player.HasOpenMenu()) - return; - - auto& menu = player.DisplayMenu("test"); - - auto& btn_echo = menu.AddItem(RM_BUTTON, "echo"); - btn_echo.SetOnClick([&player] { - player.SendChat("echo test"); - }); - - auto& btn_bc = menu.AddItem(RM_BUTTON, "broadcast"); - btn_bc.SetOnClick([this, &player] { - BroadcastChat(player.GetName() + "^r mele hovna"); - }); - - int test = 0; - auto& sel_test = menu.AddItem(RM_SELECT, "výběr"); - sel_test.SetOnSelect([test, &sel_test] (int dir) mutable { - test += dir; - sel_test.SetSelection(std::to_string(test)); - }); - sel_test.SetSelection(std::to_string(test)); - - - auto& btn_close = menu.AddItem(RM_BUTTON, "zavřít"); - btn_close.SetOnClick([&menu, &player] { - player.CloseMenu(menu); - }); - -} - -void game::Game::MovePlayerToTuning(Player& player) -{ - auto& player_info = GetPlayerInfo(player); - - if (player_info.world != openworld_.get()) - return; - - if (garage_->IsOccupied()) - { - player.SendChat("bohužel tam teď oxiduje nějakej píčus " + garage_->GetOccupantName() + "^r!"); - return; - } - - auto character = player_info.world->GetPlayerCharacter(player); - if (!character) - return; - - auto vehicle = character->GetVehicle(); - if (!vehicle) - { - player.SendChat("nemáš vehikl!!!"); - return; - } - - if (vehicle->GetPassenger(0) != character) - { - player.SendChat("nejsi ridič!!"); - return; - } - - MovePlayerToWorld(player_info, garage_.get(), glm::vec3(0.0f), 0.0f, true); -} diff --git a/src/game/game.hpp b/src/game/game.hpp index 6bc2ecf..f2fa773 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -27,6 +27,8 @@ public: void Update(); void FinishFrame(); + void AddWorld(World* world); + void PlayerJoined(Player& player); void PlayerViewAnglesChanged(Player& player, float yaw, float pitch); void PlayerInput(Player& player, PlayerInputType type, bool enabled); @@ -45,9 +47,6 @@ private: PlayerGameInfo& GetPlayerInfo(Player& player); EnterableWorld* FindPlayerWorld(Player& player) const; - void DisplayTestMenu(Player& player); - void MovePlayerToTuning(Player& player); - private: std::shared_ptr openworld_; std::shared_ptr testworld_; diff --git a/src/game/marker.cpp b/src/game/marker.cpp new file mode 100644 index 0000000..93b1f99 --- /dev/null +++ b/src/game/marker.cpp @@ -0,0 +1,77 @@ +#include "marker.hpp" + +#include "world.hpp" +#include "net/utils.hpp" + +static const glm::mat4 identity(1.0f); + +game::Marker::Marker(World& world, const MarkerInfo& info) : Super(world, net::ET_MARKER), Usable(identity), info_(info) +{ + root_.local.position = info_.position; + root_.UpdateMatrix(); +} + +void game::Marker::SendInitData(Player& player, net::OutMessage& msg) const +{ + Super::SendInitData(player, msg); + + net::PositionQ pos_q; + net::EncodePosition(info_.position, pos_q); + + msg.Write(info_.type); + net::WritePositionQ(msg, pos_q); + net::WriteRGB(msg, info_.color); +} + +void game::Marker::Update() +{ + Super::Update(); + +} + +bool game::Marker::QueryUseTarget(PlayerCharacter& character, uint32_t target_id, UseTargetQueryResult& res) +{ + if (!query_cb_) + return false; + + return query_cb_(character, res); +} + +void game::Marker::Use(PlayerCharacter& character, uint32_t target_id) +{ + if (!use_cb_) + return; + + use_cb_(character); +} + +void game::Marker::SetUseTarget(const std::string& name, MarkerQueryCallback query, MarkerUseCallback use) +{ + if (!query_obj_) + { + query_obj_ = std::make_unique(); + + static btSphereShape query_sphere(1.0f); + query_obj_->setCollisionShape(&query_sphere); + query_obj_->setWorldTransform(root_.local.ToBtTransform()); + query_obj_->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE); + collision::SetObjectInfo(query_obj_.get(), collision::OT_ENTITY, collision::OF_USABLE, this); + + world_.GetBtWorld().addCollisionObject(query_obj_.get()); + } + + query_cb_ = query; + use_cb_ = use; + + use_targets_.clear(); + use_targets_.emplace_back(this, 0, root_.GetGlobalPosition(), name); +} + +game::Marker::~Marker() +{ + if (query_obj_) + { + world_.GetBtWorld().removeCollisionObject(query_obj_.get()); + } + +} diff --git a/src/game/marker.hpp b/src/game/marker.hpp new file mode 100644 index 0000000..b2c7161 --- /dev/null +++ b/src/game/marker.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "entity.hpp" +#include "marker_info.hpp" +#include "usable.hpp" +#include + +namespace game +{ + +using MarkerQueryCallback = std::function; +using MarkerUseCallback = std::function; + +class Marker : public Entity, public Usable +{ +public: + using Super = Entity; + + Marker(World& world, const MarkerInfo& info); + + virtual void SendInitData(Player& player, net::OutMessage& msg) const override; + virtual void Update() override; + + virtual bool QueryUseTarget(PlayerCharacter& character, uint32_t target_id, UseTargetQueryResult& res) override; + virtual void Use(PlayerCharacter& character, uint32_t target_id) override; + + void SetUseTarget(const std::string& name, MarkerQueryCallback query, MarkerUseCallback use); + + virtual ~Marker() override; + +private: + MarkerInfo info_; + + std::unique_ptr query_obj_; + + MarkerQueryCallback query_cb_; + MarkerUseCallback use_cb_; +}; + + +} \ No newline at end of file diff --git a/src/game/marker_info.hpp b/src/game/marker_info.hpp new file mode 100644 index 0000000..52503d1 --- /dev/null +++ b/src/game/marker_info.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +namespace game +{ + +enum MarkerType : uint8_t +{ + MARKER_FOOT, + MARKER_VEHICLE, +}; + +struct MarkerInfo +{ + glm::vec3 position; + MarkerType type; + uint32_t color; + std::string icon; +}; + +} \ No newline at end of file diff --git a/src/game/openworld.cpp b/src/game/openworld.cpp index 1665aa3..81b8a87 100644 --- a/src/game/openworld.cpp +++ b/src/game/openworld.cpp @@ -4,11 +4,13 @@ #include "player.hpp" #include "vehicle.hpp" - #include "player_character.hpp" #include "npc_character.hpp" #include "drivable_vehicle.hpp" #include "destroyed_object.hpp" +#include "marker.hpp" +#include "tuning_world.hpp" +#include "game.hpp" namespace game { @@ -45,7 +47,7 @@ static uint32_t GetRandomColor24() return (b << 16) | (g << 8) | r; } -game::OpenWorld::OpenWorld() : EnterableWorld("openworld") +game::OpenWorld::OpenWorld(Game& game) : EnterableWorld("openworld"), game_(game) { // spawn bots for (size_t i = 0; i < 100; ++i) @@ -80,6 +82,8 @@ game::OpenWorld::OpenWorld() : EnterableWorld("openworld") daytime_offset_ = static_cast(rand() % 24); + CreateTuningGarage(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f); + } void game::OpenWorld::Update(int64_t delta_time) @@ -90,6 +94,17 @@ void game::OpenWorld::Update(int64_t delta_time) SetDayTime(static_cast(GetTime()) * 0.001f * timespeed + daytime_offset_); } +void game::OpenWorld::PlayerInput(Player& player, PlayerInputType type, bool enabled) +{ + if (type == IN_DEBUG2 && enabled) + { + RecoverPlayer(player); + return; + } + + Super::PlayerInput(player, type, enabled); +} + game::DrivableVehicle& game::OpenWorld::SpawnRandomVehicle() { game::VehicleTuning tuning; @@ -157,3 +172,131 @@ void game::OpenWorld::SpawnBot() auto& driver = Spawn(npc_tuning); driver.SetVehicle(&vehicle, 0); } + +void game::OpenWorld::CreateTuningGarage(const glm::vec3& position, float yaw) +{ + auto garage = std::make_shared(game_, *this, position, yaw, "garage"); + game_.AddWorld(garage.get()); + + MarkerInfo marker_info{}; + marker_info.position = position; + marker_info.type = MARKER_VEHICLE; + marker_info.color = 0x884400; + marker_info.icon = "tuning"; + + auto& marker = Spawn(marker_info); + marker.SetUseTarget("vject do tunírny", + [garage](PlayerCharacter& character, UseTargetQueryResult& res) { + + auto player = character.GetPlayer(); + auto vehicle = character.GetVehicle(); + + if (!vehicle) + { + res.enabled = false; + res.error_text = "nemáš vehikl"; + return true; + } + + if (vehicle->GetPassenger(0) != &character) + { + return false; // not driver + } + + if (garage->IsOccupied()) + { + res.enabled = false; + res.error_text = "někdo tam už oxiduje"; + return true; + } + + res.enabled = true; + res.error_text = nullptr; + res.delay = 0.2f; + return true; + }, + [this, garage, &marker](PlayerCharacter& character) { + auto player = character.GetPlayer(); + game_.MovePlayerToWorld(*player, *garage, true, glm::vec3(0.0f), 0.0f); + marker.SetNametag(player->GetName()); + } + ); + + garage->SetOnExit([&marker]() { + marker.SetNametag(std::string()); + }); +} + +void game::OpenWorld::RecoverPlayer(Player& player) +{ + auto character = GetPlayerCharacter(player); + if (!character) + return; + + auto vehicle = character->GetVehicle(); + + if (!vehicle) + { + auto pos = character->GetRoot().GetGlobalPosition(); + glm::vec3 recovery; + if (GetRecoveryPosition(pos, recovery)) + { + character->SetPosition(recovery); + } + else + { + player.SendChat("nejsi pod zemí"); + } + return; + } + + if (vehicle->GetPassenger(0) != character) + return; // not driver + + auto pos = vehicle->GetRoot().GetGlobalPosition(); + glm::vec3 recovery; + if (GetRecoveryPosition(pos, recovery)) + { + vehicle->SetPosition(recovery); + } + else + { + player.SendChat("nejsi pod zemí"); + } +} + +static bool RecoveryRaycast(btCollisionWorld& bt_world, const glm::vec3& pos, glm::vec3& hit) +{ + btVector3 bt_from(pos.x, pos.y, 100.0f); + btVector3 bt_to(pos.x, pos.y, -100.0f); + btCollisionWorld::ClosestRayResultCallback cb(bt_from, bt_to); + bt_world.rayTest(bt_from, bt_to, cb); + + if (!cb.hasHit()) + return false; + + hit = glm::vec3(cb.m_hitPointWorld.x(), cb.m_hitPointWorld.y(), cb.m_hitPointWorld.z()); + return true; +} + +bool game::OpenWorld::GetRecoveryPosition(const glm::vec3& current, glm::vec3& recovery) +{ + glm::vec3 start = current; + start = glm::max(start, glm::vec3(-2500.0f, -2500.0f, -1000.0f)); + start = glm::min(start, glm::vec3(3400.0f, 3100.0f, 1000.0f)); + + if (!RecoveryRaycast(GetBtWorld(), start, recovery)) + { + recovery = glm::vec3(0.0f, 0.0f, 5.0f); + return true; + + } + + if (recovery.z - 5.0f < current.z) + { + return false; // already above ground + } + + recovery.z += 5.0f; + return true; +} diff --git a/src/game/openworld.hpp b/src/game/openworld.hpp index a4ae1a1..d827b75 100644 --- a/src/game/openworld.hpp +++ b/src/game/openworld.hpp @@ -6,20 +6,29 @@ namespace game { +class Game; + class OpenWorld : public EnterableWorld { public: using Super = EnterableWorld; - OpenWorld(); + OpenWorld(Game& game); virtual void Update(int64_t delta_time) override; + virtual void PlayerInput(Player& player, PlayerInputType type, bool enabled) override; private: game::DrivableVehicle& SpawnRandomVehicle(); void SpawnBot(); + void CreateTuningGarage(const glm::vec3& position, float yaw); + + void RecoverPlayer(Player& player); + bool GetRecoveryPosition(const glm::vec3& current, glm::vec3& recovery); + private: + Game& game_; std::vector npcs_; float daytime_offset_ = 0.0f; }; diff --git a/src/game/player.cpp b/src/game/player.cpp index 1be714b..0e62194 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -249,14 +249,7 @@ void game::Player::SyncEntities() bool game::Player::ShouldSeeEntity(const Entity& entity) const { - // max distance check - float max_dist = entity.GetMaxDistance(); - if (glm::distance2(entity.GetRoot().GetGlobalPosition(), cull_pos_) > (max_dist * max_dist)) - return false; - - // TODO: custom callback - - return true; + return entity.IsVisibleTo(*this); } void game::Player::SendInitEntity(const Entity& entity) diff --git a/src/game/player.hpp b/src/game/player.hpp index 29925f6..5c3cb6c 100644 --- a/src/game/player.hpp +++ b/src/game/player.hpp @@ -46,6 +46,8 @@ public: float GetViewYaw() const { return view_yaw_; } float GetViewPitch() const { return view_pitch_; } + const glm::vec3 GetCullPos() const { return cull_pos_; } + ~Player(); private: diff --git a/src/game/tuning_world.cpp b/src/game/tuning_world.cpp index ba4a370..fce699c 100644 --- a/src/game/tuning_world.cpp +++ b/src/game/tuning_world.cpp @@ -219,6 +219,9 @@ void game::TuningWorld::Reset() { player_->CloseMenu(*menu_); game_.MovePlayerToWorld(*player_, exit_world_, true, exit_pos_, exit_yaw_); + + if (exit_cb_) + exit_cb_(); } player_ = nullptr; diff --git a/src/game/tuning_world.hpp b/src/game/tuning_world.hpp index b7c1767..1753e25 100644 --- a/src/game/tuning_world.hpp +++ b/src/game/tuning_world.hpp @@ -20,6 +20,8 @@ public: virtual void OnVehicleJoined(DrivableVehicle& vehicle); virtual void OnPlayerLeaving(Player& player); + void SetOnExit(std::function cb) { exit_cb_ = cb; } + bool IsOccupied() const { return player_ != nullptr; } const std::string& GetOccupantName() const; @@ -46,6 +48,8 @@ private: VehicleTuning tuning_; + std::function exit_cb_; + }; diff --git a/src/game/usable.hpp b/src/game/usable.hpp index 6c6fc04..676ac42 100644 --- a/src/game/usable.hpp +++ b/src/game/usable.hpp @@ -44,6 +44,8 @@ public: protected: std::vector use_targets_; + +private: const glm::mat4& matrix_; }; diff --git a/src/game/vehicle.cpp b/src/game/vehicle.cpp index 62344f3..d58b73c 100644 --- a/src/game/vehicle.cpp +++ b/src/game/vehicle.cpp @@ -333,7 +333,7 @@ void game::Vehicle::UpdateCrash() } else { - if (crash_intensity_ > 300.0f) + if (crash_intensity_ > 1000.0f) { float volume = RandomFloat(0.9f, 1.2f); float pitch = RandomFloat(1.0f, 1.3f); @@ -355,7 +355,7 @@ void game::Vehicle::UpdateCrash() } PlaySound("crash", volume, pitch); - no_crash_frames_ = 3 + rand() % 10; + no_crash_frames_ = 7 + rand() % 10; } } diff --git a/src/game/world.cpp b/src/game/world.cpp index 1f59822..f2dc1bd 100644 --- a/src/game/world.cpp +++ b/src/game/world.cpp @@ -136,9 +136,11 @@ struct UseTargetAabbCallback : public btBroadphaseAabbCallback float dist = glm::distance(pos, pos_world); if (dist < 2.0f && dist < best_dist) { - if (!usable->QueryUseTarget(character, target.id, best_res)) + game::UseTargetQueryResult res{}; + if (!usable->QueryUseTarget(character, target.id, res)) continue; + best_res = res; best_dist = dist; best_target = ⌖ } diff --git a/src/gameview/markerview.cpp b/src/gameview/markerview.cpp new file mode 100644 index 0000000..2531d40 --- /dev/null +++ b/src/gameview/markerview.cpp @@ -0,0 +1,58 @@ +#include "markerview.hpp" + +#include "net/utils.hpp" +#include "assets/cache.hpp" + +game::view::MarkerView::MarkerView(WorldView& world, net::InMessage& msg) : Super(world, msg) +{ + if (!Init(msg)) + { + throw EntityInitError(); + } +} + +void game::view::MarkerView::Update(const UpdateInfo& info) +{ + root_.local.rotation = glm::quat(glm::vec3(0.0f, 0.0f, info.time * 0.5f)); + root_.UpdateMatrix(); +} + +void game::view::MarkerView::Draw(const DrawArgs& args) +{ + Super::Draw(args); + + if (!model_) + return; + + const auto& mesh = *model_->GetMesh(); + for (const auto& surface : mesh.surfaces) + { + gfx::DrawSurfaceCmd cmd; + cmd.surface = &surface; + cmd.matrices = &root_.matrix; + cmd.color = &color_; + args.dlist.AddSurface(cmd); + } + +} + +bool game::view::MarkerView::Init(net::InMessage& msg) +{ + net::PositionQ pos_q; + uint32_t color; + + if (!msg.Read(marker_type_) || !net::ReadPositionQ(msg, pos_q) || !net::ReadRGB(msg, color)) + return false; + + net::DecodePosition(pos_q, root_.local.position); + root_.UpdateMatrix(); + + color_ = glm::unpackUnorm4x8(color | 0xFF000000); + + if (marker_type_ == MARKER_FOOT || marker_type_ == MARKER_VEHICLE) + { + model_ = assets::CacheManager::GetModel("data/marker.mdl"); + } + + return true; +} diff --git a/src/gameview/markerview.hpp b/src/gameview/markerview.hpp new file mode 100644 index 0000000..f5950a1 --- /dev/null +++ b/src/gameview/markerview.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "entityview.hpp" +#include "game/marker_info.hpp" +#include "assets/model.hpp" + +namespace game::view +{ + +class MarkerView : public EntityView +{ +public: + using Super = EntityView; + + MarkerView(WorldView& world, net::InMessage& msg); + + // virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg) override; + // virtual bool ProcessUpdateMsg(net::InMessage* msg) override; + virtual void Update(const UpdateInfo& info) override; + virtual void Draw(const DrawArgs& args) override; + +private: + bool Init(net::InMessage& msg); + +private: + MarkerType marker_type_; + glm::vec4 color_; + + std::shared_ptr model_; + +}; + + +} \ No newline at end of file diff --git a/src/gameview/worldview.cpp b/src/gameview/worldview.cpp index 5b523de..a4b5564 100644 --- a/src/gameview/worldview.cpp +++ b/src/gameview/worldview.cpp @@ -5,6 +5,7 @@ #include "simple_entity_view.hpp" #include "characterview.hpp" #include "vehicleview.hpp" +#include "markerview.hpp" #include "client_session.hpp" #include "draw_args.hpp" @@ -232,6 +233,10 @@ bool game::view::WorldView::ProcessEntSpawnMsg(net::InMessage& msg) entslot = std::make_unique(*this, msg); break; + case net::ET_MARKER: + entslot = std::make_unique(*this, msg); + break; + default: ents_.erase(entnum); return false; // unknown type diff --git a/src/net/defs.hpp b/src/net/defs.hpp index 7ced616..3f6ea4c 100644 --- a/src/net/defs.hpp +++ b/src/net/defs.hpp @@ -93,6 +93,7 @@ enum EntType : uint8_t ET_SIMPLE, ET_CHARACTER, ET_VEHICLE, + ET_MARKER, ET_COUNT, };