, 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;
: public State {
public:
- explicit InteractiveState(MasterState &);
+ explicit InteractiveState(MasterState &, std::uint32_t player_id);
World &GetWorld() noexcept { return world; }
Interface &GetInterface() noexcept { return interface; }
}
-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);
// 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());
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;
}
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);
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);
namespace blank {
+class Entity;
class Environment;
class Viewport;
class World;
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(); }
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()
Entity::Entity() noexcept
: model()
+, id(-1)
, name("anonymous")
, bounds()
, velocity(0, 0, 0)
#include "../model/CompositeInstance.hpp"
#include "../model/geometry.hpp"
+#include <cstdint>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
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; }
private:
CompositeInstance model;
+ std::uint32_t id;
std::string name;
AABB bounds;
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<std::uint32_t>::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 {
#include "Entity.hpp"
#include "Generator.hpp"
+#include <cstdint>
#include <list>
#include <string>
#include <vector>
/// 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<Entity *> &Players() const noexcept { return players; }
const std::list<Entity> &Entities() const noexcept { return entities; }