summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/DebugInfo.cpp3
-rw-r--r--src/DebugInfo.hpp1
-rw-r--r--src/GameState.cpp1178
-rw-r--r--src/GameState.hpp141
-rw-r--r--src/GlobalState.cpp11
-rw-r--r--src/GlobalState.hpp4
-rw-r--r--src/Render.cpp91
-rw-r--r--src/RendererEntity.cpp10
-rw-r--r--src/RendererEntity.hpp7
-rw-r--r--src/RendererWorld.cpp53
-rw-r--r--src/RendererWorld.hpp8
-rw-r--r--src/Section.cpp2
-rw-r--r--src/World.cpp108
-rw-r--r--src/World.hpp35
14 files changed, 859 insertions, 793 deletions
diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp
index e2d439b..89e9425 100644
--- a/src/DebugInfo.cpp
+++ b/src/DebugInfo.cpp
@@ -3,4 +3,5 @@
std::atomic_int DebugInfo::totalSections(0);
std::atomic_int DebugInfo::renderSections(0);
std::atomic_int DebugInfo::readyRenderer(0);
-std::atomic_int DebugInfo::gameThreadTime(0); \ No newline at end of file
+std::atomic_int DebugInfo::gameThreadTime(0);
+std::atomic_int DebugInfo::renderFaces(0); \ No newline at end of file
diff --git a/src/DebugInfo.hpp b/src/DebugInfo.hpp
index a29a056..e6aa17c 100644
--- a/src/DebugInfo.hpp
+++ b/src/DebugInfo.hpp
@@ -7,4 +7,5 @@ struct DebugInfo {
static std::atomic_int renderSections;
static std::atomic_int readyRenderer;
static std::atomic_int gameThreadTime;
+ static std::atomic_int renderFaces;
}; \ No newline at end of file
diff --git a/src/GameState.cpp b/src/GameState.cpp
index fabfdb8..ace2488 100644
--- a/src/GameState.cpp
+++ b/src/GameState.cpp
@@ -7,559 +7,569 @@
#include "Packet.hpp"
void GameState::Update(float deltaTime) {
- if (g_IsGameStarted) {
- std::chrono::steady_clock clock;
- static auto timeOfPreviousSendedPacket(clock.now());
- auto delta = clock.now() - timeOfPreviousSendedPacket;
- using namespace std::chrono_literals;
- if (delta >= 50ms) {
- auto packetToSend = std::make_shared<PacketPlayerPositionAndLookSB>(
- player->pos.x, player->pos.y, player->pos.z,
- player->yaw, player->pitch, player->onGround);
-
- auto packet = std::static_pointer_cast<Packet>(packetToSend);
- PUSH_EVENT("SendPacket", packet);
- timeOfPreviousSendedPacket = clock.now();
- }
-
- bool prevOnGround = player->onGround;
- world.UpdatePhysics(deltaTime);
- if (player->onGround != prevOnGround) {
- auto updatePacket = std::make_shared<PacketPlayerPosition>(
- player->pos.x, player->pos.y,
- player->pos.z, player->onGround);
-
- auto packet = std::static_pointer_cast<Packet>(updatePacket);
- PUSH_EVENT("SendPacket", packet);
- }
-
-
- double playerYaw = Entity::DecodeYaw(player->yaw);
- double playerPitch = Entity::DecodePitch(player->pitch);
-
- glm::vec3 direction;
- direction.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
- direction.y = sin(glm::radians(playerPitch));
- direction.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
-
- RaycastResult raycast = world.Raycast(player->pos + player->EyeOffset, direction);
- if (raycast.isHit != isBlockSelected || ((raycast.isHit == true && isBlockSelected == true) &&
- selectedBlock != raycast.hitBlock)) {
- PUSH_EVENT("SelectedBlockChanged", 0);
- }
-
- if (raycast.isHit) {
- selectedBlock = raycast.hitBlock;
- distanceToSelectedBlock = (player->pos - raycast.hitPos).GetLength();
- } else {
- selectedBlock = Vector(0, 0, 0);
- distanceToSelectedBlock = 0.0f;
- }
-
- isBlockSelected = raycast.isHit;
- raycastHit = raycast.hitPos;
-
- if (doDaylightCycle)
- interpolatedTimeOfDay += 20.0 * deltaTime;
- }
+ if (!gameStatus.isGameStarted)
+ return;
+
+ std::chrono::steady_clock clock;
+ static auto timeOfPreviousSendedPacket(clock.now());
+ auto delta = clock.now() - timeOfPreviousSendedPacket;
+ using namespace std::chrono_literals;
+ if (delta >= 50ms) {
+ auto packetToSend = std::make_shared<PacketPlayerPositionAndLookSB>(
+ player->pos.x, player->pos.y, player->pos.z,
+ player->yaw, player->pitch, player->onGround);
+
+ auto packet = std::static_pointer_cast<Packet>(packetToSend);
+ PUSH_EVENT("SendPacket", packet);
+ timeOfPreviousSendedPacket = clock.now();
+ }
+
+ bool prevOnGround = player->onGround;
+ world.UpdatePhysics(deltaTime);
+ if (player->onGround != prevOnGround) {
+ auto updatePacket = std::make_shared<PacketPlayerPosition>(
+ player->pos.x, player->pos.y,
+ player->pos.z, player->onGround);
+
+ auto packet = std::static_pointer_cast<Packet>(updatePacket);
+ PUSH_EVENT("SendPacket", packet);
+ }
+
+
+ double playerYaw = Entity::DecodeYaw(player->yaw);
+ double playerPitch = Entity::DecodePitch(player->pitch);
+
+ glm::vec3 direction;
+ direction.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
+ direction.y = sin(glm::radians(playerPitch));
+ direction.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
+
+ RaycastResult raycast = world.Raycast(player->pos + player->EyeOffset, direction);
+ if (raycast.isHit != selectionStatus.isBlockSelected || ((raycast.isHit == true && selectionStatus.isBlockSelected == true) &&
+ selectionStatus.selectedBlock != raycast.hitBlock)) {
+ PUSH_EVENT("SelectedBlockChanged", 0);
+ }
+
+ if (raycast.isHit) {
+ selectionStatus.selectedBlock = raycast.hitBlock;
+ selectionStatus.distanceToSelectedBlock = (player->pos - raycast.hitPos).GetLength();
+ }
+ else {
+ selectionStatus.selectedBlock = Vector(0, 0, 0);
+ selectionStatus.distanceToSelectedBlock = 0.0f;
+ }
+
+ selectionStatus.isBlockSelected = raycast.isHit;
+ selectionStatus.raycastHit = raycast.hitPos;
+
+ if (timeStatus.doDaylightCycle)
+ timeStatus.interpolatedTimeOfDay += 20.0 * deltaTime;
}
void GameState::UpdatePacket(std::shared_ptr<Packet> ptr) {
- switch ((PacketNamePlayCB) ptr->GetPacketId()) {
- case SpawnObject: {
- auto packet = std::static_pointer_cast<PacketSpawnObject>(ptr);
- Entity entity = CreateObject(static_cast<ObjectType>(packet->Type));
- 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, 1, 0);
- world.AddEntity(entity);
- PUSH_EVENT("EntityChanged", entity.entityId);
- break;
- }
-
- case SpawnExperienceOrb:
- break;
-
- case SpawnGlobalEntity:
- break;
-
- case SpawnMob: {
- auto packet = std::static_pointer_cast<PacketSpawnMob>(ptr);
- Entity entity;
- entity.entityId = packet->EntityId;
- entity.pos = VectorF(packet->X, packet->Y, packet->Z);
- entity.uuid = packet->EntityUuid;
- 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.AddEntity(entity);
- PUSH_EVENT("EntityChanged", entity.entityId);
- break;
- }
-
- case SpawnPainting:
- break;
-
- 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.6;
- world.AddEntity(entity);
- PUSH_EVENT("EntityChanged", entity.entityId);
- break;
- }
- case AnimationCB:
- break;
- case Statistics:
- break;
- case BlockBreakAnimation:
- break;
- case UpdateBlockEntity:
- break;
- case BlockAction:
- break;
-
- case BlockChange: {
- auto packet = std::static_pointer_cast<PacketBlockChange>(ptr);
- world.ParseChunkData(packet);
- break;
- }
-
- case BossBar:
- break;
- case ServerDifficulty:
- break;
- case TabCompleteCB:
- break;
-
- case ChatMessageCB: {
- auto packet = std::static_pointer_cast<PacketChatMessageCB>(ptr);
- LOG(INFO) << "Message (" << int(packet->Position) << "): " << packet->JsonData.text;
- PUSH_EVENT("ChatMessageReceived", std::make_tuple(packet->JsonData, packet->Position));
- break;
- }
-
- case MultiBlockChange: {
- auto packet = std::static_pointer_cast<PacketMultiBlockChange>(ptr);
- world.ParseChunkData(packet);
- break;
- }
-
- case ConfirmTransactionCB: {
- auto packet = std::static_pointer_cast<PacketConfirmTransactionCB>(ptr);
- if (packet->WindowId == 0) {
- try {
- playerInventory.ConfirmTransaction(*packet);
- } catch (std::exception &e) {
- PUSH_EVENT("Disconnected", std::string("Transaction failed"));
- }
- }
- break;
- }
-
- case CloseWindowCB:
- break;
-
- case OpenWindow: {
- auto packet = std::static_pointer_cast<PacketOpenWindow>(ptr);
-
- LOG(INFO) << "Open new window " << packet->WindowTitle << ": " << packet->WindowId;
- break;
- }
-
- case WindowItems: {
- auto packet = std::static_pointer_cast<PacketWindowItems>(ptr);
- if (packet->WindowId == 0) {
- playerInventory.WindowId = 0;
- playerInventory.slots = packet->SlotData;
- }
- break;
- }
-
- case WindowProperty:
- break;
-
- case SetSlot: {
- auto packet = std::static_pointer_cast<PacketSetSlot>(ptr);
- if (packet->WindowId == 0) {
- playerInventory.slots[packet->Slot] = packet->SlotData;
- }
- break;
- }
-
- case SetCooldown:
- break;
- case PluginMessageCB:
- break;
- case NamedSoundEffect:
- break;
-
- case DisconnectPlay: {
- auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr);
- LOG(INFO) << "Disconnect reason: " << packet->Reason;
- PUSH_EVENT("Disconnected", packet->Reason);
- break;
- }
-
- case EntityStatus:
- break;
- case Explosion:
- break;
-
- case UnloadChunk: {
- auto packet = std::static_pointer_cast<PacketUnloadChunk>(ptr);
- world.ParseChunkData(packet);
- break;
- }
-
- case ChangeGameState:
- break;
-
- case KeepAliveCB: {
- LOG(WARNING) << "Receive KeepAlive packet in GameState handler";
- break;
- }
-
- case ChunkData: {
- auto packet = std::static_pointer_cast<PacketChunkData>(ptr);
- world.ParseChunkData(packet);
- break;
- }
-
- case Effect:
- break;
- case Particle:
- break;
-
- case JoinGame: {
- auto packet = std::static_pointer_cast<PacketJoinGame>(ptr);
- Entity entity;
- entity.entityId = packet->EntityId;
- entity.width = 0.6;
- entity.height = 1.8;
- world.AddEntity(entity);
- player = world.GetEntityPtr(entity.entityId);
-
- g_PlayerEid = packet->EntityId;
- g_Gamemode = (packet->Gamemode & 0b11111011);
- g_Dimension = packet->Dimension;
- g_Difficulty = packet->Difficulty;
- g_MaxPlayers = packet->MaxPlayers;
- g_LevelType = packet->LevelType;
- g_ReducedDebugInfo = packet->ReducedDebugInfo;
- LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int) g_Difficulty
- << ", Level Type is " << g_LevelType;
- PUSH_EVENT("PlayerConnected", 0);
- break;
- }
-
- case Map:
- break;
-
- 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: {
- 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: {
- 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:
- break;
- case OpenSignEditor:
- break;
- case PlayerAbilitiesCB:
- break;
- case CombatEvent:
- break;
- case PlayerListItem:
- break;
-
- case PlayerPositionAndLookCB: {
- auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr);
- if ((packet->Flags & 0x10) != 0) {
- player->pitch += packet->Pitch;
- } else {
- player->pitch = packet->Pitch;
- }
-
- if ((packet->Flags & 0x08) != 0) {
- player->yaw += packet->Yaw;
- } else {
- player->yaw = packet->Yaw;
- }
-
- if ((packet->Flags & 0x01) != 0) {
- player->pos.x += packet->X;
- } else {
- player->pos.x = packet->X;
- }
-
- if ((packet->Flags & 0x02) != 0) {
- player->pos.y += packet->Y;
- } else {
- player->pos.y = packet->Y;
- }
-
- if ((packet->Flags & 0x04) != 0) {
- player->pos.z += packet->Z;
- } else {
- player->pos.z = packet->Z;
- }
-
- PUSH_EVENT("PlayerPosChanged", player->pos);
- LOG(INFO) << "PlayerPos is " << player->pos << "\t\tAngle: " << player->yaw << "," << player->pitch;;
-
- if (!g_IsGameStarted) {
- LOG(INFO) << "Game is started";
- PUSH_EVENT("RemoveLoadingScreen", 0);
- }
-
- g_IsGameStarted = true;
-
- auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
- auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
-
- PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(packetResponse));
- PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(packetPerformRespawn));
- break;
- }
-
- case UseBed:
- break;
- case UnlockRecipes:
- break;
-
- case DestroyEntities: {
- auto packet = std::static_pointer_cast<PacketDestroyEntities>(ptr);
- for (unsigned int entityId : packet->EntityIds) {
- world.DeleteEntity(entityId);
- }
- break;
- }
-
- case RemoveEntityEffect:
- break;
- case ResourcePackSend:
- break;
- case Respawn:
- break;
- case EntityHeadLook:
- break;
- case SelectAdvancementTab:
- break;
- case WorldBorder:
- break;
- case Camera:
- break;
- case HeldItemChangeCB:
- break;
- case DisplayScoreboard:
- break;
- case EntityMetadata:
- break;
- case AttachEntity:
- break;
-
- 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:
- break;
-
- case UpdateHealth: {
- auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr);
- g_PlayerHealth = packet->Health;
- if (g_PlayerHealth <= 0) {
- LOG(INFO) << "Player is dead. Respawning...";
- auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
- PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(packetPerformRespawn));
- }
- break;
- }
-
- case ScoreboardObjective:
- break;
- case SetPassengers:
- break;
- case Teams:
- break;
- case UpdateScore:
- break;
-
- case SpawnPosition: {
- auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr);
- g_SpawnPosition = packet->Location;
- LOG(INFO) << "Spawn position is " << g_SpawnPosition.x << " " << g_SpawnPosition.y << " "
- << g_SpawnPosition.z;
- break;
- }
-
- case TimeUpdate: {
- auto packet = std::static_pointer_cast<PacketTimeUpdate>(ptr);
- doDaylightCycle = TimeOfDay != packet->TimeOfDay;
- WorldAge = packet->WorldAge;
- TimeOfDay = packet->TimeOfDay;
- interpolatedTimeOfDay = TimeOfDay;
- break;
- }
-
- case Title:
- break;
- case SoundEffect:
- break;
- case PlayerListHeaderAndFooter:
- break;
- case CollectItem:
- break;
-
- 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:
- break;
- case EntityEffect:
- break;
- }
-
- while (!playerInventory.pendingTransactions.empty()) {
- auto packet = std::make_shared<PacketClickWindow>(playerInventory.pendingTransactions.front());
- playerInventory.pendingTransactions.pop();
- PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(packet));
- }
+ switch ((PacketNamePlayCB)ptr->GetPacketId()) {
+ case SpawnObject: {
+ auto packet = std::static_pointer_cast<PacketSpawnObject>(ptr);
+ Entity entity = CreateObject(static_cast<ObjectType>(packet->Type));
+ 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, 1, 0);
+ world.AddEntity(entity);
+ PUSH_EVENT("EntityChanged", entity.entityId);
+ break;
+ }
+
+ case SpawnExperienceOrb:
+ break;
+
+ case SpawnGlobalEntity:
+ break;
+
+ case SpawnMob: {
+ auto packet = std::static_pointer_cast<PacketSpawnMob>(ptr);
+ Entity entity;
+ entity.entityId = packet->EntityId;
+ entity.pos = VectorF(packet->X, packet->Y, packet->Z);
+ entity.uuid = packet->EntityUuid;
+ 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.AddEntity(entity);
+ PUSH_EVENT("EntityChanged", entity.entityId);
+ break;
+ }
+
+ case SpawnPainting:
+ break;
+
+ 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.6;
+ world.AddEntity(entity);
+ PUSH_EVENT("EntityChanged", entity.entityId);
+ break;
+ }
+ case AnimationCB:
+ break;
+ case Statistics:
+ break;
+ case BlockBreakAnimation:
+ break;
+ case UpdateBlockEntity:
+ break;
+ case BlockAction:
+ break;
+
+ case BlockChange: {
+ auto packet = std::static_pointer_cast<PacketBlockChange>(ptr);
+ world.ParseChunkData(packet);
+ break;
+ }
+
+ case BossBar:
+ break;
+ case ServerDifficulty:
+ break;
+ case TabCompleteCB:
+ break;
+
+ case ChatMessageCB: {
+ auto packet = std::static_pointer_cast<PacketChatMessageCB>(ptr);
+ LOG(INFO) << "Message (" << int(packet->Position) << "): " << packet->JsonData.text;
+ PUSH_EVENT("ChatMessageReceived", std::make_tuple(packet->JsonData, packet->Position));
+ break;
+ }
+
+ case MultiBlockChange: {
+ auto packet = std::static_pointer_cast<PacketMultiBlockChange>(ptr);
+ world.ParseChunkData(packet);
+ break;
+ }
+
+ case ConfirmTransactionCB: {
+ auto packet = std::static_pointer_cast<PacketConfirmTransactionCB>(ptr);
+ if (packet->WindowId == 0) {
+ try {
+ playerInventory.ConfirmTransaction(*packet);
+ }
+ catch (std::exception &e) {
+ PUSH_EVENT("Disconnected", std::string("Transaction failed"));
+ }
+ }
+ break;
+ }
+
+ case CloseWindowCB:
+ break;
+
+ case OpenWindow: {
+ auto packet = std::static_pointer_cast<PacketOpenWindow>(ptr);
+
+ LOG(INFO) << "Open new window " << packet->WindowTitle << ": " << packet->WindowId;
+ break;
+ }
+
+ case WindowItems: {
+ auto packet = std::static_pointer_cast<PacketWindowItems>(ptr);
+ if (packet->WindowId == 0) {
+ playerInventory.WindowId = 0;
+ playerInventory.slots = packet->SlotData;
+ }
+ break;
+ }
+
+ case WindowProperty:
+ break;
+
+ case SetSlot: {
+ auto packet = std::static_pointer_cast<PacketSetSlot>(ptr);
+ if (packet->WindowId == 0) {
+ playerInventory.slots[packet->Slot] = packet->SlotData;
+ }
+ break;
+ }
+
+ case SetCooldown:
+ break;
+ case PluginMessageCB:
+ break;
+ case NamedSoundEffect:
+ break;
+
+ case DisconnectPlay: {
+ auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr);
+ LOG(INFO) << "Disconnect reason: " << packet->Reason;
+ PUSH_EVENT("Disconnected", packet->Reason);
+ break;
+ }
+
+ case EntityStatus:
+ break;
+ case Explosion:
+ break;
+
+ case UnloadChunk: {
+ auto packet = std::static_pointer_cast<PacketUnloadChunk>(ptr);
+ world.ParseChunkData(packet);
+ break;
+ }
+
+ case ChangeGameState:
+ break;
+
+ case KeepAliveCB: {
+ LOG(WARNING) << "Receive KeepAlive packet in GameState handler";
+ break;
+ }
+
+ case ChunkData: {
+ auto packet = std::static_pointer_cast<PacketChunkData>(ptr);
+ world.ParseChunkData(packet);
+ break;
+ }
+
+ case Effect:
+ break;
+ case Particle:
+ break;
+
+ case JoinGame: {
+ auto packet = std::static_pointer_cast<PacketJoinGame>(ptr);
+ Entity entity;
+ entity.entityId = packet->EntityId;
+ entity.width = 0.6;
+ entity.height = 1.8;
+ world.AddEntity(entity);
+ player = world.GetEntityPtr(entity.entityId);
+
+ playerStatus.eid = packet->EntityId;
+ gameStatus.gamemode = (packet->Gamemode & 0b11111011);
+ gameStatus.dimension = packet->Dimension;
+ gameStatus.difficulty = packet->Difficulty;
+ gameStatus.maxPlayers = packet->MaxPlayers;
+ gameStatus.levelType = packet->LevelType;
+ gameStatus.reducedDebugInfo = packet->ReducedDebugInfo;
+ LOG(INFO) << "Gamemode is " << gameStatus.gamemode << ", Difficulty is " << (int)gameStatus.difficulty
+ << ", Level Type is " << gameStatus.levelType;
+ PUSH_EVENT("PlayerConnected", 0);
+ break;
+ }
+
+ case Map:
+ break;
+
+ 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: {
+ 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: {
+ 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:
+ break;
+ case OpenSignEditor:
+ break;
+ case PlayerAbilitiesCB:
+ break;
+ case CombatEvent:
+ break;
+ case PlayerListItem:
+ break;
+
+ case PlayerPositionAndLookCB: {
+ auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr);
+ if ((packet->Flags & 0x10) != 0) {
+ player->pitch += packet->Pitch;
+ }
+ else {
+ player->pitch = packet->Pitch;
+ }
+
+ if ((packet->Flags & 0x08) != 0) {
+ player->yaw += packet->Yaw;
+ }
+ else {
+ player->yaw = packet->Yaw;
+ }
+
+ if ((packet->Flags & 0x01) != 0) {
+ player->pos.x += packet->X;
+ }
+ else {
+ player->pos.x = packet->X;
+ }
+
+ if ((packet->Flags & 0x02) != 0) {
+ player->pos.y += packet->Y;
+ }
+ else {
+ player->pos.y = packet->Y;
+ }
+
+ if ((packet->Flags & 0x04) != 0) {
+ player->pos.z += packet->Z;
+ }
+ else {
+ player->pos.z = packet->Z;
+ }
+
+ PUSH_EVENT("PlayerPosChanged", player->pos);
+ LOG(INFO) << "PlayerPos is " << player->pos << "\t\tAngle: " << player->yaw << "," << player->pitch;;
+
+ if (!gameStatus.isGameStarted) {
+ LOG(INFO) << "Game is started";
+ PUSH_EVENT("RemoveLoadingScreen", 0);
+ }
+
+ gameStatus.isGameStarted = true;
+
+ auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+
+ PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetResponse));
+ PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetPerformRespawn));
+ break;
+ }
+
+ case UseBed:
+ break;
+ case UnlockRecipes:
+ break;
+
+ case DestroyEntities: {
+ auto packet = std::static_pointer_cast<PacketDestroyEntities>(ptr);
+ for (unsigned int entityId : packet->EntityIds) {
+ world.DeleteEntity(entityId);
+ }
+ break;
+ }
+
+ case RemoveEntityEffect:
+ break;
+ case ResourcePackSend:
+ break;
+ case Respawn:
+ break;
+ case EntityHeadLook:
+ break;
+ case SelectAdvancementTab:
+ break;
+ case WorldBorder:
+ break;
+ case Camera:
+ break;
+ case HeldItemChangeCB:
+ break;
+ case DisplayScoreboard:
+ break;
+ case EntityMetadata:
+ break;
+ case AttachEntity:
+ break;
+
+ 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:
+ break;
+
+ case UpdateHealth: {
+ auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr);
+ playerStatus.health = packet->Health;
+ if (playerStatus.health <= 0) {
+ LOG(INFO) << "Player is dead. Respawning...";
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+ PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetPerformRespawn));
+ }
+ break;
+ }
+
+ case ScoreboardObjective:
+ break;
+ case SetPassengers:
+ break;
+ case Teams:
+ break;
+ case UpdateScore:
+ break;
+
+ case SpawnPosition: {
+ auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr);
+ gameStatus.spawnPosition = packet->Location;
+ LOG(INFO) << "Spawn position is " << gameStatus.spawnPosition;
+ break;
+ }
+
+ case TimeUpdate: {
+ auto packet = std::static_pointer_cast<PacketTimeUpdate>(ptr);
+ timeStatus.doDaylightCycle = timeStatus.timeOfDay != packet->TimeOfDay;
+ timeStatus.worldAge = packet->WorldAge;
+ timeStatus.timeOfDay = packet->TimeOfDay;
+ timeStatus.interpolatedTimeOfDay = timeStatus.timeOfDay;
+ break;
+ }
+
+ case Title:
+ break;
+ case SoundEffect:
+ break;
+ case PlayerListHeaderAndFooter:
+ break;
+ case CollectItem:
+ break;
+
+ 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:
+ break;
+ case EntityEffect:
+ break;
+ }
+
+ while (!playerInventory.pendingTransactions.empty()) {
+ auto packet = std::make_shared<PacketClickWindow>(playerInventory.pendingTransactions.front());
+ playerInventory.pendingTransactions.pop();
+ PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packet));
+ }
}
-void GameState::HandleMovement(GameState::Direction direction, float deltaTime) {
- if (!g_IsGameStarted)
- return;
- const double playerSpeed = 43;
-
- float velocity = playerSpeed * deltaTime;
-
- double playerYaw = Entity::DecodeYaw(player->yaw);
- double playerPitch = Entity::DecodePitch(player->pitch);
-
- glm::vec3 front, right, worldUp, up;
- worldUp = glm::vec3(0.0f, 1.0f, 0.0f);
- front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
- front.y = player->isFlying ? sin(glm::radians(playerPitch)): 0;
- front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
- front = glm::normalize(front);
- right = glm::normalize(glm::cross(front, worldUp));
- up = glm::normalize(glm::cross(right, front));
-
- glm::vec3 vel = player->vel.glm();
- switch (direction) {
- case FORWARD: {
- vel += front * velocity;
- break;
- }
-
- case BACKWARD: {
- vel -= front * velocity;
- break;
- }
-
- case RIGHT: {
- vel += right * velocity;
- break;
- }
-
- case LEFT: {
- vel -= right * velocity;
- break;
- }
-
- case JUMP:
- if (player->onGround && !player->isFlying) {
- vel.y += 10;
- player->onGround = false;
- } else
+void GameState::HandleMovement(GameState::MoveType direction, float deltaTime) {
+ if (!gameStatus.isGameStarted)
+ return;
+
+ const double playerSpeed = 43;
+
+ float velocity = playerSpeed * deltaTime;
+
+ double playerYaw = Entity::DecodeYaw(player->yaw);
+ double playerPitch = Entity::DecodePitch(player->pitch);
+
+ glm::vec3 front, right, worldUp, up;
+ worldUp = glm::vec3(0.0f, 1.0f, 0.0f);
+ front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
+ front.y = player->isFlying ? sin(glm::radians(playerPitch)) : 0;
+ front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
+ front = glm::normalize(front);
+ right = glm::normalize(glm::cross(front, worldUp));
+ up = glm::normalize(glm::cross(right, front));
+
+ glm::vec3 vel = player->vel.glm();
+ switch (direction) {
+ case FORWARD: {
+ vel += front * velocity;
+ break;
+ }
+
+ case BACKWARD: {
+ vel -= front * velocity;
+ break;
+ }
+
+ case RIGHT: {
+ vel += right * velocity;
+ break;
+ }
+
+ case LEFT: {
+ vel -= right * velocity;
+ break;
+ }
+
+ case JUMP:
+ if (player->onGround && !player->isFlying) {
+ vel.y += 10;
+ player->onGround = false;
+ }
+ else
if (player->isFlying) {
vel += up * velocity;
}
- break;
- }
- player->vel = VectorF(vel.x, vel.y, vel.z);
+ break;
+ }
+ player->vel = VectorF(vel.x, vel.y, vel.z);
}
void GameState::HandleRotation(double yaw, double pitch) {
- if (!g_IsGameStarted)
- return;
- double playerYaw = Entity::DecodeYaw(player->yaw);
- double playerPitch = Entity::DecodePitch(player->pitch);
- playerYaw += yaw;
- playerPitch += pitch;
- if (playerPitch > 89.0)
- playerPitch = 89.0;
- if (playerPitch < -89.0)
- playerPitch = -89.0;
- player->yaw = Entity::EncodeYaw(playerYaw);
- player->pitch = Entity::EncodePitch(playerPitch);
+ if (!gameStatus.isGameStarted)
+ return;
+
+ double playerYaw = Entity::DecodeYaw(player->yaw);
+ double playerPitch = Entity::DecodePitch(player->pitch);
+ playerYaw += yaw;
+ playerPitch += pitch;
+ if (playerPitch > 89.0)
+ playerPitch = 89.0;
+ if (playerPitch < -89.0)
+ playerPitch = -89.0;
+ player->yaw = Entity::EncodeYaw(playerYaw);
+ player->pitch = Entity::EncodePitch(playerPitch);
}
glm::mat4 GameState::GetViewMatrix() {
- double playerYaw = Entity::DecodeYaw(player->yaw);
- double playerPitch = Entity::DecodePitch(player->pitch);
- glm::vec3 front, right, worldUp, up;
- worldUp = glm::vec3(0.0f, 1.0f, 0.0f);
- front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
- front.y = sin(glm::radians(playerPitch));
- front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
- front = glm::normalize(front);
- right = glm::normalize(glm::cross(front, worldUp));
- up = glm::normalize(glm::cross(right, front));
-
- glm::vec3 eyePos = player->pos.glm();
- eyePos += player->EyeOffset.glm();
- return glm::lookAt(eyePos, eyePos + front, up);
+ double playerYaw = Entity::DecodeYaw(player->yaw);
+ double playerPitch = Entity::DecodePitch(player->pitch);
+ glm::vec3 front, right, worldUp, up;
+ worldUp = glm::vec3(0.0f, 1.0f, 0.0f);
+ front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
+ front.y = sin(glm::radians(playerPitch));
+ front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch));
+ front = glm::normalize(front);
+ right = glm::normalize(glm::cross(front, worldUp));
+ up = glm::normalize(glm::cross(right, front));
+
+ glm::vec3 eyePos = player->pos.glm();
+ eyePos += player->EyeOffset.glm();
+ return glm::lookAt(eyePos, eyePos + front, up);
}
// TODO: it should actually be something like this:
@@ -567,20 +577,20 @@ glm::mat4 GameState::GetViewMatrix() {
// send_packet(packet_type=start_digging_packet)
// delay(time=selected_block_dig_time, action=finish_digging)
void GameState::StartDigging() {
- if (!isBlockSelected)
- return;
+ if (!selectionStatus.isBlockSelected)
+ return;
- auto packetStart = std::make_shared<PacketPlayerDigging>(0,selectedBlock,1);
- auto packet = std::static_pointer_cast<Packet>(packetStart);
- PUSH_EVENT("SendPacket",packet);
+ auto packetStart = std::make_shared<PacketPlayerDigging>(0, selectionStatus.selectedBlock, 1);
+ auto packet = std::static_pointer_cast<Packet>(packetStart);
+ PUSH_EVENT("SendPacket", packet);
- FinishDigging();
+ FinishDigging();
}
void GameState::FinishDigging() {
- auto packetFinish = std::make_shared<PacketPlayerDigging>(2,selectedBlock,1);
- auto packet = std::static_pointer_cast<Packet>(packetFinish);
- PUSH_EVENT("SendPacket",packet);
+ auto packetFinish = std::make_shared<PacketPlayerDigging>(2, selectionStatus.selectedBlock, 1);
+ auto packet = std::static_pointer_cast<Packet>(packetFinish);
+ PUSH_EVENT("SendPacket", packet);
}
// TODO: it should actually be something like this:
@@ -589,48 +599,48 @@ void GameState::FinishDigging() {
// send_packet(packet_type=start_digging_packet)
// remove_delayed_action(finish_digging)
void GameState::CancelDigging() {
- auto packetCancel = std::make_shared<PacketPlayerDigging>(1,selectedBlock,1);
- auto packet = std::static_pointer_cast<Packet>(packetCancel);
- PUSH_EVENT("SendPacket", packet);
+ auto packetCancel = std::make_shared<PacketPlayerDigging>(1, selectionStatus.selectedBlock, 1);
+ auto packet = std::static_pointer_cast<Packet>(packetCancel);
+ PUSH_EVENT("SendPacket", packet);
}
BlockFacing detectHitFace(VectorF raycastHit, Vector selectedBlock) {
- auto vec = VectorF(selectedBlock.x + .5, selectedBlock.y + .5, selectedBlock.z +.5) - raycastHit;
-
- // TODO: move these vectors to Vector.hpp
- static const auto vecUp = VectorF(0, 1, 0);
- static const auto vecRight = VectorF(1, 0, 0);
- static const auto vecForward = VectorF(0, 0, -1);
-
- const double up = vec.cosBetween(vecUp);
- const double down = -up;
- const double right = vec.cosBetween(vecRight);
- const double left = -right;
- const double forward = vec.cosBetween(vecForward);
- const double backward = -forward;
-
- const double min_cos = _min(up, down, right, left, forward, backward);
- if (min_cos == down)
- return BlockFacing::Bottom;
- else if (min_cos == up)
- return BlockFacing::Top;
- else if (min_cos == forward)
- return BlockFacing::North;
- else if (min_cos == backward)
- return BlockFacing::South;
- else if (min_cos == left)
- return BlockFacing::West;
- else return BlockFacing::East;
+ auto vec = VectorF(selectedBlock.x + .5, selectedBlock.y + .5, selectedBlock.z + .5) - raycastHit;
+
+ // TODO: move these vectors to Vector.hpp
+ static const auto vecUp = VectorF(0, 1, 0);
+ static const auto vecRight = VectorF(1, 0, 0);
+ static const auto vecForward = VectorF(0, 0, -1);
+
+ const double up = vec.cosBetween(vecUp);
+ const double down = -up;
+ const double right = vec.cosBetween(vecRight);
+ const double left = -right;
+ const double forward = vec.cosBetween(vecForward);
+ const double backward = -forward;
+
+ const double min_cos = _min(up, down, right, left, forward, backward);
+ if (min_cos == down)
+ return BlockFacing::Bottom;
+ else if (min_cos == up)
+ return BlockFacing::Top;
+ else if (min_cos == forward)
+ return BlockFacing::North;
+ else if (min_cos == backward)
+ return BlockFacing::South;
+ else if (min_cos == left)
+ return BlockFacing::West;
+ else return BlockFacing::East;
}
void GameState::PlaceBlock() {
- if (!isBlockSelected)
- return;
+ if (!selectionStatus.isBlockSelected)
+ return;
- BlockFacing face = detectHitFace(raycastHit, selectedBlock);
- auto packetPlace = std::make_shared<PacketPlayerBlockPlacement>(
- selectedBlock, (unsigned char) face, 0, 0, 0, 0);
+ BlockFacing face = detectHitFace(selectionStatus.raycastHit, selectionStatus.selectedBlock);
+ auto packetPlace = std::make_shared<PacketPlayerBlockPlacement>(
+ selectionStatus.selectedBlock, (unsigned char)face, 0, 0, 0, 0);
- auto packet = std::static_pointer_cast<Packet>(packetPlace);
- PUSH_EVENT("SendPacket", packet);
+ auto packet = std::static_pointer_cast<Packet>(packetPlace);
+ PUSH_EVENT("SendPacket", packet);
} \ No newline at end of file
diff --git a/src/GameState.hpp b/src/GameState.hpp
index e96af29..8318c8a 100644
--- a/src/GameState.hpp
+++ b/src/GameState.hpp
@@ -1,73 +1,122 @@
#pragma once
-#include <mutex>
-#include <queue>
#include <memory>
+#include <string>
+#include <vector>
+#include <mutex>
#include <glm/mat4x4.hpp>
+#include "Vector.hpp"
#include "World.hpp"
#include "Window.hpp"
class Packet;
-class NetworkClient;
class Entity;
+struct TimeStatus {
+ double interpolatedTimeOfDay = 0;
+ long long worldAge = 0;
+ long long timeOfDay = 0;
+ bool doDaylightCycle = true;
+};
+
+struct GameStatus {
+ std::string levelType;
+ Vector spawnPosition;
+ int gamemode = 0;
+ int dimension = 0;
+ unsigned char difficulty = 0;
+ unsigned char maxPlayers = 0;
+ bool isGameStarted = false;
+ bool reducedDebugInfo = false;
+};
+
+struct PlayerStatus {
+ std::string uid;
+ std::string name;
+ float flyingSpeed = 0;
+ float fovModifier = 0;
+ float health = 0;
+ int eid = 0;
+ bool invulnerable = false;
+ bool flying = false;
+ bool allowFlying = false;
+ bool creativeMode = false;
+};
+
+struct SelectionStatus {
+ VectorF raycastHit;
+ Vector selectedBlock;
+ float distanceToSelectedBlock;
+ bool isBlockSelected;
+};
+
class GameState {
-public:
+ Entity* player = nullptr;
- GameState() = default;
+ World world;
+
+ TimeStatus timeStatus;
- ~GameState() = default;
+ GameStatus gameStatus;
+
+ PlayerStatus playerStatus;
+
+ SelectionStatus selectionStatus;
+
+ Window playerInventory;
+
+ std::vector<Window> openedWindows;
+public:
void Update(float deltaTime);
void UpdatePacket(std::shared_ptr<Packet> ptr);
- enum Direction {
- FORWARD, BACKWARD, LEFT, RIGHT, JUMP
- };
void StartDigging();
+
void FinishDigging();
+
void CancelDigging();
+
void PlaceBlock();
- void HandleMovement(GameState::Direction direction, float deltaTime);
+
+ enum MoveType {
+ FORWARD, BACKWARD, LEFT, RIGHT, JUMP
+ };
+
+ void HandleMovement(GameState::MoveType direction, float deltaTime);
+
void HandleRotation(double yaw, double pitch);
+
glm::mat4 GetViewMatrix();
- Entity* player;
-
- World world;
-
- std::string g_PlayerUuid = "";
- std::string g_PlayerName = "";
- bool g_IsGameStarted = false;
- int g_PlayerEid = 0;
- int g_Gamemode = 0;
- int g_Dimension = 0;
- unsigned char g_Difficulty = 0;
- unsigned char g_MaxPlayers = 0;
- std::string g_LevelType = "";
- bool g_ReducedDebugInfo = false;
- Vector g_SpawnPosition;
- bool g_PlayerInvulnerable = false;
- bool g_PlayerFlying = false;
- bool g_PlayerAllowFlying = false;
- bool g_PlayerCreativeMode = false;
- float g_PlayerFlyingSpeed = 0;
- float g_PlayerFovModifier = 0;
- float g_PlayerHealth = 0;
-
- long long WorldAge = 0;
- long long TimeOfDay = 0;
-
- Window playerInventory;
- std::vector<Window> openedWindows;
-
- bool isBlockSelected;
- Vector selectedBlock;
- float distanceToSelectedBlock;
- VectorF raycastHit;
-
- double interpolatedTimeOfDay;
- bool doDaylightCycle = true;
+
+ inline Entity *GetPlayer() {
+ return player;
+ }
+
+ inline const World &GetWorld() const {
+ return world;
+ }
+
+ inline const TimeStatus &GetTimeStatus() const {
+ return timeStatus;
+ }
+
+ inline const GameStatus &GetGameStatus() const {
+ return gameStatus;
+ }
+
+ inline const PlayerStatus &GetPlayerStatus() const {
+ return playerStatus;
+ }
+
+ inline const SelectionStatus &GetSelectionStatus() const {
+ return selectionStatus;
+ }
+
+ inline const Window &GetInventory() const {
+ return playerInventory;
+ }
};
diff --git a/src/GlobalState.cpp b/src/GlobalState.cpp
index 9675d4b..afa1a56 100644
--- a/src/GlobalState.cpp
+++ b/src/GlobalState.cpp
@@ -9,6 +9,7 @@
//Global game variables
std::unique_ptr<NetworkClient> nc;
std::unique_ptr<GameState> gs;
+std::shared_ptr<GameState> gsReadOnly;
std::unique_ptr<Render> render;
bool isRunning;
bool isPhysRunning;
@@ -16,6 +17,7 @@ EventListener listener;
bool isMoving[5] = { 0,0,0,0,0 };
std::thread threadPhys;
State state;
+std::mutex gsCopyMutex;
void PhysExec();
@@ -194,6 +196,10 @@ void PhysExec() {
listener.HandleAllEvents();
+ gsCopyMutex.lock();
+ gsReadOnly = std::make_shared<GameState>(*gs.get());
+ gsCopyMutex.unlock();
+
timer.Update();
}
}
@@ -212,8 +218,9 @@ void GlobalState::Exec() {
render.reset();
}
-GameState *GlobalState::GetGameState() {
- return gs.get();
+std::shared_ptr<GameState> GlobalState::GetGameState() {
+ std::lock_guard<std::mutex> guard(gsCopyMutex);
+ return gsReadOnly;
}
Render *GlobalState::GetRender() {
diff --git a/src/GlobalState.hpp b/src/GlobalState.hpp
index b3b4635..bc7224f 100644
--- a/src/GlobalState.hpp
+++ b/src/GlobalState.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <memory>
+
class NetworkClient;
class GameState;
class Render;
@@ -15,7 +17,7 @@ enum class State {
};
struct GlobalState {
- static GameState *GetGameState();
+ static std::shared_ptr<GameState> GetGameState();
static Render *GetRender();
static void Exec();
static State GetState();
diff --git a/src/Render.cpp b/src/Render.cpp
index 41f2c7e..cf108e4 100644
--- a/src/Render.cpp
+++ b/src/Render.cpp
@@ -348,6 +348,9 @@ void Render::SetMouseCapture(bool IsCaptured) {
}
void Render::Update() {
+ if (world)
+ world->UpdateGameState(GlobalState::GetGameState());
+
HandleEvents();
if (HasFocus && GlobalState::GetState() == State::Playing) UpdateKeyboard();
if (isMouseCaptured) HandleMouseCapture();
@@ -382,6 +385,10 @@ void Render::RenderGui() {
ImGui::Text("FPS: %.1f (%.3fms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate);
float gameTime = DebugInfo::gameThreadTime / 100.0f;
if (world) {
+ Entity *playerPtr = world->GameStatePtr()->GetPlayer();
+ SelectionStatus selectionStatus = world->GameStatePtr()->GetSelectionStatus();
+ const World *worldPtr = &world->GameStatePtr()->GetWorld();
+
ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f / gameTime, gameTime);
ImGui::Text("Sections loaded: %d", (int) DebugInfo::totalSections);
ImGui::Text(
@@ -392,52 +399,56 @@ void Render::RenderGui() {
"Culled sections: %d",
(int) DebugInfo::renderSections - world->culledSections);
+ ImGui::Text(
+ "Rendered faces: %d",
+ (int)DebugInfo::renderFaces);
+
ImGui::Text(
"Player pos: %.1f %.1f %.1f OnGround=%d",
- world->GameStatePtr()->player->pos.x,
- world->GameStatePtr()->player->pos.y,
- world->GameStatePtr()->player->pos.z,
- world->GameStatePtr()->player->onGround);
+ playerPtr->pos.x,
+ playerPtr->pos.y,
+ playerPtr->pos.z,
+ playerPtr->onGround);
ImGui::Text(
"Player block pos: %d %d %d in %d %d %d",
- (int)(world->GameStatePtr()->player->pos.x - std::floor(world->GameStatePtr()->player->pos.x / 16.0) * 16),
- (int)(world->GameStatePtr()->player->pos.y - std::floor(world->GameStatePtr()->player->pos.y / 16.0) * 16),
- (int)(world->GameStatePtr()->player->pos.z - std::floor(world->GameStatePtr()->player->pos.z / 16.0) * 16),
+ (int)(playerPtr->pos.x - std::floor(playerPtr->pos.x / 16.0) * 16),
+ (int)(playerPtr->pos.y - std::floor(playerPtr->pos.y / 16.0) * 16),
+ (int)(playerPtr->pos.z - std::floor(playerPtr->pos.z / 16.0) * 16),
- (int)std::floor(world->GameStatePtr()->player->pos.x / 16.0),
- (int)std::floor(world->GameStatePtr()->player->pos.y / 16.0),
- (int)std::floor(world->GameStatePtr()->player->pos.z / 16.0));
+ (int)std::floor(playerPtr->pos.x / 16.0),
+ (int)std::floor(playerPtr->pos.y / 16.0),
+ (int)std::floor(playerPtr->pos.z / 16.0));
ImGui::Text(
"Player vel: %.1f %.1f %.1f",
- world->GameStatePtr()->player->vel.x,
- world->GameStatePtr()->player->vel.y,
- world->GameStatePtr()->player->vel.z);
+ playerPtr->vel.x,
+ playerPtr->vel.y,
+ playerPtr->vel.z);
ImGui::Text(
"Player health: %.1f/%.1f",
- world->GameStatePtr()->g_PlayerHealth, 20.0f);
+ world->GameStatePtr()->GetPlayerStatus().health, 20.0f);
ImGui::Text(
"Selected block: %d %d %d : %.1f",
- world->GameStatePtr()->selectedBlock.x,
- world->GameStatePtr()->selectedBlock.y,
- world->GameStatePtr()->selectedBlock.z,
- world->GameStatePtr()->distanceToSelectedBlock);
+ selectionStatus.selectedBlock.x,
+ selectionStatus.selectedBlock.y,
+ selectionStatus.selectedBlock.z,
+ selectionStatus.distanceToSelectedBlock);
ImGui::Text("Selected block light: %d (%d)",
- world->GameStatePtr()->world.GetBlockLight(world->GameStatePtr()->selectedBlock),
- world->GameStatePtr()->world.GetBlockSkyLight(world->GameStatePtr()->selectedBlock));
+ worldPtr->GetBlockLight(selectionStatus.selectedBlock),
+ worldPtr->GetBlockSkyLight(selectionStatus.selectedBlock));
ImGui::Text("Selected block id: %d:%d (%s)",
- world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock).id,
- world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock).state,
- AssetManager::GetAssetNameByBlockId(BlockId{ world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock).id,0 }).c_str());
+ worldPtr->GetBlockId(selectionStatus.selectedBlock).id,
+ worldPtr->GetBlockId(selectionStatus.selectedBlock).state,
+ AssetManager::GetAssetNameByBlockId(BlockId{ worldPtr->GetBlockId(selectionStatus.selectedBlock).id,0 }).c_str());
ImGui::Text("Selected block variant: %s:%s",
- TransformBlockIdToBlockStateName(world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock)).first.c_str(),
- TransformBlockIdToBlockStateName(world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock)).second.c_str());
+ TransformBlockIdToBlockStateName(worldPtr->GetBlockId(selectionStatus.selectedBlock)).first.c_str(),
+ TransformBlockIdToBlockStateName(worldPtr->GetBlockId(selectionStatus.selectedBlock)).second.c_str());
}
ImGui::End();
@@ -499,58 +510,58 @@ void Render::RenderGui() {
};
ImGui::SetNextWindowPosCenter();
ImGui::Begin("Inventory", 0, windowFlags);
- Window& inventory = world->GameStatePtr()->playerInventory;
+ const Window& inventory = world->GameStatePtr()->GetInventory();
//Hand and drop slots
if (renderSlot(inventory.handSlot, -1)) {
}
ImGui::SameLine();
if (ImGui::Button("Drop")) {
- inventory.MakeClick(-1, true, true);
+ //inventory.MakeClick(-1, true, true);
}
ImGui::SameLine();
ImGui::Text("Hand slot and drop mode");
ImGui::Separator();
//Crafting
if (renderSlot(inventory.slots[1], 1)) {
- inventory.MakeClick(1, true);
+ //inventory.MakeClick(1, true);
}
ImGui::SameLine();
if (renderSlot(inventory.slots[2], 2)) {
- inventory.MakeClick(2, true);
+ //inventory.MakeClick(2, true);
}
//Crafting result
ImGui::SameLine();
ImGui::Text("Result");
ImGui::SameLine();
if (renderSlot(inventory.slots[0], 0)) {
- inventory.MakeClick(0, true);
+ //inventory.MakeClick(0, true);
}
//Crafting second line
if (renderSlot(inventory.slots[3], 3)) {
- inventory.MakeClick(3, true);
+ //inventory.MakeClick(3, true);
}
ImGui::SameLine();
if (renderSlot(inventory.slots[4], 4)) {
- inventory.MakeClick(4, true);
+ //inventory.MakeClick(4, true);
}
ImGui::Separator();
//Armor and offhand
for (int i = 5; i < 8 + 1; i++) {
if (renderSlot(inventory.slots[i], i)) {
- inventory.MakeClick(i, true);
+ //inventory.MakeClick(i, true);
}
ImGui::SameLine();
}
if (renderSlot(inventory.slots[45], 45)) {
- inventory.MakeClick(45, true);
+ //inventory.MakeClick(45, true);
}
ImGui::SameLine();
ImGui::Text("Armor and offhand");
ImGui::Separator();
for (int i = 36; i < 44 + 1; i++) {
if (renderSlot(inventory.slots[i], i)) {
- inventory.MakeClick(i, true);
+ //inventory.MakeClick(i, true);
}
ImGui::SameLine();
}
@@ -559,21 +570,21 @@ void Render::RenderGui() {
ImGui::Text("Main inventory");
for (int i = 9; i < 17 + 1; i++) {
if (renderSlot(inventory.slots[i], i)) {
- inventory.MakeClick(i, true);
+ //inventory.MakeClick(i, true);
}
ImGui::SameLine();
}
ImGui::Text("");
for (int i = 18; i < 26 + 1; i++) {
if (renderSlot(inventory.slots[i], i)) {
- inventory.MakeClick(i, true);
+ //inventory.MakeClick(i, true);
}
ImGui::SameLine();
}
ImGui::Text("");
for (int i = 27; i < 35 + 1; i++) {
if (renderSlot(inventory.slots[i], i)) {
- inventory.MakeClick(i, true);
+ //inventory.MakeClick(i, true);
}
ImGui::SameLine();
}
@@ -615,7 +626,7 @@ void Render::RenderGui() {
if (fieldSensetivity != sensetivity)
sensetivity = fieldSensetivity;
- world->GameStatePtr()->player->isFlying = fieldFlight;
+ world->GameStatePtr()->GetPlayer()->isFlying = fieldFlight;
isWireframe = fieldWireframe;
timer.SetDelayLength(std::chrono::duration<double, std::milli>(1.0 / fieldTargetFps * 1000.0));
@@ -671,7 +682,7 @@ void Render::InitEvents() {
renderWorld = true;
GlobalState::SetState(State::Playing);
glClearColor(0, 0, 0, 1.0f);
- world->GameStatePtr()->player->isFlying = this->fieldFlight;
+ world->GameStatePtr()->GetPlayer()->isFlying = this->fieldFlight;
PUSH_EVENT("SetMinLightLevel", fieldBrightness);
});
diff --git a/src/RendererEntity.cpp b/src/RendererEntity.cpp
index a1c9566..25403be 100644
--- a/src/RendererEntity.cpp
+++ b/src/RendererEntity.cpp
@@ -4,9 +4,10 @@
#include <glm/gtc/type_ptr.hpp>
#include "Entity.hpp"
-#include "World.hpp"
+#include "GameState.hpp"
#include "Renderer.hpp"
#include "AssetManager.hpp"
+#include "GlobalState.hpp"
const GLfloat vertices[] = {
-0.5f, 0.5f, 0.5f,
@@ -114,18 +115,17 @@ GLuint RendererEntity::GetVao(){
return Vao;
}
-RendererEntity::RendererEntity(World *ptr, unsigned int id)
+RendererEntity::RendererEntity(unsigned int id)
{
- world = ptr;
entityId = id;
}
RendererEntity::~RendererEntity() {
}
-void RendererEntity::Render(RenderState & renderState) {
+void RendererEntity::Render(RenderState& renderState, const World *world) {
glm::mat4 model = glm::mat4(1.0);
- Entity& entity = world->GetEntity(entityId);
+ const 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));
diff --git a/src/RendererEntity.hpp b/src/RendererEntity.hpp
index e2e8bf1..346f9fb 100644
--- a/src/RendererEntity.hpp
+++ b/src/RendererEntity.hpp
@@ -2,17 +2,16 @@
#include <GL/glew.h>
-class World;
class RenderState;
+class World;
class RendererEntity {
unsigned int entityId;
- World *world;
public:
- RendererEntity(World *ptr, unsigned int id);
+ RendererEntity(unsigned int id);
~RendererEntity();
- void Render(RenderState& renderState);
+ void Render(RenderState& renderState, const World *world);
static GLuint GetVao();
};
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp
index 75859e9..e0a28a4 100644
--- a/src/RendererWorld.cpp
+++ b/src/RendererWorld.cpp
@@ -52,13 +52,13 @@ void RendererWorld::ParseQueueUpdate() {
vec.y -= 4500;
}
- parsing[id].data.section = gs->world.GetSection(vec);
- parsing[id].data.north = gs->world.GetSection(vec + Vector(0, 0, 1));
- parsing[id].data.south = gs->world.GetSection(vec + Vector(0, 0, -1));
- parsing[id].data.west = gs->world.GetSection(vec + Vector(1, 0, 0));
- parsing[id].data.east = gs->world.GetSection(vec + Vector(-1, 0, 0));
- parsing[id].data.bottom = gs->world.GetSection(vec + Vector(0, -1, 0));
- parsing[id].data.top = gs->world.GetSection(vec + Vector(0, 1, 0));
+ parsing[id].data.section = gs->GetWorld().GetSection(vec);
+ parsing[id].data.north = gs->GetWorld().GetSection(vec + Vector(0, 0, 1));
+ parsing[id].data.south = gs->GetWorld().GetSection(vec + Vector(0, 0, -1));
+ parsing[id].data.west = gs->GetWorld().GetSection(vec + Vector(1, 0, 0));
+ parsing[id].data.east = gs->GetWorld().GetSection(vec + Vector(-1, 0, 0));
+ parsing[id].data.bottom = gs->GetWorld().GetSection(vec + Vector(0, -1, 0));
+ parsing[id].data.top = gs->GetWorld().GetSection(vec + Vector(0, 1, 0));
parsing[id].parsing = true;
@@ -86,7 +86,7 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() {
if (std::find(elements.begin(), elements.end(), vec) != elements.end())
continue;
- const Section& section = gs->world.GetSection(vec);
+ const Section& section = gs->GetWorld().GetSection(vec);
bool skip = false;
@@ -112,10 +112,10 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() {
}
void RendererWorld::UpdateAllSections(VectorF playerPos) {
- Vector playerChunk(std::floor(gs->player->pos.x / 16), 0, std::floor(gs->player->pos.z / 16));
+ Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16));
std::vector<Vector> suitableChunks;
- auto chunks = gs->world.GetSectionsList();
+ auto chunks = gs->GetWorld().GetSectionsList();
for (auto& it : chunks) {
double distance = (Vector(it.x, 0, it.z) - playerChunk).GetLength();
if (distance > MaxRenderingDistance)
@@ -134,7 +134,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) {
PUSH_EVENT("DeleteSectionRender", it);
}
- playerChunk.y = std::floor(gs->player->pos.y / 16.0);
+ playerChunk.y = std::floor(gs->GetPlayer()->pos.y / 16.0);
std::sort(suitableChunks.begin(), suitableChunks.end(), [playerChunk](Vector lhs, Vector rhs) {
double leftLengthToPlayer = (playerChunk - lhs).GetLength();
double rightLengthToPlayer = (playerChunk - rhs).GetLength();
@@ -146,7 +146,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) {
}
}
-RendererWorld::RendererWorld(GameState* ptr) {
+RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
gs = ptr;
MaxRenderingDistance = 2;
numOfWorkers = _max(1, (signed int) std::thread::hardware_concurrency() - 2);
@@ -184,9 +184,9 @@ RendererWorld::RendererWorld(GameState* ptr) {
listener->RegisterHandler("EntityChanged", [this](const Event& eventData) {
auto data = eventData.get<unsigned int>();
- for (unsigned int entityId : gs->world.GetEntitiesList()) {
+ for (unsigned int entityId : gs->GetWorld().GetEntitiesList()) {
if (entityId == data) {
- entities.push_back(RendererEntity(&gs->world, entityId));
+ entities.push_back(RendererEntity(entityId));
}
}
});
@@ -196,7 +196,7 @@ RendererWorld::RendererWorld(GameState* ptr) {
if (vec == Vector())
return;
- Vector playerChunk(std::floor(gs->player->pos.x / 16), 0, std::floor(gs->player->pos.z / 16));
+ Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16));
double distanceToChunk = (Vector(vec.x, 0, vec.z) - playerChunk).GetLength();
if (MaxRenderingDistance != 1000 && distanceToChunk > MaxRenderingDistance) {
@@ -213,7 +213,7 @@ RendererWorld::RendererWorld(GameState* ptr) {
if (vec == Vector())
return;
- Vector playerChunk(std::floor(gs->player->pos.x / 16), 0, std::floor(gs->player->pos.z / 16));
+ Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16));
double distanceToChunk = (Vector(vec.x, 0, vec.z) - playerChunk).GetLength();
if (MaxRenderingDistance != 1000 && distanceToChunk > MaxRenderingDistance) {
@@ -228,7 +228,7 @@ RendererWorld::RendererWorld(GameState* ptr) {
});
listener->RegisterHandler("UpdateSectionsRender", [this](const Event&) {
- UpdateAllSections(gs->player->pos);
+ UpdateAllSections(gs->GetPlayer()->pos);
});
listener->RegisterHandler("PlayerPosChanged", [this](const Event& eventData) {
@@ -287,11 +287,11 @@ void RendererWorld::Render(RenderState & renderState) {
renderState.SetActiveVao(RendererEntity::GetVao());
for (auto& it : entities) {
- it.Render(renderState);
+ it.Render(renderState, &gs->GetWorld());
}
//Render selected block
- Vector selectedBlock = gs->selectedBlock;
+ Vector selectedBlock = gs->GetSelectionStatus().selectedBlock;
if (selectedBlock != Vector()) {
glLineWidth(2.0f);
{
@@ -309,7 +309,7 @@ void RendererWorld::Render(RenderState & renderState) {
//Render raycast hit
const bool renderHit = false;
if (renderHit) {
- VectorF hit = gs->raycastHit;
+ VectorF hit = gs->GetSelectionStatus().raycastHit;
glLineWidth(2.0f);
{
glm::mat4 model;
@@ -329,16 +329,16 @@ void RendererWorld::Render(RenderState & renderState) {
glCheckError();
//Render sky
- renderState.TimeOfDay = gs->TimeOfDay;
+ renderState.TimeOfDay = gs->GetTimeStatus().timeOfDay;
Shader *skyShader = AssetManager::GetAsset<AssetShader>("/altcraft/shaders/sky")->shader.get();
skyShader->Activate();
skyShader->SetUniform("projection", projection);
skyShader->SetUniform("view", view);
glm::mat4 model = glm::mat4(1.0);
- model = glm::translate(model, gs->player->pos.glm());
+ model = glm::translate(model, gs->GetPlayer()->pos.glm());
const float scale = 1000000.0f;
model = glm::scale(model, glm::vec3(scale, scale, scale));
- float shift = gs->interpolatedTimeOfDay / 24000.0f;
+ float shift = gs->GetTimeStatus().interpolatedTimeOfDay / 24000.0f;
if (shift < 0)
shift *= -1.0f;
model = glm::rotate(model, glm::radians(90.0f), glm::vec3(0, 1.0f, 0.0f));
@@ -355,7 +355,7 @@ void RendererWorld::Render(RenderState & renderState) {
const float moonriseLength = moonriseMax - moonriseMin;
float mixLevel = 0;
- float dayTime = gs->interpolatedTimeOfDay;
+ float dayTime = gs->GetTimeStatus().interpolatedTimeOfDay;
if (dayTime < 0)
dayTime *= -1;
while (dayTime > 24000)
@@ -386,6 +386,7 @@ void RendererWorld::Render(RenderState & renderState) {
Frustum frustum(projView);
size_t culledSections = sections.size();
+ unsigned int renderedFaces = 0;
for (auto& section : sections) {
glm::vec3 point{
section.second.GetPosition().x * 16 + 8,
@@ -400,8 +401,10 @@ void RendererWorld::Render(RenderState & renderState) {
continue;
}
section.second.Render(renderState);
+ renderedFaces += section.second.numOfFaces;
}
this->culledSections = culledSections;
+ DebugInfo::renderFaces = renderedFaces;
glCheckError();
}
@@ -445,5 +448,5 @@ void RendererWorld::Update(double timeToUpdate) {
}
GameState* RendererWorld::GameStatePtr() {
- return gs;
+ return gs.get();
}
diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp
index dbdd852..5148964 100644
--- a/src/RendererWorld.hpp
+++ b/src/RendererWorld.hpp
@@ -27,7 +27,7 @@ class RendererWorld {
};
//General
- GameState *gs;
+ std::shared_ptr<GameState> gs;
std::unique_ptr<EventListener> listener;
size_t numOfWorkers;
size_t currentWorker = 0;
@@ -50,7 +50,7 @@ class RendererWorld {
Texture *skyTexture;
RendererSky rendererSky;
public:
- RendererWorld(GameState* ptr);
+ RendererWorld(std::shared_ptr<GameState> ptr);
~RendererWorld();
void Render(RenderState& renderState);
@@ -63,4 +63,8 @@ public:
GameState *GameStatePtr();
int culledSections = 0;
+
+ inline void UpdateGameState(std::shared_ptr<GameState> newPtr) {
+ gs = newPtr;
+ }
}; \ No newline at end of file
diff --git a/src/Section.cpp b/src/Section.cpp
index c8c67dc..29a6a0e 100644
--- a/src/Section.cpp
+++ b/src/Section.cpp
@@ -45,6 +45,7 @@ Section::Section(Vector pos, unsigned char bitsPerBlock, std::vector<unsigned sh
std::copy(skyData.begin(), skyData.end(), sky);
hash = -1;
+ CalculateHash();
}
BlockId Section::GetBlockId(Vector pos) const {
@@ -109,6 +110,7 @@ unsigned char Section::GetBlockSkyLight(Vector pos) const
void Section::SetBlockId(Vector pos, BlockId value) {
overrideList[pos] = value;
hash = -1;
+ CalculateHash();
}
Vector Section::GetPosition() const {
diff --git a/src/World.cpp b/src/World.cpp
index 9a4bfd1..da0a33b 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -3,7 +3,6 @@
#include <bitset>
#include <glm/glm.hpp>
-#include "Section.hpp"
#include "Event.hpp"
#include "DebugInfo.hpp"
#include "Packet.hpp"
@@ -15,16 +14,16 @@ void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) {
for (int i = 0; i < 16; i++) {
if (bitmask[i]) {
Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ);
- Section section = ParseSection(&chunkData, chunkPosition);
+ auto section = std::make_shared<Section>(ParseSection(&chunkData, chunkPosition));
if (packet->GroundUpContinuous) {
- if (!sections.insert(std::make_pair(chunkPosition, std::make_unique<Section>(section))).second) {
+ if (!sections.insert(std::make_pair(chunkPosition, section)).second) {
LOG(ERROR) << "New chunk not created " << chunkPosition << " potential memory leak";
}
UpdateSectionsList();
} else {
- std::swap(*sections.at(chunkPosition).get(), section);
+ std::swap(sections.at(chunkPosition), section);
}
PUSH_EVENT("ChunkChanged", chunkPosition);
@@ -58,13 +57,7 @@ Section World::ParseSection(StreamInput *data, Vector position) {
std::move(blockLight), std::move(skyLight));
}
-World::~World() {
-}
-
-World::World() {
-}
-
-bool World::isPlayerCollides(double X, double Y, double Z) {
+bool World::isPlayerCollides(double X, double Y, double Z) const {
Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0));
if (sections.find(PlayerChunk) == sections.end() ||
sections.find(PlayerChunk - Vector(0, 1, 0)) == sections.end())
@@ -118,28 +111,26 @@ bool World::isPlayerCollides(double X, double Y, double Z) {
return false;
}
-std::vector<Vector> World::GetSectionsList() {
- sectionsListMutex.lock();
+std::vector<Vector> World::GetSectionsList() const {
auto vec = sectionsList;
- sectionsListMutex.unlock();
return vec;
}
static Section fallbackSection;
-const Section &World::GetSection(Vector sectionPos) {
+const Section &World::GetSection(Vector sectionPos) const {
auto result = sections.find(sectionPos);
if (result == sections.end()) {
//LOG(ERROR) << "Accessed not loaded section " << sectionPos;
return fallbackSection;
}
else {
- return *result->second.get();
+ return *result->second;
}
}
// TODO: skip liquid blocks
-RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) {
+RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) const {
const float maxLen = 5.0;
const float step = 0.01;
glm::vec3 pos = glm::vec3(0.0);
@@ -199,7 +190,6 @@ void World::UpdatePhysics(float delta) {
return { false };
};
- entitiesMutex.lock();
for (auto& it : entities) {
if (it.isFlying) {
VectorF newPos = it.pos + VectorF(it.vel.x, it.vel.y, it.vel.z) * delta;
@@ -247,49 +237,50 @@ void World::UpdatePhysics(float delta) {
it.vel = it.vel + resistForce;
}
}
- entitiesMutex.unlock();
DebugInfo::totalSections = sections.size();
}
Entity& World::GetEntity(unsigned int EntityId){
- entitiesMutex.lock();
for (auto& it : entities) {
if (it.entityId == EntityId) {
- entitiesMutex.unlock();
return it;
}
}
- entitiesMutex.unlock();
static Entity fallback;
return fallback;
}
-std::vector<unsigned int> World::GetEntitiesList() {
- entitiesMutex.lock();
+const Entity &World::GetEntity(unsigned int EntityId) const {
+ for (auto& it : entities) {
+ if (it.entityId == EntityId) {
+ return it;
+ }
+ }
+
+ static Entity fallback;
+ return fallback;
+}
+
+std::vector<unsigned int> World::GetEntitiesList() const {
std::vector<unsigned int> ret;
for (auto& it : entities) {
ret.push_back(it.entityId);
}
- entitiesMutex.unlock();
return ret;
}
void World::AddEntity(Entity entity) {
- entitiesMutex.lock();
for (auto& it : entities) {
if (it.entityId == entity.entityId) {
LOG(ERROR) << "Adding already existing entity: " << entity.entityId;
- entitiesMutex.unlock();
return;
}
}
entities.push_back(entity);
- entitiesMutex.unlock();
}
void World::DeleteEntity(unsigned int EntityId) {
- entitiesMutex.lock();
auto it = entities.begin();
for (; it != entities.end(); ++it) {
if (it->entityId == EntityId) {
@@ -298,7 +289,6 @@ void World::DeleteEntity(unsigned int EntityId) {
}
if (it != entities.end())
entities.erase(it);
- entitiesMutex.unlock();
}
void World::ParseChunkData(std::shared_ptr<PacketBlockChange> packet) {
@@ -333,7 +323,7 @@ void World::ParseChunkData(std::shared_ptr<PacketMultiBlockChange> packet) {
}
void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) {
- std::vector<std::map<Vector, std::unique_ptr<Section>>::iterator> toRemove;
+ std::vector<std::map<Vector, std::shared_ptr<Section>>::iterator> toRemove;
for (auto it = sections.begin(); it != sections.end(); ++it) {
if (it->first.x == packet->ChunkX && it->first.z == packet->ChunkZ)
toRemove.push_back(it);
@@ -346,20 +336,18 @@ void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) {
}
void World::UpdateSectionsList() {
- sectionsListMutex.lock();
sectionsList.clear();
for (auto& it : sections) {
sectionsList.push_back(it.first);
}
- sectionsListMutex.unlock();
}
-BlockId World::GetBlockId(Vector pos) {
+BlockId World::GetBlockId(Vector pos) const {
Vector sectionPos(std::floor(pos.x / 16.0),
std::floor(pos.y / 16.0),
std::floor(pos.z / 16.0));
- Section* section = GetSectionPtr(sectionPos);
+ const Section* section = GetSectionPtr(sectionPos);
return !section ? BlockId{0, 0} : section->GetBlockId(pos - (sectionPos * 16));
}
@@ -368,8 +356,9 @@ void World::SetBlockId(Vector pos, BlockId block) {
std::floor(pos.y / 16.0),
std::floor(pos.z / 16.0));
Vector blockPos = pos - (sectionPos * 16);
- Section* section = GetSectionPtr(sectionPos);
+ auto section = std::make_shared<Section>(*GetSectionPtr(sectionPos));
section->SetBlockId(blockPos, block);
+ sections[sectionPos] = section;
PUSH_EVENT("ChunkChanged",sectionPos);
if (blockPos.x == 0)
PUSH_EVENT("ChunkChangedForce", sectionPos + Vector(-1, 0, 0));
@@ -393,42 +382,38 @@ void World::SetBlockSkyLight(Vector pos, unsigned char light) {
}
-Section *World::GetSectionPtr(Vector position) {
+const Section *World::GetSectionPtr(Vector position) const {
auto it = sections.find(position);
if (it == sections.end())
return nullptr;
- return it->second.get();
+ return it->second.get();
}
Entity* World::GetEntityPtr(unsigned int EntityId) {
- entitiesMutex.lock();
for (auto& it : entities) {
if (it.entityId == EntityId) {
- entitiesMutex.unlock();
return &it;
}
}
- entitiesMutex.unlock();
return nullptr;
}
-unsigned char World::GetBlockLight(Vector pos)
-{
+unsigned char World::GetBlockLight(Vector pos) const {
Vector sectionPos(std::floor(pos.x / 16.0),
std::floor(pos.y / 16.0),
std::floor(pos.z / 16.0));
Vector blockPos = pos - (sectionPos * 16);
- Section* section = GetSectionPtr(sectionPos);
- Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0));
- Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0));
- Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0));
- Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0));
- Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1));
- Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1));
+ const Section* section = GetSectionPtr(sectionPos);
+ const Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0));
+ const Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0));
+ const Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0));
+ const Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0));
+ const Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1));
+ const Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1));
if (!section)
return 0;
@@ -436,8 +421,7 @@ unsigned char World::GetBlockLight(Vector pos)
return GetBlockLight(blockPos, section, xp, xn, yp, yn, zp, zn);
}
-unsigned char World::GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn)
-{
+unsigned char World::GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const {
static const Vector directions[] = {
Vector(0,0,0),
Vector(1,0,0),
@@ -475,21 +459,20 @@ unsigned char World::GetBlockLight(const Vector &blockPos, const Section *sectio
return value;
}
-unsigned char World::GetBlockSkyLight(Vector pos)
-{
+unsigned char World::GetBlockSkyLight(Vector pos) const {
Vector sectionPos( std::floor(pos.x / 16.0),
std::floor(pos.y / 16.0),
std::floor(pos.z / 16.0));
Vector blockPos = pos - (sectionPos * 16);
- Section* section = GetSectionPtr(sectionPos);
- Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0));
- Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0));
- Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0));
- Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0));
- Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1));
- Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1));
+ const Section* section = GetSectionPtr(sectionPos);
+ const Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0));
+ const Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0));
+ const Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0));
+ const Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0));
+ const Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1));
+ const Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1));
if (!section)
return 0;
@@ -497,8 +480,7 @@ unsigned char World::GetBlockSkyLight(Vector pos)
return GetBlockSkyLight(blockPos, section, xp, xn, yp, yn, zp, zn);
}
-unsigned char World::GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn)
-{
+unsigned char World::GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const {
static const Vector directions[] = {
Vector(0,0,0),
Vector(1,0,0),
diff --git a/src/World.hpp b/src/World.hpp
index 165e73d..6c9a615 100644
--- a/src/World.hpp
+++ b/src/World.hpp
@@ -11,8 +11,8 @@
#include "Entity.hpp"
#include "Block.hpp"
#include "Vector.hpp"
+#include "Section.hpp"
-class Section;
class PacketChunkData;
class PacketBlockChange;
class PacketMultiBlockChange;
@@ -28,24 +28,17 @@ struct RaycastResult {
class World {
int dimension = 0;
- std::map<Vector, std::unique_ptr<Section>> sections;
+ std::map<Vector, std::shared_ptr<Section>> sections;
Section ParseSection(StreamInput *data, Vector position);
std::list<Entity> entities;
- std::mutex entitiesMutex;
-
std::vector<Vector> sectionsList;
- std::mutex sectionsListMutex;
-
void UpdateSectionsList();
public:
- World();
-
- ~World();
void ParseChunkData(std::shared_ptr<PacketChunkData> packet);
@@ -55,13 +48,13 @@ public:
void ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet);
- bool isPlayerCollides(double X, double Y, double Z);
+ bool isPlayerCollides(double X, double Y, double Z) const;
- std::vector<Vector> GetSectionsList();
+ std::vector<Vector> GetSectionsList() const;
- const Section &GetSection(Vector sectionPos);
+ const Section &GetSection(Vector sectionPos) const;
- RaycastResult Raycast(glm::vec3 position, glm::vec3 direction);
+ RaycastResult Raycast(glm::vec3 position, glm::vec3 direction) const;
void UpdatePhysics(float delta);
@@ -69,13 +62,15 @@ public:
Entity* GetEntityPtr(unsigned int EntityId);
- std::vector<unsigned int> GetEntitiesList();
+ const Entity& GetEntity(unsigned int EntityId) const;
+
+ std::vector<unsigned int> GetEntitiesList() const;
void AddEntity(Entity entity);
void DeleteEntity(unsigned int EntityId);
- BlockId GetBlockId(Vector pos);
+ BlockId GetBlockId(Vector pos) const;
void SetBlockId(Vector pos, BlockId block);
@@ -83,13 +78,13 @@ public:
void SetBlockSkyLight(Vector pos, unsigned char light);
- Section *GetSectionPtr(Vector position);
+ const Section *GetSectionPtr(Vector position) const;
- unsigned char GetBlockLight(Vector pos);
+ unsigned char GetBlockLight(Vector pos) const;
- unsigned char GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn);
+ unsigned char GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const;
- unsigned char GetBlockSkyLight(Vector pos);
+ unsigned char GetBlockSkyLight(Vector pos) const;
- unsigned char GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn);
+ unsigned char GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const;
}; \ No newline at end of file