summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaG1924 <12997935+LaG1924@users.noreply.github.com>2017-04-21 15:31:43 +0200
committerLaG1924 <12997935+LaG1924@users.noreply.github.com>2017-04-21 15:31:43 +0200
commit71760514fc044f273914c17b1510fa3cf10419b3 (patch)
tree72f822efde300d8e1e9de1cc578d431ff72e0e03
parent2017-04-15 (diff)
downloadAltCraft-71760514fc044f273914c17b1510fa3cf10419b3.tar
AltCraft-71760514fc044f273914c17b1510fa3cf10419b3.tar.gz
AltCraft-71760514fc044f273914c17b1510fa3cf10419b3.tar.bz2
AltCraft-71760514fc044f273914c17b1510fa3cf10419b3.tar.lz
AltCraft-71760514fc044f273914c17b1510fa3cf10419b3.tar.xz
AltCraft-71760514fc044f273914c17b1510fa3cf10419b3.tar.zst
AltCraft-71760514fc044f273914c17b1510fa3cf10419b3.zip
-rw-r--r--Block.cpp29
-rw-r--r--Block.hpp27
-rw-r--r--CMakeLists.txt21
-rw-r--r--Display.cpp268
-rw-r--r--Display.hpp35
-rw-r--r--Field.cpp12
-rw-r--r--Field.hpp9
-rw-r--r--FieldParser.cpp6
-rw-r--r--Game.cpp44
-rw-r--r--Game.hpp8
-rw-r--r--Nbt.hpp516
-rw-r--r--Network.cpp24
-rw-r--r--Network.hpp2
-rw-r--r--NetworkClient.cpp36
-rw-r--r--NetworkClient.hpp9
-rw-r--r--Packet.cpp8
-rw-r--r--PacketParser.cpp9
-rw-r--r--Section.cpp126
-rw-r--r--Section.hpp38
-rw-r--r--World.cpp218
-rw-r--r--World.hpp39
-rw-r--r--json.hpp (renamed from json.h)0
-rw-r--r--main.cpp9
-rw-r--r--utility.cpp3
-rw-r--r--utility.h12
25 files changed, 1143 insertions, 365 deletions
diff --git a/Block.cpp b/Block.cpp
index 7c45e76..64e5330 100644
--- a/Block.cpp
+++ b/Block.cpp
@@ -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) {}
diff --git a/Block.hpp b/Block.hpp
index 0272e1f..7c780c1 100644
--- a/Block.hpp
+++ b/Block.hpp
@@ -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 &section = 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 &section = 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();
};
diff --git a/Field.cpp b/Field.cpp
index d061bcc..c95c32d 100644
--- a/Field.cpp
+++ b/Field.cpp
@@ -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;
diff --git a/Field.hpp b/Field.hpp
index 4620ab3..43769dc 100644
--- a/Field.hpp
+++ b/Field.hpp
@@ -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;
}
diff --git a/Game.cpp b/Game.cpp
index 86be314..8674942 100644
--- a/Game.cpp
+++ b/Game.cpp
@@ -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();
+}
diff --git a/Game.hpp b/Game.hpp
index 68be9ab..1a2edce 100644
--- a/Game.hpp
+++ b/Game.hpp
@@ -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;
diff --git a/Nbt.hpp b/Nbt.hpp
new file mode 100644
index 0000000..3e43db7
--- /dev/null
+++ b/Nbt.hpp
@@ -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;
diff --git a/Packet.cpp b/Packet.cpp
index 84cafc4..695e371 100644
--- a/Packet.cpp
+++ b/Packet.cpp
@@ -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
diff --git a/World.cpp b/World.cpp
index dfd3b60..4a750ab 100644
--- a/World.cpp
+++ b/World.cpp
@@ -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);
+}
+
diff --git a/World.hpp b/World.hpp
index 288dc4f..ac3433b 100644
--- a/World.hpp
+++ b/World.hpp
@@ -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
diff --git a/json.h b/json.hpp
index f1dd4a6..f1dd4a6 100644
--- a/json.h
+++ b/json.hpp
diff --git a/main.cpp b/main.cpp
index 320fd80..b51bb81 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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) {
diff --git a/utility.h b/utility.h
index bb2b623..32120cb 100644
--- a/utility.h
+++ b/utility.h
@@ -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