From: Daniel Karbach Date: Fri, 4 Sep 2015 22:27:15 +0000 (+0200) Subject: give unique IDs to entities X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=4e3d9c23940c4511623b5bf328cbbe42641c4b30;p=blank.git give unique IDs to entities please don't modify from outside the world :P --- diff --git a/src/app/WorldState.cpp b/src/app/WorldState.cpp index fabd332..db8c963 100644 --- a/src/app/WorldState.cpp +++ b/src/app/WorldState.cpp @@ -20,7 +20,7 @@ WorldState::WorldState( , world(block_types, wc, save) , chunk_renderer(world, wc.load.load_dist) , spawner(world, wc.gen.seed) -, interface(ic, env, world) +, interface(ic, env, world, *world.AddPlayer(ic.player_name)) , preload(env, world.Loader(), chunk_renderer) , unload(env, world.Loader()) { TextureIndex tex_index; diff --git a/src/client/InteractiveState.hpp b/src/client/InteractiveState.hpp index e679eb2..65c92d0 100644 --- a/src/client/InteractiveState.hpp +++ b/src/client/InteractiveState.hpp @@ -21,7 +21,7 @@ class InteractiveState : public State { public: - explicit InteractiveState(MasterState &); + explicit InteractiveState(MasterState &, std::uint32_t player_id); World &GetWorld() noexcept { return world; } Interface &GetInterface() noexcept { return interface; } diff --git a/src/client/client.cpp b/src/client/client.cpp index 49ea400..8dd575a 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -38,13 +38,19 @@ void InitialState::Render(Viewport &viewport) { } -InteractiveState::InteractiveState(MasterState &master) +// TODO: this clutter is a giant mess +InteractiveState::InteractiveState(MasterState &master, uint32_t player_id) : master(master) , block_types() , save(master.GetEnv().config.GetWorldPath(master.GetWorldConf().name, master.GetClientConf().host)) , world(block_types, master.GetWorldConf(), save) , chunk_renderer(world, master.GetWorldConf().load.load_dist) -, interface(master.GetInterfaceConf(), master.GetEnv(), world) { +, interface( + master.GetInterfaceConf(), + master.GetEnv(), + world, + *world.AddPlayer(master.GetInterfaceConf().player_name, player_id) +) { TextureIndex tex_index; master.GetEnv().loader.LoadBlockTypes("default", block_types, tex_index); chunk_renderer.LoadTextures(master.GetEnv().loader, tex_index); @@ -175,7 +181,10 @@ void MasterState::On(const Packet::Join &pack) { // joining game std::cout << "joined game" << std::endl; } - state.reset(new InteractiveState(*this)); + + uint32_t player_id; + pack.ReadPlayerID(player_id); + state.reset(new InteractiveState(*this, player_id)); pack.ReadPlayer(state->GetInterface().Player()); diff --git a/src/net/Packet.hpp b/src/net/Packet.hpp index fa35189..af2f872 100644 --- a/src/net/Packet.hpp +++ b/src/net/Packet.hpp @@ -72,6 +72,7 @@ struct Packet { static constexpr std::size_t MAX_LEN = 100; void WritePlayer(const Entity &) noexcept; + void ReadPlayerID(std::uint32_t &) const noexcept; void ReadPlayer(Entity &) const noexcept; void WriteWorldName(const std::string &) noexcept; void ReadWorldName(std::string &) const noexcept; diff --git a/src/net/net.cpp b/src/net/net.cpp index 852efd3..4d36412 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -282,8 +282,7 @@ void Packet::Login::ReadPlayerName(string &name) const noexcept { } void Packet::Join::WritePlayer(const Entity &player) noexcept { - // TODO: generate entity IDs - Write(uint32_t(1), 0); + Write(player.ID(), 0); Write(player.ChunkCoords(), 4); Write(player.Position(), 16); Write(player.Velocity(), 28); @@ -291,15 +290,17 @@ void Packet::Join::WritePlayer(const Entity &player) noexcept { Write(player.AngularVelocity(), 56); } +void Packet::Join::ReadPlayerID(uint32_t &id) const noexcept { + Read(id, 0); +} + void Packet::Join::ReadPlayer(Entity &player) const noexcept { - uint32_t id = 0; glm::ivec3 chunk_coords(0); glm::vec3 pos; glm::vec3 vel; glm::quat rot; glm::vec3 ang; - Read(id, 0); Read(chunk_coords, 4); Read(pos, 16); Read(vel, 28); diff --git a/src/ui/Interface.hpp b/src/ui/Interface.hpp index aab8b15..7c9a91e 100644 --- a/src/ui/Interface.hpp +++ b/src/ui/Interface.hpp @@ -20,6 +20,7 @@ namespace blank { +class Entity; class Environment; class Viewport; class World; @@ -40,7 +41,7 @@ public: bool visual_disabled = false; }; - Interface(const Config &, Environment &, World &); + Interface(const Config &, Environment &, World &, Entity &); Entity &Player() noexcept { return ctrl.Controlled(); } const Entity &Player() const noexcept { return ctrl.Controlled(); } diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index d8459e5..2ec4d88 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -102,11 +102,12 @@ void HUD::Render(Viewport &viewport) noexcept { Interface::Interface( const Config &config, Environment &env, - World &world) + World &world, + Entity &player) : env(env) , world(world) // let's assume this succeeds and hope for the best for now -, ctrl(*world.AddPlayer(config.player_name)) +, ctrl(player) , hud(world.BlockTypes(), env.assets.small_ui_font) , aim{{ 0, 0, 0 }, { 0, 0, -1 }} , aim_world() diff --git a/src/world/Entity.cpp b/src/world/Entity.cpp index f116153..b909603 100644 --- a/src/world/Entity.cpp +++ b/src/world/Entity.cpp @@ -16,6 +16,7 @@ namespace blank { Entity::Entity() noexcept : model() +, id(-1) , name("anonymous") , bounds() , velocity(0, 0, 0) diff --git a/src/world/Entity.hpp b/src/world/Entity.hpp index a381142..c0d9a0b 100644 --- a/src/world/Entity.hpp +++ b/src/world/Entity.hpp @@ -5,6 +5,7 @@ #include "../model/CompositeInstance.hpp" #include "../model/geometry.hpp" +#include #include #include #include @@ -23,6 +24,9 @@ public: CompositeInstance &GetModel() noexcept { return model; } const CompositeInstance &GetModel() const noexcept { return model; } + std::uint32_t ID() const noexcept { return id; } + void ID(std::uint32_t i) noexcept { id = i; } + const std::string &Name() const noexcept { return name; } void Name(const std::string &n) { name = n; } @@ -77,6 +81,7 @@ public: private: CompositeInstance model; + std::uint32_t id; std::string name; AABB bounds; diff --git a/src/world/World.cpp b/src/world/World.cpp index 06ccb62..6ad30ff 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -46,6 +46,70 @@ Entity *World::AddPlayer(const std::string &name) { return &player; } +Entity *World::AddPlayer(const std::string &name, std::uint32_t id) { + for (Entity *e : players) { + if (e->Name() == name) { + return nullptr; + } + } + Entity *player = AddEntity(id); + if (!player) { + return nullptr; + } + player->Name(name); + // TODO: load from save file here + player->Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } }); + player->WorldCollidable(true); + player->Position(config.spawn); + players.push_back(player); + chunks.QueueSurrounding(player->ChunkCoords()); + return player; +} + +Entity &World::AddEntity() { + if (entities.empty()) { + entities.emplace_back(); + entities.back().ID(1); + return entities.back(); + } + if (entities.back().ID() < std::numeric_limits::max()) { + std::uint32_t id = entities.back().ID() + 1; + entities.emplace_back(); + entities.back().ID(id); + return entities.back(); + } + std::uint32_t id = 1; + auto position = entities.begin(); + auto end = entities.end(); + while (position != end && position->ID() == id) { + ++id; + ++position; + } + auto entity = entities.emplace(position); + entity->ID(id); + return *entity; +} + +Entity *World::AddEntity(std::uint32_t id) { + if (entities.empty() || entities.back().ID() < id) { + entities.emplace_back(); + entities.back().ID(id); + return &entities.back(); + } + + auto position = entities.begin(); + auto end = entities.end(); + while (position != end && position->ID() < id) { + ++position; + } + if (position != end && position->ID() == id) { + return nullptr; + } + auto entity = entities.emplace(position); + entity->ID(id); + return &*entity; +} + namespace { diff --git a/src/world/World.hpp b/src/world/World.hpp index 7d2c292..9ae0faa 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -5,6 +5,7 @@ #include "Entity.hpp" #include "Generator.hpp" +#include #include #include #include @@ -70,7 +71,14 @@ public: /// add player with given name /// returns nullptr if the name is already taken Entity *AddPlayer(const std::string &name); - Entity &AddEntity() { entities.emplace_back(); return entities.back(); } + /// add player with given name and ID + /// returns nullptr if the name or ID is already taken + Entity *AddPlayer(const std::string &name, std::uint32_t id); + /// add an entity with an autogenerated ID + Entity &AddEntity(); + /// add entity with given ID + /// returns nullptr if the ID is already taken + Entity *AddEntity(std::uint32_t id); const std::vector &Players() const noexcept { return players; } const std::list &Entities() const noexcept { return entities; }