diff options
Diffstat (limited to 'src/world')
-rw-r--r-- | src/world/Collision.cpp | 28 | ||||
-rw-r--r-- | src/world/Collision.hpp | 8 | ||||
-rw-r--r-- | src/world/Section.cpp | 31 | ||||
-rw-r--r-- | src/world/Section.hpp | 37 | ||||
-rw-r--r-- | src/world/World.cpp | 151 | ||||
-rw-r--r-- | src/world/World.hpp | 27 |
6 files changed, 161 insertions, 121 deletions
diff --git a/src/world/Collision.cpp b/src/world/Collision.cpp new file mode 100644 index 0000000..4f2c837 --- /dev/null +++ b/src/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/src/world/Collision.hpp b/src/world/Collision.hpp new file mode 100644 index 0000000..b88fbf7 --- /dev/null +++ b/src/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/src/world/Section.cpp b/src/world/Section.cpp index 63c7f97..8f94ad7 100644 --- a/src/world/Section.cpp +++ b/src/world/Section.cpp @@ -1,7 +1,8 @@ #include "Section.hpp" + Section::Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock, - std::vector<unsigned short> palette) { + std::vector<unsigned short> palette) { m_dataBlocksLen = dataBlocksLength; m_dataBlocks = new byte[m_dataBlocksLen]; std::copy(dataBlocks, dataBlocks + m_dataBlocksLen, m_dataBlocks); @@ -93,30 +94,22 @@ void Section::Parse() { m_dataSkyLight = nullptr; parseWaiter.notify_all(); - /*static std::map<Block,int> totalBlocks; - for (int x=0;x<16;x++) - for (int y=0;y<16;y++) - for (int z=0;z<16;z++) - totalBlocks[GetBlock(Vector(x,y,z))]++; - LOG(ERROR)<<"Logging chunk"; - for (auto& it:totalBlocks){ - LOG(WARNING)<<it.first.id<<":"<<(int)it.first.state<<" = "<<it.second; - }*/ } Section &Section::operator=(Section other) { - other.swap(*this); + std::swap(*this,other); return *this; } -void Section::swap(Section &other) { - std::swap(other.m_dataBlocksLen, m_dataBlocksLen); - std::swap(other.m_dataBlocks, m_dataBlocks); - std::swap(other.m_dataLight, m_dataLight); - std::swap(other.m_dataSkyLight, m_dataSkyLight); - std::swap(other.m_blocks, m_blocks); - std::swap(other.m_palette, m_palette); - std::swap(other.m_bitsPerBlock, m_bitsPerBlock); +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) { diff --git a/src/world/Section.hpp b/src/world/Section.hpp index 36fc91a..657fc13 100644 --- a/src/world/Section.hpp +++ b/src/world/Section.hpp @@ -5,38 +5,39 @@ #include <condition_variable> #include <easylogging++.h> #include "Block.hpp" -#include "../packet/Field.hpp" +#include "../utility/Vector.hpp" +#include "../utility/utility.h" 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; + 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(); + Section(); public: - void Parse(); + void Parse(); - Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock, - std::vector<unsigned short> palette); + Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock, + std::vector<unsigned short> palette); - ~Section(); + ~Section(); - Block &GetBlock(Vector pos); + Block &GetBlock(Vector pos); - Section &operator=(Section other); + Section &operator=(Section other); - void swap(Section &other); + friend void swap(Section &a, Section& b); - Section(const Section &other); + Section(const Section &other); };
\ No newline at end of file diff --git a/src/world/World.cpp b/src/world/World.cpp index 2220627..394598b 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -1,84 +1,39 @@ #include "World.hpp" -void World::ParseChunkData(Packet packet) { - int chunkX = packet.GetField(0).GetInt(); - int chunkZ = packet.GetField(1).GetInt(); - bool isGroundContinuous = packet.GetField(2).GetBool(); - std::bitset<16> bitmask(packet.GetField(3).GetVarInt()); - int entities = packet.GetField(5).GetVarInt(); - - size_t dataLen = packet.GetField(5).GetLength(); - byte *content = new byte[dataLen]; - byte *contentOrigPtr = content; - packet.GetField(5).CopyToBuff(content); - - if (isGroundContinuous) - dataLen -= 256; - - byte *biomes = content + packet.GetField(5).GetLength() - 256; +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]) { - size_t len = 0; - Vector chunkPosition = Vector(chunkX, i, chunkZ); - if (!m_sections.insert(std::make_pair(chunkPosition, ParseSection(content, len))).second) - LOG(ERROR) << "Chunk not created: " << chunkPosition; - auto sectionIter = m_sections.find(chunkPosition); - if (sectionIter == m_sections.end()) - LOG(ERROR) << "Created chunk not found: " << chunkPosition; - else - sectionIter->second.Parse(); - content += len; + Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ); + Section section = ParseSection(&chunkData); + auto it = sections.find(chunkPosition); + if (it == sections.end()) { + sections.insert(std::make_pair(chunkPosition, section)); + } else { + using std::swap; + swap(it->second, section); + } + sections.find(chunkPosition)->second.Parse(); } } - delete[] contentOrigPtr; } -Section World::ParseSection(byte *data, size_t &dataLen) { - dataLen = 0; - - Field fBitsPerBlock = FieldParser::Parse(UnsignedByte, data); - byte bitsPerBlock = fBitsPerBlock.GetUByte(); - data += fBitsPerBlock.GetLength(); - dataLen += fBitsPerBlock.GetLength(); - - Field fPaletteLength = FieldParser::Parse(VarIntType, data); - int paletteLength = fPaletteLength.GetVarInt(); - data += fPaletteLength.GetLength(); - dataLen += fPaletteLength.GetLength(); - +Section World::ParseSection(StreamInput *data) { + unsigned char bitsPerBlock = data->ReadUByte(); + int paletteLength = data->ReadVarInt(); std::vector<unsigned short> palette; - if (paletteLength > 0) { - for (unsigned char i = 0; i < paletteLength; i++) { - endswap(&i); - Field f = FieldParser::Parse(VarIntType, data); - data += f.GetLength(); - dataLen += f.GetLength(); - palette.push_back(f.GetVarInt()); - endswap(&i); - } + for (int i = 0; i < paletteLength; i++) { + palette.push_back(data->ReadVarInt()); } - - Field fDataLength = FieldParser::Parse(VarIntType, data); - data += fDataLength.GetLength(); - dataLen += fDataLength.GetLength(); - - int dataLength = fDataLength.GetVarInt(); - size_t dataSize = dataLength * 8; - dataLen += dataSize; - byte *dataBlocks = data; - - data += 2048; - dataLen += 2048; - byte *dataLight = data; - - byte *dataSky = nullptr; - if (m_dimension == 0) { - data += 2048; - dataLen += 2048; - dataSky = data; - } - - return Section(dataBlocks, dataSize, dataLight, dataSky, bitsPerBlock, palette); + 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(dataArray.data(), dataArray.size(), blockLight.data(), + (skyLight.size() > 0 ? skyLight.data() : nullptr), bitsPerBlock, palette); } World::~World() { @@ -86,4 +41,56 @@ World::~World() { World::World() { -}
\ No newline at end of file +} + +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.5; + playerColl.w = PlayerWidth; + playerColl.y = Y - 0.5f; + playerColl.h = PlayerHeight; + playerColl.z = Z - PlayerLength / 2 - 0.5; + 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.5, + (y + it->first.GetY() * 16) - 0.5, + (z + it->first.GetZ() * 16) - 0.5, 1, 1, 1}; + if (TestCollision(playerColl, blockColl)) + return true; + } + } + } + } + return false; +} diff --git a/src/world/World.hpp b/src/world/World.hpp index b33499c..e315baf 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -8,27 +8,30 @@ #include <bitset> #include <easylogging++.h> #include "Block.hpp" -#include "../packet/Packet.hpp" #include "Section.hpp" +#include "../network/Packet.hpp" +#include "Collision.hpp" class World { - //utility vars - World(const World &other); + //utility vars + World(const World &other); - World &operator=(const World &other); + World &operator=(const World &other); - //game vars - int m_dimension = 0; + //game vars + int dimension = 0; - //game methods - Section ParseSection(byte *data, size_t &dataLen); + //game methods + Section ParseSection(StreamInput *data); public: - World(); + World(); - ~World(); + ~World(); - void ParseChunkData(Packet packet); + void ParseChunkData(std::shared_ptr<PacketChunkData> packet); - std::map<Vector, Section> m_sections; + std::map<Vector, Section> sections; + + bool isPlayerCollides(double X, double Y, double Z); };
\ No newline at end of file |