diff options
Diffstat (limited to '')
-rw-r--r-- | Block.cpp | 29 | ||||
-rw-r--r-- | Block.hpp | 27 | ||||
-rw-r--r-- | CMakeLists.txt | 21 | ||||
-rw-r--r-- | Display.cpp | 268 | ||||
-rw-r--r-- | Display.hpp | 35 | ||||
-rw-r--r-- | Field.cpp | 12 | ||||
-rw-r--r-- | Field.hpp | 9 | ||||
-rw-r--r-- | FieldParser.cpp | 6 | ||||
-rw-r--r-- | Game.cpp | 44 | ||||
-rw-r--r-- | Game.hpp | 8 | ||||
-rw-r--r-- | Nbt.hpp | 516 | ||||
-rw-r--r-- | Network.cpp | 24 | ||||
-rw-r--r-- | Network.hpp | 2 | ||||
-rw-r--r-- | NetworkClient.cpp | 36 | ||||
-rw-r--r-- | NetworkClient.hpp | 9 | ||||
-rw-r--r-- | Packet.cpp | 8 | ||||
-rw-r--r-- | PacketParser.cpp | 9 | ||||
-rw-r--r-- | Section.cpp | 126 | ||||
-rw-r--r-- | Section.hpp | 38 | ||||
-rw-r--r-- | World.cpp | 218 | ||||
-rw-r--r-- | World.hpp | 39 | ||||
-rw-r--r-- | json.hpp (renamed from json.h) | 0 | ||||
-rw-r--r-- | main.cpp | 9 | ||||
-rw-r--r-- | utility.cpp | 3 | ||||
-rw-r--r-- | utility.h | 12 |
25 files changed, 1143 insertions, 365 deletions
@@ -1,29 +1,10 @@ #include "Block.hpp" +Block::~Block() {} -Block::Block(int id, unsigned char state, unsigned char light, PositionI position) : m_id(id), m_position(position), - m_light(light), m_state(state) { +Block::Block(unsigned short idAndState, unsigned char light) : id(idAndState >> 4), state(idAndState & 0x0F), + light(light) {} -} +Block::Block(unsigned short id, unsigned char state, unsigned char light) : id(id), state(state), light(light) {} -Block::~Block() { - -} - -int Block::GetId() { - return m_id; -} - -int Block::GetState() { - return m_state; -} - -int Block::GetLight() { - return m_light; -} - -Block::Block(unsigned short idAndState, unsigned char light) { - m_id = idAndState >> 4; - m_state = idAndState & 0b00001111; - m_light = light; -} +Block::Block() : id(0), state(0), light(0) {} @@ -1,26 +1,15 @@ #pragma once -#include "PositionI.hpp" - -class Block { -public: - Block(int id = 0, unsigned char state = 0, unsigned char light = 15, PositionI position = PositionI()); - +struct Block { Block(unsigned short idAndState, unsigned char light); - ~Block(); - - int GetId(); - - int GetState(); + Block(unsigned short id, unsigned char state, unsigned char light); - int GetLight(); + Block(); -private: - int m_id; - unsigned char m_light; - PositionI m_position; - unsigned char m_state; - //NbtTree* nbt; -}; + ~Block(); + unsigned short id:13; + unsigned char state:4; + unsigned char light:4; +};
\ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 31b7a14..65d0205 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,10 @@ cmake_minimum_required(VERSION 3.5) project(AltCraft) set(CMAKE_CXX_STANDARD 14) -#set(CMAKE_CXX_FLAGS "-fsanitize=address") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors -w -Werror -g") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -pg") + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules) #Setup SFML @@ -12,10 +15,18 @@ if (NOT SFML_FOUND) message(ERROR "SFML not found!") endif () +#Setup Zlib +find_package(ZLIB REQUIRED) +include_directories(${ZLIB_INCLUDE_DIR}) +if (NOT ZLIB_FOUND) + message(ERROR "Zlib not found!") +endif () + + set(SOURCE_FILES main.cpp Field.hpp utility.cpp Packet.hpp FieldParser.hpp Network.hpp Network.cpp NetworkClient.cpp - NetworkClient.hpp json.h PacketBuilder.cpp PacketBuilder.hpp Packet.cpp FieldParser.cpp Field.cpp + NetworkClient.hpp json.hpp PacketBuilder.cpp PacketBuilder.hpp Packet.cpp FieldParser.cpp Field.cpp PacketParser.cpp PacketParser.hpp PositionF.cpp PositionF.hpp PositionI.cpp PositionI.hpp Game.cpp - Game.hpp World.cpp World.hpp Block.cpp Block.hpp Display.cpp Display.hpp) -#file(GLOB SOURCE_FILES "*.h" "*.hpp" "*.cpp") + Game.hpp World.cpp World.hpp Block.cpp Block.hpp Display.cpp Display.hpp Section.cpp Section.hpp Nbt.hpp) + add_executable(AltCraft ${SOURCE_FILES}) -target_link_libraries(AltCraft ${SFML_LIBRARIES})
\ No newline at end of file +target_link_libraries(AltCraft ${SFML_LIBRARIES} ${ZLIB_LIBRARIES} pthread)
\ No newline at end of file diff --git a/Display.cpp b/Display.cpp index fe9abf3..ef7dd9a 100644 --- a/Display.cpp +++ b/Display.cpp @@ -1,23 +1,142 @@ #include <iostream> #include "Display.hpp" -Display::Display(int w, int h, std::string title) { +Display::Display(int w, int h, std::string title, World *world, std::condition_variable &gameStartWaiter) + : gameStartWaiter(gameStartWaiter) { window = new sf::RenderWindow(sf::VideoMode(w, h), title); + window->clear(sf::Color::Black); + window->display(); + this->world = world; } Display::~Display() { delete window; } -void Display::SetWorld(World *wrd) { - world = wrd; +void Display::Update() { + pollEvents(); + + { + std::chrono::steady_clock clock; + static auto timeOfPreviousUpdate(clock.now()); + std::chrono::duration<double> delta = clock.now() - timeOfPreviousUpdate; + if (delta.count() > 0.5) { + window->setTitle( + std::string("Render layer: " + std::to_string(renderLayer) + "\t" + + //" BlockID: " + std::to_string(currentId) + + " Mouse pos" + std::to_string(mousePos.x) + " " + std::to_string(mousePos.y) + + " FPS: " + std::to_string(1 / frameTime))); + timeOfPreviousUpdate = clock.now(); + } + } + + window->clear(sf::Color::Black); + if (isGameStarted) + renderWorld(); + window->display(); } -void Display::Update() { +void Display::renderWorld() { + //currentId = 0; + for (auto sectionIt = world->m_sections.begin(); sectionIt != world->m_sections.end(); ++sectionIt) { + if (sectionIt->first.GetY() != renderLayer / 16) + continue; + Section §ion = sectionIt->second; + sf::Texture &texture = GetSectionTexture(sectionIt->first); + sf::Sprite sprite(texture); + sprite.setPosition(sectionIt->first.GetX() * 16, sectionIt->first.GetZ() * 16); + window->draw(sprite); + // sf::Texture &texture = GetSectionTexture(sectionIt->first); + /*for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + int y = renderLayer - sectionIt->first.GetY() * 16; + int absoluteX = sectionIt->first.GetX() * 16 + x; + int absoluteZ = sectionIt->first.GetZ() * 16 + z; + + + Block &block = section.GetBlock(PositionI(x, z, y)); + sf::RectangleShape shape(sf::Vector2f(1, 1)); + + shape.setPosition(absoluteX, absoluteZ); + shape.setFillColor(sf::Color::Magenta); + if (mousePos.x > shape.getPosition().x && mousePos.y > shape.getPosition().y) { + if (mousePos.x < shape.getPosition().x + 1 && mousePos.y < shape.getPosition().y + 1) { + currentId = block.id; + if (isClicked) { + std::cout << "Clicked it " << absoluteX << " " << absoluteZ << std::endl; + isClicked = false; + } + } + } + switch (block.id) { + case 0: + shape.setFillColor(sf::Color::Transparent); + break; + case 7: + shape.setFillColor(sf::Color::Yellow); + break; + case 1: + shape.setFillColor(sf::Color::White); + break; + case 11: + shape.setFillColor(sf::Color::Red); + break; + case 10: + shape.setFillColor(sf::Color::Red); + break; + case 3: + shape.setFillColor(sf::Color(139, 69, 69)); + break; + case 13: + shape.setFillColor(sf::Color(220, 220, 220)); + break; + case 9: + shape.setFillColor(sf::Color::Blue); + break; + case 8: + shape.setFillColor(sf::Color::Blue); + break; + case 2: + shape.setFillColor(sf::Color::Green); + break; + default: + //std::cout << "Unknown id is " << sectionIt.second.GetId() << std::endl; + break; + } + sf::Color darkness(0, 0, 0, ((15 - block.light) / 15.0f) * 255); + shape.setFillColor(shape.getFillColor() + darkness); + window->draw(shape); + } + } + sf::Vector2f p1 = sf::Vector2f(sectionIt->first.GetX() * 16, sectionIt->first.GetZ() * 16); + sf::Vector2f p2 = sf::Vector2f(sectionIt->first.GetX() * 16 + 16, sectionIt->first.GetZ() * 16); + sf::Vector2f p3 = sf::Vector2f(sectionIt->first.GetX() * 16 + 16, sectionIt->first.GetZ() * 16 + 16); + sf::Vector2f p4 = sf::Vector2f(sectionIt->first.GetX() * 16, sectionIt->first.GetZ() * 16 + 16); + sf::Vertex line1[] = { + sf::Vertex(p1), + sf::Vertex(p2), + }; + sf::Vertex line2[] = { + sf::Vertex(p2), + sf::Vertex(p3), + }; + sf::Vertex line3[] = { + sf::Vertex(p3), + sf::Vertex(p4), + }; + sf::Vertex line4[] = { + sf::Vertex(p4), + sf::Vertex(p1), + }; + window->draw(line1, 2, sf::Lines); + window->draw(line2, 2, sf::Lines); + window->draw(line3, 2, sf::Lines); + window->draw(line4, 2, sf::Lines);*/ + } +} + +void Display::pollEvents() { sf::Event e; - static sf::Vector2f mousePos; - static int renderLayer = 0, currentId = 0; - int coeff = 10; while (window->pollEvent(e)) { switch (e.type) { case sf::Event::Closed: @@ -28,9 +147,11 @@ void Display::Update() { break; case sf::Event::KeyPressed: if (e.key.code == sf::Keyboard::Z) { - renderLayer--; + if (renderLayer > 0) + renderLayer--; } else if (e.key.code == sf::Keyboard::X) { - renderLayer++; + if (renderLayer < 256) + renderLayer++; } else if (e.key.code == sf::Keyboard::Up) { sf::View view = window->getView(); view.move(0, -coeff); @@ -58,68 +179,107 @@ void Display::Update() { //view.setSize(view.getSize().x - coeff2, view.getSize().y - coeff2); window->setView(view); } + break; + case sf::Event::MouseButtonPressed: + isClicked = true; + break; } } - window->setTitle( - std::string("Render layer: " + - std::to_string(renderLayer) + "\t" + " BlockID: " + std::to_string(currentId) + - std::string("\tMouse pos: ") + std::to_string(mousePos.x) + " " + std::to_string(mousePos.y))); - currentId = 0; - window->clear(sf::Color::Green); - - if (!world->m_blocks.empty()) - for (auto it:world->m_blocks) { - if (it.first.GetY() != renderLayer) - continue; - //std::cout<<it.first.GetY()<<std::endl; - sf::RectangleShape shape(sf::Vector2f(1, 1)); - shape.setPosition(it.first.GetX(), it.first.GetZ()); - shape.setFillColor(sf::Color::Blue); - if (mousePos.x > shape.getPosition().x && mousePos.y > shape.getPosition().y) { - if (mousePos.x < shape.getPosition().x + 1 && mousePos.y < shape.getPosition().y + 1) { - currentId = it.second.GetId(); - } - } - switch (it.second.GetId()) { +} + + +bool Display::IsClosed() { + return !window->isOpen(); +} + +void Display::SetPlayerPos(float x, float z) { + x = -55; + z = 196; + isGameStarted = true; + float div = 5; + float X = window->getSize().x / div, Z = window->getSize().y / div; + sf::View view(sf::Vector2f(x, z), sf::Vector2f(X, Z)); + window->setView(view); +} + +void Display::MainLoop() { + /*std::unique_lock<std::mutex> gameStartLocker(gameStartMutex); + gameStartWaiter.wait(gameStartLocker); + while (!isGameStarted) { + std::cout << "Catch spirious wakeup" << std::endl; + gameStartWaiter.wait(gameStartLocker); + } + std::cout << "Graphics subsystem initialized" << std::endl;*/ + while (!IsClosed()) { + Update(); + std::chrono::steady_clock clock; + static auto timeOfPreviousUpdate(clock.now()); + std::chrono::duration<double> delta = clock.now() - timeOfPreviousUpdate; + timeOfPreviousUpdate = clock.now(); + frameTime = delta.count(); + } +} + +sf::Texture &Display::GetSectionTexture(PositionI pos) { + if (sectionTextures.find(pos) != sectionTextures.end() && + sectionTextures[pos][renderLayer - pos.GetY() * 16].getSize() != sf::Vector2u(0, 0)) + return sectionTextures[pos][renderLayer - pos.GetY() * 16]; + + auto sectionIt = world->m_sections.find(pos); + Section §ion = sectionIt->second; + sf::Image image; + image.create(16, 16); + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + int y = renderLayer - sectionIt->first.GetY() * 16; + sf::Color color = sf::Color::Magenta; + switch (section.GetBlock(PositionI(x, z, y)).id) { case 0: - shape.setFillColor(sf::Color::Black); + color = sf::Color::Transparent; break; case 7: - shape.setFillColor(sf::Color::Yellow); + color = sf::Color::Yellow; break; case 1: - shape.setFillColor(sf::Color::White); + color = sf::Color::White; break; case 11: - shape.setFillColor(sf::Color::Red); + color = sf::Color::Red; break; case 10: - shape.setFillColor(sf::Color::Red); + color = sf::Color::Red; break; case 3: - shape.setFillColor(sf::Color(165, 42, 42)); + color = sf::Color(139, 69, 69); break; case 13: - shape.setFillColor(sf::Color(220, 220, 220)); + color = sf::Color(220, 220, 220); + break; + case 9: + color = sf::Color::Blue; + break; + case 8: + color = sf::Color::Blue; + break; + case 2: + color = sf::Color::Green; break; default: - //std::cout << "Unknown id is " << it.second.GetId() << std::endl; break; } - window->draw(shape); + image.setPixel(x, z, color); } - window->display(); - -} - - -bool Display::IsClosed() { - return !window->isOpen(); -} - -void Display::SetPlayerPos(float x, float z) { - float div = 1; - float X = window->getSize().x / div, Z = window->getSize().y / div; - sf::View view(sf::Vector2f(x, z), sf::Vector2f(X, Z)); - window->setView(view); -} + } + /*for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + std::cout << std::hex << (int)pixels[i * 256 + j * 16] << (int)pixels[i * 256 + j * 16 + 1] + << (int)pixels[i * 256 + j * 16 + 2] <<(int) pixels[i * 256 + j * 16 + 3] << " "; + } + std::cout<<std::endl; + }*/ + sf::Texture texture; + texture.create(16, 16); + texture.update(image); + sectionTextures[pos][renderLayer - pos.GetY() * 16] = texture; + return sectionTextures[pos][renderLayer - pos.GetY() * 16]; +}
\ No newline at end of file diff --git a/Display.hpp b/Display.hpp index bb1f946..d7a9089 100644 --- a/Display.hpp +++ b/Display.hpp @@ -1,17 +1,44 @@ #pragma once #include <SFML/Graphics.hpp> +#include <thread> +#include <mutex> +#include <condition_variable> #include "World.hpp" class Display { sf::RenderWindow *window; - World* world; + std::map<PositionI, std::array<sf::Texture,16>> sectionTextures; + World *world; + bool isGameStarted = false; + std::condition_variable &gameStartWaiter; + std::mutex gameStartMutex; + + //utility methods + void pollEvents(); + + void renderWorld(); + + void Update(); + + sf::Texture &GetSectionTexture(PositionI pos); + + //gameState vars + sf::Vector2f mousePos; + int renderLayer = 70; + //int currentId = 0; + bool isClicked = false; + int coeff = 10; + double frameTime = 0; public: - Display(int w=1280,int h=720,std::string title="AltCraft"); + Display(int w, int h, std::string title, World *world, std::condition_variable &gameStartWaiter); + ~Display(); - void SetWorld(World* wrd); - void Update(); + bool IsClosed(); + void SetPlayerPos(float x, float z); + + void MainLoop(); }; @@ -7,7 +7,7 @@ Field::Field() { Field::Field(const Field &other) : m_dataLength(other.m_dataLength), m_type(other.m_type) { m_data = new byte[m_dataLength]; - memcpy(m_data, other.m_data, m_dataLength); + std::copy(other.m_data,other.m_data+m_dataLength,m_data); } void Field::swap(Field &other) { @@ -39,7 +39,7 @@ void Field::Clear() { void Field::CopyToBuff(byte *ptr) { if (m_dataLength > 0) - memcpy(ptr, m_data, m_dataLength); + std::copy(m_data,m_data+m_dataLength,ptr); } void Field::SetRaw(byte *ptr, size_t len, FieldType type) { @@ -47,7 +47,7 @@ void Field::SetRaw(byte *ptr, size_t len, FieldType type) { m_dataLength = len; m_type = type; m_data = new byte[m_dataLength]; - memcpy(m_data, ptr, m_dataLength); + std::copy(ptr,ptr+m_dataLength,m_data); } int Field::GetVarInt() { @@ -129,7 +129,7 @@ void Field::SetString(std::string value) { byte *p = m_data; fLen.CopyToBuff(p); p += fLen.GetLength(); - memcpy(p, value.c_str(), value.size()); + std::copy(value.begin(),value.end(),p); } long long Field::GetLong() { @@ -176,7 +176,7 @@ sbyte Field::GetByte() { void Field::SetByte(sbyte value) { Clear(); - m_type = Byte; + m_type = Byte8_t; endswap(&value); m_dataLength = 1; m_data = new byte[m_dataLength]; @@ -259,7 +259,7 @@ size_t Field::GetFieldLength(FieldType type) { return 0; case Boolean: return 1; - case Byte: + case Byte8_t: return 1; case UnsignedByte: return 1; @@ -1,7 +1,6 @@ #pragma once #include <cstddef> -#include <cstring> #include <cstdint> #include <string> #include <vector> @@ -14,7 +13,7 @@ typedef signed char sbyte; enum FieldType { Unknown = 0, Boolean, //Bool - Byte, //int8_t + Byte8_t, //int8_t UnsignedByte, //uint8_t Short, //int16_t UnsignedShort, //uint16_t @@ -27,7 +26,7 @@ enum FieldType { Uuid, //byte* (2 bytes) //Unknown-length data - String = 100, //std::string + String = 100, //std::string Chat, //std::string VarInt, //int32_t VarLong, //int64_t @@ -112,10 +111,6 @@ public: std::vector<Field> GetArray(); - /*Field GetArrayItem(int pos, size_t defaultFieldLen = 0); - - void SetArray(int count);*/ - private: size_t m_dataLength = 0; byte *m_data = nullptr; diff --git a/FieldParser.cpp b/FieldParser.cpp index 10148e3..500a973 100644 --- a/FieldParser.cpp +++ b/FieldParser.cpp @@ -14,7 +14,7 @@ Field FieldParser::Parse(FieldType type, byte *data, size_t len) { return ParseInt(data, len); case UnsignedByte: return ParseUByte(data, len); - case Byte: + case Byte8_t: return ParseByte(data, len); case Float: return ParseFloat(data, len); @@ -74,7 +74,7 @@ Field FieldParser::ParseUByte(byte *data, size_t len) { Field FieldParser::ParseByte(byte *data, size_t len) { Field f; - f.SetRaw(data, 1, Byte); + f.SetRaw(data, 1, Byte8_t); return f; } @@ -100,7 +100,7 @@ Field FieldParser::ParseByteArray(byte *data, size_t len) { if (len == 0) throw 119; Field f; - f.SetRaw(data, len, Byte); + f.SetRaw(data, len, Byte8_t); //f.SetRaw(data, len, ByteArray); return f; } @@ -1,43 +1,51 @@ #include "Game.hpp" #include "PacketParser.hpp" #include "PacketBuilder.hpp" -#include "json.h" -#include <chrono> - +#include "json.hpp" Game::Game() { - m_display = new Display(); - m_display->SetWorld(&m_world); + m_display = new Display(1280, 720, "AltCraft", &m_world, gameStartWaiter); m_nc = new NetworkClient("127.0.0.1", 25565, "HelloOne"); - m_nc->Update(); - Packet response = m_nc->GetPacket(); + Packet &response = *m_nc->GetPacket(); + if (response.GetId()!=0x02){ + std::cout<< response.GetId()<<std::endl; + throw 127; + } PacketParser::Parse(response, Login); g_PlayerUuid = response.GetField(0).GetString(); g_PlayerName = response.GetField(1).GetString(); + delete &response; m_networkState = ConnectionState::Play; std::cout << g_PlayerName << "'s UUID is " << g_PlayerUuid << std::endl; } Game::~Game() { + std::cout<<"Stopping game thread..."<<std::endl; + m_gameThread.join(); + std::cout<<"Stopping graphics..."<<std::endl; delete m_display; + std::cout<<"Stopping network..."<<std::endl; delete m_nc; } void Game::MainLoop() { + //std::thread(std::this_thread::get_id()).swap(m_display->GetThreadHandler()); while (!m_exit) { ParsePackets(); - if (g_IsGameStarted) - m_display->Update(); if (m_display->IsClosed()) - throw 140; + m_exit = true; } } void Game::ParsePackets() { - m_nc->Update(); - Packet packet = m_nc->GetPacket(); - if (packet.GetId() == -1) + Packet *packetPtr =m_nc->GetPacket(); + if (!packetPtr) { + using namespace std::chrono_literals; + std::this_thread::sleep_for(16ms); return; + } + Packet packet = *packetPtr; + delete packetPtr; PacketParser::Parse(packet); nlohmann::json json; @@ -109,6 +117,7 @@ void Game::ParsePackets() { std::cout << "PlayerPos is " << g_PlayerX << "," << g_PlayerY << "," << g_PlayerZ << "\t" << g_PlayerYaw << "," << g_PlayerPitch << std::endl; m_display->SetPlayerPos(g_PlayerX, g_PlayerY); + gameStartWaiter.notify_all(); break; case 0x1A: json = nlohmann::json::parse(packet.GetField(0).GetString()); @@ -116,11 +125,7 @@ void Game::ParsePackets() { throw 119; break; case 0x20: - std::cout.setstate(std::ios_base::failbit); m_world.ParseChunkData(packet); - std::cout.clear(); - //sf::sleep(sf::seconds(0.1)); - //throw 122; break; case 0x07: std::cout << "Statistics:" << std::endl; @@ -147,3 +152,8 @@ void Game::ParsePackets() { } } } + +void Game::Exec() { + m_gameThread = std::thread(&Game::MainLoop,this); + m_display->MainLoop(); +} @@ -11,17 +11,23 @@ public: ~Game(); - void MainLoop(); + void Exec(); private: //utility variables NetworkClient *m_nc; + std::thread m_ncThread; bool m_exit = false; ConnectionState m_networkState = ConnectionState::Handshaking; Display *m_display; + std::thread m_gameThread; //utility methods void ParsePackets(); + void MainLoop(); + + //GameState update - condVars + std::condition_variable gameStartWaiter; //game state variables World m_world; @@ -0,0 +1,516 @@ +#pragma once + +#include <cstddef> +#include <vector> +#include <iostream> +#include <zlib.h> +#include <fstream> +#include "utility.h" + +namespace nbt { + enum TagType { + End, //nullptr + Byte, //int8_t + Short, //int16_t + Int, //int32_t + Long, //int64_t + Float, //float + Double, //double + ByteArray, //std::vector<signed char> + String, //std::string + List, //std::vector<NbtTag> + Compound, //std::vector<NbtTag> + IntArray, //std::vector<int32_t> + Unknown, //dummy value + }; + + class NbtTag; + + typedef std::vector<NbtTag> compound_t; + + typedef std::string string_t; + + typedef std::vector<signed char> byteArray_t; + + typedef std::vector<int> intArray_t; + + class NbtTag { + TagType type = Unknown; + string_t name = ""; + unsigned char *data = nullptr; + public: + NbtTag(TagType type, string_t name) : type(type), name(name) { + switch (type) { + case End: + data = nullptr; + break; + case Compound: + data = (unsigned char *) new compound_t; + break; + case String: + data = (unsigned char *) new string_t; + break; + case Int: + data = (unsigned char *) new int32_t; + break; + case Long: + data = (unsigned char *) new int64_t; + break; + case Byte: + data = (unsigned char *) new int8_t; + break; + case Short: + data = (unsigned char *) new int16_t; + break; + case Float: + data = (unsigned char *) new float; + break; + case Double: + data = (unsigned char *) new double; + break; + case ByteArray: + data = (unsigned char *) new byteArray_t; + break; + case List: + data = (unsigned char *) new compound_t; + break; + case IntArray: + data = (unsigned char *) new intArray_t; + } + } + + NbtTag(const NbtTag &other) : type(other.type), name(other.name) { + switch (type) { + case Byte: + data = (unsigned char *) new int8_t; + *((int8_t *) data) = *((int8_t *) other.data); + break; + case Short: + data = (unsigned char *) new int16_t; + *((int16_t *) data) = *((int16_t *) other.data); + break; + case Int: + data = (unsigned char *) new int32_t; + *((int32_t *) data) = *((int32_t *) other.data); + break; + case Long: + data = (unsigned char *) new int64_t; + *((int64_t *) data) = *((int64_t *) other.data); + break; + case Float: + data = (unsigned char *) new float; + *((float *) data) = *((float *) other.data); + break; + case Double: + data = (unsigned char *) new double; + *((double *) data) = *((double *) other.data); + break; + case ByteArray: + data = (unsigned char *) new byteArray_t; + *((std::vector<signed char> *) data) = *((std::vector<signed char> *) other.data); + break; + case String: + data = (unsigned char *) new string_t; + *((std::string *) data) = *((std::string *) other.data); + break; + case List: + data = (unsigned char *) new compound_t; + *((std::vector<NbtTag> *) data) = *((std::vector<NbtTag> *) other.data); + break; + case Compound: + data = (unsigned char *) new compound_t; + *((std::vector<NbtTag> *) data) = *((std::vector<NbtTag> *) other.data); + break; + case IntArray: + data = (unsigned char *) new intArray_t; + *((std::vector<int> *) data) = *((std::vector<int> *) other.data); + break; + } + } + + ~NbtTag() { + switch (type) { + case Byte: + delete ((int8_t *) data); + break; + case Short: + delete ((int16_t *) data); + break; + case Int: + delete ((int32_t *) data); + break; + case Long: + delete ((int64_t *) data); + break; + case Float: + delete ((float *) data); + break; + case Double: + delete ((double *) data); + break; + case ByteArray: + delete ((std::vector<signed char> *) data); + break; + case String: + delete ((std::string *) data); + break; + case List: + delete ((std::vector<NbtTag> *) data); + break; + case Compound: + delete ((std::vector<NbtTag> *) data); + break; + case IntArray: + delete ((std::vector<int> *) data); + break; + } + }; + + void swap(NbtTag &other) { + std::swap(other.data, data); + std::swap(other.name, name); + std::swap(other.type, type); + } + + NbtTag &operator=(NbtTag other) { + other.swap(*this); + return *this; + } + + TagType GetType() const{ + return type; + } + + string_t GetName() const{ + return name; + } + + + string_t &GetString() { + string_t &val = *reinterpret_cast<std::string *>(data); + return val; + } + + compound_t &GetCompound() { + std::vector<NbtTag> &val = *reinterpret_cast<std::vector<NbtTag> *>(data); + return val; + } + + compound_t &GetList() { + std::vector<NbtTag> &val = *reinterpret_cast<std::vector<NbtTag> *>(data); + return val; + } + + int64_t &GetLong() { + int64_t &val = *reinterpret_cast<int64_t *>(data); + return val; + } + + float &GetFloat() { + float &val = *reinterpret_cast<float *>(data); + return val; + } + + double &GetDouble() { + double &val = *reinterpret_cast<double *>(data); + return val; + } + + byteArray_t &GetByteArray() { + auto &val = *reinterpret_cast<byteArray_t *>(data); + return val; + } + + intArray_t &GetIntArray() { + auto &val = *reinterpret_cast<intArray_t *>(data); + return val; + } + + int16_t &GetShort() { + auto &val = *reinterpret_cast<int16_t *>(data); + return val; + } + + int32_t &GetInt() { + auto &val = *reinterpret_cast<int32_t *>(data); + return val; + } + + int8_t &GetByte() { + auto &val = *reinterpret_cast<int8_t *>(data); + return val; + } + }; + + NbtTag ParseTag(unsigned char *data, size_t &size, TagType listItemType = Unknown) { + size = 0; + TagType type; + if (listItemType == Unknown) { + type = (TagType) *data; + data += 1; + size += 1; + } else + type = listItemType; + string_t name; + if (listItemType == Unknown && type != End) { + short nameLen = *((short *) data); + data += 2; + size += 2; + endswap(&nameLen); + name = std::string((char *) data, nameLen); + data += nameLen; + size += nameLen; + } + NbtTag tag(type, name); + switch (type) { + case Compound: { + do { + size_t s; + tag.GetCompound().push_back(ParseTag(data, s)); + data += s; + size += s; + } while (tag.GetCompound().back().GetType() != End); + tag.GetCompound().pop_back(); + return tag; + } + case String: { + short len = *((short *) data); + data += 2; + size += 2; + endswap(&len); + string_t str((char *) data, len); + data += len; + size += len; + tag.GetString() = str; + return tag; + } + case End: + return tag; + case Long: + tag.GetLong() = *((int64_t *) data); + endswap(&tag.GetLong()); + data += 8; + size += 8; + return tag; + case Short: + tag.GetShort() = *((int16_t *) data); + endswap(&tag.GetShort()); + data += 2; + size += 2; + return tag; + case Float: + tag.GetFloat() = *((float *) data); + endswap(&tag.GetFloat()); + data += 4; + size += 4; + return tag; + case Double: + tag.GetDouble() = *((double *) data); + endswap(&tag.GetDouble()); + data += 8; + size += 8; + return tag; + case Byte: + tag.GetByte() = *((int8_t *) data); + endswap(&tag.GetByte()); + data += 1; + size += 1; + return tag; + case Int: + tag.GetInt() = *((int32_t *) data); + endswap(&tag.GetInt()); + data += 4; + size += 4; + return tag; + case List: { + TagType listType = *((TagType *) data); + data += 1; + size += 1; + int32_t listLength = *((int32_t *) data); + endswap(&listLength); + data += 4; + size += 4; + for (int i = 0; i < listLength; i++) { + size_t s = 0; + std::vector<NbtTag> &vec = tag.GetCompound(); + vec.push_back(ParseTag(data, s, listType)); + data += s; + size += s; + } + return tag; + } + case ByteArray: { + int32_t arrLength = *((int32_t *) data); + endswap(&arrLength); + data += 4; + size += 4; + for (int i = 0; i < arrLength; i++) { + signed char val = (signed char) data[i]; + std::vector<signed char> &vec = tag.GetByteArray(); + vec.push_back(val); + } + data += arrLength; + size += arrLength; + return tag; + } + default: + throw 13; + } + } + + NbtTag ParseTag(unsigned char *data, size_t *optionalSize = nullptr) { + size_t s = 0; + size_t &size = (optionalSize ? *optionalSize : s); + return ParseTag(data, size); + } + + std::vector<unsigned char> Decompress(unsigned char *data, size_t dataLen) { + const size_t decompBuffSize = 1024 * 16; + unsigned char *decompBuff = new unsigned char[decompBuffSize]; + std::vector<unsigned char> uncompressed; + for (int i = 0; i < decompBuffSize; i++) + decompBuff[i] = 0; + + + z_stream stream; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.next_in = data; + stream.avail_in = dataLen; + stream.next_out = decompBuff; + stream.avail_out = decompBuffSize; + + if (inflateInit2(&stream, 15 + 32) != Z_OK) { + delete[] decompBuff; + throw 171; + } + + int res; + do { + stream.avail_out = decompBuffSize; + + switch ((res = inflate(&stream, Z_NO_FLUSH))) { + case Z_MEM_ERROR: + throw 172; + case Z_DATA_ERROR: + throw 173; + case Z_NEED_DICT: + throw 174; + } + + uncompressed.resize(uncompressed.size() + decompBuffSize); + std::copy(decompBuff, decompBuff + decompBuffSize, uncompressed.end() - decompBuffSize); + } while (stream.avail_out == 0); + if (res != Z_STREAM_END) + throw 175; + if (inflateEnd(&stream) != Z_OK) + throw 176; + delete[] decompBuff; + return uncompressed; + } + + NbtTag ParseCompressed(unsigned char *data, size_t dataLen) { + auto uncompressed = Decompress(data, dataLen); + NbtTag root = ParseTag(uncompressed.data()); + return root; + } + + NbtTag Parse(unsigned char *data, size_t dataLen) { + bool isCompressed = *data!=10; + if (isCompressed) + return ParseCompressed(data,dataLen); + else + return ParseTag(data); + } + + void PrintTree(NbtTag &tree, int deepness = 0, std::ostream &ostream = std::cout) { + ostream << std::string(deepness, '\t') << "Tag "; + switch (tree.GetType()) { + case Byte: + ostream << "byte"; + break; + case Short: + ostream << "short"; + break; + case Int: + ostream << "int"; + break; + case Long: + ostream << "long"; + break; + case Float: + ostream << "float"; + break; + case Double: + ostream << "double"; + break; + case ByteArray: + ostream << "byte array"; + break; + case String: + ostream << "string"; + break; + case List: + ostream << "list"; + break; + case Compound: + ostream << "compound"; + break; + case IntArray: + ostream << "int array"; + break; + case End: + ostream << "end"; + break; + } + if (tree.GetName().length() > 0) + ostream << " (" << tree.GetName() << ")"; + ostream << ": "; + + if (tree.GetType() == Compound || tree.GetType() == List) { + std::vector<NbtTag> &vec = (tree.GetType() == Compound ? tree.GetCompound() : tree.GetList()); + ostream << vec.size() << " entries {" << std::endl; + for (auto it = vec.begin(); it != vec.end(); ++it) { + PrintTree(*it, deepness + 1, std::cout); + } + ostream << std::string(deepness, '\t') << "}" << std::endl; + return; + } else { + switch (tree.GetType()) { + case Int: + ostream << tree.GetInt(); + break; + case String: + ostream << "\"" << tree.GetString() << "\""; + break; + case Double: + ostream << tree.GetDouble(); + break; + case Float: + ostream << tree.GetFloat(); + break; + case Short: + ostream << tree.GetShort(); + break; + case Byte: + ostream << (int) tree.GetByte(); + break; + case Long: + ostream << tree.GetLong(); + break; + case ByteArray: + ostream << "[" << tree.GetByteArray().size() << " bytes]: "; + for (int i = 0; i < (tree.GetByteArray().size() > 10 ? 10 : tree.GetByteArray().size()); i++) { + ostream << std::hex << "0x" << (tree.GetByteArray()[i] > 15 ? "" : "0") + << (int) tree.GetByteArray()[i] + << std::dec << " "; + } + break; + case IntArray: + break; + } + ostream << std::endl; + } + } +}
\ No newline at end of file diff --git a/Network.cpp b/Network.cpp index 8b25756..d979037 100644 --- a/Network.cpp +++ b/Network.cpp @@ -65,10 +65,20 @@ Packet Network::ReceivePacket() { return Packet(bufLen); } byte *bufPack = new byte[packetLen]; - for (int i = 0; i < packetLen; i++) - bufPack[i] = 'N'; - memcpy(bufPack, bufLen, rec); - if (m_socket.receive(bufPack + rec, packetLen - rec, rec) != sf::Socket::Done) { + std::copy(bufLen, bufLen + rec, bufPack); + size_t dataLen = rec; + while (m_socket.receive(bufPack + dataLen, packetLen - dataLen, rec) == sf::Socket::Done && dataLen < packetLen) { + dataLen += rec; + } + if (dataLen < packetLen) + throw 93; + else { + Packet p(bufPack); + delete[] bufPack; + return p; + } + + /*if (m_socket.receive(bufPack + rec, packetLen - rec, rec) != sf::Socket::Done) { delete[] bufPack; throw 93; } @@ -93,8 +103,6 @@ Packet Network::ReceivePacket() { std::cout << "\x1b[31m" << "Losted " << losted << " bytes of " << packetLen << "\x1b[0m" << std::endl; delete[] bufPack; throw 93; - } - Packet p(bufPack); - delete[] bufPack; - return p; + }*/ + throw 94; } diff --git a/Network.hpp b/Network.hpp index a135fbe..74df92c 100644 --- a/Network.hpp +++ b/Network.hpp @@ -21,6 +21,6 @@ private: std::string m_address; unsigned short m_port; sf::TcpSocket m_socket; - bool m_isCommpress; + bool m_isCommpress=false; }; diff --git a/NetworkClient.cpp b/NetworkClient.cpp index e8ba7ca..d6835e0 100644 --- a/NetworkClient.cpp +++ b/NetworkClient.cpp @@ -1,8 +1,7 @@ #include "NetworkClient.hpp" #include "PacketParser.hpp" #include "PacketBuilder.hpp" -#include "json.h" -#include <chrono> +#include "json.hpp" ServerInfo NetworkClient::ServerPing(std::string address, unsigned short port) { ServerInfo info; @@ -55,20 +54,24 @@ ServerInfo NetworkClient::ServerPing(std::string address, unsigned short port) { return info; } -NetworkClient::NetworkClient(std::string address, unsigned short port, std::string username) : m_network(address, port) { +NetworkClient::NetworkClient(std::string address, unsigned short port, std::string username) : m_network(address, + port) { m_network.SendHandshake(username); + Update(); + m_networkThread = std::thread(&NetworkClient::MainLoop, this); } NetworkClient::~NetworkClient() { - + isContinue=false; + m_networkThread.join(); } -Packet NetworkClient::GetPacket() { - if (m_received.size()<1) - return Packet(-1); +Packet * NetworkClient::GetPacket() { + if (m_received.size() < 1) + return nullptr; Packet packet = m_received.front(); m_received.pop(); - return packet; + return new Packet(packet); } void NetworkClient::AddPacketToQueue(Packet packet) { @@ -76,16 +79,29 @@ void NetworkClient::AddPacketToQueue(Packet packet) { } void NetworkClient::Update() { - if (m_toSend.size()>0){ + if (m_toSend.size() > 0) { m_network.SendPacket(m_toSend.front()); m_toSend.pop(); } Packet received = m_network.ReceivePacket(); - if (received.GetId()==0x1F){ + if (received.GetId() == 0x1F) { PacketParser::Parse(received); Packet response = PacketBuilder::CPlay0x0B(received.GetField(0).GetVarInt()); m_network.SendPacket(response); return; } + m_updateMutex.lock(); m_received.push(received); + m_updateMutex.unlock(); +} + +void NetworkClient::MainLoop() { + try { + while (isContinue) { + Update(); + } + } catch (int e){ + std::cerr<<"NetworkClient exception: "<<e<<std::endl; + } + } diff --git a/NetworkClient.hpp b/NetworkClient.hpp index df2f616..a41b5f4 100644 --- a/NetworkClient.hpp +++ b/NetworkClient.hpp @@ -1,6 +1,8 @@ #pragma once #include <queue> +#include <thread> +#include <mutex> #include "Network.hpp" struct ServerInfo{ @@ -21,11 +23,16 @@ public: void Update(); - Packet GetPacket(); + void MainLoop(); + + Packet * GetPacket(); void AddPacketToQueue(Packet packet); static ServerInfo ServerPing(std::string address,unsigned short port); private: + std::mutex m_updateMutex; + std::thread m_networkThread; + bool isContinue=true; NetworkClient (const NetworkClient&); NetworkClient&operator=(const NetworkClient&); Network m_network; @@ -2,11 +2,9 @@ Packet::Packet(int id) { Field fLen; - //fLen.SetValue<VarInt>(0); fLen.SetVarInt(0); m_fields.push_back(fLen); Field fId; - //fId.SetValue<VarInt>(id); fId.SetVarInt(id); m_fields.push_back(fId); } @@ -52,13 +50,13 @@ Packet::Packet(byte *data) { data += fId.GetLength(); m_dataLength = fLen.GetVarInt() - fId.GetLength(); m_data = new byte[m_dataLength]; - memcpy(m_data, data, m_dataLength); + std::copy(data,data+m_dataLength,m_data); m_parsePtr = m_data; m_fields.push_back(fLen); m_fields.push_back(fId); } -Field & Packet::GetField(int id) { +Field &Packet::GetField(int id) { if (id < -2 || id >= m_fields.size() - 2) throw 111; return m_fields[id + 2]; @@ -84,7 +82,7 @@ Packet::Packet(const Packet &other) { m_dataLength = other.m_dataLength; m_data = new byte[m_dataLength]; m_parsePtr = m_data + (other.m_data - other.m_parsePtr); - memcpy(m_data, other.m_data, m_dataLength); + std::copy(other.m_data, other.m_data + m_dataLength, m_data); } m_fields = other.m_fields; } diff --git a/PacketParser.cpp b/PacketParser.cpp index f4b3889..488c812 100644 --- a/PacketParser.cpp +++ b/PacketParser.cpp @@ -33,7 +33,10 @@ void PacketParser::ParseLogin(Packet &packet) { ParseLogin0x02(packet); break; default: - throw 112; + { + int i = packet.GetId(); + //throw 112; + } } } @@ -99,7 +102,7 @@ void PacketParser::ParsePlay0x0D(Packet &packet) { } void PacketParser::ParsePlay0x2B(Packet &packet) { - packet.ParseField(Byte); + packet.ParseField(Byte8_t); packet.ParseField(Float); packet.ParseField(Float); } @@ -114,7 +117,7 @@ void PacketParser::ParsePlay0x2E(Packet &packet) { packet.ParseField(Double); packet.ParseField(Float); packet.ParseField(Float); - packet.ParseField(Byte); + packet.ParseField(Byte8_t); packet.ParseField(VarInt); } diff --git a/Section.cpp b/Section.cpp new file mode 100644 index 0000000..a04ed41 --- /dev/null +++ b/Section.cpp @@ -0,0 +1,126 @@ +#include <iostream> +#include "Section.hpp" + +Section::Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock, + std::vector<unsigned short> palette) { + 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() { +} + +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(PositionI pos) { + if (m_dataBlocks != nullptr) { + Parse(); + } + return m_blocks[pos.GetY() * 256 + pos.GetZ() * 16 + pos.GetX()]; +} + +void Section::Parse() { + if (m_dataBlocks == nullptr) + return; + + long long *longArray = reinterpret_cast<long long *>(m_dataBlocks); + for (int i = 0; i < m_dataBlocksLen / 8; i++) + endswap(&longArray[i]); + std::vector<unsigned short> blocks; + blocks.reserve(4096); + int bitPos = 0; + unsigned short t = 0; + for (int 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; + } + } + } + + 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, light[i]); + m_blocks.push_back(block); + } + if ((light.size() + blocks.size()) / 2 != 4096) { + throw 118; + } + delete[] m_dataBlocks; + m_dataBlocksLen = 0; + m_dataBlocks = nullptr; + delete[] m_dataLight; + m_dataLight = nullptr; + delete[] m_dataSkyLight; + m_dataSkyLight = nullptr; +} + +Section &Section::operator=(Section other) { + other.swap(*this); + 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); +} + +Section::Section(const Section &other) { + m_dataBlocksLen = other.m_dataBlocksLen; + 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); + } + + m_palette = other.m_palette; + m_bitsPerBlock = other.m_bitsPerBlock; +} + + diff --git a/Section.hpp b/Section.hpp new file mode 100644 index 0000000..14ea2f8 --- /dev/null +++ b/Section.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include <vector> +#include <map> +#include "Block.hpp" +#include "Field.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; +public: + void Parse(); + + Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock, + std::vector<unsigned short> palette); + + Section(); + + ~Section(); + + Block &GetBlock(PositionI pos); + + Section &operator=(Section other); + + void swap(Section &other); + + Section(const Section &other); + +};
\ No newline at end of file @@ -2,217 +2,105 @@ #include <bitset> #include "World.hpp" - -Block &World::GetBlock(PositionI pos) { - //unsigned long long pos = (unsigned long long) x << 32; - //pos |= y; - return m_blocks[pos]; -} - -void World::SetBlock(PositionI pos, Block block) { - //unsigned long long pos = (unsigned long long) x << 32; - //pos |= y; - m_blocks[pos] = block; -} - void World::ParseChunkData(Packet packet) { int chunkX = packet.GetField(0).GetInt(); int chunkZ = packet.GetField(1).GetInt(); + std::cout << "Parsing chunk " << chunkX << "x" << chunkZ << std::endl; 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); - std::cout << "Chunk " << chunkX << "x" << chunkZ << std::endl; - std::cout << "\tGround continuous: " << (isGroundContinuous ? "true" : "false") << std::endl; - std::cout << "\tPrimary bitmask: " << bitmask << std::endl; - std::cout << "\tDataLen: " << dataLen << std::endl; - std::cout << "\tEntities: " << entities << std::endl; - if (isGroundContinuous) dataLen -= 256; byte *biomes = content + packet.GetField(5).GetLength() - 256; - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 16; i++) { if (bitmask[i]) { - size_t len = ParseSectionData(chunkX, chunkZ, isGroundContinuous, i, content); - //content += len; - //std::cout << "\t Size of section is " << len << std::endl; + size_t len = 0; + m_sections[PositionI(chunkX, chunkZ, i)] = ParseSection(content, len); + m_sectionToParse.push(m_sections.find(PositionI(chunkX,chunkZ,i))); + m_parseSectionWaiter.notify_one(); + content += len; } } - std::cout << std::dec << std::endl; - fflush(stdout); + delete[] contentOrigPtr; } -size_t World::ParseSectionData(int chunkX, int chunkZ, bool isGroundContinous, int section, byte *data) { +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(); - bool usePalette = bitsPerBlock <= 8; Field fPaletteLength = FieldParser::Parse(VarInt, data); int paletteLength = fPaletteLength.GetVarInt(); data += fPaletteLength.GetLength(); + dataLen += fPaletteLength.GetLength(); - std::cout << "Section: " << chunkX << "x" << chunkZ << "x" << section << std::endl; - std::cout << "\tBits per block: " << (int) bitsPerBlock << std::endl; - std::cout << "\tPalette length: " << paletteLength << std::endl; - std::vector<int> palette; - std::map<unsigned char, unsigned short> pal; + std::vector<unsigned short> palette; if (paletteLength > 0) { for (unsigned char i = 0; i < paletteLength; i++) { endswap(&i); Field f = FieldParser::Parse(VarInt, data); data += f.GetLength(); + dataLen += f.GetLength(); palette.push_back(f.GetVarInt()); - std::cout << "\t\tPalette[" << std::bitset<8>(i) << "]: " << std::bitset<13>(palette[i]) << std::endl; - pal[i] = f.GetVarInt(); endswap(&i); } } Field fDataLength = FieldParser::Parse(VarInt, data); data += fDataLength.GetLength(); + dataLen += fDataLength.GetLength(); + int dataLength = fDataLength.GetVarInt(); size_t dataSize = dataLength * 8; - std::cout << "\tData length: " << dataLength << " (" << dataSize << ")" << std::endl; - - std::vector<unsigned short> blocks = ParseBlocks(data, dataLength, palette, bitsPerBlock); - std::cout << "\tChunk content: "; - int i = 0; - for (int y = 0; y < SECTION_LENGTH; y++) { - for (int z = 0; z < SECTION_HEIGHT; z++) { - for (int x = 0; x < SECTION_WIDTH; x++) { - int X = chunkX * SECTION_WIDTH + x; - int Y = section * SECTION_HEIGHT + y; - int Z = chunkZ * SECTION_LENGTH + z; - //std::cerr<<"Block at "<<X<<" "<<Y<<" "<<Z<<std::endl; - Block block(usePalette ? pal[blocks[i]] : blocks[i],15); - SetBlock(PositionI(X, Z, Y), block); - std::cout << (PositionI(X, Z, Y).GetY()) << ": " - << block.GetId() << "\t"; - //<< (usePalette ? pal[blocks[i]] : blocks[i]) << "\t"; - //<< std::bitset<13>(usePalette ? pal[blocks[i]] : blocks[i]) << "\t"; - i++; - } - } + 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; } - std::cout << std::endl; - /*for (auto it:blocks) { - //auto m = std::bitset<4>(it).to_string(); - //std::cout<<m<<" "; - std::cout<<std::bitset<13>(pal[it])<<" "; - //std::cout << (m=="1000" || m =="0100" || m=="0010"?"":m+" "); - }*/ - return (dataSize + (m_dimension == 0 ? dataSize : 0) / 2 + dataSize / 2); + + return Section(dataBlocks, dataSize, dataLight, dataSky, bitsPerBlock, palette); } -std::vector<unsigned short> -World::ParseBlocks(byte *bytes, int dataLength, std::vector<int> palette, byte bitsPerBlock) { - std::vector<unsigned short> blocks; - for (int i = 0; i < blocks.size(); i++) { - blocks[i] = 0; - } - byte *data = new byte[dataLength * 8]; - size_t arrLength = dataLength * 8; - byte *ptr = data; - for (int i = 0; i < dataLength; i++) { - Field fData = FieldParser::Parse(Long, bytes); - bytes += fData.GetLength(); - *reinterpret_cast<long long *>(ptr) = fData.GetLong(); - ptr += 8; - } - int bitPos = 0; - unsigned short t = 0; - for (int i = 0; i < arrLength; i++) { - //endswap(&data[i]); - //std::bitset<8> bitset1 = std::bitset<8>(data[i]); - //std::cout << bitset1 << ": "; - for (int j = 0; j < 8; j++) { - //std::bitset<8> bitset2 = std::bitset<8>(t); - /*std::cout << bitset2 << "_"; - std::cout << bitset1 << "\t"; - fflush(stdout);*/ - - t |= (data[i] & 0x01) ? 0x80 : 0x00; - t >>= 1; - data[i] >>= 1; - bitPos++; - if (bitPos >= bitsPerBlock) { - bitPos = 0; - //endswap(&t); - t >>= bitsPerBlock - 1; - blocks.push_back(t); - //std::cout << bitset2 << "\t"; - t = 0; - } - /*bitset1 = std::bitset<8>(data[i]); - bitset2 = std::bitset<8>(t);*/ - } - } - //std::cout << std::endl; - /*int bitPos = 0, bytePos = 0, pushedBlocks = 0, bits = 0; - unsigned short t = 0; - while (bytePos < arrLength) { - //std::cout << std::bitset<8>(data[bytePos]) << " "; - //int bit = data[bytePos] & 1; - t|=(data[bytePos] & 1)<<bitPos; - data[bytePos] = data[bytePos]>>1; - - - //t = t | ((data[bytePos]<<bitPos) & 1); - std::cout<<std::bitset<8>(t)<<"\t"; - if (bitPos >= 7) { - bitPos = 0; - bytePos++; - blocks[pushedBlocks] = t; - std::cout<<std::bitset<13>(t)<<"\t"; - t = 0; - } else { - bitPos++; - } +World::~World() { + isContinue=false; + m_parseSectionWaiter.notify_all(); + m_sectionParseThread.join(); +} - bits++; - if (bits>=bitsPerBlock){ - bits=0; - bitPos=0; - bytePos++; - blocks[pushedBlocks] = t; - std::cout<<std::bitset<13>(t)<<"+\t"; - t = 0; - } else { - t <<= 1; +void World::SectionParsingThread() { + while (isContinue){ + std::unique_lock<std::mutex> sectionParseLocker(m_parseSectionMutex); + m_parseSectionWaiter.wait(sectionParseLocker); + while (!m_sectionToParse.size()==0 && isContinue) { + m_parseSectionWaiter.wait(sectionParseLocker); } - fflush(stdout); - }*/ - // - /*int shift = 0; - int bx = 0; - for (int bytmass = 0; bytmass < arrLength; bytmass++) { - unsigned char bitinbyte = 7; - int block = 0; - for (int posbit = 7; posbit > 0; posbit--) { - int b = (data[bytmass] >> posbit); - blocks[block + shift] = blocks[block + shift] | (b << bx); - bx++; - if (bx > bitsPerBlock) { - bx = 0; - if (shift == 0) shift = 1; - if (shift == 1) { - shift = 0; - block++; - if ((block * 2) > blocks.size()) { - std::cout<<block*2<<">"<<blocks.size()<<std::endl; - throw 124; - } - } - } + while (m_sectionToParse.size()>0){ + auto it = m_sectionToParse.front(); + m_sectionToParse.pop(); + it->second.Parse(); } - }*/ - // - delete[] data; - return blocks; + } } + +World::World() { + m_sectionParseThread = std::thread(&World::SectionParsingThread,this); +} + @@ -1,28 +1,33 @@ #pragma once #include <map> +#include <thread> +#include <mutex> +#include <condition_variable> +#include <queue> #include "Block.hpp" #include "Packet.hpp" - -const int SECTION_WIDTH=16; -const int SECTION_LENGTH=16; -const int SECTION_HEIGHT=16; +#include "Section.hpp" class World { public: - Block &GetBlock(PositionI pos); - void SetBlock(PositionI pos, Block block); + World(); + ~World(); void ParseChunkData(Packet packet); - - - std::map<PositionI,Block> m_blocks; + std::map<PositionI, Section> m_sections; private: - - - size_t ParseSectionData(int chunkX, int chunkZ, bool isGroundContinous, int section, byte *data); - - std::vector<unsigned short> - ParseBlocks(byte *bytes, int dataLength, std::vector<int> palette, byte bitsPerBlock); - - int m_dimension=0; + //utility vars + World(const World& other); + World&operator=(const World &other); + //utility methods + std::thread m_sectionParseThread; + std::queue<std::map<PositionI,Section>::iterator> m_sectionToParse; + //game vars + int m_dimension = 0; + //game methods + std::mutex m_parseSectionMutex; + std::condition_variable m_parseSectionWaiter; + Section ParseSection(byte *data, size_t &dataLen); + void SectionParsingThread(); + bool isContinue=true; };
\ No newline at end of file @@ -1,7 +1,12 @@ +#include <iostream> #include "Game.hpp" int main() { - Game game; - game.MainLoop(); + try { + Game game; + game.Exec(); + } catch (int e) { + std::cerr << "Catch exception " << e << std::endl; + } return 0; }
\ No newline at end of file diff --git a/utility.cpp b/utility.cpp index fffe2f8..aa50e9f 100644 --- a/utility.cpp +++ b/utility.cpp @@ -1,6 +1,3 @@ -// -// Created by lag1924 on 24.03.17. -// #include "utility.h" int VarIntRead(unsigned char *data, size_t &readed) { @@ -1,10 +1,4 @@ -// -// Created by lag1924 on 24.03.17. -// - -#ifndef PROJECT_UTILITY_H -#define PROJECT_UTILITY_H - +#pragma once #include <algorithm> int VarIntRead(unsigned char *data, size_t &readed); @@ -19,6 +13,4 @@ template<class T> void endswap(T *objp) { unsigned char *memp = reinterpret_cast<unsigned char *>(objp); std::reverse(memp, memp + sizeof(T)); -} - -#endif //PROJECT_UTILITY_H +}
\ No newline at end of file |