summaryrefslogtreecommitdiffstats
path: root/old/world
diff options
context:
space:
mode:
Diffstat (limited to 'old/world')
-rw-r--r--old/world/Block.cpp17
-rw-r--r--old/world/Block.hpp15
-rw-r--r--old/world/Collision.cpp28
-rw-r--r--old/world/Collision.hpp8
-rw-r--r--old/world/GameState.cpp383
-rw-r--r--old/world/GameState.hpp71
-rw-r--r--old/world/Section.cpp147
-rw-r--r--old/world/Section.hpp51
-rw-r--r--old/world/World.cpp129
-rw-r--r--old/world/World.hpp38
10 files changed, 887 insertions, 0 deletions
diff --git a/old/world/Block.cpp b/old/world/Block.cpp
new file mode 100644
index 0000000..e88068a
--- /dev/null
+++ b/old/world/Block.cpp
@@ -0,0 +1,17 @@
+#include "Block.hpp"
+
+Block::~Block() {}
+
+Block::Block(unsigned short id, unsigned char state) : id(id), state(state) {}
+
+Block::Block() : id(0), state(0) {}
+
+bool operator<(const Block &lhs, const Block &rhs) {
+ if (lhs.id < rhs.id)
+ return true;
+ if (lhs.id == rhs.id) {
+ if (lhs.state != rhs.state)
+ return lhs.state < rhs.state;
+ }
+ return false;
+}
diff --git a/old/world/Block.hpp b/old/world/Block.hpp
new file mode 100644
index 0000000..2f823fe
--- /dev/null
+++ b/old/world/Block.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+struct Block {
+ Block();
+
+ Block(unsigned short id, unsigned char state);
+
+ ~Block();
+
+ unsigned short id : 13;
+ unsigned char state : 4;
+ //unsigned char light:4;
+};
+
+bool operator<(const Block &lhs, const Block &rhs); \ No newline at end of file
diff --git a/old/world/Collision.cpp b/old/world/Collision.cpp
new file mode 100644
index 0000000..4f2c837
--- /dev/null
+++ b/old/world/Collision.cpp
@@ -0,0 +1,28 @@
+#include "Collision.hpp"
+
+bool TestCollision(AABB first, AABB second) {
+ double firstXl = first.x;
+ double firstXr = first.x + first.w;
+
+ double firstYl = first.y;
+ double firstYr = first.y + first.h;
+
+ double firstZl = first.z;
+ double firstZr = first.z + first.l;
+
+
+ double secondXl = second.x;
+ double secondXr = second.x + second.w;
+
+ double secondYl = second.y;
+ double secondYr = second.y + second.h;
+
+ double secondZl = second.z;
+ double secondZr = second.z + second.l;
+
+ bool collidesOnX = firstXr >= secondXl && firstXl <= secondXr;
+ bool collidesOnY = firstYr >= secondYl && firstYl <= secondYr;
+ bool collidesOnZ = firstZr >= secondZl && firstZl <= secondZr;
+
+ return collidesOnX && collidesOnY && collidesOnZ;
+}
diff --git a/old/world/Collision.hpp b/old/world/Collision.hpp
new file mode 100644
index 0000000..b88fbf7
--- /dev/null
+++ b/old/world/Collision.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+struct AABB {
+ double x,y,z;
+ double w,l,h;
+};
+
+bool TestCollision(AABB first, AABB second); \ No newline at end of file
diff --git a/old/world/GameState.cpp b/old/world/GameState.cpp
new file mode 100644
index 0000000..3ccff37
--- /dev/null
+++ b/old/world/GameState.cpp
@@ -0,0 +1,383 @@
+#include "GameState.hpp"
+
+GameState::GameState(NetworkClient *Net, bool &quit) : nc(Net), isRunning(quit) {
+ Front = glm::vec3(0.0f, 0.0f, -1.0f);
+ this->SetPosition(glm::vec3(0.0f, 0.0f, 3.0f));
+ this->WorldUp = glm::vec3(0.0f, 1.0f, 0.0f);
+ this->updateCameraVectors();
+}
+
+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) {
+ nc->SendPacket(std::make_shared<PacketPlayerPositionAndLookSB>(g_PlayerX, g_PlayerY, g_PlayerZ, g_PlayerYaw,
+ g_PlayerPitch, g_OnGround));
+ timeOfPreviousSendedPacket = clock.now();
+ }
+
+ const float gravity = -9.8f;
+ g_PlayerVelocityY += gravity * deltaTime;
+
+ bool isCollides = world.isPlayerCollides(g_PlayerX, g_PlayerY + g_PlayerVelocityY * deltaTime,
+ g_PlayerZ);
+ if (!isCollides) {
+ g_PlayerY += g_PlayerVelocityY * deltaTime;
+ g_OnGround = false;
+ } else {
+ g_PlayerVelocityY = 0;
+ if (g_OnGround == false) {
+ auto updatePacket = std::make_shared<PacketPlayerPosition>(g_PlayerX, g_PlayerY, g_PlayerZ, true);
+ nc->SendPacket(updatePacket);
+ }
+ g_OnGround = true;
+ }
+
+ isCollides = world.isPlayerCollides(g_PlayerX + g_PlayerVelocityX * deltaTime, g_PlayerY,
+ g_PlayerZ + g_PlayerVelocityZ * deltaTime);
+ if (!isCollides) {
+ g_PlayerX += g_PlayerVelocityX * deltaTime;
+ g_PlayerZ += g_PlayerVelocityZ * deltaTime;
+ }
+
+ const float AirResistance = 10.0f;
+ glm::vec3 vel(g_PlayerVelocityX, 0, g_PlayerVelocityZ);
+ glm::vec3 resistForce = -vel * AirResistance * deltaTime;
+ vel += resistForce;
+ g_PlayerVelocityX = vel.x;
+ g_PlayerVelocityZ = vel.z;
+ }
+
+
+ //Packet handling
+ auto ptr = nc->ReceivePacket();
+ while (ptr != nullptr) {
+ switch ((PacketNamePlayCB) ptr->GetPacketId()) {
+ case SpawnObject:
+ break;
+ case SpawnExperienceOrb:
+ break;
+ case SpawnGlobalEntity:
+ break;
+ case SpawnMob:
+ break;
+ case SpawnPainting:
+ break;
+ case SpawnPlayer:
+ break;
+ case AnimationCB:
+ break;
+ case Statistics:
+ break;
+ case BlockBreakAnimation:
+ break;
+ case UpdateBlockEntity:
+ break;
+ case BlockAction:
+ break;
+ case BlockChange:
+ break;
+ case BossBar:
+ break;
+ case ServerDifficulty:
+ break;
+ case TabCompleteCB:
+ break;
+ case ChatMessageCB:
+ break;
+ case MultiBlockChange:
+ break;
+ case ConfirmTransactionCB:
+ break;
+ case CloseWindowCB:
+ break;
+ case OpenWindow:
+ break;
+ case WindowItems:
+ break;
+ case WindowProperty:
+ break;
+ case SetSlot:
+ 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;
+ isRunning = false;
+ break;
+ }
+ case EntityStatus:
+ break;
+ case Explosion:
+ break;
+ case UnloadChunk:
+ 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);
+ 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;
+ break;
+ }
+ case Map:
+ break;
+ case EntityRelativeMove:
+ break;
+ case EntityLookAndRelativeMove:
+ break;
+ case EntityLook:
+ break;
+ case Entity:
+ 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) {
+ g_PlayerPitch += packet->Pitch;
+ } else {
+ g_PlayerPitch = packet->Pitch;
+ };
+
+ if ((packet->Flags & 0x08) != 0) {
+ g_PlayerYaw += packet->Yaw;
+ } else {
+ g_PlayerYaw = packet->Yaw;
+ }
+
+ if ((packet->Flags & 0x01) != 0) {
+ g_PlayerX += packet->X;
+ } else {
+ g_PlayerX = packet->X;
+ }
+
+ if ((packet->Flags & 0x02) != 0) {
+ g_PlayerY += packet->Y;
+ } else {
+ g_PlayerY = packet->Y;
+ }
+
+ if ((packet->Flags & 0x04) != 0) {
+ g_PlayerZ += packet->Z;
+ } else {
+ g_PlayerZ = packet->Z;
+ }
+
+ //if (!g_IsGameStarted)
+ LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\t\tAngle: "
+ << g_PlayerYaw << "," << g_PlayerPitch;
+
+ g_IsGameStarted = true;
+
+ auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+
+ nc->SendPacket(packetResponse);
+ nc->SendPacket(packetPerformRespawn);
+ break;
+ }
+ case UseBed:
+ break;
+ case UnlockRecipes:
+ break;
+ case DestroyEntities:
+ 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:
+ 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);
+ nc->SendPacket(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.GetX() << "," << g_SpawnPosition.GetY() << ","
+ << g_SpawnPosition.GetZ();
+ break;
+ }
+ case TimeUpdate:
+ break;
+ case Title:
+ break;
+ case SoundEffect:
+ break;
+ case PlayerListHeaderAndFooter:
+ break;
+ case CollectItem:
+ break;
+ case EntityTeleport:
+ break;
+ case Advancements:
+ break;
+ case EntityProperties:
+ break;
+ case EntityEffect:
+ break;
+ }
+ ptr = nc->ReceivePacket();
+ }
+}
+
+void GameState::HandleMovement(GameState::Direction direction, float deltaTime) {
+ const float PlayerSpeed = 40.0;
+ float velocity = PlayerSpeed * deltaTime;
+ glm::vec3 vel(g_PlayerVelocityX, g_PlayerVelocityY, g_PlayerVelocityZ);
+ glm::vec3 front(cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())), 0,
+ sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())));
+ front = glm::normalize(front);
+ glm::vec3 right = glm::normalize(glm::cross(front, this->WorldUp));
+ 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 (g_OnGround) {
+ vel.y += 5;
+ g_OnGround = false;
+ }
+ break;
+ }
+ g_PlayerVelocityX = vel.x;
+ g_PlayerVelocityY = vel.y;
+ g_PlayerVelocityZ = vel.z;
+}
+
+void GameState::HandleRotation(double yaw, double pitch) {
+ this->SetYaw(Yaw() + yaw);
+ this->SetPitch(Pitch() + pitch);
+ if (this->Pitch() > 89.0f)
+ this->SetPitch(89.0f);
+ if (this->Pitch() < -89.0f)
+ this->SetPitch(-89.0f);
+ this->updateCameraVectors();
+
+ auto updatePacket = std::make_shared<PacketPlayerLook>(g_PlayerYaw, g_PlayerPitch, g_OnGround);
+ nc->SendPacket(updatePacket);
+}
+
+glm::mat4 GameState::GetViewMatrix() {
+ auto pos = this->Position();
+ pos.y+=1.62;
+ return glm::lookAt(pos, pos + this->Front, this->Up);
+}
+
+void GameState::updateCameraVectors() {
+ glm::vec3 front;
+ front.x = cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch()));
+ front.y = sin(glm::radians(this->Pitch()));
+ front.z = sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch()));
+ this->Front = glm::normalize(front);
+ this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));
+ this->Up = glm::normalize(glm::cross(this->Right, this->Front));
+}
+
+float GameState::Yaw() {
+ return g_PlayerYaw + 90;
+}
+
+float GameState::Pitch() {
+ return -g_PlayerPitch;
+}
+
+void GameState::SetYaw(float yaw) {
+ g_PlayerYaw = yaw - 90;
+}
+
+void GameState::SetPitch(float pitch) {
+ g_PlayerPitch = -pitch;
+}
+
+glm::vec3 GameState::Position() {
+ return glm::vec3(g_PlayerX, g_PlayerY, g_PlayerZ);
+}
+
+void GameState::SetPosition(glm::vec3 Position) {
+ g_PlayerX = Position.x;
+ g_PlayerY = Position.y;
+ g_PlayerZ = Position.z;
+}
diff --git a/old/world/GameState.hpp b/old/world/GameState.hpp
new file mode 100644
index 0000000..2635054
--- /dev/null
+++ b/old/world/GameState.hpp
@@ -0,0 +1,71 @@
+#pragma once
+
+#include <nlohmann/json.hpp>
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+#include "World.hpp"
+#include "../network/NetworkClient.hpp"
+#include "../Vector.hpp"
+
+class GameState {
+ NetworkClient *nc;
+public:
+ GameState(NetworkClient *NetClient, bool &quit);
+
+ void Update(float deltaTime);
+
+ //Navigation
+ enum Direction {
+ FORWARD, BACKWARD, LEFT, RIGHT, JUMP
+ };
+ void HandleMovement(GameState::Direction direction, float deltaTime);
+ void HandleRotation(double yaw, double pitch);
+ glm::mat4 GetViewMatrix();
+ void updateCameraVectors();
+
+ float Yaw();
+ float Pitch();
+ void SetYaw(float yaw);
+ void SetPitch(float pitch);
+
+ glm::vec3 Position();
+ void SetPosition(glm::vec3 Position);
+ glm::vec3 Front;
+ glm::vec3 Up;
+ glm::vec3 Right;
+ glm::vec3 WorldUp;
+
+ //Everything other
+ World world;
+ bool &isRunning;
+
+ std::string g_PlayerUuid;
+ std::string g_PlayerName;
+ bool g_IsGameStarted;
+ int g_PlayerEid;
+ int g_Gamemode;
+ int g_Dimension;
+ byte g_Difficulty;
+ byte g_MaxPlayers;
+ std::string g_LevelType;
+ bool g_ReducedDebugInfo;
+ Vector g_SpawnPosition;
+ bool g_PlayerInvulnerable;
+ bool g_PlayerFlying;
+ bool g_PlayerAllowFlying;
+ bool g_PlayerCreativeMode;
+ float g_PlayerFlyingSpeed;
+ float g_PlayerFovModifier;
+ float g_PlayerPitch;
+ float g_PlayerYaw;
+ double g_PlayerX;
+ double g_PlayerY;
+ double g_PlayerZ;
+ float g_PlayerHealth;
+
+ bool g_OnGround = true;
+ double g_PlayerVelocityX = 0;
+ double g_PlayerVelocityY = 0;
+ double g_PlayerVelocityZ = 0;
+};
diff --git a/old/world/Section.cpp b/old/world/Section.cpp
new file mode 100644
index 0000000..8b86afd
--- /dev/null
+++ b/old/world/Section.cpp
@@ -0,0 +1,147 @@
+#include "Section.hpp"
+
+
+Section::Section(Vector position, byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky,
+ byte bitsPerBlock,
+ std::vector<unsigned short> palette) {
+ worldPosition = position;
+
+ m_dataBlocksLen = dataBlocksLength;
+ m_dataBlocks = new byte[m_dataBlocksLen];
+ std::copy(dataBlocks, dataBlocks + m_dataBlocksLen, m_dataBlocks);
+
+ m_dataLight = new byte[2048];
+ std::copy(dataLight, dataLight + 2048, m_dataLight);
+
+ if (dataSky) {
+ m_dataSkyLight = new byte[2048];
+ std::copy(dataSky, dataSky + 2048, m_dataSkyLight);
+ }
+
+ m_palette = palette;
+ m_bitsPerBlock = bitsPerBlock;
+}
+
+Section::~Section() {
+ delete[] m_dataBlocks;
+ m_dataBlocksLen = 0;
+ m_dataBlocks = nullptr;
+ delete[] m_dataLight;
+ m_dataLight = nullptr;
+ delete[] m_dataSkyLight;
+ m_dataSkyLight = nullptr;
+}
+
+Block &Section::GetBlock(Vector pos) {
+ return m_blocks[pos.GetY() * 256 + pos.GetZ() * 16 + pos.GetX()];
+}
+
+double totalParsingTime = 0;
+
+void Section::Parse() {
+ if (!m_blocks.empty())
+ return;
+
+ long long *longArray = reinterpret_cast<long long *>(m_dataBlocks);
+ for (size_t i = 0; i < m_dataBlocksLen / 8; i++)
+ endswap(&longArray[i]);
+ std::vector<unsigned short> blocks;
+ blocks.reserve(4096);
+ {
+ auto begin = std::chrono::steady_clock::now();
+ int bitPos = 0;
+ unsigned short t = 0;
+ for (size_t i = 0; i < m_dataBlocksLen; i++) {
+ for (int j = 0; j < 8; j++) {
+ t |= (m_dataBlocks[i] & 0x01) ? 0x80 : 0x00;
+ t >>= 1;
+ m_dataBlocks[i] >>= 1;
+ bitPos++;
+ if (bitPos >= m_bitsPerBlock) {
+ bitPos = 0;
+ t >>= m_bitsPerBlock - 1;
+ blocks.push_back(t);
+ t = 0;
+ }
+ }
+ }
+ auto end = std::chrono::steady_clock::now();
+ std::chrono::duration<double, std::milli> time = end - begin;
+ totalParsingTime += time.count();
+ }
+ std::vector<byte> light;
+ light.reserve(4096);
+ for (int i = 0; i < 2048; i++) {
+ byte t = m_dataLight[i];
+ byte first = t & 0b11110000;
+ byte second = t >> 4;
+ light.push_back(first);
+ light.push_back(second);
+ }
+ for (int i = 0; i < 4096; i++) {
+ unsigned short blockId = m_palette.size() > 0 ? m_palette[blocks[i]] : blocks[i];
+ Block block(blockId >> 4, blockId & 0xF);
+ m_blocks.push_back(block);
+ }
+ delete[] m_dataBlocks;
+ m_dataBlocksLen = 0;
+ m_dataBlocks = nullptr;
+ delete[] m_dataLight;
+ m_dataLight = nullptr;
+ delete[] m_dataSkyLight;
+ m_dataSkyLight = nullptr;
+
+ parseWaiter.notify_all();
+}
+
+Section &Section::operator=(Section other) {
+ std::swap(*this, other);
+ return *this;
+}
+
+void swap(Section &a, Section &b) {
+ using std::swap;
+ swap(a.m_dataBlocksLen, b.m_dataBlocksLen);
+ swap(a.m_dataBlocks, b.m_dataBlocks);
+ swap(a.m_dataLight, b.m_dataLight);
+ swap(a.m_dataSkyLight, b.m_dataSkyLight);
+ swap(a.m_blocks, b.m_blocks);
+ swap(a.m_palette, b.m_palette);
+ swap(a.m_bitsPerBlock, b.m_bitsPerBlock);
+}
+
+Section::Section(const Section &other) {
+ worldPosition = other.worldPosition;
+ m_dataBlocksLen = other.m_dataBlocksLen;
+ if (other.m_blocks.empty()) {
+ m_dataBlocks = new byte[m_dataBlocksLen];
+ std::copy(other.m_dataBlocks, other.m_dataBlocks + m_dataBlocksLen, m_dataBlocks);
+
+ m_dataLight = new byte[2048];
+ std::copy(other.m_dataLight, other.m_dataLight + 2048, m_dataLight);
+
+ if (other.m_dataSkyLight) {
+ m_dataSkyLight = new byte[2048];
+ std::copy(other.m_dataSkyLight, other.m_dataSkyLight + 2048, m_dataSkyLight);
+ }
+ } else {
+ std::copy(other.m_blocks.begin(), other.m_blocks.end(), std::back_inserter(m_blocks));
+ }
+
+ m_palette = other.m_palette;
+ m_bitsPerBlock = other.m_bitsPerBlock;
+}
+
+Vector Section::GetPosition() {
+ return worldPosition;
+}
+
+size_t Section::GetHash() {
+ if (m_blocks.empty()) return 0;
+
+ unsigned char *from = reinterpret_cast<unsigned char *>(m_blocks.data());
+ size_t length = m_blocks.size() * sizeof(Block);
+
+ std::string str(from, from + length);
+ return std::hash<std::string>{}(str);
+} \ No newline at end of file
diff --git a/old/world/Section.hpp b/old/world/Section.hpp
new file mode 100644
index 0000000..e98e231
--- /dev/null
+++ b/old/world/Section.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <vector>
+#include <map>
+#include <condition_variable>
+#include <functional>
+
+#include <easylogging++.h>
+
+#include "Block.hpp"
+#include "../Vector.hpp"
+#include "../Utility.hpp"
+
+const int SECTION_WIDTH = 16;
+const int SECTION_LENGTH = 16;
+const int SECTION_HEIGHT = 16;
+
+class Section {
+ std::vector<unsigned short> m_palette;
+ byte *m_dataBlocks = nullptr;
+ size_t m_dataBlocksLen;
+ byte *m_dataLight = nullptr;
+ byte *m_dataSkyLight = nullptr;
+ byte m_bitsPerBlock = 0;
+ std::vector<Block> m_blocks;
+ std::condition_variable parseWaiter;
+
+ Section();
+
+ Vector worldPosition;
+
+public:
+ void Parse();
+
+ Section(Vector position, byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock,
+ std::vector<unsigned short> palette);
+
+ ~Section();
+
+ Block &GetBlock(Vector pos);
+
+ Section &operator=(Section other);
+
+ friend void swap(Section &a, Section &b);
+
+ Section(const Section &other);
+
+ Vector GetPosition();
+
+ size_t GetHash();
+}; \ No newline at end of file
diff --git a/old/world/World.cpp b/old/world/World.cpp
new file mode 100644
index 0000000..487f4ba
--- /dev/null
+++ b/old/world/World.cpp
@@ -0,0 +1,129 @@
+#include "World.hpp"
+
+void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) {
+ StreamBuffer chunkData(packet->Data.data(), packet->Data.size());
+ std::bitset<16> bitmask(packet->PrimaryBitMask);
+ for (int i = 0; i < 16; i++) {
+ if (bitmask[i]) {
+ Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ);
+ Section section = ParseSection(&chunkData, chunkPosition);
+ section.Parse();
+ sectionMutexes[chunkPosition].lock();
+ auto it = sections.find(chunkPosition);
+ if (it == sections.end()) {
+ sections.insert(std::make_pair(chunkPosition, section));
+ } else {
+ using std::swap;
+ swap(it->second, section);
+ }
+ sectionMutexes[chunkPosition].unlock();
+ }
+ }
+}
+
+Section World::ParseSection(StreamInput *data, Vector position) {
+ unsigned char bitsPerBlock = data->ReadUByte();
+ int paletteLength = data->ReadVarInt();
+ std::vector<unsigned short> palette;
+ for (int i = 0; i < paletteLength; i++) {
+ palette.push_back(data->ReadVarInt());
+ }
+ int dataArrayLength = data->ReadVarInt();
+ auto dataArray = data->ReadByteArray(dataArrayLength * 8);
+ auto blockLight = data->ReadByteArray(4096 / 2);
+ std::vector<unsigned char> skyLight;
+ if (dimension == 0)
+ skyLight = data->ReadByteArray(4096 / 2);
+ return Section(position, dataArray.data(), dataArray.size(), blockLight.data(),
+ (skyLight.size() > 0 ? skyLight.data() : nullptr), bitsPerBlock, palette);
+}
+
+World::~World() {
+}
+
+World::World() {
+
+}
+
+bool World::isPlayerCollides(double X, double Y, double Z) {
+ Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0));
+ std::vector<Vector> closestSectionsCoordinates = {
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX() + 1, PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX() - 1, PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY() + 1, PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY() - 1, PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ() + 1),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ() - 1),
+ };
+ std::vector<std::map<Vector, Section>::iterator> closestSections;
+ for (auto &coord:closestSectionsCoordinates) {
+ auto it = sections.find(coord);
+ if (it != sections.end())
+ closestSections.push_back(it);
+ }
+ if (closestSections.empty())
+ return false;
+
+ for (auto &it:closestSections) {
+
+ const double PlayerWidth = 0.6;
+ const double PlayerHeight = 1.82;
+ const double PlayerLength = 0.6;
+
+ AABB playerColl;
+ playerColl.x = X - PlayerWidth / 2.0;
+ playerColl.w = PlayerWidth;
+ playerColl.y = Y;
+ playerColl.h = PlayerHeight;
+ playerColl.z = Z - PlayerLength / 2.0;
+ playerColl.l = PlayerLength;
+
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ for (int z = 0; z < 16; z++) {
+ Block block = it->second.GetBlock(Vector(x, y, z));
+ if (block.id == 0 || block.id == 31)
+ continue;
+ AABB blockColl{(x + it->first.GetX() * 16.0),
+ (y + it->first.GetY() * 16.0),
+ (z + it->first.GetZ() * 16.0), 1, 1, 1};
+ if (TestCollision(playerColl, blockColl))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+Block &World::GetBlock(Vector pos) {
+ Vector sectionPos (floor(pos.GetX() / 16.0f),floor(pos.GetY() / 16.0f),floor(pos.GetZ()/16.0f));
+ Vector inSectionPos = pos - (sectionPos * 16);
+ if (sections.find(sectionPos)==sections.end()){
+ static Block block(0,0);
+ return block;
+ }
+ sectionMutexes[sectionPos].lock();
+ Block& block = sections.find(sectionPos)->second.GetBlock(inSectionPos);
+ sectionMutexes[sectionPos].unlock();
+ return block;
+}
+
+std::vector<Vector> World::GetSectionsList() {
+ std::vector<Vector> sectionsList;
+ for (auto& it:sections) {
+ sectionsList.push_back(it.first);
+ }
+ return sectionsList;
+}
+
+Section &World::GetSection(Vector sectionPos) {
+ sectionMutexes[sectionPos].lock();
+ sectionMutexes[sectionPos].unlock();
+ return sections.find(sectionPos)->second;
+}
+
+glm::vec3 World::Raycast(glm::vec3 position, glm::vec3 direction, float maxLength, float minPrecision) {
+ return glm::vec3(position * direction / maxLength * minPrecision);
+}
diff --git a/old/world/World.hpp b/old/world/World.hpp
new file mode 100644
index 0000000..05fe57d
--- /dev/null
+++ b/old/world/World.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <map>
+#include <bitset>
+
+#include <easylogging++.h>
+
+#include <old/world/Block.hpp>
+#include <old/world/Section.hpp>
+#include <old/network/Packet.hpp>
+#include <old/world/Collision.hpp>
+
+class World {
+ std::map<Vector, Section> sections;
+ std::map<Vector, std::mutex> sectionMutexes;
+ int dimension = 0;
+
+ Section ParseSection(StreamInput *data, Vector position);
+
+ World(const World &other);
+ World &operator=(const World &other);
+public:
+ World();
+
+ ~World();
+
+ void ParseChunkData(std::shared_ptr<PacketChunkData> packet);
+
+ bool isPlayerCollides(double X, double Y, double Z);
+
+ Block &GetBlock(Vector pos);
+
+ std::vector<Vector> GetSectionsList();
+
+ Section &GetSection(Vector sectionPos);
+
+ glm::vec3 Raycast(glm::vec3 position, glm::vec3 direction, float maxLength = 1000.0f, float minPrecision = 0.01f);
+}; \ No newline at end of file