summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
m---------external/imgui0
-rw-r--r--src/AssetManager.cpp96
-rw-r--r--src/AssetManager.hpp6
-rw-r--r--src/Block.cpp4
-rw-r--r--src/Block.hpp4
-rw-r--r--src/GameState.cpp20
-rw-r--r--src/GameState.hpp4
-rw-r--r--src/Network.cpp13
-rw-r--r--src/Packet.hpp198
-rw-r--r--src/Render.cpp73
-rw-r--r--src/Render.hpp2
-rw-r--r--src/RendererSection.cpp234
-rw-r--r--src/RendererSection.hpp8
-rw-r--r--src/RendererWorld.cpp20
-rw-r--r--src/RendererWorld.hpp5
-rw-r--r--src/Section.cpp46
-rw-r--r--src/Section.hpp6
-rw-r--r--src/Stream.cpp27
-rw-r--r--src/Stream.hpp11
-rw-r--r--src/Utility.hpp2
-rw-r--r--src/Vector.hpp5
-rw-r--r--src/Window.cpp6
-rw-r--r--src/Window.hpp20
-rw-r--r--src/World.cpp227
-rw-r--r--src/World.hpp33
26 files changed, 687 insertions, 385 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bcef8ee..edf5588 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,6 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
-include(externalProject)
##########
# SOURCES
@@ -72,7 +71,6 @@ find_package(OpenGL REQUIRED)
target_link_libraries(AltCraft ${OPENGL_LIBRARIES})
target_include_directories(AltCraft PUBLIC ${OPENGL_INCLUDE_DIRS})
-
#################
# COPY RESOURCES
#################
diff --git a/external/imgui b/external/imgui
deleted file mode 160000
-Subproject 7a7327addec8cde30c13d6224a121033043874b
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp
index 6e35160..02ee7ee 100644
--- a/src/AssetManager.cpp
+++ b/src/AssetManager.cpp
@@ -1,6 +1,6 @@
#include <fstream>
#include "AssetManager.hpp"
-#include <filesystem>
+#include <experimental/filesystem>
namespace fs = std::experimental::filesystem::v1;
@@ -15,7 +15,7 @@ const fs::path pathToModels = "./assets/minecraft/models/";
AssetManager::AssetManager() {
LoadIds();
LoadTextureResources();
- //LoadBlockModels();
+ LoadBlockModels();
}
void AssetManager::LoadIds() {
@@ -194,32 +194,58 @@ AssetManager &AssetManager::Instance() {
}
const BlockModel *AssetManager::GetBlockModelByBlockId(BlockId block) {
- std::string blockName = "";
- for (const auto& it : assetIds) {
- if (BlockId{ it.second.id,0 } == BlockId{ block.id,0 }) {
- blockName = it.first;
- break;
+ block.state = 0;
+ if (blockIdToBlockName.find(block) == blockIdToBlockName.end()) {
+ std::string blockName = "";
+ for (const auto& it : assetIds) {
+ if (BlockId{ it.second.id,0 } == block) {
+ blockName = it.first;
+ break;
+ }
}
+ if (blockName == "grass")
+ blockName = "grass_normal";
+ if (blockName == "torch")
+ blockName = "normal_torch";
+ if (blockName == "leaves")
+ blockName = "oak_leaves";
+ if (blockName == "tallgrass")
+ blockName = "tall_grass";
+ if (blockName == "log")
+ blockName = "oak_bark";
+ if (blockName == "snow_layer")
+ blockName = "snow_height2";
+
+ blockName = "block/" + blockName;
+
+ if (blockName == "")
+ return nullptr;
+
+ blockIdToBlockName[block] = blockName;
}
- blockName = "block/" + blockName;
+ std::string blockName = blockIdToBlockName[block];
- if (blockName == "" || models.find(blockName) == models.end())
+ auto modelIt = models.find(blockName);
+ if (modelIt == models.end())
return nullptr;
-
- return &models[blockName];
+
+ return &modelIt->second;
}
void AssetManager::LoadBlockModels() {
std::function<void(std::string)> parseModel = [&](std::string ModelName) {
+ if (models.find(ModelName) != models.end())
+ return;
+
fs::path ModelPath = pathToModels / fs::path(ModelName + ".json");
std::ifstream in(ModelPath);
if (!in.is_open())
throw std::runtime_error("Trying to load unknown model \"" + ModelName + "\" at " + ModelPath.generic_string());
nlohmann::json modelData;
in >> modelData;
- BlockModel model;
+ BlockModel model;
if (modelData.find("parent") != modelData.end()) {
if (models.find(modelData["parent"]) == models.end())
@@ -228,6 +254,14 @@ void AssetManager::LoadBlockModels() {
model = models.find(modelData["parent"])->second;
}
+ model.BlockName = ModelName;
+
+ if (model.BlockName == "block/block")
+ model.IsBlock = true;
+
+ if (model.BlockName == "block/thin_block" || model.BlockName=="block/leaves")
+ model.IsBlock = false;
+
if (modelData.find("ambientocclusion") != modelData.end())
model.AmbientOcclusion = modelData["ambientocclusion"].get<bool>();
@@ -240,6 +274,7 @@ void AssetManager::LoadBlockModels() {
}
if (modelData.find("elements") != modelData.end()) {
+ model.Elements.clear();
for (auto& it : modelData["elements"]) {
BlockModel::ElementData element;
@@ -257,8 +292,11 @@ void AssetManager::LoadBlockModels() {
element.rotationOrigin = rotOrig;
element.rotationAxis = (it["rotation"]["axis"].get<std::string>() == "x") ? BlockModel::ElementData::Axis::x : ((it["rotation"]["axis"].get<std::string>() == "y") ? BlockModel::ElementData::Axis::y : BlockModel::ElementData::Axis::z);
- element.rotationAngle = it["rotation"]["angle"].get<int>();
- element.rotationRescale = it["rotation"]["recale"].get<bool>();
+ if (it["rotation"].find("angle") != it["rotation"].end())
+ element.rotationAngle = it["rotation"]["angle"].get<int>();
+
+ if (it["rotation"].find("rescale") != it["rotation"].end())
+ element.rotationRescale = it["rotation"]["rescale"].get<bool>();
}
if (it.find("shade") != it.end())
@@ -291,7 +329,7 @@ void AssetManager::LoadBlockModels() {
faceData.uv = uv;
}
- BlockModel::ElementData::FaceDirection cullface;
+ BlockModel::ElementData::FaceDirection cullface = faceDir;
if (face.find("cullface") != face.end()) {
if (face["cullface"] == "down")
cullface = BlockModel::ElementData::FaceDirection::down;
@@ -304,9 +342,9 @@ void AssetManager::LoadBlockModels() {
else if (face["cullface"] == "west")
cullface = BlockModel::ElementData::FaceDirection::west;
else if (face["cullface"] == "east")
- cullface = BlockModel::ElementData::FaceDirection::east;
- faceData.cullface = cullface;
- }
+ cullface = BlockModel::ElementData::FaceDirection::east;
+ }
+ faceData.cullface = cullface;
faceData.texture = face["texture"].get<std::string>();
@@ -314,7 +352,7 @@ void AssetManager::LoadBlockModels() {
faceData.rotation = face["rotation"].get<int>();
if (face.find("tintindex") != face.end())
- faceData.tintIndex = face["tintindex"];
+ faceData.tintIndex = true;
element.faces[faceDir] = faceData;
}
@@ -326,12 +364,24 @@ void AssetManager::LoadBlockModels() {
models.insert(std::make_pair(ModelName, model));
};
- parseModel("block/stone");
+ fs::path pathToBlockModels = pathToModels.generic_string() + "/block/";
- /*for (auto& dirEntry : fs::directory_iterator(pathToBlockModels)) {
+ for (auto& dirEntry : fs::recursive_directory_iterator(pathToBlockModels)) {
if (dirEntry.path().extension() != ".json")
continue;
+
+ std::string modelName = dirEntry.path().stem().generic_string();
+
+ parseModel("block/" + modelName);
+ }
+}
- parseModel(dirEntry.path().generic_string());
- }*/
+std::string AssetManager::GetAssetNameByBlockId(BlockId block) {
+ for (auto& it : assetIds) {
+ BlockId value = it.second;
+ value.state = 0;
+ if (value == block)
+ return it.first;
+ }
+ return "#NF";
} \ No newline at end of file
diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp
index 96f9741..50d9bbf 100644
--- a/src/AssetManager.hpp
+++ b/src/AssetManager.hpp
@@ -55,6 +55,9 @@ struct BlockTextureId {
};
struct BlockModel {
+ bool IsBlock = false;
+ std::string BlockName;
+
bool AmbientOcclusion=true;
enum DisplayVariants {
@@ -123,6 +126,7 @@ class AssetManager {
std::map<std::string, TextureCoordinates> assetTextures;
std::map<BlockTextureId,glm::vec4> textureAtlasIndexes;
std::map<std::string, BlockModel> models;
+ std::map<BlockId, std::string> blockIdToBlockName;
public:
AssetManager();
@@ -147,4 +151,6 @@ public:
const BlockModel *GetBlockModelByBlockId(BlockId block);
void LoadBlockModels();
+
+ std::string GetAssetNameByBlockId(BlockId block);
};
diff --git a/src/Block.cpp b/src/Block.cpp
index 840dbcf..667670d 100644
--- a/src/Block.cpp
+++ b/src/Block.cpp
@@ -8,4 +8,8 @@ Block::Block() : id(0), state(0), light(0), sky(0) {}
bool operator==(const BlockId& lhs, const BlockId &rhs) {
return (lhs.id == rhs.id) && (lhs.state == rhs.state);
+}
+
+bool operator<(const BlockId& lhs, const BlockId &rhs) {
+ return (lhs.id < rhs.id);
} \ No newline at end of file
diff --git a/src/Block.hpp b/src/Block.hpp
index 78c9cca..c3dfcec 100644
--- a/src/Block.hpp
+++ b/src/Block.hpp
@@ -18,4 +18,6 @@ struct BlockId {
unsigned char state : 4;
};
-bool operator==(const BlockId& lhs, const BlockId &rhs); \ No newline at end of file
+bool operator==(const BlockId& lhs, const BlockId &rhs);
+
+bool operator<(const BlockId& lhs, const BlockId &rhs); \ No newline at end of file
diff --git a/src/GameState.cpp b/src/GameState.cpp
index b9f9b28..46b236c 100644
--- a/src/GameState.cpp
+++ b/src/GameState.cpp
@@ -144,10 +144,20 @@ void GameState::UpdatePacket()
break;
case CloseWindowCB:
break;
- case OpenWindow:
+ case OpenWindow: {
+ auto packet = std::static_pointer_cast<PacketOpenWindow>(ptr);
+
+ LOG(INFO) << "Open new window " << packet->WindowTitle << ": " << packet->WindowId;
break;
- case WindowItems:
+ }
+ case WindowItems: {
+ auto packet = std::static_pointer_cast<PacketWindowItems>(ptr);
+ if (packet->WindowId == 0) {
+ playerInventory.WindowId = 0;
+ playerInventory.slots = packet->SlotData;
+ }
break;
+ }
case WindowProperty:
break;
case SetSlot:
@@ -392,6 +402,10 @@ void GameState::UpdatePacket()
}
ptr = nc->ReceivePacket();
}
+ while (!playerInventory.pendingTransactions.empty()) {
+ nc->SendPacket(std::make_shared<PacketClickWindow>(playerInventory.pendingTransactions.front()));
+ playerInventory.pendingTransactions.pop();
+ }
}
void GameState::HandleMovement(GameState::Direction direction, float deltaTime) {
@@ -419,7 +433,7 @@ void GameState::HandleMovement(GameState::Direction direction, float deltaTime)
break;
case JUMP:
if (g_OnGround) {
- vel.y += 5;
+ vel.y += 10;
g_OnGround = false;
}
break;
diff --git a/src/GameState.hpp b/src/GameState.hpp
index 6dbb194..659f829 100644
--- a/src/GameState.hpp
+++ b/src/GameState.hpp
@@ -8,6 +8,7 @@
#include "NetworkClient.hpp"
#include "Vector.hpp"
#include "Event.hpp"
+#include "Window.hpp"
class GameState {
std::shared_ptr<NetworkClient> nc;
@@ -73,4 +74,7 @@ public:
long long TimeOfDay = 0;
std::shared_ptr<GameState> gs;
+
+ Window playerInventory;
+ std::vector<Window> openedWindows;
};
diff --git a/src/Network.cpp b/src/Network.cpp
index 4606959..cf4fe15 100644
--- a/src/Network.cpp
+++ b/src/Network.cpp
@@ -47,6 +47,7 @@ std::shared_ptr<Packet> Network::ReceivePacketByPacketId(int packetId, Connectio
packet = std::make_shared<PacketHandshake>();
break;
}
+ break;
case Login:
switch (packetId) {
case PacketNameLoginCB::LoginSuccess:
@@ -102,17 +103,17 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
case MultiBlockChange:
return std::make_shared<PacketMultiBlockChange>();
case ConfirmTransactionCB:
- break;
+ return std::make_shared<PacketConfirmTransactionCB>();
case CloseWindowCB:
- break;
+ return std::make_shared<PacketCloseWindowCB>();
case OpenWindow:
- break;
+ return std::make_shared<PacketOpenWindow>();
case WindowItems:
- break;
+ return std::make_shared<PacketWindowItems>();
case WindowProperty:
- break;
+ return std::make_shared<PacketWindowProperty>();
case SetSlot:
- break;
+ return std::make_shared<PacketSetSlot>();
case SetCooldown:
break;
case PluginMessageCB:
diff --git a/src/Packet.hpp b/src/Packet.hpp
index d1d80e6..e00f1ed 100644
--- a/src/Packet.hpp
+++ b/src/Packet.hpp
@@ -1,7 +1,5 @@
#pragma once
-#include <easylogging++.h>
-
#include "Stream.hpp"
enum PacketNameLoginSB {
@@ -417,7 +415,7 @@ struct PacketChunkData : Packet {
stream->WriteVarInt(Data.size());
stream->WriteByteArray(Data);
stream->WriteVarInt(BlockEntities.size());
- LOG(FATAL) << "Serializing unimplemented packet";
+ //LOG(FATAL) << "Serializing unimplemented packet";
}
void FromStream(StreamInput *stream) override {
@@ -587,11 +585,10 @@ struct PacketEntityLookAndRelativeMove : Packet {
DeltaX = stream->ReadShort();
DeltaY = stream->ReadShort();
DeltaZ = stream->ReadShort();
- return;
//TODO: WTF?
- Yaw = stream->ReadAngle();
+ /*Yaw = stream->ReadAngle();
Pitch = stream->ReadAngle();
- OnGround = stream->ReadBool();
+ OnGround = stream->ReadBool();*/
}
int GetPacketId() override {
@@ -837,4 +834,193 @@ struct PacketUnloadChunk : Packet {
int ChunkX;
int ChunkZ;
+};
+
+struct PacketCloseWindowCB : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ WindowId = stream->ReadUByte();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::CloseWindowCB;
+ }
+
+ unsigned char WindowId;
+};
+
+struct PacketOpenWindow : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ WindowId = stream->ReadUByte();
+ WindowType = stream->ReadString();
+ WindowTitle = stream->ReadChat();
+ NumberOfSlots = stream->ReadUByte();
+
+ if (WindowType == "EntityHorse")
+ EntityId = stream->ReadInt();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::OpenWindow;
+ }
+
+ unsigned char WindowId;
+ std::string WindowType;
+ std::string WindowTitle;
+ unsigned char NumberOfSlots;
+ int EntityId;
+};
+
+struct PacketWindowItems : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ WindowId = stream->ReadUByte();
+ short count = stream->ReadShort();
+ for (int i = 0; i < count; i++)
+ SlotData.push_back(stream->ReadSlot());
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::WindowItems;
+ }
+
+ unsigned char WindowId;
+ std::vector<SlotData> SlotData;
+};
+
+struct PacketWindowProperty : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ WindowId = stream->ReadUByte();
+ Property = stream->ReadShort();
+ Value = stream->ReadShort();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::WindowProperty;
+ }
+
+ unsigned char WindowId;
+ short Property;
+ short Value;
+};
+
+struct PacketSetSlot : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ WindowId = stream->ReadByte();
+ Slot = stream->ReadShort();
+ SlotData = stream->ReadSlot();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::SetSlot;
+ }
+
+ signed char WindowId;
+ short Slot;
+ SlotData SlotData;
+};
+
+struct PacketConfirmTransactionCB : Packet {
+ void ToStream(StreamOutput *stream) override {
+
+ }
+
+ void FromStream(StreamInput *stream) override {
+ WindowId = stream->ReadByte();
+ ActionNumber = stream->ReadShort();
+ Accepted = stream->ReadBool();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlayCB::ConfirmTransactionCB;
+ }
+
+ signed char WindowId;
+ short ActionNumber;
+ bool Accepted;
+};
+
+struct PacketConfirmTransactionSB : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteByte(WindowId);
+ stream->WriteShort(ActionNumber);
+ stream->WriteBool(Accepted);
+ }
+
+ void FromStream(StreamInput *stream) override {
+ WindowId = stream->ReadByte();
+ ActionNumber = stream->ReadShort();
+ Accepted = stream->ReadBool();
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::ConfirmTransactionSB;
+ }
+
+ signed char WindowId;
+ short ActionNumber;
+ bool Accepted;
+};
+
+struct PacketClickWindow : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteUByte(WindowId);
+ stream->WriteShort(Slot);
+ stream->WriteByte(Button);
+ stream->WriteShort(ActionNumber);
+ stream->WriteInt(Mode);
+ stream->WriteSlot(ClickedItem);
+ }
+
+ void FromStream(StreamInput *stream) override {
+
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::ClickWindow;
+ }
+
+ unsigned char WindowId;
+ short Slot;
+ signed char Button;
+ short ActionNumber;
+ int Mode;
+ SlotData ClickedItem;
+
+ PacketClickWindow(unsigned char windowId, short slot, signed char button, short actionNumber, int mode, SlotData ClickedItem) : WindowId(windowId), Slot(slot),
+ Button(button), ActionNumber(actionNumber), Mode(mode), ClickedItem(ClickedItem) {};
+};
+
+struct PacketCloseWindowSB : Packet {
+ void ToStream(StreamOutput *stream) override {
+ stream->WriteUByte(WindowId);
+ }
+
+ void FromStream(StreamInput *stream) override {
+
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::CloseWindowSB;
+ }
+
+ unsigned char WindowId;
}; \ No newline at end of file
diff --git a/src/Render.cpp b/src/Render.cpp
index 0504d0a..2382ec2 100644
--- a/src/Render.cpp
+++ b/src/Render.cpp
@@ -16,6 +16,8 @@ Render::Render(unsigned int windowWidth, unsigned int windowHeight, std::string
glCheckError();
PrepareToRendering();
glCheckError();
+
+ LOG(INFO) << "Supported threads: " << std::thread::hardware_concurrency();
}
Render::~Render() {
@@ -60,10 +62,11 @@ void Render::InitGlew() {
int width, height;
SDL_GL_GetDrawableSize(window, &width, &height);
glViewport(0, 0, width, height);
+ glClearColor(0.8,0.8,0.8, 1.0f);
glEnable(GL_DEPTH_TEST);
- /*glEnable(GL_CULL_FACE);
+ glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
- glFrontFace(GL_CCW);*/
+ glFrontFace(GL_CCW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glCheckError();
@@ -102,13 +105,15 @@ void Render::UpdateKeyboard() {
}
}
-void Render::RenderFrame() {
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+void Render::RenderFrame() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
+ if (isWireframe)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (renderWorld)
world->Render(renderState);
+ if (isWireframe)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (world) {
world->Update(timer.RemainTimeMs());
@@ -141,11 +146,13 @@ void Render::HandleEvents() {
break;
}
case SDL_WINDOWEVENT_FOCUS_GAINED:
+ HasFocus = true;
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
HasFocus = false;
SetMouseCapture(false);
- state = GlobalState::Paused;
+ if (state == GlobalState::Playing)
+ state = GlobalState::Paused;
break;
}
break;
@@ -156,6 +163,7 @@ void Render::HandleEvents() {
if (state == GlobalState::Playing) {
state = GlobalState::Paused;
SetMouseCapture(false);
+ isDisplayInventory = false;
}
else if (state == GlobalState::Paused) {
state = GlobalState::Playing;
@@ -166,8 +174,14 @@ void Render::HandleEvents() {
isRunning = false;
}
break;
+ case SDL_SCANCODE_E:
+ if (state != GlobalState::Playing)
+ return;
+ isDisplayInventory = !isDisplayInventory;
+ SetMouseCapture(!isDisplayInventory);
+ break;
}
- break;
+ break;
case SDL_MOUSEMOTION:
if (isMouseCaptured) {
double deltaX = event.motion.xrel;
@@ -207,7 +221,7 @@ void Render::ExecuteRenderLoop() {
listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) {
auto data = std::get<ConnectionSuccessfullData>(eventData);
- stateString = "Logging in...";
+ stateString = "Logging in...";
});
listener.RegisterHandler(EventType::PlayerConnected, [this](EventData eventData) {
@@ -221,6 +235,7 @@ void Render::ExecuteRenderLoop() {
renderWorld = true;
state = GlobalState::Playing;
SetMouseCapture(true);
+ glClearColor(0, 0, 0, 1.0f);
});
listener.RegisterHandler(EventType::ConnectionFailed, [this](EventData eventData) {
@@ -228,6 +243,7 @@ void Render::ExecuteRenderLoop() {
renderWorld = false;
world.reset();
state = GlobalState::MainMenu;
+ glClearColor(0.8, 0.8, 0.8, 1.0f);
});
listener.RegisterHandler(EventType::Disconnected, [this](EventData eventData) {
@@ -235,6 +251,8 @@ void Render::ExecuteRenderLoop() {
renderWorld = false;
world.reset();
state = GlobalState::MainMenu;
+ SetMouseCapture(false);
+ glClearColor(0.8, 0.8, 0.8, 1.0f);
});
listener.RegisterHandler(EventType::Connecting, [this](EventData eventData) {
@@ -246,13 +264,14 @@ void Render::ExecuteRenderLoop() {
while (isRunning) {
HandleEvents();
- if (HasFocus) UpdateKeyboard();
+ if (HasFocus && state == GlobalState::Playing) UpdateKeyboard();
if (isMouseCaptured) HandleMouseCapture();
glCheckError();
RenderFrame();
- while (listener.IsEventsQueueIsNotEmpty())
- listener.HandleEvent();
+ while (listener.IsEventsQueueIsNotEmpty()) {
+ listener.HandleEvent();
+ }
timer.Update();
}
EventAgregator::PushEvent(EventType::Exit, ExitData{});
@@ -279,6 +298,8 @@ void Render::RenderGui() {
ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f/gameTime, gameTime);
ImGui::Text("Sections loaded: %d", (int)DebugInfo::totalSections);
ImGui::Text("SectionsRenderer: %d (%d)", (int)DebugInfo::renderSections, (int)DebugInfo::readyRenderer);
+ if (world)
+ ImGui::Text("Player pos: %.1f %.1f %.1f", world->GameStatePtr()->g_PlayerX, world->GameStatePtr()->g_PlayerY, world->GameStatePtr()->g_PlayerZ);
ImGui::End();
@@ -302,6 +323,29 @@ void Render::RenderGui() {
case GlobalState::Loading:
break;
case GlobalState::Playing:
+ if (isDisplayInventory) {
+ ImGui::SetNextWindowPosCenter();
+ ImGui::Begin("Inventory", 0, windowFlags);
+ Window& inventory = world->GameStatePtr()->playerInventory;
+ for (int i = 0; i < inventory.slots.size()+1; i++) {
+ SlotData slot;
+ if (i == inventory.slots.size())
+ slot = inventory.handSlot;
+ else
+ slot = inventory.slots[i];
+
+ if (slot.BlockId == -1) {
+ ImGui::Button("Empty");
+ continue;
+ }
+ std::string slotName = AssetManager::Instance().GetAssetNameByBlockId(BlockId{(unsigned short) slot.BlockId,0 });
+ if (ImGui::Button((slotName + "##"+std::to_string(i)).c_str())) {
+ inventory.MakeClick(i, true);
+ LOG(INFO) << "Clicked " << slotName << "("<<slot.BlockId<<") in slot " << i;
+ }
+ }
+ ImGui::End();
+ }
break;
case GlobalState::Paused: {
ImGui::SetNextWindowPosCenter();
@@ -317,13 +361,20 @@ void Render::RenderGui() {
static float sense = sensetivity;
ImGui::SliderFloat("Sensetivity", &sense, 0.01f, 1.0f);
+ static bool wireframe = isWireframe;
+
+ ImGui::Checkbox("Wireframe", &wireframe);
+
if (ImGui::Button("Apply settings")) {
if (distance != world->MaxRenderingDistance) {
world->MaxRenderingDistance = distance;
EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{});
}
+
if (sense != sensetivity)
sensetivity = sense;
+
+ isWireframe = wireframe;
}
ImGui::Separator();
diff --git a/src/Render.hpp b/src/Render.hpp
index 0b67218..2a48356 100644
--- a/src/Render.hpp
+++ b/src/Render.hpp
@@ -21,6 +21,8 @@ class Render {
std::map<SDL_Scancode, bool> isKeyPressed;
bool HasFocus=true;
float sensetivity = 0.1f;
+ bool isWireframe = false;
+ bool isDisplayInventory = false;
enum GlobalState {
InitialLoading,
diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp
index 2b5fc1e..22acc61 100644
--- a/src/RendererSection.cpp
+++ b/src/RendererSection.cpp
@@ -170,9 +170,7 @@ size_t RendererSection::GetHash()
RendererSectionData::RendererSectionData(World * world, Vector sectionPosition) {
const std::map<BlockTextureId, glm::vec4> &textureAtlas = AssetManager::Instance().GetTextureAtlasIndexes();
- if (!world->GetSection(sectionPosition))
- return;
- const Section &section = *world->GetSection(sectionPosition);
+ const Section &section = world->GetSection(sectionPosition);
hash = section.GetHash();
sectionPos = sectionPosition;
@@ -187,217 +185,72 @@ RendererSectionData::RendererSectionData(World * world, Vector sectionPosition)
if (block.id == 0)
continue;
- /*transform = glm::translate(baseOffset, Vector(x, y, z).glm());
+ const bool useNewMethod = true;
+
+
+ transform = glm::translate(baseOffset, Vector(x, y, z).glm());
const BlockModel* model = AssetManager::Instance().GetBlockModelByBlockId(block);
- if (model ) {
- this->AddFacesByBlockModel(world, Vector(x,y,z), *model, transform, section.GetBlockLight(Vector(x,y,z)),section.GetBlockSkyLight(Vector(x,y,z)));
- } else {
+ if (model) {
+ this->AddFacesByBlockModel(sectionsList, world, Vector(x, y, z), *model, transform, section.GetBlockLight(Vector(x, y, z)), section.GetBlockSkyLight(Vector(x, y, z)));
+ }
+ else {
transform = glm::translate(transform, glm::vec3(0, 1, 0));
+
+ if (block.id == 8 || block.id == 9) {
+ textures.push_back(AssetManager::Instance().GetTextureByAssetName("minecraft/textures/blocks/water_still"));
+ textures.back().w /= 32.0f;
+ transform = glm::translate(transform, glm::vec3(0, -0.2, 0));
+ } else
+ textures.push_back(AssetManager::Instance().GetTextureByAssetName("minecraft/textures/blocks/tnt_side"));
+
models.push_back(transform);
- textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
colors.push_back(glm::vec3(0, 0, 0));
lights.push_back(glm::vec2(16, 16));
- }*/
-
- auto testBlockNonExist = [&](Vector block) -> bool {
- Vector offset;
- if (block.x == -1) {
- offset = Vector(-1, 0, 0);
- block.x = 15;
- } else if (block.x == 16) {
- offset = Vector(1, 0, 0);
- block.x = 0;
- } else if (block.y == -1) {
- offset = Vector(0, -1, 0);
- block.y = 15;
- } else if (block.y == 16) {
- offset = Vector(0, 1, 0);
- block.y = 0;
- } else if (block.z == -1) {
- offset = Vector(0, 0, -1);
- block.z = 15;
- } else if (block.z == 16) {
- offset = Vector(0, 0, 1);
- block.z = 0;
- }
- if (offset != Vector(0, 0, 0)) {
- if (std::find(sectionsList.begin(), sectionsList.end(), sectionPosition + offset) == sectionsList.end())
- return true;
- const Section& blockSection = *world->GetSection(sectionPosition + offset);
- return blockSection.GetBlockId(block).id == 0 || blockSection.GetBlockId(block).id == 31 || blockSection.GetBlockId(block).id == 18;
- }
- return section.GetBlockId(block).id == 0 || section.GetBlockId(block).id == 31 || section.GetBlockId(block).id == 18;
- };
-
- unsigned char isVisible = 0;
- isVisible |= testBlockNonExist(Vector(x - 1, y, z)) << 0;
- isVisible |= testBlockNonExist(Vector(x + 1, y, z)) << 1;
- isVisible |= testBlockNonExist(Vector(x, y + 1, z)) << 2;
- isVisible |= testBlockNonExist(Vector(x, y - 1, z)) << 3;
- isVisible |= testBlockNonExist(Vector(x, y, z - 1)) << 4;
- isVisible |= testBlockNonExist(Vector(x, y, z + 1)) << 5;
-
- if (isVisible == 0x00)
- continue;
-
- glm::mat4 transform;
- transform = glm::translate(transform, glm::vec3(sectionPosition * 16u));
- transform = glm::translate(transform, glm::vec3(x, y, z));
- glm::vec3 biomeColor(0.275, 0.63, 0.1);
- glm::vec3 color(0.0f, 0.0f, 0.0f);
- if (block.id == 31 || block.id == 18)
- color = biomeColor;
-
- if (block.id == 31) { //X-cross like blocks rendering
- auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 2));
- for (int i = 0; i < 4; i++) {
- textures.push_back(texture->second);
- colors.push_back(color);
- lights.push_back(glm::vec2(0, 0));
- }
- glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0.15f, 0, 0.15f));
- faceTransform = glm::scale(faceTransform, glm::vec3(1.0f, 0.9f, 1.0f));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f));
- faceTransform = glm::rotate(faceTransform, glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0));
- for (int i = 0; i < 4; i++) {
- models.push_back(faceTransform);
- faceTransform = glm::translate(faceTransform, glm::vec3(0.0f, 0.0f, 0.5f));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
- faceTransform = glm::translate(faceTransform, glm::vec3(0.0f, 0.0f, -0.5f));
- }
- continue;
}
- if (isVisible >> 0 & 0x1) { //east side of block (X+)
- glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 0));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f));
- models.push_back(faceTransform);
- auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 2));
- if (texture != textureAtlas.end())
- textures.push_back(texture->second);
- else
- textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
- 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
- colors.push_back(color);
- lights.push_back(glm::vec2(0, 0));
- }
- if (isVisible >> 1 & 0x1) { //west side X-
- glm::mat4 faceTransform = glm::translate(transform, glm::vec3(1, 0, 0));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f));
- faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f));
- faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1));
- models.push_back(faceTransform);
- auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 3));
- if (texture != textureAtlas.end())
- textures.push_back(texture->second);
- else
- textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
- 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
- colors.push_back(color);
- lights.push_back(glm::vec2(0, 0));
- }
- if (isVisible >> 2 & 0x1) { //Top side Y+
- glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 1, 0));
- models.push_back(faceTransform);
- auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 1));
- if (texture != textureAtlas.end())
- textures.push_back(texture->second);
- else
- textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
- 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
- if (block.id != 2)
- colors.push_back(color);
- else
- colors.push_back(biomeColor);
- lights.push_back(glm::vec2(0, 0));
- }
- if (isVisible >> 3 & 0x1) { //Bottom side Y-
- glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 0));
- faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0, 0));
- faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1));
- models.push_back(faceTransform);
- auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 0));
- if (texture != textureAtlas.end())
- textures.push_back(texture->second);
- else
- textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
- 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
- colors.push_back(color);
- lights.push_back(glm::vec2(0, 0));
- }
- if (isVisible >> 4 & 0x1) { //south side Z+
- glm::mat4 faceTransform = glm::translate(transform, glm::vec3(1, 0, 0));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f));
- models.push_back(faceTransform);
- auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 3));
- if (texture != textureAtlas.end())
- textures.push_back(texture->second);
- else
- textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
- 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
- colors.push_back(color);
- lights.push_back(glm::vec2(0, 0));
- }
- if (isVisible >> 5 & 0x1) { //north side Z-
- glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 1));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f));
- faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f));
- faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1));
- faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1, 0, 0.0f));
- faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1.0f));
- models.push_back(faceTransform);
- auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 4));
- if (texture != textureAtlas.end())
- textures.push_back(texture->second);
- else
- textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
- 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
- colors.push_back(color);
- lights.push_back(glm::vec2(0, 0));
- }
}
}
- }
+ }
textures.shrink_to_fit();
models.shrink_to_fit();
colors.shrink_to_fit();
}
-void RendererSectionData::AddFacesByBlockModel(World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight) {
+void RendererSectionData::AddFacesByBlockModel(const std::vector<Vector> &sectionsList, World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight) {
glm::mat4 elementTransform, faceTransform;
for (const auto& element : model.Elements) {
- VectorF elementSize(VectorF(element.to - element.from) / 16.0f);
- VectorF elementOrigin(VectorF(element.from) / 16.0f);
+ Vector t = element.to - element.from;
+ VectorF elementSize(VectorF(t.x,t.y,t.z) / 16.0f);
+ VectorF elementOrigin(VectorF(element.from.x,element.from.y,element.from.z) / 16.0f);
elementTransform = glm::translate(transform, elementOrigin.glm());
- elementTransform = glm::scale(elementTransform, elementSize.glm());
+ elementTransform = glm::scale(elementTransform, elementSize.glm());
for (const auto& face : element.faces) {
if (face.second.cullface != BlockModel::ElementData::FaceDirection::none) {
switch (face.second.cullface) {
case BlockModel::ElementData::FaceDirection::down:
- if (TestBlockExists(world, blockPos - Vector(0, -1, 0)))
+ if (TestBlockExists(sectionsList, world, blockPos - Vector(0, +1, 0)))
continue;
break;
case BlockModel::ElementData::FaceDirection::up:
- if (TestBlockExists(world, blockPos - Vector(0, +1, 0)))
+ if (TestBlockExists(sectionsList, world, blockPos - Vector(0, -1, 0)))
continue;
break;
case BlockModel::ElementData::FaceDirection::north:
- if (TestBlockExists(world, blockPos - Vector(0, 0, -1)))
+ if (TestBlockExists(sectionsList, world, blockPos - Vector(0, 0, -1)))
continue;
break;
case BlockModel::ElementData::FaceDirection::south:
- if (TestBlockExists(world, blockPos - Vector(0, 0, +1)))
+ if (TestBlockExists(sectionsList, world, blockPos - Vector(0, 0, +1)))
continue;
break;
case BlockModel::ElementData::FaceDirection::west:
- if (TestBlockExists(world, blockPos - Vector(-1, 0, 0)))
+ if (TestBlockExists(sectionsList, world, blockPos - Vector(-1, 0, 0)))
continue;
break;
case BlockModel::ElementData::FaceDirection::east:
- if (TestBlockExists(world, blockPos - Vector(+1, 0, 0)))
+ if (TestBlockExists(sectionsList, world, blockPos - Vector(+1, 0, 0)))
continue;
break;
}
@@ -443,41 +296,48 @@ void RendererSectionData::AddFacesByBlockModel(World *world, Vector blockPos, co
}
glm::vec4 texture = AssetManager::Instance().GetTextureByAssetName("minecraft/textures/" + textureName);
textures.push_back(texture);
- colors.push_back(glm::vec3(0, 0, 0));
+ if (face.second.tintIndex)
+ colors.push_back(glm::vec3(0.275, 0.63, 0.1));
+ else
+ colors.push_back(glm::vec3(0, 0, 0));
lights.push_back(glm::vec2(light, skyLight));
}
}
}
-bool RendererSectionData::TestBlockExists(World *world, Vector blockPos) {
+bool RendererSectionData::TestBlockExists(const std::vector<Vector> &sectionsList, World *world, Vector blockPos) {
Vector section = sectionPos;
if (blockPos.x == -1) {
- section = section - Vector(-1, 0, 0);
+ section = section + Vector(-1, 0, 0);
blockPos.x = 15;
}
else if (blockPos.x == 16) {
- section = section - Vector(+1, 0, 0);
+ section = section + Vector(+1, 0, 0);
blockPos.x = 0;
}
else if (blockPos.y == -1) {
- section = section - Vector(0, -1, 0);
+ section = section + Vector(0, -1, 0);
blockPos.y = 15;
}
else if (blockPos.y == 16) {
- section = section - Vector(0, +1, 0);
+ section = section + Vector(0, +1, 0);
blockPos.y = 0;
}
else if (blockPos.z == -1) {
- section = section - Vector(0, 0, -1);
+ section = section + Vector(0, 0, -1);
blockPos.z = 15;
}
else if (blockPos.z == 16) {
- section = section - Vector(0, 0, +1);
+ section = section + Vector(0, 0, +1);
blockPos.z = 0;
}
- auto ptr = world->GetSection(sectionPos);
- if (!ptr)
+
+ if (std::find(sectionsList.begin(), sectionsList.end(),section) == sectionsList.end())
return true;
- return ptr->GetBlockId(blockPos).id != 0;
+ BlockId blockId = world->GetSection(section).GetBlockId(blockPos);
+
+ auto blockModel = AssetManager::Instance().GetBlockModelByBlockId(world->GetSection(section).GetBlockId(blockPos));
+
+ return blockId.id != 0 && blockModel && blockModel->IsBlock;
} \ No newline at end of file
diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp
index 9931239..1c7fc3d 100644
--- a/src/RendererSection.hpp
+++ b/src/RendererSection.hpp
@@ -21,11 +21,11 @@ struct RendererSectionData {
size_t hash;
Vector sectionPos;
- bool TestBlockExists(World *world, Vector blockPos);
-
- void AddFacesByBlockModel(World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight);
-
RendererSectionData(World *world, Vector sectionPosition);
+private:
+ bool TestBlockExists(const std::vector<Vector> &sectionsList, World *world, Vector blockPos);
+
+ void AddFacesByBlockModel(const std::vector<Vector> &sectionsList, World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight);
};
class RendererSection {
enum Vbos {
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp
index a0cb8a7..3e5868b 100644
--- a/src/RendererWorld.cpp
+++ b/src/RendererWorld.cpp
@@ -13,7 +13,7 @@ void RendererWorld::WorkerFunction(size_t workerId) {
sectionsMutex.lock();
auto result = sections.find(vec);
if (result != sections.end()) {
- if (result->second.GetHash() != gs->world.GetSection(result->first)->GetHash()) {
+ if (result->second.GetHash() != gs->world.GetSection(result->first).GetHash()) {
sectionsMutex.unlock();
RendererSectionData data(&gs->world, vec);
renderDataMutex.lock();
@@ -76,7 +76,9 @@ void RendererWorld::UpdateAllSections(VectorF playerPos)
playerChunk.y = std::floor(gs->g_PlayerY / 16.0);
std::sort(suitableChunks.begin(), suitableChunks.end(), [playerChunk](Vector lhs, Vector rhs) {
- return (playerChunk - lhs).GetLength() < (playerChunk - rhs).GetLength();
+ double leftLengthToPlayer = (playerChunk - lhs).GetLength();
+ double rightLengthToPlayer = (playerChunk - rhs).GetLength();
+ return leftLengthToPlayer < rightLengthToPlayer;
});
for (auto& it : suitableChunks) {
@@ -86,7 +88,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos)
RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) {
MaxRenderingDistance = 1;
- numOfWorkers = 1;
+ numOfWorkers = std::thread::hardware_concurrency() - 2;
PrepareRender();
@@ -105,7 +107,7 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) {
listener.RegisterHandler(EventType::NewRenderDataAvailable,[this](EventData eventData) {
renderDataMutex.lock();
int i = 0;
- while (!renderData.empty() && i<20) {
+ while (!renderData.empty() && i++ < 20) {
auto &data = renderData.front();
isParsingMutex.lock();
if (isParsing[data.sectionPos] != true)
@@ -188,8 +190,6 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) {
workers.push_back(std::thread(&RendererWorld::WorkerFunction, this, i));
EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{});
-
- //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
RendererWorld::~RendererWorld() {
@@ -226,7 +226,7 @@ void RendererWorld::Render(RenderState & renderState) {
glCheckError();
sectionsMutex.lock();
- for (auto& section : sections) {
+ for (auto& section : sections) {
sectionsMutex.unlock();
std::vector<Vector> sectionCorners = {
Vector(0, 0, 0),
@@ -253,7 +253,7 @@ void RendererWorld::Render(RenderState & renderState) {
}
double lengthToSection = (VectorF(gs->g_PlayerX, gs->g_PlayerY, gs->g_PlayerZ) - VectorF(section.first.x*16,section.first.y*16,section.first.z*16)).GetLength();
- if (isBreak && lengthToSection > 30.0f) {
+ if (isBreak && lengthToSection > 30.0f && false) {
sectionsMutex.lock();
continue;
}
@@ -364,3 +364,7 @@ void RendererWorld::Update(double timeToUpdate) {
DebugInfo::readyRenderer = this->renderData.size();
DebugInfo::renderSections = this->sections.size();
}
+
+GameState* RendererWorld::GameStatePtr() {
+ return gs.get();
+} \ No newline at end of file
diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp
index 4e098e5..751f1a7 100644
--- a/src/RendererWorld.hpp
+++ b/src/RendererWorld.hpp
@@ -20,6 +20,8 @@ class RendererWorld {
std::mutex isParsingMutex;
std::map<Vector, bool> isParsing;
//Blocks
+ std::mutex renderDataMutex;
+ std::queue<RendererSectionData> renderData;
std::vector<Vector> renderList;
std::mutex sectionsMutex;
std::map<Vector, RendererSection> sections;
@@ -43,6 +45,5 @@ public:
void Update(double timeToUpdate);
- std::mutex renderDataMutex;
- std::queue<RendererSectionData> renderData;
+ GameState *GameStatePtr();
}; \ No newline at end of file
diff --git a/src/Section.cpp b/src/Section.cpp
index 554cdbf..67dde70 100644
--- a/src/Section.cpp
+++ b/src/Section.cpp
@@ -2,14 +2,26 @@
#include <bitset>
-void Section::CalculateHash() {
- std::vector<unsigned char> rawData;
- rawData.reserve(block.size() * sizeof(long long) + light.size() + sky.size());
- std::copy(block.begin(), block.end(), std::back_inserter(rawData));
- std::copy(light.begin(), light.end(), std::back_inserter(rawData));
+void Section::CalculateHash() const {
+ size_t offset = 0;
+
+ std::vector<unsigned char> rawData;
+ rawData.resize(block.size() * sizeof(long long) + light.size() + sky.size());
+
+ std::memcpy(rawData.data() + offset, block.data(), block.size() * sizeof(BlockId));
+ offset += block.size() * sizeof(BlockId);
+
+ std::memcpy(rawData.data() + offset, light.data(), light.size() * sizeof(unsigned char));
+ offset += light.size() * sizeof(unsigned char);
+
if (!sky.empty())
- std::copy(sky.begin(), sky.end(), std::back_inserter(rawData));
+ std::memcpy(rawData.data() + offset, sky.data(), sky.size() * sizeof(unsigned char));
+ for (auto& it : overrideList) {
+ rawData.push_back(*reinterpret_cast<const unsigned short*> (&it.second) & 0xF);
+ rawData.push_back(*reinterpret_cast<const unsigned short*> (&it.second) >> 0xF);
+ }
+
const unsigned char *from = reinterpret_cast<const unsigned char *>(rawData.data());
size_t length = rawData.size();
@@ -30,12 +42,10 @@ Section::Section(Vector pos, unsigned char bitsPerBlock, std::vector<unsigned sh
this->light = std::move(lightData);
this->sky = std::move(skyData);
- CalculateHash();
+ hash = -1;
}
-Section::Section() {
-
- CalculateHash();
+Section::Section():hash(-1),bitsPerBlock(0) {
}
Section::~Section() {
@@ -45,19 +55,24 @@ Section::~Section() {
Section::Section(Section && other) noexcept {
using std::swap;
swap(*this, other);
- CalculateHash();
+ hash = -1;
}
Section &Section::operator=(Section other) noexcept {
using std::swap;
swap(*this, other);
- CalculateHash();
+ hash = -1;
return *this;
}
BlockId Section::GetBlockId(Vector pos) const {
if (block.empty())
return BlockId{ 0,0 };
+
+ auto iter = overrideList.find(pos);
+ if (iter != overrideList.end())
+ return iter->second;
+
int value;
unsigned char individualValueMask = ((1 << bitsPerBlock) - 1);
@@ -67,7 +82,7 @@ BlockId Section::GetBlockId(Vector pos) const {
int startOffset = (blockNumber * bitsPerBlock) % 64;
int endLong = ((blockNumber + 1) * bitsPerBlock - 1) / 64;
- unsigned short t;
+ unsigned char t;
if (startLong == endLong) {
t = (block[startLong] >> startOffset);
@@ -108,7 +123,8 @@ unsigned char Section::GetBlockSkyLight(Vector pos) const
}
void Section::SetBlockId(Vector pos, BlockId value) {
- LOG(WARNING) << "Block changing not implemented!";
+ overrideList[pos] = value;
+ hash = -1;
}
void swap(Section& lhs, Section& rhs) noexcept {
@@ -137,5 +153,7 @@ Vector Section::GetPosition() const {
}
size_t Section::GetHash() const {
+ if (hash == -1)
+ CalculateHash();
return hash;
} \ No newline at end of file
diff --git a/src/Section.hpp b/src/Section.hpp
index 7a7a3d0..41bef7b 100644
--- a/src/Section.hpp
+++ b/src/Section.hpp
@@ -19,9 +19,11 @@ class Section {
std::vector<unsigned short> palette;
Vector worldPosition;
- size_t hash;
+ mutable size_t hash;
- void CalculateHash();
+ void CalculateHash() const;
+
+ std::map<Vector, BlockId> overrideList;
public:
Section(Vector pos, unsigned char bitsPerBlock, std::vector<unsigned short> palette, std::vector<long long> blockData, std::vector<unsigned char> lightData, std::vector<unsigned char> skyData);
diff --git a/src/Stream.cpp b/src/Stream.cpp
index 28680c6..665247d 100644
--- a/src/Stream.cpp
+++ b/src/Stream.cpp
@@ -118,14 +118,28 @@ long long StreamInput::ReadVarLong() {
}
std::vector<unsigned char> StreamInput::ReadEntityMetadata() {
+ LOG(FATAL) << "Reading EntityMetadata is not implemented";
return std::vector<unsigned char>();
}
-std::vector<unsigned char> StreamInput::ReadSlot() {
- return std::vector<unsigned char>();
+SlotData StreamInput::ReadSlot() {
+ SlotData slot;
+ slot.BlockId = ReadShort();
+
+ if (slot.BlockId == -1)
+ return slot;
+
+ slot.ItemCount = ReadByte();
+ slot.ItemDamage = ReadShort();
+
+ if (ReadByte() != 0)
+ throw std::runtime_error("Slot data with NBT not supported");
+
+ return slot;
}
std::vector<unsigned char> StreamInput::ReadNbtTag() {
+ LOG(FATAL) << "Reading NBT is not implemented";
return std::vector<unsigned char>();
}
@@ -255,8 +269,13 @@ void StreamOutput::WriteEntityMetadata(std::vector<unsigned char> value) {
LOG(FATAL) << "Used unimplemented WriteEntityMetadata: " << value.size();
}
-void StreamOutput::WriteSlot(std::vector<unsigned char> value) {
- LOG(FATAL) << "Used unimplemented WriteSlot " << value.size();
+void StreamOutput::WriteSlot(SlotData value) {
+ WriteShort(value.BlockId);
+ if (value.BlockId == -1)
+ return;
+ WriteByte(value.ItemCount);
+ WriteShort(value.ItemDamage);
+ WriteUByte(0);
}
void StreamOutput::WriteNbtTag(std::vector<unsigned char> value) {
diff --git a/src/Stream.hpp b/src/Stream.hpp
index 012addf..5432383 100644
--- a/src/Stream.hpp
+++ b/src/Stream.hpp
@@ -13,6 +13,13 @@
#include "Vector.hpp"
#include "Utility.hpp"
+struct SlotData {
+ short BlockId = -1;
+ signed char ItemCount = 1;
+ short ItemDamage = 0;
+ //Nbt NBT;
+};
+
class Stream {
public:
virtual ~Stream() {};
@@ -36,7 +43,7 @@ public:
int ReadVarInt();
long long ReadVarLong();
std::vector<unsigned char> ReadEntityMetadata();
- std::vector<unsigned char> ReadSlot();
+ SlotData ReadSlot();
std::vector<unsigned char> ReadNbtTag();
Vector ReadPosition();
unsigned char ReadAngle();
@@ -62,7 +69,7 @@ public:
void WriteVarInt(int value);
void WriteVarLong(long long value);
void WriteEntityMetadata(std::vector<unsigned char> value);
- void WriteSlot(std::vector<unsigned char> value);
+ void WriteSlot(SlotData value);
void WriteNbtTag(std::vector<unsigned char> value);
void WritePosition(Vector value);
void WriteAngle(unsigned char value);
diff --git a/src/Utility.hpp b/src/Utility.hpp
index d31a1a3..064f4dd 100644
--- a/src/Utility.hpp
+++ b/src/Utility.hpp
@@ -59,4 +59,4 @@ public:
double GetRealDeltaS();
double RemainTimeMs();
-};
+}; \ No newline at end of file
diff --git a/src/Vector.hpp b/src/Vector.hpp
index 6389bbb..c89154f 100644
--- a/src/Vector.hpp
+++ b/src/Vector.hpp
@@ -14,11 +14,6 @@ struct Vector3 {
Vector3(const Vector3 &rhs) : x(rhs.x), y(rhs.y), z(rhs.z) {}
- template<class U>
- Vector3(const Vector3<U> &rhs) : x(rhs.x), y(rhs.y), z(rhs.z) {}
-
- Vector3(Vector3 &&rhs) = default;
-
~Vector3() = default;
double GetLength() const { return std::sqrt(std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2)); }
diff --git a/src/Window.cpp b/src/Window.cpp
new file mode 100644
index 0000000..fbf9aaa
--- /dev/null
+++ b/src/Window.cpp
@@ -0,0 +1,6 @@
+#include "Window.hpp"
+
+void Window::MakeClick(short ClickedSlot, bool Lmb) {
+ PacketClickWindow packet(WindowId, ClickedSlot, Lmb? 0 : 1, actions++, 0, slots[ClickedSlot]);
+ this->pendingTransactions.push(packet);
+} \ No newline at end of file
diff --git a/src/Window.hpp b/src/Window.hpp
new file mode 100644
index 0000000..4dae294
--- /dev/null
+++ b/src/Window.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <string>
+#include <queue>
+
+#include "Packet.hpp"
+
+struct Window {
+ unsigned char WindowId = 0;
+ std::string type;
+
+ SlotData handSlot;
+ std::vector<SlotData> slots;
+
+ short actions = 1;
+
+ void MakeClick(short ClickedSlot, bool Lmb);
+
+ std::queue<PacketClickWindow> pendingTransactions;
+}; \ No newline at end of file
diff --git a/src/World.cpp b/src/World.cpp
index 19eddbf..5b4bb03 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -3,122 +3,128 @@
#include "DebugInfo.hpp"
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]) {
- Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ);
- Section section = ParseSection(&chunkData, chunkPosition);
-
+ StreamBuffer chunkData(packet->Data.data(), packet->Data.size());
+ std::bitset<16> bitmask(packet->PrimaryBitMask);
+ for (int i = 0; i < 16; i++) {
+ if (bitmask[i]) {
+ Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ);
+ Section section = ParseSection(&chunkData, chunkPosition);
+
if (packet->GroundUpContinuous) {
- if (!sections.insert(std::make_pair(chunkPosition, section)).second) {
+ if (!sections.insert(std::make_pair(chunkPosition, std::make_unique<Section>(section))).second) {
LOG(ERROR) << "New chunk not created " << chunkPosition << " potential memory leak";
}
- UpdateSectionList();
- } else {
+ UpdateSectionsList();
+ }
+ else {
using std::swap;
- swap(sections.at(chunkPosition), section);
+ swap(*sections.at(chunkPosition).get(), section);
}
EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ chunkPosition });
}
- }
+ }
}
Section World::ParseSection(StreamInput *data, Vector position) {
- unsigned char bitsPerBlock = data->ReadUByte();
-
- int paletteLength = data->ReadVarInt();
- std::vector<unsigned short> palette;
- for (int i = 0; i < paletteLength; i++) {
- palette.push_back(data->ReadVarInt());
- }
- int dataArrayLength = data->ReadVarInt();
- auto dataArray = data->ReadByteArray(dataArrayLength * 8);
- auto blockLight = data->ReadByteArray(2048);
- std::vector<unsigned char> skyLight;
- if (dimension == 0)
- skyLight = data->ReadByteArray(2048);
+ unsigned char bitsPerBlock = data->ReadUByte();
+
+ int paletteLength = data->ReadVarInt();
+ std::vector<unsigned short> palette;
+ for (int i = 0; i < paletteLength; i++) {
+ palette.push_back(data->ReadVarInt());
+ }
+ int dataArrayLength = data->ReadVarInt();
+ auto dataArray = data->ReadByteArray(dataArrayLength * 8);
+ auto blockLight = data->ReadByteArray(2048);
+ std::vector<unsigned char> skyLight;
+ if (dimension == 0)
+ skyLight = data->ReadByteArray(2048);
long long *blockData = reinterpret_cast<long long*>(dataArray.data());
for (int i = 0; i < dataArray.size() / sizeof(long long); i++)
endswap(blockData[i]);
- std::vector<long long> blockArray (blockData, blockData + dataArray.size() / sizeof (long long));
+ std::vector<long long> blockArray(blockData, blockData + dataArray.size() / sizeof(long long));
return Section(position, bitsPerBlock, std::move(palette), std::move(blockArray), std::move(blockLight), std::move(skyLight));
}
World::~World() {
- DebugInfo::totalSections = 0;
}
World::World() {
}
bool World::isPlayerCollides(double X, double Y, double Z) {
- Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0));
- if (sections.find(PlayerChunk) == sections.end() || sections.find(PlayerChunk - Vector(0,1,0)) == sections.end())
- return true;
- std::vector<Vector> closestSectionsCoordinates = {
- Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z),
- Vector(PlayerChunk.x + 1, PlayerChunk.y, PlayerChunk.z),
- Vector(PlayerChunk.x - 1, PlayerChunk.y, PlayerChunk.z),
- Vector(PlayerChunk.x, PlayerChunk.y + 1, PlayerChunk.z),
- Vector(PlayerChunk.x, PlayerChunk.y - 1, PlayerChunk.z),
- Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z + 1),
- Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z - 1),
- };
- std::vector<Vector> closestSections;
- for (auto &coord:closestSectionsCoordinates) {
+ Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0));
+ if (sections.find(PlayerChunk) == sections.end() || sections.find(PlayerChunk - Vector(0, 1, 0)) == sections.end())
+ return false;
+
+ std::vector<Vector> closestSectionsCoordinates = {
+ Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z),
+ Vector(PlayerChunk.x + 1, PlayerChunk.y, PlayerChunk.z),
+ Vector(PlayerChunk.x - 1, PlayerChunk.y, PlayerChunk.z),
+ Vector(PlayerChunk.x, PlayerChunk.y + 1, PlayerChunk.z),
+ Vector(PlayerChunk.x, PlayerChunk.y - 1, PlayerChunk.z),
+ Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z + 1),
+ Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z - 1),
+ };
+ std::vector<Vector> closestSections;
+ for (auto &coord : closestSectionsCoordinates) {
if (sections.find(coord) != sections.end())
closestSections.push_back(coord);
- }
-
- 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;
- playerColl.w = PlayerWidth;
- playerColl.y = Y;
- playerColl.h = PlayerHeight;
- playerColl.z = Z - PlayerLength / 2.0;
- playerColl.l = PlayerLength;
-
- const Section &section = *this->GetSection(it);
- for (int x = 0; x < 16; x++) {
- for (int y = 0; y < 16; y++) {
- for (int z = 0; z < 16; z++) {
- BlockId block = section.GetBlockId(Vector(x, y, z));
- if (block.id == 0 || block.id == 31)
- continue;
- AABB blockColl{(x + it.x * 16.0),
- (y + it.y * 16.0),
- (z + it.z * 16.0), 1, 1, 1};
- if (TestCollision(playerColl, blockColl))
- return true;
- }
- }
- }
- }
- return false;
-}
-
-const std::vector<Vector>& World::GetSectionsList() {
- return sectionsList;
+ }
+
+ 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;
+ playerColl.w = PlayerWidth;
+ playerColl.y = Y;
+ playerColl.h = PlayerHeight;
+ playerColl.z = Z - PlayerLength / 2.0;
+ playerColl.l = PlayerLength;
+
+ const Section &section = this->GetSection(it);
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ for (int z = 0; z < 16; z++) {
+ BlockId block = section.GetBlockId(Vector(x, y, z));
+ if (block.id == 0 || block.id == 31)
+ continue;
+ AABB blockColl{ (x + it.x * 16.0),
+ (y + it.y * 16.0),
+ (z + it.z * 16.0), 1, 1, 1 };
+ if (TestCollision(playerColl, blockColl))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+std::vector<Vector> World::GetSectionsList() {
+ sectionsListMutex.lock();
+ auto vec = sectionsList;
+ sectionsListMutex.unlock();
+ return vec;
}
static Section fallbackSection;
-const Section* World::GetSection(Vector sectionPos) {
+const Section &World::GetSection(Vector sectionPos) {
auto result = sections.find(sectionPos);
if (result == sections.end()) {
- return nullptr;
- } else {
- return &result->second;
+ LOG(ERROR) << "Accessed not loaded section " << sectionPos;
+ return fallbackSection;
+ }
+ else {
+ return *result->second.get();
}
}
@@ -128,7 +134,7 @@ glm::vec3 World::Raycast(glm::vec3 position, glm::vec3 direction, float maxLengt
void World::UpdatePhysics(float delta)
{
- //delta /= 5;
+ delta /= 5;
entitiesMutex.lock();
for (auto& it : entities) {
it.pos = it.pos + it.vel * delta;
@@ -190,32 +196,32 @@ void World::DeleteEntity(unsigned int EntityId)
}
void World::ParseChunkData(std::shared_ptr<PacketBlockChange> packet) {
- /*Block& block = this->GetBlock(packet->Position);
- block = Block(packet->BlockId >> 4, packet->BlockId & 15, block.light, block.sky);
+ SetBlockId(packet->Position, BlockId{(unsigned short) (packet->BlockId >> 4),(unsigned char) (packet->BlockId & 0xF) });
+
Vector sectionPos(std::floor(packet->Position.x / 16.0), std::floor(packet->Position.y / 16.0), std::floor(packet->Position.z / 16.0));
- EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos });*/
+ EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos });
}
void World::ParseChunkData(std::shared_ptr<PacketMultiBlockChange> packet) {
- /*std::vector<Vector> changedSections;
+ std::vector<Vector> changedSections;
for (auto& it : packet->Records) {
int x = (it.HorizontalPosition >> 4 & 15) + (packet->ChunkX * 16);
int y = it.YCoordinate;
int z = (it.HorizontalPosition & 15) + (packet->ChunkZ * 16);
Vector worldPos(x, y, z);
- Block& block = GetBlock(worldPos);
- block = Block(it.BlockId >> 4, it.BlockId & 15, block.light, block.sky);
+ SetBlockId(worldPos, BlockId{(unsigned short) (it.BlockId >> 4),(unsigned char) (it.BlockId & 0xF) });
Vector sectionPos(packet->ChunkX, std::floor(it.YCoordinate / 16.0), packet->ChunkZ);
if (std::find(changedSections.begin(), changedSections.end(), sectionPos) == changedSections.end())
changedSections.push_back(sectionPos);
}
- for (auto& sectionPos: changedSections)
- EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos });*/
+
+ for (auto& sectionPos : changedSections)
+ EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos });
}
void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) {
- std::vector<std::map<Vector,Section>::iterator> toRemove;
+ std::vector<std::map<Vector, std::unique_ptr<Section>>::iterator> toRemove;
for (auto it = sections.begin(); it != sections.end(); ++it) {
if (it->first.x == packet->ChunkX && it->first.z == packet->ChunkZ)
toRemove.push_back(it);
@@ -224,12 +230,45 @@ void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) {
EventAgregator::PushEvent(EventType::ChunkDeleted, ChunkDeletedData{ it->first });
sections.erase(it);
}
- UpdateSectionList();
+ UpdateSectionsList();
}
-void World::UpdateSectionList() {
+void World::UpdateSectionsList() {
+ sectionsListMutex.lock();
sectionsList.clear();
for (auto& it : sections) {
sectionsList.push_back(it.first);
}
+ sectionsListMutex.unlock();
+}
+
+BlockId World::GetBlockId(Vector pos) {
+ Vector sectionPos(std::floor(pos.x / 16.0), std::floor(pos.y / 16.0), std::floor(pos.z / 16.0));
+
+ Section* section = GetSectionPtr(sectionPos);
+ return section->GetBlockId(pos - (sectionPos * 16));
+}
+
+void World::SetBlockId(Vector pos, BlockId block) {
+ Vector sectionPos(std::floor(pos.x / 16.0), std::floor(pos.y / 16.0), std::floor(pos.z / 16.0));
+
+ Section* section = GetSectionPtr(sectionPos);
+ section->SetBlockId(pos - (sectionPos * 16), block);
+}
+
+void World::SetBlockLight(Vector pos, unsigned char light) {
+
+}
+
+void World::SetBlockSkyLight(Vector pos, unsigned char light) {
+
+}
+
+Section *World::GetSectionPtr(Vector position) {
+ auto it = sections.find(position);
+
+ if (it == sections.end())
+ return nullptr;
+
+ return it->second.get();
} \ No newline at end of file
diff --git a/src/World.hpp b/src/World.hpp
index 89c40d4..6b8b5d1 100644
--- a/src/World.hpp
+++ b/src/World.hpp
@@ -3,6 +3,7 @@
#include <map>
#include <bitset>
#include <queue>
+#include <memory>
#include <easylogging++.h>
@@ -17,9 +18,9 @@
class World {
int dimension = 0;
- std::map<Vector, Section> sections;
+ std::map<Vector, std::unique_ptr<Section>> sections;
- Section ParseSection(StreamInput *data, Vector position);
+ Section ParseSection(StreamInput *data, Vector position);
std::vector<Entity> entities;
@@ -27,14 +28,16 @@ class World {
std::vector<Vector> sectionsList;
- void UpdateSectionList();
+ std::mutex sectionsListMutex;
+
+ void UpdateSectionsList();
public:
- World();
+ World();
- ~World();
+ ~World();
- void ParseChunkData(std::shared_ptr<PacketChunkData> packet);
+ void ParseChunkData(std::shared_ptr<PacketChunkData> packet);
void ParseChunkData(std::shared_ptr<PacketBlockChange> packet);
@@ -42,13 +45,13 @@ public:
void ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet);
- bool isPlayerCollides(double X, double Y, double Z);
+ bool isPlayerCollides(double X, double Y, double Z);
- const std::vector<Vector>& GetSectionsList();
+ std::vector<Vector> GetSectionsList();
- const Section* GetSection(Vector sectionPos);
+ const Section &GetSection(Vector sectionPos);
- glm::vec3 Raycast(glm::vec3 position, glm::vec3 direction, float maxLength = 1000.0f, float minPrecision = 0.01f);
+ glm::vec3 Raycast(glm::vec3 position, glm::vec3 direction, float maxLength = 1000.0f, float minPrecision = 0.01f);
void UpdatePhysics(float delta);
@@ -59,4 +62,14 @@ public:
void AddEntity(Entity entity);
void DeleteEntity(unsigned int EntityId);
+
+ BlockId GetBlockId(Vector pos);
+
+ void SetBlockId(Vector pos, BlockId block);
+
+ void SetBlockLight(Vector pos, unsigned char light);
+
+ void SetBlockSkyLight(Vector pos, unsigned char light);
+
+ Section *GetSectionPtr(Vector position);
}; \ No newline at end of file