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