summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/Core.cpp144
-rw-r--r--src/core/Core.hpp5
-rw-r--r--src/gamestate/GameState.cpp518
-rw-r--r--src/gamestate/GameState.hpp93
-rw-r--r--src/network/Network.cpp284
-rw-r--r--src/network/Network.hpp42
-rw-r--r--src/network/NetworkClient.cpp175
-rw-r--r--src/network/NetworkClient.hpp52
-rw-r--r--src/network/Packet.hpp492
-rw-r--r--src/network/Socket.cpp29
-rw-r--r--src/network/Socket.hpp45
-rw-r--r--src/network/Stream.cpp334
-rw-r--r--src/network/Stream.hpp115
-rw-r--r--src/packet/Field.cpp303
-rw-r--r--src/packet/Field.hpp121
-rw-r--r--src/packet/FieldParser.cpp105
-rw-r--r--src/packet/FieldParser.hpp30
-rw-r--r--src/packet/Packet.cpp101
-rw-r--r--src/packet/Packet.hpp130
-rw-r--r--src/packet/PacketBuilder.cpp65
-rw-r--r--src/packet/PacketBuilder.hpp17
-rw-r--r--src/packet/PacketParser.cpp147
-rw-r--r--src/packet/PacketParser.hpp38
-rw-r--r--src/world/Collision.cpp28
-rw-r--r--src/world/Collision.hpp8
-rw-r--r--src/world/Section.cpp31
-rw-r--r--src/world/Section.hpp37
-rw-r--r--src/world/World.cpp151
-rw-r--r--src/world/World.hpp27
29 files changed, 2010 insertions, 1657 deletions
diff --git a/src/core/Core.cpp b/src/core/Core.cpp
index 9ad36ba..bb5bc12 100644
--- a/src/core/Core.cpp
+++ b/src/core/Core.cpp
@@ -140,8 +140,8 @@ Core::Core() {
glCheckError();
InitGlew();
glCheckError();
- client = new NetworkClient("127.0.0.1", 25565, "HelloOne");
- gameState = new GameState(client);
+ client = new NetworkClient("127.0.0.1", 25565, "HelloOne", isRunning);
+ gameState = new GameState(client, isRunning);
std::thread loop = std::thread(&Core::UpdateGameState, this);
std::swap(loop, gameStateLoopThread);
assetManager = new AssetManager;
@@ -177,9 +177,14 @@ void Core::Exec() {
}
std::ostringstream toWindow;
- glm::highp_vec3 camPos(camera.Position);
+ auto camPos = gameState->Position();
+ auto velPos = glm::vec3(gameState->g_PlayerVelocityX, gameState->g_PlayerVelocityY,
+ gameState->g_PlayerVelocityZ);
toWindow << std::setprecision(2) << std::fixed;
- toWindow << "Pos: " << camPos.x << ", " << camPos.y << ", " << camPos.z << "; ";
+ toWindow << "Pos: " << camPos.x << ", " << camPos.y - 1.12 << ", " << camPos.z << "; ";
+ toWindow << "Health: " << gameState->g_PlayerHealth<<"; ";
+ //toWindow << "OG: " << gameState->g_OnGround << "; ";
+ toWindow << "Vel: " << velPos.x << ", " << velPos.y << ", " << velPos.z << "; ";
toWindow << "FPS: " << (1.0f / deltaTime) << " ";
toWindow << " (" << deltaTime * 1000 << "ms) ";
window->setTitle(toWindow.str());
@@ -227,7 +232,7 @@ void Core::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string W
contextSetting.depthBits = 24;
window = new sf::Window(sf::VideoMode(WinWidth, WinHeight), WinTitle, sf::Style::Default, contextSetting);
glCheckError();
- //window->setVerticalSyncEnabled(true);
+ window->setVerticalSyncEnabled(true);
//window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2, sf::VideoMode::getDesktopMode().height / 2));
window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2 - window->getSize().x / 2,
sf::VideoMode::getDesktopMode().height / 2 - window->getSize().y / 2));
@@ -283,52 +288,47 @@ void Core::HandleEvents() {
case sf::Keyboard::T:
SetMouseCapture(!isMouseCaptured);
break;
- case sf::Keyboard::Z:
- camera.MovementSpeed /= 2;
- break;
- case sf::Keyboard::X:
- camera.MovementSpeed *= 2;
- break;
case sf::Keyboard::M:
std::sort(toRender.begin(), toRender.end(), [this](const Vector &lhs, const Vector &rhs) {
- return glm::length((glm::vec3) lhs - camera.Position) <
- glm::length((glm::vec3) rhs - camera.Position);
+ return glm::length((glm::vec3) lhs - gameState->Position()) <
+ glm::length((glm::vec3) rhs - gameState->Position());
});
LOG(WARNING) << "Render list is optimized";
break;
- case sf::Keyboard::K:
- ChunkDistance++;
- LOG(INFO)<<"Increased render distance: "<<ChunkDistance;
- break;
case sf::Keyboard::L:
- ChunkDistance--;
- LOG(INFO)<<"Decreased render distance: "<<ChunkDistance;
+ ChunkDistance++;
+ LOG(INFO) << "Increased render distance: " << ChunkDistance;
break;
- case sf::Keyboard::O:
- UpdateChunksToRender();
- LOG(INFO)<<"Render list is updated";
+ case sf::Keyboard::K:
+ if (ChunkDistance > 1) {
+ ChunkDistance--;
+ LOG(INFO) << "Decreased render distance: " << ChunkDistance;
+ }
break;
default:
break;
}
- case sf::Event::MouseWheelScrolled:
- if (!window->hasFocus())
- break;
- camera.ProcessMouseScroll(event.mouseWheelScroll.delta);
- break;
+ /*case sf::Event::MouseWheelScrolled:
+ if (!window->hasFocus())
+ break;
+ camera.ProcessMouseScroll(event.mouseWheelScroll.delta);
+ break;*/
default:
break;
}
}
if (window->hasFocus()) {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
- camera.ProcessKeyboard(Camera_Movement::FORWARD, deltaTime);
+ gameState->HandleMovement(GameState::FORWARD, deltaTime);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
- camera.ProcessKeyboard(Camera_Movement::BACKWARD, deltaTime);
+ gameState->HandleMovement(GameState::BACKWARD, deltaTime);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
- camera.ProcessKeyboard(Camera_Movement::LEFT, deltaTime);
+ gameState->HandleMovement(GameState::LEFT, deltaTime);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
- camera.ProcessKeyboard(Camera_Movement::RIGHT, deltaTime);
+ gameState->HandleMovement(GameState::RIGHT, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
+ gameState->HandleMovement(GameState::JUMP, deltaTime);
+ UpdateChunksToRender();
}
}
@@ -337,7 +337,9 @@ void Core::HandleMouseCapture() {
sf::Vector2i center = sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2);
sf::Mouse::setPosition(center, *window);
mouseXDelta = (mousePos - center).x, mouseYDelta = (center - mousePos).y;
- camera.ProcessMouseMovement(mouseXDelta, mouseYDelta);
+ const float Sensetivity = 0.7f;
+ gameState->HandleRotation(mouseXDelta * Sensetivity, mouseYDelta * Sensetivity);
+ //camera.ProcessMouseMovement(mouseXDelta, mouseYDelta);
}
void Core::RenderGui(Gui &Target) {
@@ -354,8 +356,8 @@ void Core::RenderWorld() {
GLint blockLoc = glGetUniformLocation(shader->Program, "Block");
GLint stateLoc = glGetUniformLocation(shader->Program, "State");
GLint timeLoc = glGetUniformLocation(shader->Program, "time");
- glm::mat4 projection = glm::perspective(camera.Zoom, (float) width() / (float) height(), 0.1f, 10000000.0f);
- glm::mat4 view = camera.GetViewMatrix();
+ glm::mat4 projection = glm::perspective(45.0f, (float) width() / (float) height(), 0.1f, 10000000.0f);
+ glm::mat4 view = gameState->GetViewMatrix();
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniform1f(timeLoc, absTime);
@@ -365,7 +367,7 @@ void Core::RenderWorld() {
glBindVertexArray(VAO);
for (auto &sectionPos : toRender) {
- Section &section = gameState->world.m_sections.find(sectionPos)->second;
+ Section &section = gameState->world.sections.find(sectionPos)->second;
std::vector<Vector> sectionCorners = {
Vector(0, 0, 0),
@@ -389,10 +391,9 @@ void Core::RenderWorld() {
break;
}
}
- if (isBreak && glm::length(
- camera.Position - glm::vec3(sectionPos.GetX() * 16, sectionPos.GetY() * 16, sectionPos.GetZ() * 16)) >
+ if (isBreak && glm::length(gameState->Position() -
+ glm::vec3(sectionPos.GetX() * 16, sectionPos.GetY() * 16, sectionPos.GetZ() * 16)) >
30) {
- //zLOG(ERROR)<<"CULL";
continue;
}
@@ -502,32 +503,6 @@ void Core::PrepareToWorldRendering() {
TextureCoordinates tc = assetManager->GetTextureByBlock(BlockTextureId(id, state, side));
textureCoordinates.push_back(glm::vec4(tc.x, tc.y, tc.w, tc.h));
indexes.push_back(index);
- /*LOG(ERROR) << "Encoded texture (" << id << " " << state << " " << side << ") as " << index << " ("
- << std::bitset<19>(index) << ")" << " = " << tc.x << "," << tc.y << "," << tc.w << ","
- << tc.h;*/
- /*LOG(FATAL)<<std::bitset<18>(index);
- side = 0x7;
- id = 0xFFF;
- state = 0xF;
- LOG(WARNING) << "side: " << side << " id: " << id << " state: " << state;
- int i, si, st, index = 0;
- si = side << 15;
- i = id<<3;
- st = state;
- index = i | si | st;
- LOG(FATAL) << std::bitset<18>(index) << " (" << index << "): " << std::bitset<18>(si) << " "
- << std::bitset<18>(i) << " " << std::bitset<18>(st);*/
- /*if (rand() == 73) //Almost impossible(Almost==1/32768)
- {
- int index = 393233;
- LOG(WARNING) << std::bitset<20>(index) << "(" << index << ")";
- int side = (index & 0xE0000) >> 16;
- int id = (index & 0xFF0) >> 4;
- int state = index & 0xF;
- LOG(WARNING) << std::bitset<20>(side) << " " << std::bitset<20>(id) << " "
- << std::bitset<20>(state);
- LOG(FATAL) << side << " " << id << " " << state;
- }*/
side++;
} while (side < 6);
}
@@ -585,10 +560,17 @@ void Core::PrepareToWorldRendering() {
}
void Core::UpdateChunksToRender() {
- camera.Position = glm::vec3(gameState->g_PlayerX, gameState->g_PlayerY, gameState->g_PlayerZ);
- toRender.clear();
Vector playerChunk = Vector(floor(gameState->g_PlayerX / 16.0f), 0, floor(gameState->g_PlayerZ / 16.0f));
- for (auto &it:gameState->world.m_sections) {
+ static Vector previousPlayerChunk = playerChunk;
+ static bool firstTime = true;
+ static int previousRenderDistance = ChunkDistance;
+ if (previousPlayerChunk == playerChunk && !firstTime && ChunkDistance == previousRenderDistance) {
+ return;
+ }
+ previousPlayerChunk = playerChunk;
+ previousRenderDistance = ChunkDistance;
+ toRender.clear();
+ for (auto &it:gameState->world.sections) {
Vector chunkPosition = it.first;
chunkPosition.SetY(0);
Vector delta = chunkPosition - playerChunk;
@@ -596,9 +578,10 @@ void Core::UpdateChunksToRender() {
continue;
toRender.push_back(it.first);
}
- LOG(INFO) << "Chunks to render: " << toRender.size();
+ if (firstTime)
+ LOG(INFO) << "Chunks to render: " << toRender.size();
for (auto &it:toRender) {
- Section &section = gameState->world.m_sections.find(it)->second;
+ Section &section = gameState->world.sections.find(it)->second;
std::vector<glm::mat4> models;
std::vector<glm::vec2> blocks;
for (int y = 0; y < 16; y++) {
@@ -635,26 +618,31 @@ void Core::UpdateChunksToRender() {
toRenderModels[it] = models;
}
std::sort(toRender.begin(), toRender.end(), [this](const Vector &lhs, const Vector &rhs) {
- return glm::length((glm::vec3) lhs - camera.Position) < glm::length((glm::vec3) rhs - camera.Position);
+ return glm::length((glm::vec3) lhs - gameState->Position()) <
+ glm::length((glm::vec3) rhs - gameState->Position());
});
- LOG(INFO) << "Chunks is prepared to rendering...";
+ if (firstTime)
+ LOG(INFO) << "Chunks is prepared to rendering...";
+ firstTime = false;
}
void Core::UpdateGameState() {
el::Helpers::setThreadName("Game");
LOG(INFO) << "GameState thread is started";
+ sf::Clock delta;
while (isRunning) {
- gameState->Update();
- if (toRender.size() > 0)
- break;
+ float deltaTime = delta.getElapsedTime().asSeconds();
+ delta.restart();
+ gameState->Update(deltaTime);
+
}
LOG(INFO) << "GameState thread is stopped";
}
void Core::DrawLine(glm::vec3 from, glm::vec3 to, glm::vec3 color) {
shader2->Use();
- glm::mat4 projection = glm::perspective(camera.Zoom, (float) width() / (float) height(), 0.1f, 10000000.0f);
- glm::mat4 view = camera.GetViewMatrix();
+ glm::mat4 projection = glm::perspective(45.0f, (float) width() / (float) height(), 0.1f, 10000000.0f);
+ glm::mat4 view = gameState->GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(shader2->Program, "projection"), 1, GL_FALSE,
glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shader2->Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
@@ -686,7 +674,3 @@ void Core::DrawLine(glm::vec3 from, glm::vec3 to, glm::vec3 color) {
glEnable(GL_DEPTH_TEST);
}
-void Core::UpdateOptimizedRender() {
-
- LOG(INFO) << "Render list is optimized";
-}
diff --git a/src/core/Core.hpp b/src/core/Core.hpp
index 97a51fd..cc355db 100644
--- a/src/core/Core.hpp
+++ b/src/core/Core.hpp
@@ -61,16 +61,13 @@ class Core {
std::thread gameStateLoopThread;
- Camera3D camera;
Shader *shader,*shader2;
//Cube verticies, Cube VAO, Cube UVs, TextureIndexes UBO, TextureData UBO, TextureData2 UBO, Blocks VBO, Models VBO, Line VAO, Lines VBO
GLuint VBO, VAO, VBO2, UBO, UBO2, VBO3, VBO4, VAO2, VBO5;
std::vector<Vector> toRender;
std::vector<Vector> optimizedRender;
- void UpdateOptimizedRender();
-
- int ChunkDistance = 4;
+ int ChunkDistance = 2;
std::map<Vector, std::vector<glm::mat4>> toRenderModels;
std::map<Vector, std::vector<glm::vec2>> toRenderBlocks;
diff --git a/src/gamestate/GameState.cpp b/src/gamestate/GameState.cpp
index 5c5b9c4..3f3469d 100644
--- a/src/gamestate/GameState.cpp
+++ b/src/gamestate/GameState.cpp
@@ -1,131 +1,397 @@
#include "GameState.hpp"
-GameState::GameState(NetworkClient *Net) : nc(Net) {
- Packet *response = nc->GetPacket();
- if (response->GetId() != 0x02) {
- LOG(ERROR) << "Response id is " << response->GetId();
- throw std::runtime_error("Response id is not 0x02");
- }
- PacketParser::Parse(*response, Login);
- g_PlayerUuid = response->GetField(0).GetString();
- g_PlayerName = response->GetField(1).GetString();
- delete response;
- m_networkState = ConnectionState::Play;
- LOG(INFO) << g_PlayerName << "'s UUID is " << g_PlayerUuid;
+GameState::GameState(NetworkClient *Net, bool &quit) : nc(Net), isRunning(quit) {
+ Front = glm::vec3(0.0f, 0.0f, -1.0f);
+ this->SetPosition(glm::vec3(0.0f, 0.0f, 3.0f));
+ this->WorldUp = glm::vec3(0.0f, 1.0f, 0.0f);
+ this->updateCameraVectors();
}
-void GameState::Update() {
- Packet *packetPtr;
-
- try {
- packetPtr = nc->GetPacket();
- if (packetPtr == nullptr)
- return;
- PacketParser::Parse(*packetPtr, m_networkState);
- } catch (std::exception &e) {
- LOG(ERROR) << "Catched exception during packet pulling: " << e.what();
- return;
- }
- Packet &packet = *packetPtr;
- nlohmann::json json;
-
- switch (packet.GetId()) {
- case 0x23:
- g_PlayerEid = packet.GetField(0).GetInt();
- g_Gamemode = (packet.GetField(1).GetUByte() & 0b11111011);
- g_Dimension = packet.GetField(2).GetInt();
- g_Difficulty = packet.GetField(3).GetUByte();
- g_MaxPlayers = packet.GetField(4).GetUByte();
- g_LevelType = packet.GetField(5).GetString();
- g_ReducedDebugInfo = packet.GetField(6).GetBool();
- LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int) g_Difficulty
- << ", Level Type is " << g_LevelType;
- break;
- case 0x0D:
- g_Difficulty = packet.GetField(0).GetUByte();
- LOG(INFO) << "Difficulty now is " << (int) g_Difficulty;
- break;
- case 0x43:
- g_SpawnPosition = packet.GetField(0).GetPosition();
- LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << ","
- << g_SpawnPosition.GetZ();
- break;
- case 0x2B:
- g_PlayerInvulnerable = (packet.GetField(0).GetByte() & 0x01) != 0;
- g_PlayerFlying = (packet.GetField(0).GetByte() & 0x02) != 0;
- g_PlayerAllowFlying = (packet.GetField(0).GetByte() & 0x04) != 0;
- g_PlayerCreativeMode = (packet.GetField(0).GetByte() & 0x08) != 0;
- g_PlayerFlyingSpeed = packet.GetField(1).GetFloat();
- g_PlayerFovModifier = packet.GetField(2).GetFloat();
- LOG(INFO) << "FOV modifier is " << g_PlayerFovModifier;
- break;
- case 0x2E:
- if ((packet.GetField(5).GetByte() & 0x10) != 0) {
- g_PlayerPitch += packet.GetField(4).GetFloat();
- } else {
- g_PlayerPitch = packet.GetField(4).GetFloat();
- };
-
- if ((packet.GetField(5).GetByte() & 0x08) != 0) {
- g_PlayerYaw += packet.GetField(3).GetFloat();
- } else {
- g_PlayerYaw = packet.GetField(3).GetFloat();
- }
-
- if ((packet.GetField(5).GetByte() & 0x01) != 0) {
- g_PlayerX += packet.GetField(0).GetDouble();
- } else {
- g_PlayerX = packet.GetField(0).GetDouble();
- }
-
- if ((packet.GetField(5).GetByte() & 0x02) != 0) {
- g_PlayerY += packet.GetField(1).GetDouble();
- } else {
- g_PlayerY = packet.GetField(1).GetDouble();
- }
-
- if ((packet.GetField(5).GetByte() & 0x04) != 0) {
- g_PlayerZ += packet.GetField(2).GetDouble();
- } else {
- g_PlayerZ = packet.GetField(2).GetDouble();
- }
-
- g_IsGameStarted = true;
- nc->AddPacketToQueue(PacketBuilder::CPlay0x03(0));
- nc->AddPacketToQueue(PacketBuilder::CPlay0x00(packet.GetField(6).GetVarInt()));
- LOG(INFO) << "Game is started!";
- LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\tAngle: "
- << g_PlayerYaw
- << "," << g_PlayerPitch;
- break;
- case 0x1A:
- json = nlohmann::json::parse(packet.GetField(0).GetString());
- LOG(INFO) << "Disconnect reason: " << json["text"].get<std::string>();
- throw 119;
- break;
- case 0x20:
- world.ParseChunkData(packet);
- break;
- case 0x07:
- LOG(INFO) << "Statistics: ";
- for (int i = 0; i < packet.GetField(0).GetVarInt(); i++) {
- LOG(INFO) << "\t" << packet.GetField(1).GetArray()[0].GetString() << ": "
- << packet.GetField(1).GetArray()[1].GetVarInt();
- }
- break;
- default:
- break;
- }
- if (g_IsGameStarted) {
- std::chrono::steady_clock clock;
- static auto timeOfPreviousSendedPpalPacket(clock.now());
- std::chrono::duration<double, std::milli> delta = clock.now() - timeOfPreviousSendedPpalPacket;
- if (delta.count() >= 50) {
- nc->AddPacketToQueue(
- PacketBuilder::CPlay0x0D(g_PlayerX, g_PlayerY, g_PlayerZ, g_PlayerYaw, g_PlayerPitch, true));
- timeOfPreviousSendedPpalPacket = clock.now();
- }
- }
-
- delete packetPtr;
+void GameState::Update(float deltaTime) {
+ if (g_IsGameStarted) {
+ std::chrono::steady_clock clock;
+ static auto timeOfPreviousSendedPacket(clock.now());
+ auto delta = clock.now() - timeOfPreviousSendedPacket;
+ using namespace std::chrono_literals;
+ if (delta >= 50ms) {
+ nc->SendPacket(std::make_shared<PacketPlayerPositionAndLookSB>(g_PlayerX, g_PlayerY, g_PlayerZ, g_PlayerYaw,
+ g_PlayerPitch, g_OnGround));
+ timeOfPreviousSendedPacket = clock.now();
+ }
+
+ const float gravity = -9.8f;
+ g_PlayerVelocityY += gravity * deltaTime;
+
+ bool isCollides = world.isPlayerCollides(g_PlayerX, g_PlayerY + g_PlayerVelocityY * deltaTime,
+ g_PlayerZ);
+ if (!isCollides) {
+ g_PlayerY += g_PlayerVelocityY * deltaTime;
+ g_OnGround = false;
+ } else {
+ g_PlayerVelocityY = 0;
+ g_OnGround = true;
+ }
+
+ isCollides = world.isPlayerCollides(g_PlayerX + g_PlayerVelocityX * deltaTime, g_PlayerY,
+ g_PlayerZ + g_PlayerVelocityZ * deltaTime);
+ if (!isCollides) {
+ g_PlayerX += g_PlayerVelocityX * deltaTime;
+ g_PlayerZ += g_PlayerVelocityZ * deltaTime;
+ }
+
+ /*const float AirResistance = 10.0f;
+ if (std::abs(g_PlayerVelocityX) > 0.01)
+ g_PlayerVelocityX -= AirResistance * deltaTime * (g_PlayerVelocityX > 0 ? 1 : -1);
+ else
+ g_PlayerVelocityX = 0;
+ if (std::abs(g_PlayerVelocityZ) > 0.01)
+ g_PlayerVelocityZ -= AirResistance * deltaTime * (g_PlayerVelocityZ > 0 ? 1 : -1);
+ else
+ g_PlayerVelocityZ = 0;*/
+ const float AirResistance = 10.0f;
+ glm::vec3 vel(g_PlayerVelocityX, 0, g_PlayerVelocityZ);
+ glm::vec3 resistForce = -vel * AirResistance * deltaTime;
+ vel += resistForce;
+ g_PlayerVelocityX = vel.x;
+ g_PlayerVelocityZ = vel.z;
+ }
+
+
+ //Packet handling
+ auto ptr = nc->ReceivePacket();
+ if (ptr == nullptr)
+ return;
+ switch ((PacketNamePlayCB) ptr->GetPacketId()) {
+ case SpawnObject:
+ break;
+ case SpawnExperienceOrb:
+ break;
+ case SpawnGlobalEntity:
+ break;
+ case SpawnMob:
+ break;
+ case SpawnPainting:
+ break;
+ case SpawnPlayer:
+ break;
+ case AnimationCB:
+ break;
+ case Statistics:
+ break;
+ case BlockBreakAnimation:
+ break;
+ case UpdateBlockEntity:
+ break;
+ case BlockAction:
+ break;
+ case BlockChange:
+ break;
+ case BossBar:
+ break;
+ case ServerDifficulty:
+ break;
+ case TabCompleteCB:
+ break;
+ case ChatMessageCB:
+ break;
+ case MultiBlockChange:
+ break;
+ case ConfirmTransactionCB:
+ break;
+ case CloseWindowCB:
+ break;
+ case OpenWindow:
+ break;
+ case WindowItems:
+ break;
+ case WindowProperty:
+ break;
+ case SetSlot:
+ break;
+ case SetCooldown:
+ break;
+ case PluginMessageCB:
+ break;
+ case NamedSoundEffect:
+ break;
+ case DisconnectPlay: {
+ auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr);
+ LOG(INFO) << "Disconnect reason: " << packet->Reason;
+ isRunning = false;
+ break;
+ }
+ case EntityStatus:
+ break;
+ case Explosion:
+ break;
+ case UnloadChunk:
+ break;
+ case ChangeGameState:
+ break;
+ case KeepAliveCB:
+ LOG(WARNING) << "Receive KeepAlive packet in GameState handler";
+ break;
+ case ChunkData: {
+ auto packet = std::static_pointer_cast<PacketChunkData>(ptr);
+ world.ParseChunkData(packet);
+ break;
+ }
+ case Effect:
+ break;
+ case Particle:
+ break;
+ case JoinGame: {
+ auto packet = std::static_pointer_cast<PacketJoinGame>(ptr);
+ g_PlayerEid = packet->EntityId;
+ g_Gamemode = (packet->Gamemode & 0b11111011);
+ g_Dimension = packet->Dimension;
+ g_Difficulty = packet->Difficulty;
+ g_MaxPlayers = packet->MaxPlayers;
+ g_LevelType = packet->LevelType;
+ g_ReducedDebugInfo = packet->ReducedDebugInfo;
+ LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int) g_Difficulty
+ << ", Level Type is " << g_LevelType;
+ break;
+ }
+ case Map:
+ break;
+ case EntityRelativeMove:
+ break;
+ case EntityLookAndRelativeMove:
+ break;
+ case EntityLook:
+ break;
+ case Entity:
+ break;
+ case VehicleMove:
+ break;
+ case OpenSignEditor:
+ break;
+ case PlayerAbilitiesCB:
+ break;
+ case CombatEvent:
+ break;
+ case PlayerListItem:
+ break;
+ case PlayerPositionAndLookCB: {
+ auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr);
+ if ((packet->Flags & 0x10) != 0) {
+ g_PlayerPitch += packet->Pitch;
+ } else {
+ g_PlayerPitch = packet->Pitch;
+ };
+
+ if ((packet->Flags & 0x08) != 0) {
+ g_PlayerYaw += packet->Yaw;
+ } else {
+ g_PlayerYaw = packet->Yaw;
+ }
+
+ if ((packet->Flags & 0x01) != 0) {
+ g_PlayerX += packet->X;
+ } else {
+ g_PlayerX = packet->X;
+ }
+
+ if ((packet->Flags & 0x02) != 0) {
+ g_PlayerY += packet->Y;
+ } else {
+ g_PlayerY = packet->Y;
+ }
+
+ if ((packet->Flags & 0x04) != 0) {
+ g_PlayerZ += packet->Z;
+ } else {
+ g_PlayerZ = packet->Z;
+ }
+
+ //if (!g_IsGameStarted)
+ LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\t\tAngle: "
+ << g_PlayerYaw << "," << g_PlayerPitch;
+
+ g_IsGameStarted = true;
+
+ auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+
+ nc->SendPacket(packetResponse);
+ nc->SendPacket(packetPerformRespawn);
+ break;
+ }
+ case UseBed:
+ break;
+ case UnlockRecipes:
+ break;
+ case DestroyEntities:
+ break;
+ case RemoveEntityEffect:
+ break;
+ case ResourcePackSend:
+ break;
+ case Respawn:
+ break;
+ case EntityHeadLook:
+ break;
+ case SelectAdvancementTab:
+ break;
+ case WorldBorder:
+ break;
+ case Camera:
+ break;
+ case HeldItemChangeCB:
+ break;
+ case DisplayScoreboard:
+ break;
+ case EntityMetadata:
+ break;
+ case AttachEntity:
+ break;
+ case EntityVelocity:
+ break;
+ case EntityEquipment:
+ break;
+ case SetExperience:
+ break;
+ case UpdateHealth: {
+ auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr);
+ g_PlayerHealth = packet->Health;
+ if (g_PlayerHealth<1) {
+ LOG(INFO)<<"Player is dead. Respawning...";
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+ nc->SendPacket(packetPerformRespawn);
+ }
+ break;
+ }
+ case ScoreboardObjective:
+ break;
+ case SetPassengers:
+ break;
+ case Teams:
+ break;
+ case UpdateScore:
+ break;
+ case SpawnPosition: {
+ auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr);
+ g_SpawnPosition = packet->Location;
+ LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << ","
+ << g_SpawnPosition.GetZ();
+ break;
+ }
+ case TimeUpdate:
+ break;
+ case Title:
+ break;
+ case SoundEffect:
+ break;
+ case PlayerListHeaderAndFooter:
+ break;
+ case CollectItem:
+ break;
+ case EntityTeleport:
+ break;
+ case Advancements:
+ break;
+ case EntityProperties:
+ break;
+ case EntityEffect:
+ break;
+ }
+}
+
+void GameState::HandleMovement(GameState::Direction direction, float deltaTime) {
+ const float PlayerSpeed = 40.0;
+ float velocity = PlayerSpeed * deltaTime;
+ glm::vec3 vel(g_PlayerVelocityX, g_PlayerVelocityY, g_PlayerVelocityZ);
+ glm::vec3 front(cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())), 0,
+ sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())));
+ front = glm::normalize(front);
+ glm::vec3 right = glm::normalize(glm::cross(front, this->WorldUp));
+ switch (direction) {
+ case FORWARD:
+ vel += front * velocity;
+ break;
+ case BACKWARD:
+ vel -= front * velocity;
+ break;
+ case RIGHT:
+ vel += right * velocity;
+ break;
+ case LEFT:
+ vel -= right * velocity;
+ break;
+ case JUMP:
+ if (g_OnGround)
+ vel.y += 5;
+ break;
+ }
+ g_PlayerVelocityX = vel.x;
+ g_PlayerVelocityY = vel.y;
+ g_PlayerVelocityZ = vel.z;
+ const double MaxSpeed = 5.0;
+ /*if (g_PlayerVelocityX > MaxSpeed || g_PlayerVelocityX < -MaxSpeed)
+ g_PlayerVelocityX = MaxSpeed * (g_PlayerVelocityX > 0 ? 1 : -1);
+ if (g_PlayerVelocityZ > MaxSpeed || g_PlayerVelocityZ < -MaxSpeed)
+ g_PlayerVelocityZ = MaxSpeed * (g_PlayerVelocityZ > 0 ? 1 : -1);*/
+
+
+ /*bool isCollides = world.isPlayerCollides(g_PlayerX, g_PlayerY, g_PlayerZ);
+ if (isCollides) {
+ SetPosition(previousPos);
+ return;
+ }
+ auto updatePacket = std::make_shared<PacketPlayerPosition>(g_PlayerX, g_PlayerY, g_PlayerZ, true);
+ nc->SendPacket(updatePacket);*/
+}
+
+void GameState::HandleRotation(double yaw, double pitch) {
+ this->SetYaw(Yaw() + yaw);
+ this->SetPitch(Pitch() + pitch);
+ if (this->Pitch() > 89.0f)
+ this->SetPitch(89.0f);
+ if (this->Pitch() < -89.0f)
+ this->SetPitch(-89.0f);
+ this->updateCameraVectors();
+
+ auto updatePacket = std::make_shared<PacketPlayerLook>(g_PlayerYaw, g_PlayerPitch, g_OnGround);
+ nc->SendPacket(updatePacket);
+}
+
+glm::mat4 GameState::GetViewMatrix() {
+ return glm::lookAt(this->Position(), this->Position() + this->Front, this->Up);
+}
+
+void GameState::updateCameraVectors() {
+ glm::vec3 front;
+ front.x = cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch()));
+ front.y = sin(glm::radians(this->Pitch()));
+ front.z = sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch()));
+ this->Front = glm::normalize(front);
+ this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));
+ this->Up = glm::normalize(glm::cross(this->Right, this->Front));
+}
+
+float GameState::Yaw() {
+ return g_PlayerYaw + 90;
+}
+
+float GameState::Pitch() {
+ return -g_PlayerPitch;
+}
+
+void GameState::SetYaw(float yaw) {
+ g_PlayerYaw = yaw - 90;
+}
+
+void GameState::SetPitch(float pitch) {
+ g_PlayerPitch = -pitch;
+}
+
+glm::vec3 GameState::Position() {
+ return glm::vec3(g_PlayerX - 0.5, g_PlayerY + 1.12, g_PlayerZ - 0.5);
+}
+
+void GameState::SetPosition(glm::vec3 Position) {
+ g_PlayerX = Position.x + 0.5;
+ g_PlayerY = Position.y - 1.12;
+ g_PlayerZ = Position.z + 0.5;
}
diff --git a/src/gamestate/GameState.hpp b/src/gamestate/GameState.hpp
index 8817f4c..27338fb 100644
--- a/src/gamestate/GameState.hpp
+++ b/src/gamestate/GameState.hpp
@@ -1,41 +1,70 @@
#pragma once
#include <nlohmann/json.hpp>
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
#include "../world/World.hpp"
#include "../network/NetworkClient.hpp"
-#include "../packet/PacketParser.hpp"
-#include "../packet/PacketBuilder.hpp"
+#include "../utility/Vector.hpp"
class GameState {
- NetworkClient *nc;
+ NetworkClient *nc;
public:
- GameState(NetworkClient *NetClient);
-
- World world;
-
- void Update();
-
- std::string g_PlayerUuid;
- std::string g_PlayerName;
- ConnectionState m_networkState;
- bool g_IsGameStarted;
- int g_PlayerEid;
- int g_Gamemode;
- int g_Dimension;
- byte g_Difficulty;
- byte g_MaxPlayers;
- std::string g_LevelType;
- bool g_ReducedDebugInfo;
- Vector g_SpawnPosition;
- bool g_PlayerInvulnerable;
- bool g_PlayerFlying;
- bool g_PlayerAllowFlying;
- bool g_PlayerCreativeMode;
- float g_PlayerFlyingSpeed;
- float g_PlayerFovModifier;
- float g_PlayerPitch;
- float g_PlayerYaw;
- double g_PlayerX;
- double g_PlayerY;
- double g_PlayerZ;
+ GameState(NetworkClient *NetClient, bool &quit);
+
+ void Update(float deltaTime);
+
+ //Navigation
+ enum Direction {
+ FORWARD, BACKWARD, LEFT, RIGHT, JUMP
+ };
+ void HandleMovement(GameState::Direction direction, float deltaTime);
+ void HandleRotation(double yaw, double pitch);
+ glm::mat4 GetViewMatrix();
+ void updateCameraVectors();
+
+ float Yaw();
+ float Pitch();
+ void SetYaw(float yaw);
+ void SetPitch(float pitch);
+
+ glm::vec3 Position();
+ void SetPosition(glm::vec3 Position);
+ glm::vec3 Front;
+ glm::vec3 Up;
+ glm::vec3 Right;
+ glm::vec3 WorldUp;
+
+ //Everything other
+ World world;
+ bool &isRunning;
+
+ std::string g_PlayerUuid;
+ std::string g_PlayerName;
+ bool g_IsGameStarted;
+ int g_PlayerEid;
+ int g_Gamemode;
+ int g_Dimension;
+ byte g_Difficulty;
+ byte g_MaxPlayers;
+ std::string g_LevelType;
+ bool g_ReducedDebugInfo;
+ Vector g_SpawnPosition;
+ bool g_PlayerInvulnerable;
+ bool g_PlayerFlying;
+ bool g_PlayerAllowFlying;
+ bool g_PlayerCreativeMode;
+ float g_PlayerFlyingSpeed;
+ float g_PlayerFovModifier;
+ float g_PlayerPitch;
+ float g_PlayerYaw;
+ double g_PlayerX;
+ double g_PlayerY;
+ double g_PlayerZ;
+ float g_PlayerHealth;
+
+ bool g_OnGround = true;
+ double g_PlayerVelocityX = 0;
+ double g_PlayerVelocityY = 0;
+ double g_PlayerVelocityZ = 0;
};
diff --git a/src/network/Network.cpp b/src/network/Network.cpp
index 4ce424c..59c4e00 100644
--- a/src/network/Network.cpp
+++ b/src/network/Network.cpp
@@ -1,101 +1,215 @@
#include "Network.hpp"
+#include <iostream>
-Network::Network(std::string address, unsigned short port) : m_address(address), m_port(port) {
- LOG(INFO) << "Connecting to server " << m_address << ":" << m_port;
- sf::Socket::Status status = m_socket.connect(sf::IpAddress(m_address), m_port);
- m_socket.setBlocking(true);
- if (status != sf::Socket::Done) {
- if (status == sf::Socket::Error) {
- LOG(ERROR) << "Can't connect to remote server";
- } else {
- LOG(ERROR) << "Connection failed with unknown reason";
- throw std::runtime_error("Connection is failed");
- throw 13;
- }
- }
- LOG(INFO) << "Connected to server";
+Network::Network(std::string address, unsigned short port) {
+ socket = new Socket(address, port);
+ stream = new StreamSocket(socket);
}
Network::~Network() {
- m_socket.disconnect();
- LOG(INFO) << "Disconnected";
-}
-
-void Network::SendHandshake(std::string username) {
- //Handshake packet
- Packet handshakePacket = PacketBuilder::CHandshaking0x00(316, m_address, m_port, 2);
- SendPacket(handshakePacket);
-
- //LoginStart packet
- Field fName;
- fName.SetString(username);
- Packet loginPacket(0);
- loginPacket.AddField(fName);
- SendPacket(loginPacket);
+ delete stream;
+ delete socket;
}
-void DumpPacket(Packet &packet, std::string DumpName) {
- return;
- byte *buff = new byte[packet.GetLength()];
- packet.CopyToBuff(buff);
- std::ofstream fs(DumpName, std::ios::out | std::ios::binary);
- fs.write(reinterpret_cast<const char *>(buff), packet.GetLength());
- fs.close();
- delete buff;
+std::shared_ptr<Packet> Network::ReceivePacket(ConnectionState state) {
+ int packetSize = stream->ReadVarInt();
+ auto packetData = stream->ReadByteArray(packetSize);
+ StreamBuffer streamBuffer(packetData.data(), packetData.size());
+ int packetId = streamBuffer.ReadVarInt();
+ auto packet = ReceivePacketByPacketId(packetId, state, streamBuffer);
+ return packet;
}
-static int pn = 0;
-
void Network::SendPacket(Packet &packet) {
- m_socket.setBlocking(true);
- byte *packetData = new byte[packet.GetLength()];
- packet.CopyToBuff(packetData);
- m_socket.send(packetData, packet.GetLength());
- std::ostringstream out;
- out << "s" << pn++ << "-";
- out << "0x" << (packet.GetId() < 15 ? "0" : "") << std::hex << packet.GetId() << std::dec;
- DumpPacket(packet, out.str());
-
- delete[] packetData;
+ StreamCounter packetSize;
+ packetSize.WriteVarInt(packet.GetPacketId());
+ packet.ToStream(&packetSize);
+ stream->WriteVarInt(packetSize.GetCountedSize());
+ stream->WriteVarInt(packet.GetPacketId());
+ packet.ToStream(stream);
}
-Packet Network::ReceivePacket() {
- byte bufLen[5] = {0};
- size_t rec = 0;
- for (int i = 0; i < 5; i++) {
- byte buff = 0;
- size_t r = 0;
- m_socket.receive(&buff, 1, r);
- rec += r;
- bufLen[i] = buff;
- if ((buff & 0b10000000) == 0) {
- break;
- }
- }
- Field fLen = FieldParser::Parse(VarIntType, bufLen);
- size_t packetLen = fLen.GetVarInt() + fLen.GetLength();
- if (packetLen > 1024 * 1024 * 15)
- LOG(WARNING) << "OMG SIZEOF PACKAGE IS " << packetLen;
- if (packetLen < rec) {
- return Packet(bufLen);
- }
- byte *bufPack = new byte[packetLen];
- 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;
+std::shared_ptr<Packet> Network::ReceivePacketByPacketId(int packetId, ConnectionState state, StreamInput &stream) {
+ std::shared_ptr<Packet> packet(nullptr);
+ switch (state) {
+ case Handshaking:
+ switch (packetId) {
+ case PacketNameHandshakingCB::Handshake:
+ packet = std::make_shared<PacketHandshake>();
+ break;
+ }
+ case Login:
+ switch (packetId) {
+ case PacketNameLoginCB::LoginSuccess:
+ packet = std::make_shared<PacketLoginSuccess>();
+ break;
+ }
+ break;
+ case Play:
+ packet = ParsePacketPlay((PacketNamePlayCB) packetId);
+ break;
+ case Status:
+ break;
}
- if (dataLen < packetLen) {
- LOG(ERROR) << "Received data is " << dataLen << " but " << packetLen << " is promoted";
- throw std::runtime_error("Data is losted");
- } else {
- Packet p(bufPack);
- delete[] bufPack;
+ if (packet.get() != nullptr)
+ packet->FromStream(&stream);
+ return packet;
+}
- std::ostringstream out;
- out << "r" << pn++ << "-";
- out << "0x" << (p.GetId() < 15 ? "0" : "") << std::hex << p.GetId() << std::dec;
- DumpPacket(p, out.str());
- return p;
+std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
+ switch (id) {
+ case SpawnObject:
+ break;
+ case SpawnExperienceOrb:
+ break;
+ case SpawnGlobalEntity:
+ break;
+ case SpawnMob:
+ break;
+ case SpawnPainting:
+ break;
+ case SpawnPlayer:
+ break;
+ case AnimationCB:
+ break;
+ case Statistics:
+ break;
+ case BlockBreakAnimation:
+ break;
+ case UpdateBlockEntity:
+ break;
+ case BlockAction:
+ break;
+ case BlockChange:
+ break;
+ case BossBar:
+ break;
+ case ServerDifficulty:
+ break;
+ case TabCompleteCB:
+ break;
+ case ChatMessageCB:
+ break;
+ case MultiBlockChange:
+ break;
+ case ConfirmTransactionCB:
+ break;
+ case CloseWindowCB:
+ break;
+ case OpenWindow:
+ break;
+ case WindowItems:
+ break;
+ case WindowProperty:
+ break;
+ case SetSlot:
+ break;
+ case SetCooldown:
+ break;
+ case PluginMessageCB:
+ break;
+ case NamedSoundEffect:
+ break;
+ case DisconnectPlay:
+ return std::make_shared<PacketDisconnectPlay>();
+ case EntityStatus:
+ break;
+ case Explosion:
+ break;
+ case UnloadChunk:
+ break;
+ case ChangeGameState:
+ break;
+ case KeepAliveCB:
+ return std::make_shared<PacketKeepAliveCB>();
+ case ChunkData:
+ return std::make_shared<PacketChunkData>();
+ case Effect:
+ break;
+ case Particle:
+ break;
+ case JoinGame:
+ return std::make_shared<PacketJoinGame>();
+ case Map:
+ break;
+ case EntityRelativeMove:
+ break;
+ case EntityLookAndRelativeMove:
+ break;
+ case EntityLook:
+ break;
+ case Entity:
+ break;
+ case VehicleMove:
+ break;
+ case OpenSignEditor:
+ break;
+ case PlayerAbilitiesCB:
+ break;
+ case CombatEvent:
+ break;
+ case PlayerListItem:
+ break;
+ case PlayerPositionAndLookCB:
+ return std::make_shared<PacketPlayerPositionAndLookCB>();
+ case UseBed:
+ break;
+ case DestroyEntities:
+ break;
+ case RemoveEntityEffect:
+ break;
+ case ResourcePackSend:
+ break;
+ case Respawn:
+ break;
+ case EntityHeadLook:
+ break;
+ case WorldBorder:
+ break;
+ case Camera:
+ break;
+ case HeldItemChangeCB:
+ break;
+ case DisplayScoreboard:
+ break;
+ case EntityMetadata:
+ break;
+ case AttachEntity:
+ break;
+ case EntityVelocity:
+ break;
+ case EntityEquipment:
+ break;
+ case SetExperience:
+ break;
+ case UpdateHealth:
+ return std::make_shared<PacketUpdateHealth>();
+ case ScoreboardObjective:
+ break;
+ case SetPassengers:
+ break;
+ case Teams:
+ break;
+ case UpdateScore:
+ break;
+ case SpawnPosition:
+ return std::make_shared<PacketSpawnPosition>();
+ case TimeUpdate:
+ break;
+ case Title:
+ break;
+ case SoundEffect:
+ break;
+ case PlayerListHeaderAndFooter:
+ break;
+ case CollectItem:
+ break;
+ case EntityTeleport:
+ break;
+ case EntityProperties:
+ break;
+ case EntityEffect:
+ break;
}
+ return nullptr;
}
diff --git a/src/network/Network.hpp b/src/network/Network.hpp
index 84f2e7f..1281289 100644
--- a/src/network/Network.hpp
+++ b/src/network/Network.hpp
@@ -1,28 +1,26 @@
#pragma once
-#include <string>
-#include <easylogging++.h>
-#include <SFML/Network.hpp>
-#include "../packet/Packet.hpp"
-#include "../packet/PacketBuilder.hpp"
-
+#include <memory>
+#include "Socket.hpp"
+#include "Packet.hpp"
+
+enum ConnectionState {
+ Handshaking,
+ Login,
+ Play,
+ Status,
+};
class Network {
-public:
- Network(std::string address, unsigned short port);
-
- ~Network();
-
- void SendHandshake(std::string username);
+ Socket *socket;
+ StreamSocket *stream;
- void SendPacket(Packet &packet);
-
- Packet ReceivePacket();
-
-private:
- std::string m_address;
- unsigned short m_port;
- sf::TcpSocket m_socket;
- bool m_isCommpress=false;
-};
+ std::shared_ptr<Packet> ReceivePacketByPacketId(int packetId, ConnectionState state, StreamInput &stream);
+public:
+ Network(std::string address, unsigned short port);
+ ~Network();
+ std::shared_ptr<Packet> ReceivePacket(ConnectionState state = Play);
+ void SendPacket(Packet &packet);
+ std::shared_ptr<Packet> ParsePacketPlay(PacketNamePlayCB id);
+}; \ No newline at end of file
diff --git a/src/network/NetworkClient.cpp b/src/network/NetworkClient.cpp
index fd957a5..b8d880d 100644
--- a/src/network/NetworkClient.cpp
+++ b/src/network/NetworkClient.cpp
@@ -1,107 +1,94 @@
#include "NetworkClient.hpp"
+#include "Packet.hpp"
-ServerInfo NetworkClient::ServerPing(std::string address, unsigned short port) {
- ServerInfo info;
- Network network(address, port);
- Packet packet_handshake = PacketBuilder::CHandshaking0x00(316, address, port, 1);
- network.SendPacket(packet_handshake);
- Packet packet_request(0);
- network.SendPacket(packet_request);
- Packet packet_response = network.ReceivePacket();
- PacketParser::Parse(packet_response, Login);
- //std::string json = static_cast<FieldString *>(packet_response_parsed.GetFieldById(0))->GetValue();
- std::string json = packet_response.GetField(0).GetString();
- try {
- nlohmann::json j = nlohmann::json::parse(json);
- info.protocol = j["version"]["protocol"].get<int>();
- info.version = j["version"]["name"].get<std::string>();
- info.players_max = j["players"]["max"].get<int>();
- info.players_online = j["players"]["online"].get<int>();
- info.description = j["description"]["text"].get<std::string>();
- for (auto t:j["description"]["extra"]) {
- info.description += t["text"].get<std::string>();
- }
- if (!j["favicon"].is_null())
- info.favicon = j["favicon"].get<std::string>();
- info.json = json;
- for (auto t:j["players"]["sample"]) {
- std::pair<std::string, std::string> player;
- player.first = t["id"].get<std::string>();
- player.second = t["name"].get<std::string>();
- info.players.push_back(player);
- }
- } catch (const nlohmann::detail::exception e) {
- std::cerr << "Parsed json is not valid (" << e.id << "): " << e.what() << std::endl;
- }
- //Ping
- Packet packet_ping(0x01);
- Field payload;
- payload.SetLong(771235);
- packet_ping.AddField(payload);
- std::chrono::high_resolution_clock clock;
- auto t1 = clock.now();
- network.SendPacket(packet_ping);
- Packet pong = network.ReceivePacket();
- auto t2 = clock.now();
- pong.ParseField(Long);
- if (pong.GetField(0).GetLong() == 771235) {
- std::chrono::duration<double, std::milli> pingTime = t2 - t1;
- info.ping = pingTime.count();
- }
- return info;
-}
+NetworkClient::NetworkClient(std::string address, unsigned short port, std::string username, bool &quit)
+ : network(address, port), isRunning(quit) {
+ state = Handshaking;
-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);
-}
+ PacketHandshake handshake;
+ handshake.protocolVersion = 335;
+ handshake.serverAddress = "127.0.0.1";
+ handshake.serverPort = 25565;
+ handshake.nextState = 2;
+ network.SendPacket(handshake);
+ state = Login;
-NetworkClient::~NetworkClient() {
- LOG(INFO)<<"NC stopping...";
- isContinue=false;
- m_networkThread.join();
- LOG(INFO)<<"NC is stopped";
-}
+ PacketLoginStart loginStart;
+ loginStart.Username = "HelloOne";
+ network.SendPacket(loginStart);
-Packet * NetworkClient::GetPacket() {
- if (m_received.size() < 1)
- return nullptr;
- Packet packet = m_received.front();
- m_received.pop();
- return new Packet(packet);
+ auto response = std::static_pointer_cast<PacketLoginSuccess>(network.ReceivePacket(Login));
+ if (response->Username != username) {
+ throw std::logic_error("Received username is not sended username");
+ }
+
+ state = Play;
+
+ isActive = true;
+ std::thread thread(&NetworkClient::NetworkLoop, this);
+ std::swap(networkThread, thread);
}
-void NetworkClient::AddPacketToQueue(Packet packet) {
- m_toSend.push(packet);
+NetworkClient::~NetworkClient() {
+ isActive = false;
+ networkThread.join();
}
-void NetworkClient::Update() {
- if (m_toSend.size() > 0) {
- m_network.SendPacket(m_toSend.front());
- m_toSend.pop();
- }
- Packet received = m_network.ReceivePacket();
- 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();
+std::shared_ptr<Packet> NetworkClient::ReceivePacket() {
+ if (toReceive.empty())
+ return std::shared_ptr<Packet>(nullptr);
+ toReceiveMutex.lock();
+ auto ret = toReceive.front();
+ toReceive.pop();
+ toReceiveMutex.unlock();
+ return ret;
}
-void NetworkClient::MainLoop() {
- el::Helpers::setThreadName("Network");
- try {
- while (isContinue) {
- Update();
- }
- } catch (int e){
- LOG(ERROR)<<"Catched exception in NC: "<<e;
- }
+void NetworkClient::SendPacket(std::shared_ptr<Packet> packet) {
+ toSendMutex.lock();
+ toSend.push(packet);
+ toSendMutex.unlock();
+}
+void NetworkClient::NetworkLoop() {
+ auto timeOfLastKeepAlivePacket = std::chrono::steady_clock::now();
+ el::Helpers::setThreadName("Network");
+ LOG(INFO) << "Network thread is started";
+ try {
+ while (isActive) {
+ toSendMutex.lock();
+ while (!toSend.empty()) {
+ if (toSend.front()!=nullptr)
+ network.SendPacket(*toSend.front());
+ toSend.pop();
+ }
+ toSendMutex.unlock();
+ auto packet = network.ReceivePacket(state);
+ if (packet.get() != nullptr) {
+ if (packet->GetPacketId() != PacketNamePlayCB::KeepAliveCB) {
+ toReceiveMutex.lock();
+ toReceive.push(packet);
+ toReceiveMutex.unlock();
+ } else {
+ timeOfLastKeepAlivePacket = std::chrono::steady_clock::now();
+ auto packetKeepAlive = std::static_pointer_cast<PacketKeepAliveCB>(packet);
+ auto packetKeepAliveSB = std::make_shared<PacketKeepAliveSB>(packetKeepAlive->KeepAliveId);
+ network.SendPacket(*packetKeepAliveSB);
+ }
+ }
+ using namespace std::chrono_literals;
+ if (std::chrono::steady_clock::now() - timeOfLastKeepAlivePacket > 20s) {
+ auto disconnectPacket = std::make_shared<PacketDisconnectPlay>();
+ disconnectPacket->Reason = "Timeout";
+ toReceiveMutex.lock();
+ toReceive.push(disconnectPacket);
+ toReceiveMutex.unlock();
+ break;
+ }
+ }
+ } catch (std::exception &e) {
+ LOG(ERROR) << "Exception catched in NetworkLoop: " << e.what();
+ isRunning = false;
+ }
+ LOG(INFO) << "Network thread is stopped";
}
diff --git a/src/network/NetworkClient.hpp b/src/network/NetworkClient.hpp
index 14745a5..bf7aa4e 100644
--- a/src/network/NetworkClient.hpp
+++ b/src/network/NetworkClient.hpp
@@ -1,45 +1,25 @@
#pragma once
-#include <queue>
#include <thread>
+#include <queue>
#include <mutex>
-#include <nlohmann/json.hpp>
#include "Network.hpp"
-#include "../packet/PacketParser.hpp"
-#include "../packet/PacketBuilder.hpp"
-struct ServerInfo{
- std::string version;
- int protocol = 0;
- int players_max = 0;
- int players_online = 0;
- std::vector<std::pair<std::string, std::string>> players;
- std::string description;
- double ping = 0;
- std::string favicon;
- std::string json;
-};
class NetworkClient {
+ Network network;
+ std::thread networkThread;
+ std::mutex toSendMutex;
+ std::mutex toReceiveMutex;
+ std::queue <std::shared_ptr<Packet>> toSend;
+ std::queue <std::shared_ptr<Packet>> toReceive;
+ bool isActive=true;
+ bool &isRunning;
+ ConnectionState state;
+ void NetworkLoop();
public:
- NetworkClient(std::string address, unsigned short port, std::string username);
- ~NetworkClient();
-
- void Update();
-
- 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;
- std::queue <Packet> m_received;
- std::queue <Packet> m_toSend;
-};
+ NetworkClient(std::string address, unsigned short port, std::string username, bool &quit);
+ ~NetworkClient();
+ std::shared_ptr <Packet> ReceivePacket();
+ void SendPacket(std::shared_ptr<Packet> packet);
+}; \ No newline at end of file
diff --git a/src/network/Packet.hpp b/src/network/Packet.hpp
new file mode 100644
index 0000000..9249a34
--- /dev/null
+++ b/src/network/Packet.hpp
@@ -0,0 +1,492 @@
+#pragma once
+
+#include <easylogging++.h>
+#include "Stream.hpp"
+
+enum PacketNameLoginSB {
+ LoginStart = 0x00,
+ EncryptionResponse = 0x01,
+};
+enum PacketNamePlaySB {
+ TeleportConfirm,
+ PrepareCraftingGrid,
+ TabCompleteSB,
+ ChatMessageSB,
+ ClientStatus,
+ ClientSettings,
+ ConfirmTransactionSB,
+ EnchantItem,
+ ClickWindow,
+ CloseWindowSB,
+ PluginMessageSB,
+ UseEntity,
+ KeepAliveSB,
+ Player,
+ PlayerPosition,
+ PlayerPositionAndLookSB,
+ PlayerLook,
+ VehicleMoveSB,
+ SteerBoat,
+ PlayerAbilitiesSB,
+ PlayerDigging,
+ EntityAction,
+ SteerVehicle,
+ CraftingBookData,
+ ResourcePackStatus,
+ AdvancementTab,
+ HeldItemChangeSB,
+ CreativeInventoryAction,
+ UpdateSign,
+ AnimationSB,
+ Spectate,
+ PlayerBlockPlacement,
+ UseItem,
+};
+
+enum PacketNameHandshakingCB {
+ Handshake = 0x00,
+};
+enum PacketNameLoginCB {
+ Disconnect = 0x00,
+ EncryptionRequest = 0x01,
+ LoginSuccess = 0x02,
+ SetCompression = 0x03,
+};
+enum PacketNamePlayCB {
+ SpawnObject = 0x00,
+ SpawnExperienceOrb,
+ SpawnGlobalEntity,
+ SpawnMob,
+ SpawnPainting,
+ SpawnPlayer,
+ AnimationCB,
+ Statistics,
+ BlockBreakAnimation,
+ UpdateBlockEntity,
+ BlockAction,
+ BlockChange,
+ BossBar,
+ ServerDifficulty,
+ TabCompleteCB,
+ ChatMessageCB,
+ MultiBlockChange,
+ ConfirmTransactionCB,
+ CloseWindowCB,
+ OpenWindow,
+ WindowItems,
+ WindowProperty,
+ SetSlot,
+ SetCooldown,
+ PluginMessageCB,
+ NamedSoundEffect,
+ DisconnectPlay,
+ EntityStatus,
+ Explosion,
+ UnloadChunk,
+ ChangeGameState,
+ KeepAliveCB,
+ ChunkData,
+ Effect,
+ Particle,
+ JoinGame,
+ Map,
+ EntityRelativeMove,
+ EntityLookAndRelativeMove,
+ EntityLook,
+ Entity,
+ VehicleMove,
+ OpenSignEditor,
+ PlayerAbilitiesCB,
+ CombatEvent,
+ PlayerListItem,
+ PlayerPositionAndLookCB,
+ UseBed,
+ UnlockRecipes,
+ DestroyEntities,
+ RemoveEntityEffect,
+ ResourcePackSend,
+ Respawn,
+ EntityHeadLook,
+ SelectAdvancementTab,
+ WorldBorder,
+ Camera,
+ HeldItemChangeCB,
+ DisplayScoreboard,
+ EntityMetadata,
+ AttachEntity,
+ EntityVelocity,
+ EntityEquipment,
+ SetExperience,
+ UpdateHealth,
+ ScoreboardObjective,
+ SetPassengers,
+ Teams,
+ UpdateScore,
+ SpawnPosition,
+ TimeUpdate,
+ Title,
+ SoundEffect,
+ PlayerListHeaderAndFooter,
+ CollectItem,
+ EntityTeleport,
+ Advancements,
+ EntityProperties,
+ EntityEffect,
+};
+
+struct Packet {
+ virtual ~Packet() = default;
+ virtual void ToStream(StreamOutput *stream) = 0;
+ virtual void FromStream(StreamInput *stream) = 0;
+ virtual int GetPacketId() = 0;
+};
+
+struct PacketHandshake : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteVarInt(protocolVersion);
+ stream->WriteString(serverAddress);
+ stream->WriteUShort(serverPort);
+ stream->WriteVarInt(nextState);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ protocolVersion = stream->ReadVarInt();
+ serverAddress = stream->ReadString();
+ serverPort = stream->ReadUShort();
+ nextState = stream->ReadVarInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNameHandshakingCB::Handshake;
+ }
+
+ int protocolVersion;
+ std::string serverAddress;
+ unsigned short serverPort;
+ int nextState;
+};
+
+struct PacketLoginStart : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteString(Username);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ Username = stream->ReadString();
+ }
+
+ int GetPacketId() override {
+ return PacketNameLoginSB::LoginStart;
+ }
+
+ std::string Username;
+};
+
+struct PacketLoginSuccess : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteString(Uuid);
+ stream->WriteString(Username);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ Uuid = stream->ReadString();
+ Username = stream->ReadString();
+ }
+
+ int GetPacketId() override {
+ return PacketNameLoginCB::LoginSuccess;
+ }
+
+ std::string Uuid;
+ std::string Username;
+};
+
+struct PacketJoinGame : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteInt(EntityId);
+ stream->WriteUByte(Gamemode);
+ stream->WriteInt(Dimension);
+ stream->WriteUByte(Difficulty);
+ stream->WriteUByte(MaxPlayers);
+ stream->WriteString(LevelType);
+ stream->WriteBool(ReducedDebugInfo);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ EntityId = stream->ReadInt();
+ Gamemode = stream->ReadUByte();
+ Dimension = stream->ReadInt();
+ Difficulty = stream->ReadUByte();
+ MaxPlayers = stream->ReadUByte();
+ LevelType = stream->ReadString();
+ ReducedDebugInfo = stream->ReadBool();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::JoinGame;
+ }
+
+ int EntityId;
+ unsigned char Gamemode;
+ int Dimension;
+ unsigned char Difficulty;
+ unsigned char MaxPlayers;
+ std::string LevelType;
+ bool ReducedDebugInfo;
+};
+
+struct PacketDisconnectPlay : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ Reason = stream->ReadChat();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::DisconnectPlay;
+ }
+
+ std::string Reason;
+};
+
+struct PacketSpawnPosition : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ Location = stream->ReadPosition();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::SpawnPosition;
+ }
+
+ Vector Location;
+};
+
+struct PacketKeepAliveCB : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteVarInt(KeepAliveId);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ KeepAliveId = stream->ReadVarInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::KeepAliveCB;
+ }
+
+ int KeepAliveId;
+};
+
+struct PacketKeepAliveSB : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteVarInt(KeepAliveId);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ KeepAliveId = stream->ReadVarInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::KeepAliveSB;
+ }
+
+ int KeepAliveId;
+
+ PacketKeepAliveSB(int KeepAliveId) : KeepAliveId(KeepAliveId) {}
+};
+
+struct PacketPlayerPositionAndLookCB : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ X = stream->ReadDouble();
+ Y = stream->ReadDouble();
+ Z = stream->ReadDouble();
+ Yaw = stream->ReadFloat();
+ Pitch = stream->ReadFloat();
+ Flags = stream->ReadUByte();
+ TeleportId = stream->ReadVarInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::PlayerPositionAndLookCB;
+ }
+
+ double X;
+ double Y;
+ double Z;
+ float Yaw;
+ float Pitch;
+ unsigned char Flags;
+ int TeleportId;
+};
+
+struct PacketTeleportConfirm : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteVarInt(TeleportId);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ TeleportId = stream->ReadVarInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::TeleportConfirm;
+ }
+
+ int TeleportId;
+
+ PacketTeleportConfirm(int TeleportId) : TeleportId(TeleportId) {}
+};
+
+struct PacketClientStatus : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteVarInt(ActionId);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ ActionId = stream->ReadVarInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::ClientStatus;
+ }
+
+ int ActionId;
+
+ PacketClientStatus(int ActionId) : ActionId(ActionId) {}
+};
+
+struct PacketPlayerPositionAndLookSB : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteDouble(X);
+ stream->WriteDouble(FeetY);
+ stream->WriteDouble(Z);
+ stream->WriteFloat(Yaw);
+ stream->WriteFloat(Pitch);
+ stream->WriteBool(OnGround);
+ }
+
+ void FromStream(StreamInput *stream) override {
+
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::PlayerPositionAndLookSB;
+ }
+
+
+ double X;
+ double FeetY;
+ double Z;
+ float Yaw;
+ float Pitch;
+ bool OnGround;
+
+ PacketPlayerPositionAndLookSB(double X, double FeetY, double Z,
+ float Yaw, float Pitch, bool OnGround) : X(X), FeetY(FeetY), Z(Z), Yaw(Yaw),
+ Pitch(Pitch), OnGround(OnGround) {}
+};
+
+struct PacketChunkData : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ ChunkX = stream->ReadInt();
+ ChunkZ = stream->ReadInt();
+ GroundUpContinuous = stream->ReadBool();
+ PrimaryBitMask = stream->ReadVarInt();
+ Size = stream->ReadVarInt();
+ Data = stream->ReadByteArray(Size);
+ NumberOfBlockEntities = stream->ReadVarInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::ChunkData;
+ }
+
+ int ChunkX;
+ int ChunkZ;
+ bool GroundUpContinuous;
+ int PrimaryBitMask;
+ int Size;
+ std::vector<unsigned char> Data;
+ int NumberOfBlockEntities;
+ //std::vector<NbtTag> BlockEntities;
+};
+
+struct PacketPlayerPosition : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteDouble(X);
+ stream->WriteDouble(FeetY);
+ stream->WriteDouble(Z);
+ stream->WriteBool(OnGround);
+ }
+
+ void FromStream(StreamInput *stream) override {
+
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::PlayerPosition;
+ }
+
+ double X;
+ double FeetY;
+ double Z;
+ bool OnGround;
+
+ PacketPlayerPosition(double X, double Y, double Z, bool ground) : X(X), FeetY(Y), Z(Z), OnGround(ground) {}
+};
+
+struct PacketPlayerLook : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteFloat(Yaw);
+ stream->WriteFloat(Pitch);
+ stream->WriteBool(OnGround);
+ }
+
+ void FromStream(StreamInput *stream) override {
+
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::PlayerLook;
+ }
+
+ float Yaw;
+ float Pitch;
+ bool OnGround;
+
+ PacketPlayerLook(float Yaw, float Pitch, bool ground) : Yaw(Yaw), Pitch(Pitch), OnGround(ground) {}
+};
+
+struct PacketUpdateHealth : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ Health = stream->ReadFloat();
+ Food = stream->ReadVarInt();
+ FoodSaturation = stream->ReadFloat();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::UpdateHealth;
+ }
+
+ float Health;
+ int Food;
+ float FoodSaturation;
+}; \ No newline at end of file
diff --git a/src/network/Socket.cpp b/src/network/Socket.cpp
new file mode 100644
index 0000000..2bbf49a
--- /dev/null
+++ b/src/network/Socket.cpp
@@ -0,0 +1,29 @@
+#include "Socket.hpp"
+
+Socket::Socket(std::string address, unsigned short port) {
+ sf::Socket::Status connectionStatus = socket.connect(sf::IpAddress(address), port);
+ if (connectionStatus == sf::Socket::Status::Error)
+ throw std::runtime_error("Can't connect to remote server");
+ else if (connectionStatus != sf::Socket::Status::Done)
+ throw std::runtime_error("Connection failed with unknown reason");
+}
+
+Socket::~Socket() {
+ socket.disconnect();
+}
+
+void Socket::Read(unsigned char *buffPtr, size_t buffLen) {
+ size_t received = 0;
+ socket.receive(buffPtr, buffLen, received);
+ size_t totalReceived = received;
+ while (totalReceived < buffLen) {
+ if (socket.receive(buffPtr + totalReceived, buffLen - totalReceived, received) != sf::Socket::Done)
+ throw std::runtime_error("Raw socket data receiving is failed");
+ totalReceived += received;
+ }
+}
+
+void Socket::Write(unsigned char *buffPtr, size_t buffLen) {
+ if (socket.send(buffPtr, buffLen) != sf::Socket::Done)
+ throw std::runtime_error("Raw socket data sending is failed");
+}
diff --git a/src/network/Socket.hpp b/src/network/Socket.hpp
new file mode 100644
index 0000000..ee449b3
--- /dev/null
+++ b/src/network/Socket.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <string>
+#include <SFML/Network.hpp>
+
+/**
+ * Platform independent class for working with platform dependent hardware socket
+ * @brief Wrapper around raw sockets
+ * @warning Connection state is based on lifetime of Socket object instance, ie connected at ctor and disconnect at dtor
+ * @todo Replace SFML's socket with WinSock and POSIX's socket implementation
+ */
+class Socket {
+ sf::TcpSocket socket;
+public:
+ /**
+ * Constructs Socket class instance from IP's string and Port number and connects to remote server
+ * @param[in] address IP address of remote server. String should be ANSI and contains 4 one-byte values separated by dots
+ * @param[in] port target port of remote server to connect
+ * @throw std::runtime_error if connection is failed
+ */
+ Socket(std::string address, unsigned short port);
+
+ /**
+ * Destruct Socket instance and disconnect from server
+ * @warning There is no way to force disconnect, except use delete for manually allocated objects and scope of visibility for variables on stack
+ */
+ ~Socket();
+
+ /**
+ * Reads data from socket and write to buffer
+ * @warning This is blocking function, and execution flow will not be returned until all required data is sended
+ * @warning Reported buffer length must be <= actual size of buffer, or memory corruption will be caused
+ * @param[out] buffPtr Pointer to buffer, where data must be placed
+ * @param[in] buffLen Length of data, that must be readed from server and writed to buffer
+ */
+ void Read(unsigned char *buffPtr, size_t buffLen);
+
+ /**
+ * Writes data from buffer to socket
+ * @warning This is blocking function, and execution flow will not be returned until all required data is received
+ * @param[in] buffPtr Pointer to buffer that contain data to send
+ * @param[in] buffLen Length of buffer
+ */
+ void Write(unsigned char *buffPtr, size_t buffLen);
+}; \ No newline at end of file
diff --git a/src/network/Stream.cpp b/src/network/Stream.cpp
new file mode 100644
index 0000000..a0c6cb0
--- /dev/null
+++ b/src/network/Stream.cpp
@@ -0,0 +1,334 @@
+#include "Stream.hpp"
+
+const int MAX_VARINT_LENGTH = 5;
+
+bool StreamInput::ReadBool() {
+ unsigned char value;
+ ReadData(&value, 1);
+ return value != 0;
+}
+
+signed char StreamInput::ReadByte() {
+ signed char value;
+ ReadData((unsigned char *) &value, 1);
+ endswap(value);
+ return value;
+}
+
+unsigned char StreamInput::ReadUByte() {
+ unsigned char value;
+ ReadData(&value, 1);
+ endswap(value);
+ return value;
+}
+
+short StreamInput::ReadShort() {
+ unsigned short value;
+ ReadData((unsigned char *) &value, 2);
+ endswap(value);
+ return value;
+}
+
+unsigned short StreamInput::ReadUShort() {
+ unsigned char buff[2];
+ ReadData(buff, 2);
+ unsigned short val = *(reinterpret_cast<unsigned short *>(buff));
+ endswap(val);
+ return val;
+}
+
+int StreamInput::ReadInt() {
+ int value;
+ ReadData((unsigned char *) &value, 4);
+ endswap(value);
+ return value;
+}
+
+long long StreamInput::ReadLong() {
+ long long value;
+ ReadData((unsigned char *) &value, 8);
+ endswap(value);
+ return value;
+}
+
+float StreamInput::ReadFloat() {
+ float value;
+ ReadData((unsigned char *) &value, 4);
+ endswap(value);
+ return value;
+}
+
+double StreamInput::ReadDouble() {
+ double value;
+ ReadData((unsigned char *) &value, 8);
+ endswap(value);
+ return value;
+}
+
+std::string StreamInput::ReadString() {
+ int strLength = ReadVarInt();
+ unsigned char *buff = new unsigned char[strLength + 1];
+ ReadData(buff, strLength);
+ buff[strLength] = 0;
+ std::string str((char *) buff);
+ delete buff;
+ return str;
+}
+
+std::string StreamInput::ReadChat() {
+ std::string str, jsonStr = ReadString();
+ nlohmann::json json;
+ try {
+ json = nlohmann::json::parse(jsonStr);
+ } catch (std::exception &e) {
+ LOG(WARNING) << "Chat json parsing failed: " << e.what();
+ LOG(WARNING) << "Corrupted json: " << jsonStr;
+ return "";
+ }
+ if (json.find("translate") != json.end())
+ if (json["translate"].get<std::string>() == "multiplayer.disconnect.kicked")
+ return "kicked by operator";
+ for (auto &it:json["extra"]) {
+ str += it["text"].get<std::string>();
+ }
+ return str;
+}
+
+int StreamInput::ReadVarInt() {
+ unsigned char data[MAX_VARINT_LENGTH] = {0};
+ size_t dataLen = 0;
+ do {
+ ReadData(&data[dataLen], 1);
+ } while ((data[dataLen++] & 0x80) != 0);
+
+ int readed = 0;
+ int result = 0;
+ char read;
+ do {
+ read = data[readed];
+ int value = (read & 0b01111111);
+ result |= (value << (7 * readed));
+ readed++;
+ } while ((read & 0b10000000) != 0);
+
+ return result;
+}
+
+long long StreamInput::ReadVarLong() {
+ return 0;
+}
+
+std::vector<unsigned char> StreamInput::ReadEntityMetadata() {
+ return std::vector<unsigned char>();
+}
+
+std::vector<unsigned char> StreamInput::ReadSlot() {
+ return std::vector<unsigned char>();
+}
+
+std::vector<unsigned char> StreamInput::ReadNbtTag() {
+ return std::vector<unsigned char>();
+}
+
+Vector StreamInput::ReadPosition() {
+ unsigned long long t = ReadLong();
+ int x = t >> 38;
+ int y = (t >> 26) & 0xFFF;
+ int z = t << 38 >> 38;
+ if (x >= pow(2, 25)) {
+ x -= pow(2, 26);
+ }
+ if (y >= pow(2, 11)) {
+ y -= pow(2, 12);
+ }
+ if (z >= pow(2, 25)) {
+ z -= pow(2, 26);
+ }
+ return Vector(x, y, z);
+}
+
+unsigned char StreamInput::ReadAngle() {
+ return ReadUByte();
+}
+
+std::vector<unsigned char> StreamInput::ReadUuid() {
+ unsigned char buff[16];
+ ReadData(buff, 16);
+ endswap(buff, 16);
+ return std::vector<unsigned char>(buff, buff + 16);
+}
+
+std::vector<unsigned char> StreamInput::ReadByteArray(size_t arrLength) {
+ unsigned char *buffer = new unsigned char[arrLength];
+ ReadData(buffer, arrLength);
+ std::vector<unsigned char> ret(buffer, buffer + arrLength);
+ delete buffer;
+ return ret;
+
+}
+
+void StreamOutput::WriteBool(bool value) {
+ unsigned char val = value ? 1 : 0;
+ endswap(val);
+ WriteData(&val, 1);
+}
+
+void StreamOutput::WriteByte(signed char value) {
+
+}
+
+void StreamOutput::WriteUByte(unsigned char value) {
+ endswap(value);
+ WriteData(&value,1);
+}
+
+void StreamOutput::WriteShort(short value) {
+
+}
+
+void StreamOutput::WriteUShort(unsigned short value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 2);
+}
+
+void StreamOutput::WriteInt(int value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 4);
+}
+
+void StreamOutput::WriteLong(long long value) {
+
+}
+
+void StreamOutput::WriteFloat(float value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 4);
+}
+
+void StreamOutput::WriteDouble(double value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 8);
+}
+
+void StreamOutput::WriteString(std::string value) {
+ WriteVarInt(value.size());
+ WriteData((unsigned char *) value.data(), value.size());
+}
+
+void StreamOutput::WriteChat(std::string value) {
+
+}
+
+void StreamOutput::WriteVarInt(int value) {
+ unsigned char buff[5];
+ size_t len = 0;
+ do {
+ unsigned char temp = (unsigned char) (value & 0b01111111);
+ value >>= 7;
+ if (value != 0) {
+ temp |= 0b10000000;
+ }
+ buff[len] = temp;
+ len++;
+ } while (value != 0);
+ WriteData(buff, len);
+}
+
+void StreamOutput::WriteVarLong(long long value) {
+
+}
+
+void StreamOutput::WriteEntityMetadata(std::vector<unsigned char> value) {
+
+}
+
+void StreamOutput::WriteSlot(std::vector<unsigned char> value) {
+
+}
+
+void StreamOutput::WriteNbtTag(std::vector<unsigned char> value) {
+
+}
+
+void StreamOutput::WritePosition(Vector value) {
+
+}
+
+void StreamOutput::WriteAngle(unsigned char value) {
+
+}
+
+void StreamOutput::WriteUuid(std::vector<unsigned char> value) {
+
+}
+
+void StreamOutput::WriteByteArray(std::vector<unsigned char> value) {
+
+}
+
+void StreamBuffer::ReadData(unsigned char *buffPtr, size_t buffLen) {
+ size_t bufferLengthLeft = buffer + bufferLength - bufferPtr;
+ if (bufferLengthLeft < buffLen)
+ throw std::runtime_error("Required data is more, than in buffer available");
+ std::memcpy(buffPtr, bufferPtr, buffLen);
+ bufferPtr += buffLen;
+}
+
+void StreamBuffer::WriteData(unsigned char *buffPtr, size_t buffLen) {
+ size_t bufferLengthLeft = buffer + bufferLength - bufferPtr;
+ if (bufferLengthLeft < buffLen)
+ throw std::runtime_error("Required data is more, than in buffer available");
+ std::memcpy(bufferPtr, buffPtr, buffLen);
+ bufferPtr += buffLen;
+}
+
+StreamBuffer::StreamBuffer(unsigned char *data, size_t dataLen) {
+ buffer = new unsigned char[dataLen];
+ bufferPtr = buffer;
+ bufferLength = dataLen;
+ std::memcpy(buffer, data, dataLen);
+}
+
+StreamBuffer::StreamBuffer(size_t bufferLen) {
+ buffer = new unsigned char[bufferLen];
+ bufferPtr = buffer;
+ bufferLength = bufferLen;
+ for (unsigned char *p = buffer; p != buffer + bufferLength; ++p)
+ *p = 0;
+}
+
+StreamBuffer::~StreamBuffer() {
+ delete buffer;
+}
+
+std::vector<unsigned char> StreamBuffer::GetBuffer() {
+ return std::vector<unsigned char>(buffer, buffer + bufferLength);
+}
+
+void StreamCounter::WriteData(unsigned char *buffPtr, size_t buffLen) {
+ size += buffLen;
+}
+
+StreamCounter::StreamCounter(size_t initialSize) : size(initialSize) {
+
+}
+
+StreamCounter::~StreamCounter() {
+
+}
+
+size_t StreamCounter::GetCountedSize() {
+ return size;
+}
+
+void StreamSocket::ReadData(unsigned char *buffPtr, size_t buffLen) {
+ socket->Read(buffPtr, buffLen);
+}
+
+void StreamSocket::WriteData(unsigned char *buffPtr, size_t buffLen) {
+ socket->Write(buffPtr, buffLen);
+}
+
+StreamSocket::StreamSocket(Socket *socketPtr) : socket(socketPtr) {
+
+} \ No newline at end of file
diff --git a/src/network/Stream.hpp b/src/network/Stream.hpp
new file mode 100644
index 0000000..5babb08
--- /dev/null
+++ b/src/network/Stream.hpp
@@ -0,0 +1,115 @@
+#pragma once
+
+#include <algorithm>
+#include <string>
+#include <stdexcept>
+#include <vector>
+#include <cstring>
+#include <nlohmann/json.hpp>
+#include <easylogging++.h>
+#include "Socket.hpp"
+#include "../utility/Vector.hpp"
+
+class Stream {
+protected:
+ template<class T>
+ void endswap(T &obj) {
+ unsigned char *raw = reinterpret_cast<unsigned char *>(&obj);
+ std::reverse(raw, raw + sizeof(T));
+ }
+
+ void endswap(unsigned char *arr, size_t arrLen) {
+ std::reverse(arr, arr + arrLen);
+ }
+
+public:
+ virtual ~Stream() {};
+};
+
+class StreamInput : Stream {
+ virtual void ReadData(unsigned char *buffPtr, size_t buffLen) = 0;
+public:
+ virtual ~StreamInput() = default;
+ bool ReadBool();
+ signed char ReadByte();
+ unsigned char ReadUByte();
+ short ReadShort();
+ unsigned short ReadUShort();
+ int ReadInt();
+ long long ReadLong();
+ float ReadFloat();
+ double ReadDouble();
+ std::string ReadString();
+ std::string ReadChat();
+ int ReadVarInt();
+ long long ReadVarLong();
+ std::vector<unsigned char> ReadEntityMetadata();
+ std::vector<unsigned char> ReadSlot();
+ std::vector<unsigned char> ReadNbtTag();
+ Vector ReadPosition();
+ unsigned char ReadAngle();
+ std::vector<unsigned char> ReadUuid();
+ std::vector<unsigned char> ReadByteArray(size_t arrLength);
+};
+
+class StreamOutput : Stream {
+ virtual void WriteData(unsigned char *buffPtr, size_t buffLen) = 0;
+public:
+ virtual ~StreamOutput() = default;
+ void WriteBool(bool value);
+ void WriteByte(signed char value);
+ void WriteUByte(unsigned char value);
+ void WriteShort(short value);
+ void WriteUShort(unsigned short value);
+ void WriteInt(int value);
+ void WriteLong(long long value);
+ void WriteFloat(float value);
+ void WriteDouble(double value);
+ void WriteString(std::string value);
+ void WriteChat(std::string value);
+ void WriteVarInt(int value);
+ void WriteVarLong(long long value);
+ void WriteEntityMetadata(std::vector<unsigned char> value);
+ void WriteSlot(std::vector<unsigned char> value);
+ void WriteNbtTag(std::vector<unsigned char> value);
+ void WritePosition(Vector value);
+ void WriteAngle(unsigned char value);
+ void WriteUuid(std::vector<unsigned char> value);
+ void WriteByteArray(std::vector<unsigned char> value);
+};
+
+class StreamBuffer : public StreamInput, public StreamOutput {
+ unsigned char *buffer;
+ unsigned char *bufferPtr;
+ size_t bufferLength;
+
+ void ReadData(unsigned char *buffPtr, size_t buffLen) override;
+ void WriteData(unsigned char *buffPtr, size_t buffLen) override;
+
+public:
+ StreamBuffer(unsigned char *data, size_t dataLen);
+ StreamBuffer(size_t bufferLen);
+ ~StreamBuffer();
+
+ std::vector<unsigned char> GetBuffer();
+};
+
+class StreamCounter : public StreamOutput {
+ void WriteData(unsigned char *buffPtr, size_t buffLen) override;
+
+ size_t size;
+public:
+ StreamCounter(size_t initialSize = 0);
+ ~StreamCounter();
+
+ size_t GetCountedSize();
+};
+
+class StreamSocket : public StreamInput, public StreamOutput {
+ Socket *socket;
+ void ReadData(unsigned char *buffPtr, size_t buffLen) override;
+ void WriteData(unsigned char *buffPtr, size_t buffLen) override;
+public:
+ StreamSocket(Socket *socketPtr);
+ ~StreamSocket() = default;
+}; \ No newline at end of file
diff --git a/src/packet/Field.cpp b/src/packet/Field.cpp
deleted file mode 100644
index 9be2469..0000000
--- a/src/packet/Field.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-#include "Field.hpp"
-
-Field::Field() {
-}
-
-Field::Field(const Field &other) : m_dataLength(other.m_dataLength), m_type(other.m_type) {
-
- m_data = new byte[m_dataLength];
- std::copy(other.m_data,other.m_data+m_dataLength,m_data);
-}
-
-void Field::swap(Field &other) {
- std::swap(other.m_dataLength, m_dataLength);
- std::swap(other.m_data, m_data);
- std::swap(other.m_type, m_type);
-}
-
-Field &Field::operator=(Field other) {
- other.swap(*this);
- return *this;
-}
-
-Field::~Field() {
- Clear();
-}
-
-size_t Field::GetLength() {
- if (m_data != nullptr && m_dataLength == 0)
- throw 102;
- return m_dataLength;
-}
-
-void Field::Clear() {
- m_dataLength = 0;
- delete[] m_data;
- m_data = nullptr;
-}
-
-void Field::CopyToBuff(byte *ptr) {
- if (m_dataLength > 0)
- std::copy(m_data,m_data+m_dataLength,ptr);
-}
-
-void Field::SetRaw(byte *ptr, size_t len, FieldType type) {
- Clear();
- m_dataLength = len;
- m_type = type;
- m_data = new byte[m_dataLength];
- std::copy(ptr,ptr+m_dataLength,m_data);
-}
-
-int Field::GetVarInt() {
-
- size_t readed;
- return VarIntRead(m_data, readed);
-
-}
-
-void Field::SetVarInt(int value) {
- Clear();
- m_type = VarIntType;
- m_data = new byte[5];
- m_dataLength = VarIntWrite(value, m_data);
-}
-
-int Field::GetInt() {
- int value = *(reinterpret_cast<int *>(m_data));
- endswap(&value);
- return value;
-}
-
-void Field::SetInt(int value) {
- Clear();
- m_type = Int;
- m_data = new byte[4];
- m_dataLength = 4;
- int *p = reinterpret_cast<int *>(m_data);
- *p = value;
- endswap(p);
-}
-
-bool Field::GetBool() {
- return *m_data != 0x00;
-}
-
-void Field::SetBool(bool value) {
- Clear();
- m_type = Boolean;
- m_data = new byte[1];
- m_dataLength = 1;
- *m_data = value ? 0x01 : 0x00;
-}
-
-unsigned short Field::GetUShort() {
- unsigned short *p = reinterpret_cast<unsigned short *>(m_data);
- unsigned short t = *p;
- endswap(&t);
- return t;
-}
-
-void Field::SetUShort(unsigned short value) {
- Clear();
- m_type = UnsignedShort;
- m_dataLength = 2;
- m_data = new byte[2];
- unsigned short *p = reinterpret_cast<unsigned short *>(m_data);
- *p = value;
- endswap(p);
-}
-
-std::string Field::GetString() {
- Field fLen;
- byte *ptr = m_data;
- size_t l;
- int val = VarIntRead(ptr, l);
- ptr += l;
- std::string s((char *) ptr, val);
- return s;
-}
-
-void Field::SetString(std::string value) {
- Clear();
- m_type = String;
- Field fLen;
- fLen.SetVarInt(value.size());
- m_dataLength = value.size() + fLen.GetLength();
- m_data = new byte[m_dataLength];
- byte *p = m_data;
- fLen.CopyToBuff(p);
- p += fLen.GetLength();
- std::copy(value.begin(),value.end(),p);
-}
-
-long long Field::GetLong() {
- long long t = *reinterpret_cast<long long *>(m_data);
- endswap(&t);
- return t;
-}
-
-void Field::SetLong(long long value) {
- Clear();
- m_type = Long;
- m_dataLength = 8;
- m_data = new byte[m_dataLength];
- long long *p = reinterpret_cast<long long *>(m_data);
- *p = value;
- endswap(p);
-}
-
-FieldType Field::GetType() {
- return m_type;
-}
-
-byte Field::GetUByte() {
- byte t = *reinterpret_cast<byte *>(m_data);
- endswap(&t);
- return t;
-}
-
-void Field::SetUByte(byte value) {
- Clear();
- m_type = UnsignedByte;
- endswap(&value);
- m_dataLength = 1;
- m_data = new byte[m_dataLength];
- byte *p = reinterpret_cast<byte *>(m_data);
- *p = value;
-}
-
-sbyte Field::GetByte() {
- sbyte t = *reinterpret_cast<sbyte *>(m_data);
- endswap(&t);
- return t;
-}
-
-void Field::SetByte(sbyte value) {
- Clear();
- m_type = Byte8_t;
- endswap(&value);
- m_dataLength = 1;
- m_data = new byte[m_dataLength];
- sbyte *p = reinterpret_cast<sbyte *>(m_data);
- *p = value;
-}
-
-float Field::GetFloat() {
- float t = *reinterpret_cast<float *>(m_data);
- endswap(&t);
- return t;
-}
-
-void Field::SetFloat(float value) {
- Clear();
- m_type = Float;
- endswap(&value);
- m_dataLength = 4;
- m_data = new byte[m_dataLength];
- float *p = reinterpret_cast<float *>(m_data);
- *p = value;
-}
-
-Vector Field::GetPosition() {
- unsigned long long t = *reinterpret_cast<unsigned long long *>(m_data);
- endswap(&t);
- int x = t >> 38;
- int y = (t >> 26) & 0xFFF;
- int z = t << 38 >> 38;
- if (x >= pow(2, 25)) {
- x -= pow(2, 26);
- }
- if (y >= pow(2, 11)) {
- y -= pow(2, 12);
- }
- if (z >= pow(2, 25)) {
- z -= pow(2, 26);
- }
- Vector val(x,y,z);
- return val;
-}
-
-void Field::SetPosition(Vector value) {
- Clear();
- m_type = Position;
- m_dataLength = 8;
- m_data = new byte[m_dataLength];
- unsigned long long *t = reinterpret_cast<unsigned long long *>(m_data);
- unsigned long long x = ((unsigned long long) value.GetX()) << 38;
- unsigned long long y = ((unsigned long long) value.GetY()) << 26;
- unsigned long long z = value.GetZ();
- endswap(&x);
- endswap(&z);
- endswap(&y);
- *t = x | y | z;
-}
-
-double Field::GetDouble() {
- double t = *reinterpret_cast<double *>(m_data);
- endswap(&t);
- return t;
-}
-
-void Field::SetDouble(double value) {
- Clear();
- m_type = Double;
- endswap(&value);
- m_dataLength = 8;
- m_data = new byte[m_dataLength];
- double *p = reinterpret_cast<double *>(m_data);
- *p = value;
-}
-
-size_t Field::GetFieldLength(FieldType type) {
- switch (type) {
- case UnknownType:
- return 0;
- case Boolean:
- return 1;
- case Byte8_t:
- return 1;
- case UnsignedByte:
- return 1;
- case Short:
- return 2;
- case UnsignedShort:
- return 2;
- case Int:
- return 4;
- case Long:
- return 8;
- case Float:
- return 4;
- case Double:
- return 8;
- case Position:
- return 8;
- case Angle:
- return 4;
- case Uuid:
- return 16;
- default:
- return 0;
- }
-}
-
-std::vector<Field> Field::GetArray() {
- /*std::vector<Field> vec;
- if (m_type<20){
- size_t fieldLen=GetFieldLength(m_type);
- byte* ptr = m_data;
- for (int i=0;i<m_dataLength/fieldLen;i++){
- Field f;
- f.SetRaw(ptr,fieldLen,m_type);
- vec.push_back(f);
- ptr+=fieldLen;
- }
- return vec;
- }*/
- return m_childs;
-}
-
-void Field::Attach(Field field) {
- m_childs.push_back(field);
-}
diff --git a/src/packet/Field.hpp b/src/packet/Field.hpp
deleted file mode 100644
index c33cd1c..0000000
--- a/src/packet/Field.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#pragma once
-
-#include <cstddef>
-#include <cstdint>
-#include <cmath>
-#include <string>
-#include <vector>
-
-#include "../utility/utility.h"
-#include "../utility/Vector.hpp"
-
-typedef unsigned char byte;
-typedef signed char sbyte;
-
-enum FieldType {
- UnknownType = 0,
- Boolean, //Bool
- Byte8_t, //int8_t
- UnsignedByte, //uint8_t
- Short, //int16_t
- UnsignedShort, //uint16_t
- Int, //int32_t
- Long, //int64_t
- Float, //float
- Double, //double
- Position, //PositionI
- Angle, //uint8_t
- Uuid, //byte* (2 bytes)
- //Unknown-length data
-
- String = 100, //std::string
- Chat, //std::string
- VarIntType, //int32_t
- VarLong, //int64_t
- ChunkSection, //byte*
- EntityMetadata, //byte*
- Slot, //byte*
- NbtTag, //byte*
- ByteArray, //byte*
-};
-
-class Field {
-public:
- Field();
-
- Field(const Field &other);
-
- void swap(Field &other);
-
- Field &operator=(Field other);
-
- ~Field();
-
- size_t GetLength();
-
- void Clear();
-
- void CopyToBuff(byte *ptr);
-
- void SetRaw(byte *ptr, size_t len = 0, FieldType type = UnknownType);
-
- FieldType GetType();
-
- void Attach(Field field);
-
- static size_t GetFieldLength(FieldType type);
-
- //Cpp-types setters/getters for binary content of MC's data types
-
- int GetVarInt();
-
- void SetVarInt(int value);
-
- int GetInt();
-
- void SetInt(int value);
-
- bool GetBool();
-
- void SetBool(bool value);
-
- unsigned short GetUShort();
-
- void SetUShort(unsigned short value);
-
- std::string GetString();
-
- void SetString(std::string value);
-
- long long GetLong();
-
- void SetLong(long long value);
-
- byte GetUByte();
-
- void SetUByte(byte value);
-
- sbyte GetByte();
-
- void SetByte(sbyte value);
-
- float GetFloat();
-
- void SetFloat(float value);
-
- Vector GetPosition();
-
- void SetPosition(Vector value);
-
- double GetDouble();
-
- void SetDouble(double value);
-
- std::vector<Field> GetArray();
-
-private:
- size_t m_dataLength = 0;
- byte *m_data = nullptr;
- FieldType m_type = UnknownType;
- std::vector<Field> m_childs;
-};
diff --git a/src/packet/FieldParser.cpp b/src/packet/FieldParser.cpp
deleted file mode 100644
index 295e78f..0000000
--- a/src/packet/FieldParser.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#include "FieldParser.hpp"
-
-Field FieldParser::Parse(FieldType type, byte *data, size_t len) {
- switch (type) {
- case VarIntType:
- return ParseVarInt(data, len);
- case Boolean:
- return ParseBool(data);
- case String:
- return ParseString(data);
- case Long:
- return ParseLong(data);
- case Int:
- return ParseInt(data);
- case UnsignedByte:
- return ParseUByte(data);
- case Byte8_t:
- return ParseByte(data);
- case Float:
- return ParseFloat(data);
- case Position:
- return ParsePosition(data);
- case Double:
- return ParseDouble(data);
- case ByteArray:
- return ParseByteArray(data, len);
- default:
- throw 105;
- }
-}
-
-Field FieldParser::ParseString(byte *data) {
- Field fLen = ParseVarInt(data, 0);
- Field f;
- f.SetRaw(data, fLen.GetLength() + fLen.GetVarInt(), String);
- return f;
-}
-
-Field FieldParser::ParseBool(byte *data) {
- Field f;
- f.SetRaw(data, 1, Boolean);
- return f;
-}
-
-Field FieldParser::ParseVarInt(byte *data, size_t len) {
- if (len != 0) {
- Field f;
- f.SetRaw(data, len, VarIntType);
- return f;
- }
- int val = VarIntRead(data, len);
- Field f;
- f.SetVarInt(val);
- return f;
-}
-
-Field FieldParser::ParseLong(byte *data) {
- Field f;
- f.SetRaw(data, 8, Long);
- return f;
-}
-
-Field FieldParser::ParseInt(byte *data) {
- Field f;
- f.SetRaw(data, 4, Int);
- return f;
-}
-
-Field FieldParser::ParseUByte(byte *data) {
- Field f;
- f.SetRaw(data, 1, UnsignedByte);
- return f;
-}
-
-Field FieldParser::ParseByte(byte *data) {
- Field f;
- f.SetRaw(data, 1, Byte8_t);
- return f;
-}
-
-Field FieldParser::ParseFloat(byte *data) {
- Field f;
- f.SetRaw(data, 4, Float);
- return f;
-}
-
-Field FieldParser::ParsePosition(byte *data) {
- Field f;
- f.SetRaw(data, 8, Position);
- return f;
-}
-
-Field FieldParser::ParseDouble(byte *data) {
- Field f;
- f.SetRaw(data, 8, Double);
- return f;
-}
-
-Field FieldParser::ParseByteArray(byte *data, size_t len) {
- if (len == 0)
- throw 119;
- Field f;
- f.SetRaw(data, len, Byte8_t);
- return f;
-}
diff --git a/src/packet/FieldParser.hpp b/src/packet/FieldParser.hpp
deleted file mode 100644
index f256b34..0000000
--- a/src/packet/FieldParser.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-#include "Field.hpp"
-
-class FieldParser {
-public:
- static Field ParseVarInt(byte *data, size_t len);
-
- static Field ParseBool(byte *data);
-
- static Field ParseString(byte *data);
-
- static Field Parse(FieldType type, byte* data, size_t len=0);
-
- static Field ParseLong(byte *data);
-
- static Field ParseInt(byte *data);
-
- static Field ParseUByte(byte *data);
-
- static Field ParseByte(byte *data);
-
- static Field ParseFloat(byte *data);
-
- static Field ParsePosition(byte *data);
-
- static Field ParseDouble(byte *data);
-
- static Field ParseByteArray(byte *data, size_t len);
-}; \ No newline at end of file
diff --git a/src/packet/Packet.cpp b/src/packet/Packet.cpp
deleted file mode 100644
index 68cc3c3..0000000
--- a/src/packet/Packet.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-#include "Packet.hpp"
-
-Packet::Packet(int id) {
- Field fLen;
- fLen.SetVarInt(0);
- m_fields.push_back(fLen);
- Field fId;
- fId.SetVarInt(id);
- m_fields.push_back(fId);
-}
-
-Packet Packet::operator=(Packet other) {
- other.swap(*this);
- return *this;
-}
-
-void Packet::swap(Packet &other) {
- std::swap(m_fields, other.m_fields);
- std::swap(m_data, other.m_data);
- std::swap(m_parsePtr, other.m_parsePtr);
- std::swap(m_dataLength, other.m_dataLength);
-}
-
-void Packet::CopyToBuff(byte *ptr) {
- m_fields[0].SetVarInt(GetLength() - m_fields[0].GetLength());
- for (auto &it:m_fields) {
- it.CopyToBuff(ptr);
- ptr += it.GetLength();
- }
-}
-
-void Packet::ParseField(FieldType type, size_t len) {
- if (type == ByteArray && len == 0)
- throw 118;
- Field f = FieldParser::Parse(type, m_parsePtr, len);
- m_fields.push_back(f);
- m_parsePtr += f.GetLength();
- if (m_parsePtr == m_data + m_dataLength) {
- delete[] m_data;
- m_data = nullptr;
- m_dataLength = 0;
- m_parsePtr = nullptr;
- }
-}
-
-Packet::Packet(byte *data) {
- Field fLen = FieldParser::Parse(VarIntType, data);
- data += fLen.GetLength();
- Field fId = FieldParser::Parse(VarIntType, data);
- data += fId.GetLength();
- m_dataLength = fLen.GetVarInt() - fId.GetLength();
- m_data = new byte[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) {
- if (id < -2 || id >= (int) m_fields.size() - 2)
- throw 111;
- return m_fields[id + 2];
-}
-
-size_t Packet::GetLength() {
- size_t len = 0;
- for (auto &it:m_fields) {
- len += it.GetLength();
- }
- return len + m_dataLength;
-}
-
-void Packet::AddField(Field field) {
- m_fields.push_back(field);
-}
-
-int Packet::GetId() {
- return m_fields[1].GetVarInt();
-}
-
-Packet::Packet(const Packet &other) {
- if (other.m_dataLength > 0) {
- m_dataLength = other.m_dataLength;
- m_data = new byte[m_dataLength];
- m_parsePtr = m_data + (other.m_data - other.m_parsePtr);
- std::copy(other.m_data, other.m_data + m_dataLength, m_data);
- }
- m_fields = other.m_fields;
-}
-
-void Packet::ParseFieldArray(Field &field, FieldType type, size_t len) {
- Field f = FieldParser::Parse(type, m_parsePtr, len);
- field.Attach(f);
- m_parsePtr += f.GetLength();
- if (m_parsePtr == m_data + m_dataLength) {
- delete[] m_data;
- m_data = nullptr;
- m_dataLength = 0;
- m_parsePtr = nullptr;
- }
-}
diff --git a/src/packet/Packet.hpp b/src/packet/Packet.hpp
deleted file mode 100644
index 68a5d5e..0000000
--- a/src/packet/Packet.hpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#pragma once
-
-#include <vector>
-#include "Field.hpp"
-#include "FieldParser.hpp"
-
-enum ConnectionState {
- Login,
- Handshaking,
- Play,
- Status,
-};
-
-enum PacketsClientBound{
- SpawnObject=0x00,
- SpawnExperienceOrb,
- SpawnGlobalEntity,
- SpawnMob,
- SpawnPainting,
- SpawnPlayer,
- Animation,
- Statistics,
- BlockBreakAnimation,
- UpdateBlockEntity,
- BlockAction,
- BlockChange,
- BossBar,
- ServerDifficulty,
- Tab,
- ChatMessage,
- MultiBlockChange,
- ConfirmTransaction,
- CloseWindowEvent,
- OpenWindow,
- WindowItems,
- WindowProperty,
- SetSlot,
- SetCooldown,
- PluginMessage,
- NamedSoundEffect,
- Disconnect,
- EntityStatus,
- Explosion,
- UnloadChunk,
- ChangeGameState,
- KeepAlive,
- ChunkData,
- Effect,
- Particle,
- JoinGame,
- Map,
- EntityRelativeMove,
- EntityLookAndRelativeMove,
- EntityLook,
- Entity,
- VehicleMove,
- OpenSignEditor,
- PlayerAbilities,
- CombatEvent,
- PlayerListItem,
- PlayerPositionAndLook,
- UseBed,
- DestroyEntities,
- RemoveEntityEffect,
- ResourcePackSend,
- Respawn,
- EntityHeadLook,
- WorldBorder,
- Camera,
- HeldItemChange,
- DisplayScoreboard,
- EntityMetadata_,
- AttachEntity,
- EntityVelocity,
- EntityEquipment,
- SetExperience,
- UpdateHealth,
- ScoreboardObjective,
- SetPassengers,
- Teams,
- UpdateScore,
- SpawnPosition,
- TimeUpdate,
- Title,
- SoundEffect,
- PlayerListHeaderAndFooter,
- CollectItem,
- EntityTeleport,
- EntityProperties,
- EntityEffect,
-};
-
-class Packet {
-public:
- Packet(int id);
-
- Packet(byte *data);
-
- Packet(const Packet &other);
-
- ~Packet() {
- delete[] m_data;
- }
-
- int GetId();
-
- void AddField(Field field);
-
- void ParseField(FieldType type, size_t len = 0);
-
- void ParseFieldArray(Field &field, FieldType type, size_t len);
-
- Field & GetField(int id);
-
- size_t GetLength();
-
- void CopyToBuff(byte *ptr);
-
- void swap(Packet &other);
-
- Packet operator=(Packet other);
-
-private:
- Packet();
-
- std::vector<Field> m_fields;
- byte *m_data = nullptr;
- byte *m_parsePtr = nullptr;
- size_t m_dataLength = 0;
-}; \ No newline at end of file
diff --git a/src/packet/PacketBuilder.cpp b/src/packet/PacketBuilder.cpp
deleted file mode 100644
index 4083ea3..0000000
--- a/src/packet/PacketBuilder.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "PacketBuilder.hpp"
-
-Packet PacketBuilder::CHandshaking0x00(int protocolVerison, std::string address, unsigned short port, int nextState) {
- Packet handshakePacket(0);
- Field fProtocol;
- fProtocol.SetVarInt(protocolVerison);
- Field fAddress;
- fAddress.SetString(address);
- Field fPort;
- fPort.SetUShort(port);
- Field fNextState;
- fNextState.SetVarInt(nextState);
- handshakePacket.AddField(fProtocol);
- handshakePacket.AddField(fAddress);
- handshakePacket.AddField(fPort);
- handshakePacket.AddField(fNextState);
- return handshakePacket;
-}
-
-Packet PacketBuilder::CPlay0x0B(int keepAliveId) {
- Packet keepAlivePacket(0x0B);
- Field fKeepAlive;
- fKeepAlive.SetVarInt(keepAliveId);
- keepAlivePacket.AddField(fKeepAlive);
- return keepAlivePacket;
-}
-
-Packet PacketBuilder::CPlay0x03(int actionId) {
- Packet clientStatusPacket(0x03);
- Field fActionId;
- fActionId.SetVarInt(actionId);
- clientStatusPacket.AddField(fActionId);
- return clientStatusPacket;
-}
-
-Packet PacketBuilder::CPlay0x00(int teleportId) {
- Packet teleportConfirmPacket(0x00);
- Field fTeleportId;
- fTeleportId.SetVarInt(teleportId);
- teleportConfirmPacket.AddField(fTeleportId);
- return teleportConfirmPacket;
-}
-
-Packet PacketBuilder::CPlay0x0D(double x, double y, double z, float yaw, float pitch, bool onGround) {
- Packet playerPositionAndLookPacket(0x0D);
- Field fX;
- Field fY;
- Field fZ;
- Field fYaw;
- Field fPitch;
- Field fOnGround;
- fX.SetDouble(x);
- fY.SetDouble(y);
- fZ.SetDouble(z);
- fYaw.SetFloat(yaw);
- fPitch.SetFloat(pitch);
- fOnGround.SetBool(onGround);
- playerPositionAndLookPacket.AddField(fX);
- playerPositionAndLookPacket.AddField(fY);
- playerPositionAndLookPacket.AddField(fZ);
- playerPositionAndLookPacket.AddField(fYaw);
- playerPositionAndLookPacket.AddField(fPitch);
- playerPositionAndLookPacket.AddField(fOnGround);
- return playerPositionAndLookPacket;
-}
diff --git a/src/packet/PacketBuilder.hpp b/src/packet/PacketBuilder.hpp
deleted file mode 100644
index 2fcb737..0000000
--- a/src/packet/PacketBuilder.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-
-#include "Packet.hpp"
-
-class PacketBuilder {
-public:
- static Packet CHandshaking0x00(int protocolVerison, std::string address, unsigned short port, int nextState);
- static Packet CPlay0x0B(int keepAliveId);
-
- static Packet CPlay0x03(int actionId);
-
- static Packet CPlay0x00(int teleportId);
-
- static Packet CPlay0x0D(double x, double y, double z, float yaw, float pitch, bool onGround);
-};
-
diff --git a/src/packet/PacketParser.cpp b/src/packet/PacketParser.cpp
deleted file mode 100644
index a609011..0000000
--- a/src/packet/PacketParser.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-#include "PacketParser.hpp"
-
-void PacketParser::Parse(Packet &packet, ConnectionState state, bool ClientBound) {
- if (ClientBound) {
- switch (state) {
- case Login:
- ParseLogin(packet);
- break;
- case Handshaking:
- break;
- case Play:
- ParsePlay(packet);
- break;
- case Status:
-
- break;
- }
- } else {
- ParseServerBound(packet, state);
- }
-}
-
-void PacketParser::ParseServerBound(Packet &packet, ConnectionState state) {
- if (packet.GetLength() != state)
- throw 107;
-}
-
-void PacketParser::ParseLogin(Packet &packet) {
- switch (packet.GetId()) {
- case 0x00:
- ParseLogin0x00(packet);
- break;
- case 0x02:
- ParseLogin0x02(packet);
- break;
- default: {
-
- //throw 112;
- }
- }
-}
-
-void PacketParser::ParsePlay(Packet &packet) {
- switch (packet.GetId()) {
- case 0x23:
- ParsePlay0x23(packet);
- break;
- case 0x1F:
- ParsePlay0x1F(packet);
- break;
- case 0x0D:
- ParsePlay0x0D(packet);
- break;
- case 0x2B:
- ParsePlay0x2B(packet);
- break;
- case 0x43:
- ParsePlay0x43(packet);
- break;
- case 0x2E:
- ParsePlay0x2E(packet);
- break;
- case 0x1A:
- ParsePlay0x1A(packet);
- break;
- case 0x20:
- ParsePlay0x20(packet);
- break;
- case 0x07:
- ParsePlay0x07(packet);
- default:
- //throw 113;
- break;
- }
-}
-
-void PacketParser::ParseLogin0x00(Packet &packet) {
- packet.ParseField(String);
-}
-
-void PacketParser::ParseLogin0x02(Packet &packet) {
- packet.ParseField(String);
- packet.ParseField(String);
-}
-
-void PacketParser::ParsePlay0x23(Packet &packet) {
- packet.ParseField(Int);
- packet.ParseField(UnsignedByte);
- packet.ParseField(Int);
- packet.ParseField(UnsignedByte);
- packet.ParseField(UnsignedByte);
- packet.ParseField(String);
- packet.ParseField(Boolean);
-}
-
-void PacketParser::ParsePlay0x1F(Packet &packet) {
- packet.ParseField(VarIntType);
-}
-
-void PacketParser::ParsePlay0x0D(Packet &packet) {
- packet.ParseField(UnsignedByte);
-}
-
-void PacketParser::ParsePlay0x2B(Packet &packet) {
- packet.ParseField(Byte8_t);
- packet.ParseField(Float);
- packet.ParseField(Float);
-}
-
-void PacketParser::ParsePlay0x43(Packet &packet) {
- packet.ParseField(Position);
-}
-
-void PacketParser::ParsePlay0x2E(Packet &packet) {
- packet.ParseField(Double);
- packet.ParseField(Double);
- packet.ParseField(Double);
- packet.ParseField(Float);
- packet.ParseField(Float);
- packet.ParseField(Byte8_t);
- packet.ParseField(VarIntType);
-}
-
-void PacketParser::ParsePlay0x1A(Packet &packet) {
- packet.ParseField(String);
-}
-
-void PacketParser::ParsePlay0x20(Packet &packet) {
- packet.ParseField(Int);
- packet.ParseField(Int);
- packet.ParseField(Boolean);
- packet.ParseField(VarIntType);
- packet.ParseField(VarIntType);
- packet.ParseField(ByteArray, packet.GetField(4).GetVarInt());
- packet.ParseField(VarIntType);
- //packet.ParseField(NbtTag);
- //packet.GetField(7).SetArray(packet.GetField(6).GetVarInt());
-}
-
-void PacketParser::ParsePlay0x07(Packet &packet) {
- packet.ParseField(VarIntType);
- packet.AddField(Field());
- for (int i = 0; i < packet.GetField(0).GetVarInt(); i++) {
- packet.ParseFieldArray(packet.GetField(1), String, 0);
- packet.ParseFieldArray(packet.GetField(1), VarIntType, 0);
- }
-}
diff --git a/src/packet/PacketParser.hpp b/src/packet/PacketParser.hpp
deleted file mode 100644
index 8ca6195..0000000
--- a/src/packet/PacketParser.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-
-#include "Packet.hpp"
-
-class PacketParser {
-public:
- static void Parse(Packet &packet, ConnectionState state = Play, bool ClientBound = true);
-
- static void ParseServerBound(Packet &packet, ConnectionState state);
-
- static void ParseLogin(Packet &packet);
-
- static void ParsePlay(Packet &packet);
-
- static void ParseLogin0x00(Packet &packet);
-
- static void ParseLogin0x02(Packet &packet);
-
- static void ParsePlay0x23(Packet &packet);
-
- static void ParsePlay0x1F(Packet &packet);
-
- static void ParsePlay0x0D(Packet &packet);
-
- static void ParsePlay0x2B(Packet &packet);
-
- static void ParsePlay0x43(Packet &packet);
-
- static void ParsePlay0x2E(Packet &packet);
-
- static void ParsePlay0x1A(Packet &packet);
-
- static void ParsePlay0x20(Packet &packet);
-
- static void ParsePlay0x07(Packet &packet);
-};
-
diff --git a/src/world/Collision.cpp b/src/world/Collision.cpp
new file mode 100644
index 0000000..4f2c837
--- /dev/null
+++ b/src/world/Collision.cpp
@@ -0,0 +1,28 @@
+#include "Collision.hpp"
+
+bool TestCollision(AABB first, AABB second) {
+ double firstXl = first.x;
+ double firstXr = first.x + first.w;
+
+ double firstYl = first.y;
+ double firstYr = first.y + first.h;
+
+ double firstZl = first.z;
+ double firstZr = first.z + first.l;
+
+
+ double secondXl = second.x;
+ double secondXr = second.x + second.w;
+
+ double secondYl = second.y;
+ double secondYr = second.y + second.h;
+
+ double secondZl = second.z;
+ double secondZr = second.z + second.l;
+
+ bool collidesOnX = firstXr >= secondXl && firstXl <= secondXr;
+ bool collidesOnY = firstYr >= secondYl && firstYl <= secondYr;
+ bool collidesOnZ = firstZr >= secondZl && firstZl <= secondZr;
+
+ return collidesOnX && collidesOnY && collidesOnZ;
+}
diff --git a/src/world/Collision.hpp b/src/world/Collision.hpp
new file mode 100644
index 0000000..b88fbf7
--- /dev/null
+++ b/src/world/Collision.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+struct AABB {
+ double x,y,z;
+ double w,l,h;
+};
+
+bool TestCollision(AABB first, AABB second); \ No newline at end of file
diff --git a/src/world/Section.cpp b/src/world/Section.cpp
index 63c7f97..8f94ad7 100644
--- a/src/world/Section.cpp
+++ b/src/world/Section.cpp
@@ -1,7 +1,8 @@
#include "Section.hpp"
+
Section::Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock,
- std::vector<unsigned short> palette) {
+ std::vector<unsigned short> palette) {
m_dataBlocksLen = dataBlocksLength;
m_dataBlocks = new byte[m_dataBlocksLen];
std::copy(dataBlocks, dataBlocks + m_dataBlocksLen, m_dataBlocks);
@@ -93,30 +94,22 @@ void Section::Parse() {
m_dataSkyLight = nullptr;
parseWaiter.notify_all();
- /*static std::map<Block,int> totalBlocks;
- for (int x=0;x<16;x++)
- for (int y=0;y<16;y++)
- for (int z=0;z<16;z++)
- totalBlocks[GetBlock(Vector(x,y,z))]++;
- LOG(ERROR)<<"Logging chunk";
- for (auto& it:totalBlocks){
- LOG(WARNING)<<it.first.id<<":"<<(int)it.first.state<<" = "<<it.second;
- }*/
}
Section &Section::operator=(Section other) {
- other.swap(*this);
+ std::swap(*this,other);
return *this;
}
-void Section::swap(Section &other) {
- std::swap(other.m_dataBlocksLen, m_dataBlocksLen);
- std::swap(other.m_dataBlocks, m_dataBlocks);
- std::swap(other.m_dataLight, m_dataLight);
- std::swap(other.m_dataSkyLight, m_dataSkyLight);
- std::swap(other.m_blocks, m_blocks);
- std::swap(other.m_palette, m_palette);
- std::swap(other.m_bitsPerBlock, m_bitsPerBlock);
+void swap(Section &a, Section &b) {
+ using std::swap;
+ swap(a.m_dataBlocksLen, b.m_dataBlocksLen);
+ swap(a.m_dataBlocks, b.m_dataBlocks);
+ swap(a.m_dataLight, b.m_dataLight);
+ swap(a.m_dataSkyLight, b.m_dataSkyLight);
+ swap(a.m_blocks, b.m_blocks);
+ swap(a.m_palette, b.m_palette);
+ swap(a.m_bitsPerBlock, b.m_bitsPerBlock);
}
Section::Section(const Section &other) {
diff --git a/src/world/Section.hpp b/src/world/Section.hpp
index 36fc91a..657fc13 100644
--- a/src/world/Section.hpp
+++ b/src/world/Section.hpp
@@ -5,38 +5,39 @@
#include <condition_variable>
#include <easylogging++.h>
#include "Block.hpp"
-#include "../packet/Field.hpp"
+#include "../utility/Vector.hpp"
+#include "../utility/utility.h"
const int SECTION_WIDTH = 16;
const int SECTION_LENGTH = 16;
const int SECTION_HEIGHT = 16;
class Section {
- std::vector<unsigned short> m_palette;
- byte *m_dataBlocks = nullptr;
- size_t m_dataBlocksLen;
- byte *m_dataLight = nullptr;
- byte *m_dataSkyLight = nullptr;
- byte m_bitsPerBlock = 0;
- std::vector<Block> m_blocks;
- std::condition_variable parseWaiter;
+ std::vector<unsigned short> m_palette;
+ byte *m_dataBlocks = nullptr;
+ size_t m_dataBlocksLen;
+ byte *m_dataLight = nullptr;
+ byte *m_dataSkyLight = nullptr;
+ byte m_bitsPerBlock = 0;
+ std::vector<Block> m_blocks;
+ std::condition_variable parseWaiter;
- Section();
+ Section();
public:
- void Parse();
+ void Parse();
- Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock,
- std::vector<unsigned short> palette);
+ Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock,
+ std::vector<unsigned short> palette);
- ~Section();
+ ~Section();
- Block &GetBlock(Vector pos);
+ Block &GetBlock(Vector pos);
- Section &operator=(Section other);
+ Section &operator=(Section other);
- void swap(Section &other);
+ friend void swap(Section &a, Section& b);
- Section(const Section &other);
+ Section(const Section &other);
}; \ No newline at end of file
diff --git a/src/world/World.cpp b/src/world/World.cpp
index 2220627..394598b 100644
--- a/src/world/World.cpp
+++ b/src/world/World.cpp
@@ -1,84 +1,39 @@
#include "World.hpp"
-void World::ParseChunkData(Packet packet) {
- int chunkX = packet.GetField(0).GetInt();
- int chunkZ = packet.GetField(1).GetInt();
- bool isGroundContinuous = packet.GetField(2).GetBool();
- std::bitset<16> bitmask(packet.GetField(3).GetVarInt());
- int entities = packet.GetField(5).GetVarInt();
-
- size_t dataLen = packet.GetField(5).GetLength();
- byte *content = new byte[dataLen];
- byte *contentOrigPtr = content;
- packet.GetField(5).CopyToBuff(content);
-
- if (isGroundContinuous)
- dataLen -= 256;
-
- byte *biomes = content + packet.GetField(5).GetLength() - 256;
+void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) {
+ StreamBuffer chunkData(packet->Data.data(), packet->Data.size());
+ std::bitset<16> bitmask(packet->PrimaryBitMask);
for (int i = 0; i < 16; i++) {
if (bitmask[i]) {
- size_t len = 0;
- Vector chunkPosition = Vector(chunkX, i, chunkZ);
- if (!m_sections.insert(std::make_pair(chunkPosition, ParseSection(content, len))).second)
- LOG(ERROR) << "Chunk not created: " << chunkPosition;
- auto sectionIter = m_sections.find(chunkPosition);
- if (sectionIter == m_sections.end())
- LOG(ERROR) << "Created chunk not found: " << chunkPosition;
- else
- sectionIter->second.Parse();
- content += len;
+ Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ);
+ Section section = ParseSection(&chunkData);
+ auto it = sections.find(chunkPosition);
+ if (it == sections.end()) {
+ sections.insert(std::make_pair(chunkPosition, section));
+ } else {
+ using std::swap;
+ swap(it->second, section);
+ }
+ sections.find(chunkPosition)->second.Parse();
}
}
- delete[] contentOrigPtr;
}
-Section World::ParseSection(byte *data, size_t &dataLen) {
- dataLen = 0;
-
- Field fBitsPerBlock = FieldParser::Parse(UnsignedByte, data);
- byte bitsPerBlock = fBitsPerBlock.GetUByte();
- data += fBitsPerBlock.GetLength();
- dataLen += fBitsPerBlock.GetLength();
-
- Field fPaletteLength = FieldParser::Parse(VarIntType, data);
- int paletteLength = fPaletteLength.GetVarInt();
- data += fPaletteLength.GetLength();
- dataLen += fPaletteLength.GetLength();
-
+Section World::ParseSection(StreamInput *data) {
+ unsigned char bitsPerBlock = data->ReadUByte();
+ int paletteLength = data->ReadVarInt();
std::vector<unsigned short> palette;
- if (paletteLength > 0) {
- for (unsigned char i = 0; i < paletteLength; i++) {
- endswap(&i);
- Field f = FieldParser::Parse(VarIntType, data);
- data += f.GetLength();
- dataLen += f.GetLength();
- palette.push_back(f.GetVarInt());
- endswap(&i);
- }
+ for (int i = 0; i < paletteLength; i++) {
+ palette.push_back(data->ReadVarInt());
}
-
- Field fDataLength = FieldParser::Parse(VarIntType, data);
- data += fDataLength.GetLength();
- dataLen += fDataLength.GetLength();
-
- int dataLength = fDataLength.GetVarInt();
- size_t dataSize = dataLength * 8;
- dataLen += dataSize;
- byte *dataBlocks = data;
-
- data += 2048;
- dataLen += 2048;
- byte *dataLight = data;
-
- byte *dataSky = nullptr;
- if (m_dimension == 0) {
- data += 2048;
- dataLen += 2048;
- dataSky = data;
- }
-
- return Section(dataBlocks, dataSize, dataLight, dataSky, bitsPerBlock, palette);
+ int dataArrayLength = data->ReadVarInt();
+ auto dataArray = data->ReadByteArray(dataArrayLength * 8);
+ auto blockLight = data->ReadByteArray(4096 / 2);
+ std::vector<unsigned char> skyLight;
+ if (dimension == 0)
+ skyLight = data->ReadByteArray(4096 / 2);
+ return Section(dataArray.data(), dataArray.size(), blockLight.data(),
+ (skyLight.size() > 0 ? skyLight.data() : nullptr), bitsPerBlock, palette);
}
World::~World() {
@@ -86,4 +41,56 @@ World::~World() {
World::World() {
-} \ No newline at end of file
+}
+
+bool World::isPlayerCollides(double X, double Y, double Z) {
+ Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0));
+ std::vector<Vector> closestSectionsCoordinates = {
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX() + 1, PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX() - 1, PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY() + 1, PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY() - 1, PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ() + 1),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ() - 1),
+ };
+ std::vector<std::map<Vector, Section>::iterator> closestSections;
+ for (auto &coord:closestSectionsCoordinates) {
+ auto it = sections.find(coord);
+ if (it != sections.end())
+ closestSections.push_back(it);
+ }
+ if (closestSections.empty())
+ return false;
+
+ for (auto &it:closestSections) {
+
+ const double PlayerWidth = 0.6;
+ const double PlayerHeight = 1.82;
+ const double PlayerLength = 0.6;
+
+ AABB playerColl;
+ playerColl.x = X - PlayerWidth / 2 - 0.5;
+ playerColl.w = PlayerWidth;
+ playerColl.y = Y - 0.5f;
+ playerColl.h = PlayerHeight;
+ playerColl.z = Z - PlayerLength / 2 - 0.5;
+ playerColl.l = PlayerLength;
+
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ for (int z = 0; z < 16; z++) {
+ Block block = it->second.GetBlock(Vector(x, y, z));
+ if (block.id == 0 || block.id == 31)
+ continue;
+ AABB blockColl{(x + it->first.GetX() * 16) - 0.5,
+ (y + it->first.GetY() * 16) - 0.5,
+ (z + it->first.GetZ() * 16) - 0.5, 1, 1, 1};
+ if (TestCollision(playerColl, blockColl))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/world/World.hpp b/src/world/World.hpp
index b33499c..e315baf 100644
--- a/src/world/World.hpp
+++ b/src/world/World.hpp
@@ -8,27 +8,30 @@
#include <bitset>
#include <easylogging++.h>
#include "Block.hpp"
-#include "../packet/Packet.hpp"
#include "Section.hpp"
+#include "../network/Packet.hpp"
+#include "Collision.hpp"
class World {
- //utility vars
- World(const World &other);
+ //utility vars
+ World(const World &other);
- World &operator=(const World &other);
+ World &operator=(const World &other);
- //game vars
- int m_dimension = 0;
+ //game vars
+ int dimension = 0;
- //game methods
- Section ParseSection(byte *data, size_t &dataLen);
+ //game methods
+ Section ParseSection(StreamInput *data);
public:
- World();
+ World();
- ~World();
+ ~World();
- void ParseChunkData(Packet packet);
+ void ParseChunkData(std::shared_ptr<PacketChunkData> packet);
- std::map<Vector, Section> m_sections;
+ std::map<Vector, Section> sections;
+
+ bool isPlayerCollides(double X, double Y, double Z);
}; \ No newline at end of file