summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Entity.cpp78
-rw-r--r--src/Entity.hpp138
-rw-r--r--src/Event.hpp8
-rw-r--r--src/FSM.cpp1
-rw-r--r--src/FSM.hpp36
-rw-r--r--src/GameState.cpp94
-rw-r--r--src/Network.cpp14
-rw-r--r--src/Packet.hpp200
-rw-r--r--src/Render.cpp9
-rw-r--r--src/RendererEntity.cpp161
-rw-r--r--src/RendererEntity.hpp25
-rw-r--r--src/RendererSection.cpp11
-rw-r--r--src/RendererSection.hpp6
-rw-r--r--src/RendererWorld.cpp134
-rw-r--r--src/RendererWorld.hpp16
-rw-r--r--src/Stream.cpp4
-rw-r--r--src/ThreadGame.cpp4
-rw-r--r--src/Utility.cpp2
-rw-r--r--src/World.cpp33
-rw-r--r--src/World.hpp6
20 files changed, 874 insertions, 106 deletions
diff --git a/src/Entity.cpp b/src/Entity.cpp
index 8f76818..cdfd85d 100644
--- a/src/Entity.cpp
+++ b/src/Entity.cpp
@@ -6,3 +6,81 @@ VectorF Entity::DecodeVelocity(short x, short y, short z)
const double velMod = 1 / 8000.0;
return VectorF(x * velMod * ticksPerSecond, y*velMod*ticksPerSecond, z*velMod*ticksPerSecond);
}
+
+VectorF Entity::DecodeDeltaPos(short deltaX, short deltaY, short deltaZ)
+{
+ const double posMod = 4096.0;
+ return VectorF(deltaX / posMod, deltaY / posMod, deltaZ / posMod);
+}
+
+Entity CreateObject(ObjectType type)
+{
+ Entity entity;
+ entity.isMob = false;
+ switch (type) {
+ case ObjectType::Boat:
+ break;
+ case ObjectType::ItemStack:
+ entity.width = 0.25;
+ entity.height = 0.25;
+ break;
+ case ObjectType::AreaEffectCloud:
+ break;
+ case ObjectType::Minecart:
+ break;
+ case ObjectType::ActivatedTNT:
+ break;
+ case ObjectType::EnderCrystal:
+ break;
+ case ObjectType::TippedArrow:
+ break;
+ case ObjectType::Snowball:
+ break;
+ case ObjectType::Egg:
+ break;
+ case ObjectType::FireBall:
+ break;
+ case ObjectType::FireCharge:
+ break;
+ case ObjectType::ThrownEnderpearl:
+ break;
+ case ObjectType::WitherSkull:
+ break;
+ case ObjectType::ShulkerBullet:
+ break;
+ case ObjectType::LlamaSpit:
+ break;
+ case ObjectType::FallingObjects:
+ break;
+ case ObjectType::Itemframes:
+ break;
+ case ObjectType::EyeOfEnder:
+ break;
+ case ObjectType::ThrownPotion:
+ break;
+ case ObjectType::ThrownExpBottle:
+ break;
+ case ObjectType::FireworkRocket:
+ break;
+ case ObjectType::LeashKnot:
+ break;
+ case ObjectType::ArmorStand:
+ break;
+ case ObjectType::EvocationFangs:
+ break;
+ case ObjectType::FishingHook:
+ break;
+ case ObjectType::SpectralArrow:
+ break;
+ case ObjectType::DragonFireball:
+ break;
+ default:
+ break;
+ }
+ return entity;
+}
+
+Entity CreateMob(MobType type)
+{
+ return Entity();
+}
diff --git a/src/Entity.hpp b/src/Entity.hpp
index 6df7983..c818abe 100644
--- a/src/Entity.hpp
+++ b/src/Entity.hpp
@@ -3,12 +3,138 @@
#include "Utility.hpp"
#include "Vector.hpp"
+enum class ObjectType{
+ Boat=1,
+ ItemStack,
+ AreaEffectCloud,
+ Minecart=10,
+ ActivatedTNT=50,
+ EnderCrystal,
+ TippedArrow=60,
+ Snowball,
+ Egg,
+ FireBall,
+ FireCharge,
+ ThrownEnderpearl,
+ WitherSkull,
+ ShulkerBullet,
+ LlamaSpit,
+ FallingObjects=70,
+ Itemframes,
+ EyeOfEnder,
+ ThrownPotion,
+ ThrownExpBottle=75,
+ FireworkRocket,
+ LeashKnot,
+ ArmorStand,
+ EvocationFangs,
+ FishingHook=90,
+ SpectralArrow,
+ DragonFireball=93,
+};
+
+enum MobType {
+ Item = 1,
+ XPOrb,
+ AreaEffectCloud,
+ ElderGuardian,
+ WitherSkeleton,
+ Stray,
+ ThrownEgg,
+ LeashKnot,
+ Painting,
+ Arrow,
+ Snowball,
+ Fireball,
+ SmallFireball,
+ ThrownEnderpearl,
+ EyeOfEnderSignal,
+ ThrownPotion,
+ ThrownExpBottle,
+ ItemFrame,
+ WitherSkull,
+ PrimedTnt,
+ FallingSand,
+ FireworksRocketEntity,
+ Husk,
+ SpectralArrow,
+ ShulkerBullet,
+ DragonFireball,
+ ZombieVillager,
+ SkeletonHorse,
+ ZombieHorse,
+ ArmorStand,
+ Donkey,
+ Mule,
+ EvocationFangs,
+ EvocationIllager,
+ Vex,
+ VindicationIllager,
+ IllusionIllager,
+ MinecartCommandBlock=40,
+ Boat,
+ MinecartRideable,
+ MinecartChest,
+ MinecartFurnace,
+ MinecartTNT,
+ MinecartHopper,
+ MinecartSpawner,
+ Creeper=50,
+ Skeleton,
+ Spider,
+ Giant,
+ Zombie,
+ Slime,
+ Ghast,
+ PigZombie,
+ Enderman,
+ CaveSpider,
+ Silverfish,
+ Blaze,
+ LavaSlime,
+ EnderDragon,
+ WitherBoss,
+ Bat,
+ Witch,
+ Endermite,
+ Guardian,
+ Shulker,
+ Pig=90,
+ Sheep,
+ Cow,
+ Chicken,
+ Squid,
+ Wolf,
+ MushroomCow,
+ SnowMan,
+ Ozelot,
+ VillagerGolem,
+ Horse,
+ Rabbit,
+ PolarBear,
+ Llama,
+ LlamaSpit,
+ Parrot,
+ Villager=120,
+ EnderCrystal=200,
+};
+
struct Entity {
Uuid uuid;
- VectorF pos;
- VectorF vel;
- unsigned int entityId;
- double yaw;
- double pitch;
+ VectorF pos = 0;
+ VectorF vel = 0;
+ unsigned int entityId = 0;
+ double yaw = 0;
+ double pitch = 0;
+ double width = 1.0;
+ double height = 1.0;
+ glm::vec3 renderColor;
+ int entityType=0;
+ bool isMob=false;
static VectorF DecodeVelocity(short x, short y, short z);
-}; \ No newline at end of file
+ static VectorF DecodeDeltaPos(short deltaX, short deltaY, short deltaZ);
+};
+
+Entity CreateObject(ObjectType type);
+
+Entity CreateMob(MobType type); \ No newline at end of file
diff --git a/src/Event.hpp b/src/Event.hpp
index 232e6f2..f07ed57 100644
--- a/src/Event.hpp
+++ b/src/Event.hpp
@@ -13,7 +13,6 @@
#include "Vector.hpp"
#include "Packet.hpp"
-#include "FSM.hpp"
enum class EventType {
Echo,
@@ -39,6 +38,7 @@ enum class EventType {
CreatedSectionRender,
PlayerPosChanged,
DeleteSectionRender,
+ EntityChanged,
};
struct EchoData {
@@ -146,12 +146,16 @@ struct DeleteSectionRenderData {
Vector pos;
};
+struct EntityChangedData {
+ unsigned int EntityId;
+};
+
using EventData = std::variant<EchoData, ChunkChangedData, ConnectToServerData, ConnectionSuccessfullData,
DisconnectData, SendPacketData, ReceivePacketData, RequestNetworkClientData, RegisterNetworkClientData,
PlayerConnectedData, RemoveLoadingScreenData, ConnectionFailedData, ExitData, DisconnectedData,
ConnectingData, NetworkClientExceptionData, MouseMovedData, KeyPressedData, KeyReleasedData,
InitalizeSectionRenderData, CreateSectionRenderData, CreatedSectionRenderData, PlayerPosChangedData,
- UpdateSectionsRenderData, DeleteSectionRenderData>;
+ UpdateSectionsRenderData, DeleteSectionRenderData, EntityChangedData>;
struct Event {
EventType type;
diff --git a/src/FSM.cpp b/src/FSM.cpp
deleted file mode 100644
index 6614c58..0000000
--- a/src/FSM.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "FSM.hpp"
diff --git a/src/FSM.hpp b/src/FSM.hpp
deleted file mode 100644
index 346d0f0..0000000
--- a/src/FSM.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include <utility>
-#include <functional>
-#include <map>
-
-template<class T>
-class FSM {
-public:
- using Transaction = std::pair<T, T>;
- using Handler = std::function<void(T &)>;
-
- FSM(T initialState) : state(initialState), previousState(initialState) {}
-
- ~FSM() = default;
-
- void Update() {
- auto &handler = handlers[Transaction{previousState, state}];
- if (handler)
- handler(state);
- previousState = state;
- }
-
- void RegisterHandler(T state, Handler handler) {
- handlers[Transaction{state, state}] = handler;
- }
-
- void RegisterTransactionHandler(Transaction transaction, Handler handler) {
- handlers[transaction] = handler;
- }
-
-private:
- T previousState;
- T state;
- std::map<Transaction, Handler> handlers;
-}; \ No newline at end of file
diff --git a/src/GameState.cpp b/src/GameState.cpp
index 18ea722..afe1e26 100644
--- a/src/GameState.cpp
+++ b/src/GameState.cpp
@@ -61,31 +61,57 @@ void GameState::UpdatePacket()
{
//Packet handling
auto ptr = nc->ReceivePacket();
- if (ptr) {
+ while (ptr) {
switch ((PacketNamePlayCB)ptr->GetPacketId()) {
case SpawnObject: {
auto packet = std::static_pointer_cast<PacketSpawnObject>(ptr);
- Entity entity;
+ Entity entity = CreateObject(static_cast<ObjectType>(packet->Type));
entity.entityId = packet->EntityId;
- entity.pitch = packet->Pitch;
entity.pos = VectorF(packet->X, packet->Y, packet->Z);
entity.uuid = packet->ObjectUuid;
entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ);
- entity.yaw = packet->Yaw;
- if (entity.vel != VectorF())
- world.entities.push_back(entity);
+ entity.yaw = packet->Yaw / 256.0;
+ entity.pitch = packet->Pitch / 256.0;
+ entity.renderColor = glm::vec3(0,1,0);
+ world.entities.push_back(entity);
+ EventAgregator::PushEvent(EventType::EntityChanged, EntityChangedData{ entity.entityId });
break;
- }
+ }
case SpawnExperienceOrb:
break;
case SpawnGlobalEntity:
break;
- case SpawnMob:
+ case SpawnMob: {
+ auto packet = std::static_pointer_cast<PacketSpawnObject>(ptr);
+ Entity entity;
+ entity.entityId = packet->EntityId;
+ entity.pos = VectorF(packet->X, packet->Y, packet->Z);
+ entity.uuid = packet->ObjectUuid;
+ entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ);
+ entity.yaw = packet->Yaw / 256.0;
+ entity.pitch = packet->Pitch / 256.0;
+ entity.renderColor = glm::vec3(0,0,1);
+ world.entities.push_back(entity);
+ EventAgregator::PushEvent(EventType::EntityChanged, EntityChangedData{ entity.entityId });
break;
+ }
case SpawnPainting:
break;
- case SpawnPlayer:
+ case SpawnPlayer: {
+ auto packet = std::static_pointer_cast<PacketSpawnPlayer>(ptr);
+ Entity entity;
+ entity.entityId = packet->EntityId;
+ entity.pos = VectorF(packet->X, packet->Y, packet->Z);
+ entity.uuid = packet->PlayerUuid;
+ entity.yaw = packet->Yaw / 256.0;
+ entity.pitch = packet->Pitch / 256.0;
+ entity.renderColor = glm::vec3(1, 0, 0);
+ entity.height = 1.8;
+ entity.width = 0.5;
+ world.entities.push_back(entity);
+ EventAgregator::PushEvent(EventType::EntityChanged, EntityChangedData{ entity.entityId });
break;
+ }
case AnimationCB:
break;
case Statistics:
@@ -168,12 +194,30 @@ void GameState::UpdatePacket()
}
case Map:
break;
- case EntityRelativeMove:
+ case EntityRelativeMove: {
+ auto packet = std::static_pointer_cast<PacketEntityRelativeMove>(ptr);
+ Entity& entity = world.GetEntity(packet->EntityId);
+ entity.pos = entity.pos + Entity::DecodeDeltaPos(packet->DeltaX, packet->DeltaY, packet->DeltaZ);
+ if (entity.entityId != 0)
+ LOG(INFO) << "M: " << packet->EntityId;
break;
- case EntityLookAndRelativeMove:
+ }
+ case EntityLookAndRelativeMove: {
+ auto packet = std::static_pointer_cast<PacketEntityLookAndRelativeMove>(ptr);
+ Entity& entity = world.GetEntity(packet->EntityId);
+ entity.pos = entity.pos + Entity::DecodeDeltaPos(packet->DeltaX, packet->DeltaY, packet->DeltaZ);
+ entity.pitch = packet->Pitch / 256.0;
+ entity.yaw = packet->Yaw / 256.0;
break;
- case EntityLook:
+ }
+ case EntityLook: {
+ auto packet = std::static_pointer_cast<PacketEntityLook>(ptr);
+ Entity& entity = world.GetEntity(packet->EntityId);
+ entity.pitch = packet->Pitch / 256.0;
+ entity.yaw = packet->Yaw / 256.0;
+ //LOG(INFO) << "L: " << packet->EntityId;
break;
+ }
case EntityCB:
break;
case VehicleMove:
@@ -245,8 +289,17 @@ void GameState::UpdatePacket()
break;
case UnlockRecipes:
break;
- case DestroyEntities:
+ case DestroyEntities: {
+ auto packet = std::static_pointer_cast<PacketDestroyEntities>(ptr);
+ for (auto& entityId : packet->EntityIds) {
+ auto it = world.entities.begin();
+ while (it != world.entities.end() && it->entityId != entityId)
+ ++it;
+ if (it != world.entities.end())
+ world.entities.erase(it);
+ }
break;
+ }
case RemoveEntityEffect:
break;
case ResourcePackSend:
@@ -269,8 +322,12 @@ void GameState::UpdatePacket()
break;
case AttachEntity:
break;
- case EntityVelocity:
+ case EntityVelocity: {
+ auto packet = std::static_pointer_cast<PacketEntityVelocity>(ptr);
+ Entity& entity = world.GetEntity(packet->EntityId);
+ entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ);
break;
+ }
case EntityEquipment:
break;
case SetExperience:
@@ -309,8 +366,14 @@ void GameState::UpdatePacket()
break;
case CollectItem:
break;
- case EntityTeleport:
+ case EntityTeleport: {
+ auto packet = std::static_pointer_cast<PacketEntityTeleport>(ptr);
+ Entity& entity = world.GetEntity(packet->EntityId);
+ entity.pos = VectorF(packet->X, packet->Y, packet->Z);
+ entity.pitch = packet->Pitch / 256.0;
+ entity.yaw = packet->Yaw / 256.0;
break;
+ }
case Advancements:
break;
case EntityProperties:
@@ -318,6 +381,7 @@ void GameState::UpdatePacket()
case EntityEffect:
break;
}
+ ptr = nc->ReceivePacket();
}
}
diff --git a/src/Network.cpp b/src/Network.cpp
index e70cce9..789e650 100644
--- a/src/Network.cpp
+++ b/src/Network.cpp
@@ -75,11 +75,11 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
case SpawnGlobalEntity:
break;
case SpawnMob:
- break;
+ return std::make_shared<PacketSpawnMob>();
case SpawnPainting:
break;
case SpawnPlayer:
- break;
+ return std::make_shared<PacketSpawnPlayer>();
case AnimationCB:
break;
case Statistics:
@@ -143,11 +143,11 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
case Map:
break;
case EntityRelativeMove:
- break;
+ return std::make_shared<PacketEntityRelativeMove>();
case EntityLookAndRelativeMove:
- break;
+ return std::make_shared<PacketEntityLookAndRelativeMove>();
case EntityLook:
- break;
+ return std::make_shared<PacketEntityLook>();
case EntityCB:
break;
case VehicleMove:
@@ -165,7 +165,7 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
case UseBed:
break;
case DestroyEntities:
- break;
+ return std::make_shared<PacketDestroyEntities>();
case RemoveEntityEffect:
break;
case ResourcePackSend:
@@ -187,6 +187,7 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
case AttachEntity:
break;
case EntityVelocity:
+ return std::make_shared<PacketEntityVelocity>();
break;
case EntityEquipment:
break;
@@ -215,6 +216,7 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
case CollectItem:
break;
case EntityTeleport:
+ return std::make_shared<PacketEntityTeleport>();
break;
case EntityProperties:
break;
diff --git a/src/Packet.hpp b/src/Packet.hpp
index f48088d..c499720 100644
--- a/src/Packet.hpp
+++ b/src/Packet.hpp
@@ -9,7 +9,7 @@ enum PacketNameLoginSB {
EncryptionResponse = 0x01,
};
enum PacketNamePlaySB {
- TeleportConfirm,
+ TeleportConfirm = 0x00,
PrepareCraftingGrid,
TabCompleteSB,
ChatMessageSB,
@@ -553,4 +553,202 @@ struct PacketSpawnObject : Packet {
short VelocityX;
short VelocityY;
short VelocityZ;
+};
+
+struct PacketEntityRelativeMove : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadVarInt();
+ DeltaX = stream->ReadShort();
+ DeltaY = stream->ReadShort();
+ DeltaZ = stream->ReadShort();
+ OnGround = stream->ReadBool();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::EntityRelativeMove;
+ }
+
+ int EntityId;
+ short DeltaX, DeltaY, DeltaZ;
+ bool OnGround;
+};
+
+struct PacketEntityLookAndRelativeMove : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadVarInt();
+ DeltaX = stream->ReadShort();
+ DeltaY = stream->ReadShort();
+ DeltaZ = stream->ReadShort();
+ return;
+ //TODO: WTF?
+ Yaw = stream->ReadAngle();
+ Pitch = stream->ReadAngle();
+ OnGround = stream->ReadBool();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::EntityLookAndRelativeMove;
+ }
+
+ int EntityId;
+ short DeltaX, DeltaY, DeltaZ;
+ unsigned char Yaw, Pitch;
+ bool OnGround;
+};
+
+struct PacketEntityLook : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadVarInt();
+ Yaw = stream->ReadAngle();
+ Pitch = stream->ReadAngle();
+ OnGround = stream->ReadBool();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::EntityLook;
+ }
+
+ int EntityId;
+ unsigned char Yaw, Pitch;
+ bool OnGround;
+};
+
+struct PacketEntityVelocity : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadVarInt();
+ VelocityX = stream->ReadShort();
+ VelocityY = stream->ReadShort();
+ VelocityZ = stream->ReadShort();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::EntityVelocity;
+ }
+
+ int EntityId;
+ short VelocityX;
+ short VelocityY;
+ short VelocityZ;
+};
+
+struct PacketEntityTeleport : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadVarInt();
+ X = stream->ReadDouble();
+ Y = stream->ReadDouble();
+ Z = stream->ReadDouble();
+ Yaw = stream->ReadAngle();
+ Pitch = stream->ReadAngle();
+ OnGround = stream->ReadBool();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::EntityTeleport;
+ }
+
+ int EntityId;
+ double X, Y, Z;
+ unsigned char Yaw, Pitch;
+ bool OnGround;
+};
+
+struct PacketSpawnPlayer : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadVarInt();
+ PlayerUuid = stream->ReadUuid();
+ X = stream->ReadDouble();
+ Y = stream->ReadDouble();
+ Z = stream->ReadDouble();
+ Yaw = stream->ReadAngle();
+ Pitch = stream->ReadAngle();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::SpawnPlayer;
+ }
+
+ int EntityId;
+ Uuid PlayerUuid;
+ double X, Y, Z;
+ unsigned char Yaw, Pitch;
+
+
+};
+
+struct PacketDestroyEntities : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ int count = stream->ReadVarInt();
+ EntityIds.reserve(count);
+ for (int i = 0; i < count; i++) {
+ int entityId = stream->ReadVarInt();
+ EntityIds.push_back(entityId);
+ }
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::DestroyEntities;
+ }
+
+ std::vector <unsigned int> EntityIds;
+};
+
+struct PacketSpawnMob : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadVarInt();
+ EntityUuid = stream->ReadUuid();
+ type = stream->ReadVarInt();
+ X = stream->ReadDouble();
+ Y = stream->ReadDouble();
+ Z = stream->ReadDouble();
+ Yaw = stream->ReadAngle();
+ Pitch = stream->ReadAngle();
+ HeadPitch = stream->ReadAngle();
+ VelocityX = stream->ReadShort();
+ VelocityY = stream->ReadShort();
+ VelocityZ = stream->ReadShort();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::SpawnMob;
+ }
+
+ unsigned int EntityId;
+ Uuid EntityUuid;
+ int type;
+ double X, Y, Z;
+ unsigned char Yaw, Pitch, HeadPitch;
+ short VelocityX, VelocityY, VelocityZ;
+ //Metadata
}; \ No newline at end of file
diff --git a/src/Render.cpp b/src/Render.cpp
index aec60aa..c44c346 100644
--- a/src/Render.cpp
+++ b/src/Render.cpp
@@ -60,10 +60,13 @@ void Render::PrepareToRendering() {
void Render::RenderFrame() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ if (world) {
+ world->Update();
+ }
if (renderWorld)
- world->Render(renderState);
+ world->Render(renderState);
window->display();
}
@@ -209,7 +212,7 @@ void Render::ExecuteRenderLoop() {
window->setTitle("Connecting");
});
- LoopExecutionTimeController timer(std::chrono::milliseconds(32));
+ LoopExecutionTimeController timer(std::chrono::milliseconds(16));
while (isRunning) {
HandleEvents();
if (isMouseCaptured) HandleMouseCapture();
diff --git a/src/RendererEntity.cpp b/src/RendererEntity.cpp
new file mode 100644
index 0000000..3adcf60
--- /dev/null
+++ b/src/RendererEntity.cpp
@@ -0,0 +1,161 @@
+#include "RendererEntity.hpp"
+
+const GLfloat vertices[] = {
+ //Z+ edge
+ -0.5f, 0.5f, 0.5f,
+ -0.5f, -0.5f, 0.5f,
+ 0.5f, -0.5f, 0.5f,
+ -0.5f, 0.5f, 0.5f,
+ 0.5f, -0.5f, 0.5f,
+ 0.5f, 0.5f, 0.5f,
+
+ //Z- edge
+ -0.5f, -0.5f, -0.5f,
+ -0.5f, 0.5f, -0.5f,
+ 0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f, -0.5f,
+ -0.5f, 0.5f, -0.5f,
+ 0.5f, 0.5f, -0.5f,
+
+ //X+ edge
+ -0.5f, -0.5f, -0.5f,
+ -0.5f, -0.5f, 0.5f,
+ -0.5f, 0.5f, -0.5f,
+ -0.5f, 0.5f, -0.5f,
+ -0.5f, -0.5f, 0.5f,
+ -0.5f, 0.5f, 0.5f,
+
+ //X- edge
+ 0.5f, -0.5f, 0.5f,
+ 0.5f, 0.5f, -0.5f,
+ 0.5f, 0.5f, 0.5f,
+ 0.5f, -0.5f, 0.5f,
+ 0.5f, -0.5f, -0.5f,
+ 0.5f, 0.5f, -0.5f,
+
+ //Y+ edge
+ 0.5f, 0.5f, -0.5f,
+ -0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5f, -0.5f,
+ -0.5f, 0.5f, -0.5f,
+ -0.5f, 0.5f, 0.5f,
+
+ //Y- edge
+ -0.5f, -0.5f, 0.5f,
+ 0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f, 0.5f,
+ -0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f, -0.5f,
+ -0.5f, -0.5f, 0.5f,
+};
+
+const GLfloat uv_coords[] = {
+ //Z+
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+
+ //Z-
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 0.0f,
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+
+ //X+
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+
+ //X-
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+
+ //Y+
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+
+ //Y-
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+};
+
+const GLuint magic = 993214;
+GLuint Vbo = magic,Vao = magic,Vbo2 = magic;
+
+RendererEntity::RendererEntity(World *ptr, unsigned int id)
+{
+ world = ptr;
+ entityId = id;
+
+
+ if (Vbo == magic || Vao == magic) {
+ glGenVertexArrays(1, &Vao);
+ glGenBuffers(1, &Vbo);
+ glGenBuffers(1, &Vbo2);
+
+ glBindVertexArray(Vao);
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, Vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
+ glEnableVertexAttribArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, Vbo2);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coords), uv_coords, GL_STATIC_DRAW);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
+ glEnableVertexAttribArray(1);
+ }
+ glBindVertexArray(0);
+ }
+}
+
+RendererEntity::~RendererEntity() {
+}
+
+void RendererEntity::Render(RenderState & renderState) {
+ renderState.SetActiveVao(Vao);
+ glm::mat4 model;
+ Entity& entity = world->GetEntity(entityId);
+ model = glm::translate(model, entity.pos.glm());
+ model = glm::translate(model, glm::vec3(0, entity.height / 2.0, 0));
+ model = glm::scale(model, glm::vec3(entity.width, entity.height, entity.width));
+
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+ glUniform3f(colorLoc, entity.renderColor.x, entity.renderColor.y, entity.renderColor.z);
+ glDrawArrays(GL_TRIANGLES, 0, 36);
+
+ glCheckError();
+}
+
+void RendererEntity::PrepareResources()
+{
+}
+
+void RendererEntity::PrepareRender()
+{
+}
+
+bool RendererEntity::IsNeedResourcesPrepare()
+{
+ return false;
+}
diff --git a/src/RendererEntity.hpp b/src/RendererEntity.hpp
new file mode 100644
index 0000000..23fd029
--- /dev/null
+++ b/src/RendererEntity.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtc/type_ptr.hpp>
+
+#include "Renderer.hpp"
+#include "Entity.hpp"
+#include "World.hpp"
+
+class RendererEntity :Renderer {
+ unsigned int entityId;
+ World *world;
+public:
+ RendererEntity(World *ptr, unsigned int id);
+ ~RendererEntity();
+
+ void Render(RenderState& renderState) override;
+ void PrepareResources() override;
+ void PrepareRender() override;
+ bool IsNeedResourcesPrepare() override;
+
+ GLint modelLoc = 0;
+ GLint colorLoc = 0;
+}; \ No newline at end of file
diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp
index 439fab1..a2d6825 100644
--- a/src/RendererSection.cpp
+++ b/src/RendererSection.cpp
@@ -123,7 +123,7 @@ RendererSection::~RendererSection() {
refCounterVbo[VboModels]--;
refCounterVbo[VboColors]--;
refCounterVao[Vao]--;
- if (refCounterVbo[VboTextures] <= 0)
+ /*if (refCounterVbo[VboTextures] <= 0)
glDeleteBuffers(1, &VboTextures);
if (refCounterVbo[VboModels] <= 0)
@@ -132,12 +132,13 @@ RendererSection::~RendererSection() {
glDeleteBuffers(1, &VboColors);
if (refCounterVao[Vao] <= 0)
- glDeleteVertexArrays(1, &Vao);
+ glDeleteVertexArrays(1, &Vao);*/
}
void RendererSection::Render(RenderState &renderState) {
if (!isEnabled) return;
if (!models.empty()) {
+ LOG(INFO) << "Rendering unready section";
PrepareRender();
}
renderState.SetActiveVao(Vao);
@@ -332,15 +333,15 @@ void RendererSection::PrepareResources() {
void RendererSection::PrepareRender() {
glBindBuffer(GL_ARRAY_BUFFER, VboTextures);
glBufferData(GL_ARRAY_BUFFER, textures.size() * sizeof(glm::vec4), textures.data(), GL_DYNAMIC_DRAW);
- textures.clear();
+ std::vector<glm::vec4>().swap(textures);
glBindBuffer(GL_ARRAY_BUFFER, VboModels);
glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_DYNAMIC_DRAW);
- models.clear();
+ std::vector<glm::mat4>().swap(models);
glBindBuffer(GL_ARRAY_BUFFER, VboColors);
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_DYNAMIC_DRAW);
- colors.clear();
+ std::vector<glm::vec3>().swap(colors);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp
index c165da4..57d04d5 100644
--- a/src/RendererSection.hpp
+++ b/src/RendererSection.hpp
@@ -25,9 +25,9 @@ class RendererSection : Renderer {
static std::map<GLuint, int> refCounterVbo;
static std::map<GLuint, int> refCounterVao;
- size_t numOfFaces = 0;
+
- bool isEnabled = true;
+ bool isEnabled = false;
size_t hash = 0;
public:
@@ -46,4 +46,6 @@ public:
Section *GetSection();
bool IsNeedResourcesPrepare() override;
+
+ size_t numOfFaces = 0;
}; \ No newline at end of file
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp
index 7d965f6..c2ba3ae 100644
--- a/src/RendererWorld.cpp
+++ b/src/RendererWorld.cpp
@@ -1,7 +1,7 @@
#include "RendererWorld.hpp"
void RendererWorld::LoadedSectionController() {
-
+ el::Helpers::setThreadName("RenderParser");
std::function<void(Vector)> updateAllSections = [this](Vector playerPos) {
Vector playerChunk(std::floor(gs->g_PlayerX / 16), 0, std::floor(gs->g_PlayerZ / 16));
@@ -25,20 +25,24 @@ void RendererWorld::LoadedSectionController() {
for (auto& it : toRemove) {
EventAgregator::PushEvent(EventType::DeleteSectionRender, DeleteSectionRenderData{ it });
}
-
+ std::sort(suitableChunks.begin(), suitableChunks.end(), [playerChunk](Vector lhs, Vector rhs) {
+ return (playerChunk - lhs).GetLength() < (playerChunk - rhs).GetLength();
+ });
for (auto& it : suitableChunks) {
EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ it });
}
};
- EventListener contentListener;
+ EventListener contentListener;
contentListener.RegisterHandler(EventType::ChunkChanged, [this](EventData eventData) {
auto vec = std::get<ChunkChangedData>(eventData).chunkPosition;
- Vector playerChunk(std::floor(gs->g_PlayerX / 16), 0, std::floor(gs->g_PlayerZ / 16));
+ Vector playerChunk(std::floor(gs->g_PlayerX / 16), 0, std::floor(gs->g_PlayerZ / 16));
- if ((Vector(vec.x,0,vec.z) - playerChunk).GetLength() > MaxRenderingDistance)
+ //if (playerChunk != Vector())
+ if ((Vector(vec.x, 0, vec.z) - playerChunk).GetLength() > MaxRenderingDistance)
return;
+
sectionsMutex.lock();
auto& result = sections.find(vec);
if (result != sections.end()) {
@@ -56,7 +60,13 @@ void RendererWorld::LoadedSectionController() {
contentListener.RegisterHandler(EventType::CreatedSectionRender, [this](EventData eventData) {
auto vec = std::get<CreatedSectionRenderData>(eventData).pos;
sectionsMutex.lock();
- sections.find(vec)->second.PrepareResources();
+ auto it = sections.find(vec);
+ if (it == sections.end()) {
+ LOG(ERROR) << "Created wrnog sectionRenderer";
+ sectionsMutex.unlock();
+ return;
+ }
+ it->second.PrepareResources();
sectionsMutex.unlock();
EventAgregator::PushEvent(EventType::InitalizeSectionRender, InitalizeSectionRenderData{ vec });
});
@@ -69,6 +79,7 @@ void RendererWorld::LoadedSectionController() {
contentListener.RegisterHandler(EventType::UpdateSectionsRender, [this,&updateAllSections](EventData eventData) {
updateAllSections(Vector(gs->g_PlayerX, gs->g_PlayerY, gs->g_PlayerZ));
});
+
LoopExecutionTimeController timer(std::chrono::milliseconds(32));
auto timeSincePreviousUpdate = std::chrono::steady_clock::now();
@@ -83,6 +94,38 @@ void RendererWorld::LoadedSectionController() {
}
}
+void RendererWorld::RenderBlocks(RenderState& renderState)
+{
+ renderState.SetActiveShader(blockShader->Program);
+ glCheckError();
+
+ GLint projectionLoc = glGetUniformLocation(blockShader->Program, "projection");
+ GLint viewLoc = glGetUniformLocation(blockShader->Program, "view");
+ GLint windowSizeLoc = glGetUniformLocation(blockShader->Program, "windowSize");
+ glm::mat4 projection = glm::perspective(45.0f, (float)renderState.WindowWidth / (float)renderState.WindowHeight, 0.1f, 10000000.0f);
+ glm::mat4 view = gs->GetViewMatrix();
+ glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
+ glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
+ glUniform2f(windowSizeLoc, renderState.WindowWidth, renderState.WindowHeight);
+
+ glCheckError();
+
+ sectionsMutex.lock();
+ for (auto& it : sections) {
+
+ it.second.Render(renderState);
+ }
+
+ sectionsMutex.unlock();
+}
+
+void RendererWorld::RenderEntities(RenderState& renderState)
+{
+ renderState.SetActiveShader(entityShader->Program);
+ glCheckError();
+
+}
+
RendererWorld::RendererWorld(GameState * ptr):gs(ptr) {
MaxRenderingDistance = 2;
@@ -91,15 +134,22 @@ RendererWorld::RendererWorld(GameState * ptr):gs(ptr) {
listener.RegisterHandler(EventType::InitalizeSectionRender, [this](EventData eventData) {
auto data = std::get<InitalizeSectionRenderData>(eventData);
sectionsMutex.lock();
- sections.find(data.pos)->second.PrepareRender();
- sections.find(data.pos)->second.SetEnabled(true);
+ auto it = sections.find(data.pos);
+ if (it == sections.end()) {
+ LOG(ERROR) << "Initializing wrong sectionRenderer";
+ sectionsMutex.unlock();
+ return;
+ }
+ it->second.PrepareRender();
+ it->second.SetEnabled(true);
sectionsMutex.unlock();
});
listener.RegisterHandler(EventType::CreateSectionRender, [this](EventData eventData) {
auto vec = std::get<CreateSectionRenderData>(eventData).pos;
+ auto pair = std::make_pair(vec, RendererSection(&gs->world, vec));
sectionsMutex.lock();
- sections.insert(std::make_pair(vec, RendererSection(&gs->world, vec)));
+ sections.insert(pair);
sectionsMutex.unlock();
EventAgregator::PushEvent(EventType::CreatedSectionRender, CreatedSectionRenderData{ vec });
});
@@ -107,32 +157,55 @@ RendererWorld::RendererWorld(GameState * ptr):gs(ptr) {
listener.RegisterHandler(EventType::DeleteSectionRender, [this](EventData eventData) {
auto vec = std::get<DeleteSectionRenderData>(eventData).pos;
sectionsMutex.lock();
- sections.erase(sections.find(vec));
+ auto it = sections.find(vec);
+ if (it == sections.end()) {
+ LOG(ERROR) << "Deleting wrong sectionRenderer";
+ sectionsMutex.unlock();
+ return;
+ }
+ sections.erase(it);
sectionsMutex.unlock();
});
+
+ listener.RegisterHandler(EventType::EntityChanged, [this](EventData eventData) {
+ auto data = std::get<EntityChangedData>(eventData);
+ for (auto&it : gs->world.entities) {
+ if (it.entityId == data.EntityId) {
+ entities.push_back(RendererEntity(&gs->world,it.entityId));
+ return;
+ }
+ }
+ });
resourceLoader = std::thread(&RendererWorld::LoadedSectionController, this);
}
RendererWorld::~RendererWorld() {
+ size_t faces = 0;
+ sectionsMutex.lock();
+ for (auto& it : sections) {
+ faces += it.second.numOfFaces;
+ }
+ sectionsMutex.unlock();
+ LOG(INFO) << "Total faces to render: "<<faces;
isRunning = false;
resourceLoader.join();
- delete shader;
+ delete blockShader;
+ delete entityShader;
}
void RendererWorld::Render(RenderState & renderState) {
- renderState.SetActiveShader(shader->Program);
+ renderState.SetActiveShader(blockShader->Program);
glCheckError();
- GLint projectionLoc = glGetUniformLocation(shader->Program, "projection");
- GLint viewLoc = glGetUniformLocation(shader->Program, "view");
- GLint windowSizeLoc = glGetUniformLocation(shader->Program, "windowSize");
+ GLint projectionLoc = glGetUniformLocation(blockShader->Program, "projection");
+ GLint viewLoc = glGetUniformLocation(blockShader->Program, "view");
+ GLint windowSizeLoc = glGetUniformLocation(blockShader->Program, "windowSize");
glm::mat4 projection = glm::perspective(45.0f, (float)renderState.WindowWidth / (float)renderState.WindowHeight, 0.1f, 10000000.0f);
glm::mat4 view = gs->GetViewMatrix();
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniform2f(windowSizeLoc, renderState.WindowWidth, renderState.WindowHeight);
-
glCheckError();
sectionsMutex.lock();
@@ -140,10 +213,24 @@ void RendererWorld::Render(RenderState & renderState) {
it.second.Render(renderState);
}
-
sectionsMutex.unlock();
- listener.HandleEvent();
+
+ renderState.SetActiveShader(entityShader->Program);
+ glCheckError();
+ projectionLoc = glGetUniformLocation(entityShader->Program, "projection");
+ viewLoc = glGetUniformLocation(entityShader->Program, "view");
+ glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
+ glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
+ glCheckError();
+ GLint modelLoc = glGetUniformLocation(entityShader->Program, "model");
+ GLint colorLoc = glGetUniformLocation(entityShader->Program, "color");
+ for (auto& it : entities) {
+ it.modelLoc = modelLoc;
+ it.colorLoc = colorLoc;
+ it.Render(renderState);
+ }
+
}
void RendererWorld::PrepareResources() {
@@ -151,12 +238,17 @@ void RendererWorld::PrepareResources() {
}
void RendererWorld::PrepareRender() {
- shader = new Shader("./shaders/face.vs", "./shaders/face.fs");
- shader->Use();
- glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0);
+ blockShader = new Shader("./shaders/face.vs", "./shaders/face.fs");
+ blockShader->Use();
+ glUniform1i(glGetUniformLocation(blockShader->Program, "textureAtlas"), 0);
+ entityShader = new Shader("./shaders/entity.vs", "./shaders/entity.fs");
}
bool RendererWorld::IsNeedResourcesPrepare() {
LOG(ERROR) << "Incorrect call";
return false;
}
+
+void RendererWorld::Update() {
+ listener.HandleEvent();
+}
diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp
index 2ae4e37..fb10c88 100644
--- a/src/RendererWorld.hpp
+++ b/src/RendererWorld.hpp
@@ -1,20 +1,28 @@
#pragma once
#include "RendererSection.hpp"
+#include "RendererEntity.hpp"
#include "GameState.hpp"
#include "Shader.hpp"
#include <glm/gtc/type_ptr.hpp>
class RendererWorld: public Renderer {
+ //General
GameState *gs;
- std::mutex sectionsMutex;
- std::map<Vector, RendererSection> sections;
EventListener listener;
- Shader *shader;
std::thread resourceLoader;
void LoadedSectionController();
bool isRunning = true;
+ //Blocks
+ std::mutex sectionsMutex;
+ std::map<Vector, RendererSection> sections;
+ Shader *blockShader;
+ void RenderBlocks(RenderState& renderState);
+ //Entities
+ Shader *entityShader;
+ std::vector<RendererEntity> entities;
+ void RenderEntities(RenderState& renderState);
public:
RendererWorld(GameState* ptr);
~RendererWorld();
@@ -25,4 +33,6 @@ public:
bool IsNeedResourcesPrepare() override;
double MaxRenderingDistance;
+
+ void Update();
}; \ No newline at end of file
diff --git a/src/Stream.cpp b/src/Stream.cpp
index d7b1072..a44b91c 100644
--- a/src/Stream.cpp
+++ b/src/Stream.cpp
@@ -281,8 +281,8 @@ void StreamOutput::WriteByteArray(std::vector<unsigned char> value) {
void StreamBuffer::ReadData(unsigned char *buffPtr, size_t buffLen) {
size_t bufferLengthLeft = buffer + bufferLength - bufferPtr;
- if (bufferLengthLeft < buffLen)
- throw std::runtime_error("Required data is more, than in buffer available");
+ if (bufferLengthLeft < buffLen)
+ throw std::runtime_error("Required data is more, than in buffer available");
std::memcpy(buffPtr, bufferPtr, buffLen);
bufferPtr += buffLen;
}
diff --git a/src/ThreadGame.cpp b/src/ThreadGame.cpp
index 74802bb..d3750ea 100644
--- a/src/ThreadGame.cpp
+++ b/src/ThreadGame.cpp
@@ -84,8 +84,8 @@ void ThreadGame::Execute() {
while (isRunning) {
if (gs != nullptr)
gs->Update(timer.GetRealDeltaS());
- listener.HandleEvent();
- if (gs != nullptr) {
+ listener.HandleEvent();
+ if (gs != nullptr) {
gs->UpdatePacket();
if (isMoving[GameState::FORWARD])
gs->HandleMovement(GameState::FORWARD, timer.GetRealDeltaS());
diff --git a/src/Utility.cpp b/src/Utility.cpp
index ebb6981..655c26f 100644
--- a/src/Utility.cpp
+++ b/src/Utility.cpp
@@ -29,7 +29,7 @@ GLenum glCheckError_(const char *file, int line) {
break;
}
static int t = 0;
- t++;
+ //t++;
if (t > 10)
LOG(FATAL);
LOG(ERROR) << "OpenGL error: " << error << " at " << file << ":" << line;
diff --git a/src/World.cpp b/src/World.cpp
index 17f9cd2..3eff5dd 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -169,7 +169,40 @@ glm::vec3 World::Raycast(glm::vec3 position, glm::vec3 direction, float maxLengt
void World::UpdatePhysics(float delta)
{
+ delta /= 5;
for (auto& it : entities) {
it.pos = it.pos + it.vel * delta;
}
}
+
+Entity & World::GetEntity(unsigned int EntityId)
+{
+ for (auto& it : entities) {
+ if (it.entityId == EntityId) {
+ return it;
+ }
+ }
+ static Entity fallback;
+ return fallback;
+}
+
+std::vector<unsigned int> World::GetEntitiesList()
+{
+ std::vector<unsigned int> ret;
+ for (auto& it : entities) {
+ ret.push_back(it.entityId);
+ }
+ return ret;
+}
+
+void World::AddEntity(Entity entity)
+{
+ for (auto& it : entities) {
+ if (it.entityId == entity.entityId) {
+ LOG(ERROR) << "Adding already existing entity" << entity.entityId;
+ return;
+ }
+ }
+ entities.push_back(entity);
+
+}
diff --git a/src/World.hpp b/src/World.hpp
index 2415610..06155cf 100644
--- a/src/World.hpp
+++ b/src/World.hpp
@@ -49,4 +49,10 @@ public:
std::vector<Entity> entities;
void UpdatePhysics(float delta);
+
+ Entity& GetEntity(unsigned int EntityId);
+
+ std::vector<unsigned int> GetEntitiesList();
+
+ void AddEntity(Entity entity);
}; \ No newline at end of file