diff options
-rw-r--r-- | cwd/shaders/face.fs | 5 | ||||
-rw-r--r-- | src/Event.hpp | 7 | ||||
-rw-r--r-- | src/GameState.cpp | 5 | ||||
-rw-r--r-- | src/Network.cpp | 2 | ||||
-rw-r--r-- | src/Packet.hpp | 18 | ||||
-rw-r--r-- | src/Render.cpp | 7 | ||||
-rw-r--r-- | src/RendererWorld.cpp | 13 | ||||
-rw-r--r-- | src/Section.cpp | 176 | ||||
-rw-r--r-- | src/Section.hpp | 12 | ||||
-rw-r--r-- | src/World.cpp | 64 | ||||
-rw-r--r-- | src/World.hpp | 4 | ||||
-rw-r--r-- | src/main.cpp | 6 |
12 files changed, 214 insertions, 105 deletions
diff --git a/cwd/shaders/face.fs b/cwd/shaders/face.fs index 6e9d8f0..aa45997 100644 --- a/cwd/shaders/face.fs +++ b/cwd/shaders/face.fs @@ -45,7 +45,6 @@ void main() { vec3 hsvColor = rgb2hsv(gl_FragColor.xyz); hsvColor+=fs_in.Color; gl_FragColor = vec4(hsv2rgb(hsvColor),1); -// gl_FragColor = vec4(fs_in.Light.x / 16.0,0,fs_in.Light.y / 16.0,1); - float faceLight = clamp((fs_in.Light.x + fs_in.Light.y) / 16.0,0,16); - gl_FragColor = vec4(gl_FragColor.rgb * faceLight,gl_FragColor.a); + //float faceLight = clamp((fs_in.Light.x + fs_in.Light.y) / 15.0,0.2,1.0); + //gl_FragColor = vec4(gl_FragColor.rgb * faceLight,gl_FragColor.a); }
\ No newline at end of file diff --git a/src/Event.hpp b/src/Event.hpp index e7ebe66..b137a85 100644 --- a/src/Event.hpp +++ b/src/Event.hpp @@ -42,6 +42,7 @@ enum class EventType { NewRenderDataAvailable, BlockChange, RendererWorkerTask, + ChunkDeleted, }; struct EchoData { @@ -166,13 +167,17 @@ struct RendererWorkerTaskData { Vector Task; }; +struct ChunkDeletedData { + Vector pos; +}; + using EventData = std::variant<EchoData, ChunkChangedData, ConnectToServerData, ConnectionSuccessfullData, DisconnectData, SendPacketData, ReceivePacketData, RequestNetworkClientData, RegisterNetworkClientData, PlayerConnectedData, RemoveLoadingScreenData, ConnectionFailedData, ExitData, DisconnectedData, ConnectingData, NetworkClientExceptionData, MouseMovedData, KeyPressedData, KeyReleasedData, InitalizeSectionRenderData, CreateSectionRenderData, CreatedSectionRenderData, PlayerPosChangedData, UpdateSectionsRenderData, DeleteSectionRenderData, EntityChangedData,NewRenderDataAvailableData, - BlockChangeData, RendererWorkerTaskData>; + BlockChangeData, RendererWorkerTaskData, ChunkDeletedData>; struct Event { EventType type; diff --git a/src/GameState.cpp b/src/GameState.cpp index e536df0..b9f9b28 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -168,8 +168,11 @@ void GameState::UpdatePacket() break; case Explosion: break; - case UnloadChunk: + case UnloadChunk: { + auto packet = std::static_pointer_cast<PacketUnloadChunk>(ptr); + world.ParseChunkData(packet); break; + } case ChangeGameState: break; case KeepAliveCB: diff --git a/src/Network.cpp b/src/Network.cpp index 71de943..4606959 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -126,7 +126,7 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) { case Explosion: break; case UnloadChunk: - break; + return std::make_shared<PacketUnloadChunk>(); case ChangeGameState: break; case KeepAliveCB: diff --git a/src/Packet.hpp b/src/Packet.hpp index e3d09fd..d1d80e6 100644 --- a/src/Packet.hpp +++ b/src/Packet.hpp @@ -819,4 +819,22 @@ struct PacketTimeUpdate : Packet { long long WorldAge; long long TimeOfDay; +}; + +struct PacketUnloadChunk : Packet { + void ToStream(StreamOutput *stream) override { + + } + + void FromStream(StreamInput *stream) override { + ChunkX = stream->ReadInt(); + ChunkZ = stream->ReadInt(); + } + + int GetPacketId() override { + return PacketNamePlayCB::UnloadChunk; + } + + int ChunkX; + int ChunkZ; };
\ No newline at end of file diff --git a/src/Render.cpp b/src/Render.cpp index 56541e9..7e88068 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -49,7 +49,6 @@ void Render::InitGlew() { glFrontFace(GL_CCW); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glLineWidth(3.0); glCheckError(); } @@ -185,12 +184,12 @@ void Render::ExecuteRenderLoop() { listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) { auto data = std::get<ConnectionSuccessfullData>(eventData); - window->setTitle("Connected"); + window->setTitle("Logging in..."); }); listener.RegisterHandler(EventType::PlayerConnected, [this](EventData eventData) { auto data = std::get<PlayerConnectedData>(eventData); - window->setTitle("Joined the game"); + window->setTitle("Loading terrain..."); world = std::make_unique<RendererWorld>(data.ptr); }); @@ -212,7 +211,7 @@ void Render::ExecuteRenderLoop() { }); listener.RegisterHandler(EventType::Connecting, [this](EventData eventData) { - window->setTitle("Connecting"); + window->setTitle("Connecting to the server..."); }); while (isRunning) { diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 9bd2ccf..dd5fdb4 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -84,7 +84,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) } RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) { - MaxRenderingDistance = 10; + MaxRenderingDistance = 4; numOfWorkers = 4; PrepareRender(); @@ -176,6 +176,15 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) { UpdateAllSections(pos); }); + listener.RegisterHandler(EventType::ChunkDeleted, [this](EventData eventData) { + auto pos = std::get<ChunkDeletedData>(eventData).pos; + sectionsMutex.lock(); + auto it = sections.find(pos); + if (it != sections.end()) + sections.erase(it); + sectionsMutex.unlock(); + }); + for (int i = 0; i < numOfWorkers; i++) workers.push_back(std::thread(&RendererWorld::WorkerFunction, this, i)); @@ -251,6 +260,7 @@ void RendererWorld::Render(RenderState & renderState) { sectionsMutex.unlock(); glCheckError(); + glLineWidth(3.0); renderState.SetActiveShader(entityShader->Program); glCheckError(); projectionLoc = glGetUniformLocation(entityShader->Program, "projection"); @@ -265,6 +275,7 @@ void RendererWorld::Render(RenderState & renderState) { it.colorLoc = colorLoc; it.Render(renderState); } + glLineWidth(1.0); diff --git a/src/Section.cpp b/src/Section.cpp index 7a9f947..c9af5c6 100644 --- a/src/Section.cpp +++ b/src/Section.cpp @@ -1,8 +1,15 @@ #include "Section.hpp" +#include <bitset> + Section::~Section() { } +Section::Section(Section && other) noexcept { + using std::swap; + swap(*this, other); +} + Block &Section::GetBlock(Vector pos) { return blocks[pos.y * 256 + pos.z * 16 + pos.x]; } @@ -24,71 +31,130 @@ Section::Section(PackedSection data) return; worldPosition = data.position; - long long *longArray = reinterpret_cast<long long *>(data.blocks.data()); - for (size_t i = 0; i < data.blocks.size() / 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 < data.blocks.size(); i++) { - for (int j = 0; j < 8; j++) { - t |= (data.blocks.data()[i] & 0x01) ? 0x80 : 0x00; - t >>= 1; - data.blocks.data()[i] >>= 1; - bitPos++; - if (bitPos >= data.bitsPerBlock) { - bitPos = 0; - t >>= data.bitsPerBlock - 1; - blocks.push_back(t); - t = 0; + bool useFirst = false; + + if (useFirst) { + unsigned char *blocksData = reinterpret_cast<unsigned char*>(data.blocks.data()); + 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 < data.blocks.size() * 8; i++) { + for (int j = 0; j < 8; j++) { + t |= (blocksData[i] & 0x01) ? 0x80 : 0x00; + t >>= 1; + blocksData[i] >>= 1; + bitPos++; + if (bitPos >= data.bitsPerBlock) { + bitPos = 0; + t >>= data.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(); } - 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 = data.light[i]; - byte first = t & 0xF; - byte second = (t >> 4) & 0xF; - light.push_back(0); - light.push_back(0); - } + std::vector<byte> light; + light.reserve(4096); + for (int i = 0; i < 2048; i++) { + byte t = data.light[i]; + byte first = t & 0x0F; + byte second = t >> 4; + light.push_back(0); + light.push_back(0); + } + + std::vector<byte> sky; + if (!data.sky.empty()) { + sky.reserve(4096); + for (int i = 0; i < 2048; i++) { + byte t = data.sky[i]; + byte first = t & 0x0F; + byte second = t >> 4; + sky.push_back(first); + sky.push_back(second); + } + } + + for (int i = 0; i < 4096; i++) { + unsigned short blockId = !data.palette.empty() ? data.palette[blocks[i]] : blocks[i]; + Block block(blockId >> 4, blockId & 0xF, light[i], sky.empty() ? 0 : sky[i]); + this->blocks.push_back(block); + } + } else { + + std::vector<unsigned short> blocks; + blocks.reserve(4096); + + unsigned char individualValueMask = ((1 << data.bitsPerBlock) - 1); + + for (int blockNumber = 0; blockNumber < 4096; blockNumber++) { + int startLong = (blockNumber * data.bitsPerBlock) / 64; + int startOffset = (blockNumber * data.bitsPerBlock) % 64; + int endLong = ((blockNumber + 1) * data.bitsPerBlock - 1) / 64; + + unsigned short t; - std::vector<byte> sky; - if (!data.sky.empty()) { - sky.reserve(4096); + if (startLong == endLong) { + t = (data.blocks[startLong] >> startOffset); + } + else { + int endOffset = 64 - startOffset; + t = (data.blocks[startLong] >> startOffset | data.blocks[endLong] << endOffset); + } + + t &= individualValueMask; + + + if (t >= data.palette.size()) { + //LOG(ERROR) << "Out of palette: "<<t; + blocks.push_back(0); + } + else + blocks.push_back(data.palette.empty() ? t : data.palette[t]); + } + + + std::vector<unsigned char> light; + light.reserve(4096); for (int i = 0; i < 2048; i++) { - byte t = data.sky[i]; - byte first = t & 0xF; - byte second = (t >> 4) & 0xF; - sky.push_back(first); - sky.push_back(0xF); + unsigned char t = data.light[i]; + light.push_back(t & 0xF); + light.push_back(t >> 4 & 0xF); } - } + std::vector<unsigned char> sky; + if (!data.sky.empty()) { + sky.reserve(4096); + for (int i = 0; i < 2048; i++) { + unsigned char t = data.sky[i]; + sky.push_back(t & 0xF); + sky.push_back(t >> 4 & 0xF); + } + } - for (int i = 0; i < 4096; i++) { - unsigned short blockId = data.palette.size() > 0 ? data.palette[blocks[i]] : blocks[i]; - Block block(blockId >> 4, blockId & 0xF, light[i], sky.empty() ? 0 : sky[i]); - this->blocks.push_back(block); - } + for (int i = 0; i < 4096; i++) { + unsigned short blockId = blocks[i]; + Block block(blockId >> 4, blockId & 0xF, light[i], sky.empty() ? 0 : sky[i]); + this->blocks.push_back(block); + } + } } -Section &Section::operator=(Section other) { - std::swap(*this, other); +Section &Section::operator=(Section other) noexcept { + using std::swap; + swap(*this, other); return *this; } -void swap(Section &a, Section &b) { - using std::swap; - swap(a.blocks, b.blocks); +void swap(Section& lhs, Section& rhs) noexcept { + std::swap(lhs.blocks, rhs.blocks); + std::swap(lhs.worldPosition, rhs.worldPosition); } Section::Section(const Section &other) { @@ -118,7 +184,11 @@ PackedSection::PackedSection(Vector position, byte * dataBlocks, size_t dataBloc this->bitsPerBlock = bitsPerBlock; - blocks.assign(dataBlocks, dataBlocks + dataBlocksLength); + for (long long *t = reinterpret_cast<long long *>(dataBlocks); (byte*)t < dataBlocks + dataBlocksLength; t++) { + long long l = *t; + endswap(l); + this->blocks.push_back(l); + } light.assign(dataLight, dataLight + 2048); diff --git a/src/Section.hpp b/src/Section.hpp index c7deeb1..dfa738a 100644 --- a/src/Section.hpp +++ b/src/Section.hpp @@ -11,10 +11,6 @@ #include "Vector.hpp" #include "Utility.hpp" -const int SECTION_WIDTH = 16; -const int SECTION_LENGTH = 16; -const int SECTION_HEIGHT = 16; - struct PackedSection { Vector position; @@ -22,7 +18,7 @@ struct PackedSection { std::vector<unsigned short> palette; - std::vector<unsigned char> blocks; + std::vector<long long> blocks; std::vector<unsigned char> light; std::vector<unsigned char> sky; @@ -43,13 +39,15 @@ public: ~Section(); + Section(Section &&other) noexcept; + Block &GetBlock(Vector pos); Block GetBlock(Vector pos) const; - Section &operator=(Section other); + Section &operator=(Section other) noexcept; - friend void swap(Section &a, Section &b); + friend void swap(Section& lhs, Section& rhs) noexcept; Section(const Section &other); diff --git a/src/World.cpp b/src/World.cpp index c79d1b7..f9edbe1 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -9,13 +9,14 @@ void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) { Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ); PackedSection packedSection = ParseSection(&chunkData, chunkPosition); Section section(packedSection); - auto it = cachedSections.find(chunkPosition); - if (it == cachedSections.end()) { - cachedSections.insert(std::make_pair(chunkPosition, section)); - } - else { + + if (packet->GroundUpContinuous) { + if (!cachedSections.insert(std::make_pair(chunkPosition, section)).second) { + LOG(ERROR) << "New chunk not created " << chunkPosition << " potential memory leak"; + } + } else { using std::swap; - swap(it->second, section); + swap(cachedSections.at(chunkPosition), section); } EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ chunkPosition }); } @@ -24,6 +25,12 @@ void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) { PackedSection World::ParseSection(StreamInput *data, Vector position) { unsigned char bitsPerBlock = data->ReadUByte(); + if (bitsPerBlock < 4) + bitsPerBlock = 4; + + if (bitsPerBlock > 8) + bitsPerBlock = 13; + int paletteLength = data->ReadVarInt(); std::vector<unsigned short> palette; for (int i = 0; i < paletteLength; i++) { @@ -31,10 +38,10 @@ PackedSection World::ParseSection(StreamInput *data, Vector position) { } int dataArrayLength = data->ReadVarInt(); auto dataArray = data->ReadByteArray(dataArrayLength * 8); - auto blockLight = data->ReadByteArray(4096 / 2); + auto blockLight = data->ReadByteArray(2048); std::vector<unsigned char> skyLight; if (dimension == 0) - skyLight = data->ReadByteArray(4096 / 2); + skyLight = data->ReadByteArray(2048); return PackedSection(position, dataArray.data(), dataArray.size(), blockLight.data(), (skyLight.size() > 0 ? skyLight.data() : nullptr), bitsPerBlock, palette); } @@ -44,13 +51,7 @@ World::~World() { Block & World::GetBlock(Vector worldPosition) { - Vector sectionPos(std::floor(worldPosition.x / 16.0), std::floor(worldPosition.y / 16.0), std::floor(worldPosition.z / 16.0)); - auto sectionIt = sections.find(sectionPos); - if (sectionIt != sections.end()) { - Section section(sectionIt->second); - auto result = cachedSections.insert(std::make_pair(sectionPos, section)); - sections.erase(sectionIt); - } + Vector sectionPos(std::floor(worldPosition.x / 16.0), std::floor(worldPosition.y / 16.0), std::floor(worldPosition.z / 16.0)); auto it = cachedSections.find(sectionPos); if (it == cachedSections.end()) { static Block fallbackBlock; @@ -79,9 +80,7 @@ bool World::isPlayerCollides(double X, double Y, double Z) { }; std::vector<Vector> closestSections; for (auto &coord:closestSectionsCoordinates) { - if (sections.find(coord) != sections.end()) - closestSections.push_back(coord); - else if (cachedSections.find(coord) != cachedSections.end()) + if (cachedSections.find(coord) != cachedSections.end()) closestSections.push_back(coord); } @@ -120,9 +119,6 @@ bool World::isPlayerCollides(double X, double Y, double Z) { std::vector<Vector> World::GetSectionsList() { std::vector<Vector> sectionsList; - for (auto& it:sections) { - sectionsList.push_back(it.first); - } for (auto& it : cachedSections) { if (std::find(sectionsList.begin(), sectionsList.end(), it.first) == sectionsList.end()) sectionsList.push_back(it.first); @@ -135,14 +131,8 @@ static Section fallbackSection = Section(PackedSection()); const Section &World::GetSection(Vector sectionPos) { auto result = cachedSections.find(sectionPos); if (result == cachedSections.end()) { - auto it = sections.find(sectionPos); - if (it == sections.end()) { - LOG(ERROR) << "Accessed not loaded section " << sectionPos; - return fallbackSection; - } - Section section(it->second); - auto result = cachedSections.insert(std::make_pair(sectionPos, section)); - return result.first->second; + LOG(ERROR) << "Accessed not loaded section " << sectionPos; + return fallbackSection; } else { return result->second; } @@ -161,10 +151,6 @@ void World::UpdatePhysics(float delta) } entitiesMutex.unlock(); } -//Faces: 14 650 653 -//Models: 937.641.792 Bytes x64 -//Textures: 234.410.448 Bytes x16 -//Colors: 175.807.836 Bytes x12 Entity & World::GetEntity(unsigned int EntityId) { @@ -241,4 +227,16 @@ void World::ParseChunkData(std::shared_ptr<PacketMultiBlockChange> packet) { } for (auto& sectionPos: changedSections) EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos }); +} + +void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) { + std::vector<std::map<Vector,Section>::iterator> toRemove; + for (auto it = cachedSections.begin(); it != cachedSections.end(); ++it) { + if (it->first.x == packet->ChunkX && it->first.z == packet->ChunkZ) + toRemove.push_back(it); + } + for (auto& it : toRemove) { + EventAgregator::PushEvent(EventType::ChunkDeleted, ChunkDeletedData{ it->first }); + cachedSections.erase(it); + } }
\ No newline at end of file diff --git a/src/World.hpp b/src/World.hpp index a90d437..6ff0619 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -16,7 +16,7 @@ class World { int dimension = 0; - std::map<Vector, PackedSection> sections; + //std::map<Vector, PackedSection> sections; std::map<Vector, Section> cachedSections; PackedSection ParseSection(StreamInput *data, Vector position); @@ -38,6 +38,8 @@ public: void ParseChunkData(std::shared_ptr<PacketMultiBlockChange> packet); + void ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet); + bool isPlayerCollides(double X, double Y, double Z); std::vector<Vector> GetSectionsList(); diff --git a/src/main.cpp b/src/main.cpp index 2500fb2..0a6ad17 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,13 @@ const char *getTimeSinceProgramStart(void) { INITIALIZE_EASYLOGGINGPP + +#ifdef WIN32 +int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, + _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { +#else int main() { +#endif el::Configurations loggerConfiguration; el::Helpers::installCustomFormatSpecifier( el::CustomFormatSpecifier("%startTime", std::bind(getTimeSinceProgramStart))); |