Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server-side chunk sending decision #174

Merged
merged 42 commits into from
May 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
2410b2c
2nd attempt.
Unarelith Dec 29, 2020
22c77a6
[ServerWorld] Fixed infinite loop.
Unarelith Dec 29, 2020
6312213
[ServerWorld] Fixed render distance.
Unarelith Dec 29, 2020
f4a229f
[ServerWorld] Chunks are now sent correctly.
Unarelith Dec 29, 2020
1f7d7b6
Closest thing to a working version. Still have holes when flying a fe…
Unarelith Dec 29, 2020
a4d1c2c
Seems to be working, but some trees are incomplete.
Unarelith Jan 1, 2021
1db8d56
Fixed incomplete trees.
Unarelith Jan 2, 2021
89b083f
[ClientWorld] Renamed 'isChunkRequested' to 'isReadyForMeshing'.
Unarelith Jan 2, 2021
46ca172
[ClientChunk] Added a timer to limit chunk updates. [ClientWorld] Imp…
Unarelith Jan 2, 2021
93236cf
Various fixes.
Unarelith Jan 3, 2021
2aa2e34
Best working version.
Unarelith Jan 3, 2021
0c667ae
[default/listeners.lua] Changed intro text.
Unarelith May 16, 2021
c04a48f
Moved ChunkUnload sending from client to server.
Unarelith May 16, 2021
91d63bd
[ClientWorld] Client is no longer in charge of removing chunks.
Unarelith May 16, 2021
75eab2d
[PlayerList] Now clearing player loaded chunks when disconnecting.
Unarelith May 16, 2021
94eb509
[ClientWorld] Client still needs to remove empty chunks it creates.
Unarelith May 16, 2021
6747dd9
[ServerWorld] Now sending ChunkUnload when needed.
Unarelith May 16, 2021
c259740
[ServerWorld] Fixed holes in the world.
Unarelith May 16, 2021
66478d6
[ClientPlayer] Now sending PlayerChunkPosUpdate.
Unarelith May 16, 2021
97718d2
Improved server-side player chunk management.
Unarelith May 16, 2021
9091003
Attempting to remove the big loops in ClientWorld and ServerWorld.
Unarelith May 17, 2021
079d4e2
[external/backtrace] Added backtrace printer tool.
Unarelith May 17, 2021
620d3e1
ChunkLightmap::updateLights() no longer returns a boolean.
Unarelith May 17, 2021
d26cd41
[DebugLightmapViewer] Added.
Unarelith May 17, 2021
14c5b7b
[ClientWorld] Now removes far uninitialized chunks.
Unarelith May 17, 2021
0d480c7
[ServerChunk] Only update light with all neighbours.
Unarelith May 17, 2021
2a9440e
[ServerWorld] Tried to improve chunk sending.
Unarelith May 17, 2021
95cbb10
[ServerWorld] Chunk send requests seems to be working.
Unarelith May 17, 2021
2b47796
[ClientChunk] Only start meshing if all neighbours are initialized.
Unarelith May 18, 2021
afdfee9
No longer using string to represent vertex attr.
Unarelith May 20, 2021
13ef819
Fixed dimension change.
Unarelith May 20, 2021
b926016
Fixed InventoryCube display.
Unarelith May 20, 2021
9075397
Fixed sunlight update.
Unarelith May 20, 2021
f2b5eb7
[ClientWorld] Removed debug message.
Unarelith May 20, 2021
679da2e
[ServerWorld] Added a timeout to chunk request queue loop.
Unarelith May 20, 2021
7190d3b
[EngineConfig] Bump VERSION_SUFFIX to 'pre8'.
Unarelith May 20, 2021
b80b9d8
[World] Performance fix (for MinGW).
Unarelith May 21, 2021
81d8659
[ClientProfiler] Added.
Unarelith May 21, 2021
c2c817b
[Minimap] Now allows switching mode with 'M' key.
Unarelith May 22, 2021
79e3247
[ClientChunk] Cleaned useless code.
Unarelith May 22, 2021
3873278
Cleaned useless commented code.
Unarelith May 22, 2021
10f605e
[ChunkLightmap] Removed useless lines.
Unarelith May 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/network-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ Packet sent at the beginning of every server tick.
| - Block data | u32 | Block ID and data |
| - Light value | u8 | Sunlight and torchlight values |

#### ChunkUnload

| Field name | Field type | Notes |
| ------------- | ----------- | ---------------------------------------------------- |
| Chunk X | s32 | Chunk X coordinate |
| Chunk Y | s32 | Chunk Y coordinate |
| Chunk Z | s32 | Chunk Z coordinate |

#### PlayerInvUpdate (clientbound)

| Field name | Field type | Notes |
Expand Down Expand Up @@ -260,6 +268,20 @@ Packet sent at the beginning of every server tick.
| Hotbar slot | u8 | ID of the current hotbar slot |
| Item ID | u16 | Current item ID (to check match with server) |

#### PlayerReady

Packet sent from a client when it is ready to receive chunks.

_This packet has no field._

#### PlayerChunkPosUpdate

| Field name | Field type | Notes |
| ------------- | ----------- | ---------------------------------------------------- |
| Chunk X | s32 | Chunk X coordinate |
| Chunk Y | s32 | Chunk Y coordinate |
| Chunk Z | s32 | Chunk Z coordinate |

#### BlockActivated

| Field name | Field type | Notes |
Expand Down
87 changes: 87 additions & 0 deletions external/backtrace.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2009-2017, Farooq Mela
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BACKTRACE_HPP_
#define BACKTRACE_HPP_

#include <cstdio>
#include <string>

#ifdef _WIN32
static std::string Backtrace(int skip = 1)
{
std::string buf = "Backtrace is not available on Windows.";
printf("%s\n", buf.c_str());
return buf;
}
#else

#include <execinfo.h> // for backtrace
#include <dlfcn.h> // for dladdr
#include <cxxabi.h> // for __cxa_demangle

#include <cstdlib>
#include <sstream>

// This function produces a stack backtrace with demangled function & method names.
// Needs compilation with --export-dynamic or -Wl,-export-dynamic
// From https://gist.github.com/fmela/591333
static std::string Backtrace(int skip = 1)
{
void *callstack[128];
const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
char buf[1024];
int nFrames = backtrace(callstack, nMaxFrames);
char **symbols = backtrace_symbols(callstack, nFrames);

std::ostringstream trace_buf;
for (int i = skip; i < nFrames; i++) {
printf("%s\n", symbols[i]);

Dl_info info;
if (dladdr(callstack[i], &info) && info.dli_sname) {
char *demangled = NULL;
int status = -1;
if (info.dli_sname[0] == '_')
demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status);
snprintf(buf, sizeof(buf), "%-3d %*p %s + %zd\n",
i, int(2 + sizeof(void*) * 2), callstack[i],
status == 0 ? demangled :
info.dli_sname == 0 ? symbols[i] : info.dli_sname,
(char *)callstack[i] - (char *)info.dli_saddr);
free(demangled);
} else {
snprintf(buf, sizeof(buf), "%-3d %*p %s\n",
i, int(2 + sizeof(void*) * 2), callstack[i], symbols[i]);
}
trace_buf << buf;
}
free(symbols);
if (nFrames == nMaxFrames)
trace_buf << "[truncated]\n";
return trace_buf.str();
}

#endif // _WIN32

#endif // BACKTRACE_HPP_
3 changes: 0 additions & 3 deletions misc/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ cp /usr/i686-w64-mingw32/bin/libwinpthread-1.dll deploy/win32/bin/openminer && \
cp /usr/i686-w64-mingw32/bin/libssp-0.dll deploy/win32/bin/openminer && \
cp /usr/i686-w64-mingw32/bin/zlib1.dll deploy/win32/bin/openminer && \
cp /usr/i686-w64-mingw32/bin/libgcc_s_dw2-1.dll deploy/win32/bin/openminer && \
cp deploy/win32/libjpeg.dll deploy/win32/bin/openminer && \
mkdir -p deploy/win32/bin/openminer/docs/markdown && \
cp docs/*.md deploy/win32/bin/openminer/docs/markdown/ && \
cp -r deploy/html_docs deploy/win32/bin/openminer/docs/html && \
Expand All @@ -50,7 +49,6 @@ cp /usr/x86_64-w64-mingw32/bin/libwinpthread-1.dll deploy/win64/bin/openminer &&
cp /usr/x86_64-w64-mingw32/bin/libssp-0.dll deploy/win64/bin/openminer && \
cp /usr/x86_64-w64-mingw32/bin/zlib1.dll deploy/win64/bin/openminer && \
cp /usr/x86_64-w64-mingw32/bin/libgcc_s_seh-1.dll deploy/win64/bin/openminer && \
cp deploy/win64/libjpeg.dll deploy/win64/bin/openminer && \
mkdir -p deploy/win64/bin/openminer/docs/markdown && \
cp docs/*.md deploy/win64/bin/openminer/docs/markdown/ && \
cp -r deploy/html_docs deploy/win64/bin/openminer/docs/html && \
Expand All @@ -75,7 +73,6 @@ cp /usr/lib/ld-linux-x86-64.so.2 \
/usr/lib/libglib-2.0.so.0 \
/usr/lib/libGLU.so.1 \
/usr/lib/libGLX.so.0 \
/usr/lib/libjpeg.so.8 \
/usr/lib/libm.so.6 \
/usr/lib/libpcre.so.1 \
/usr/lib/libpthread.so.0 \
Expand Down
2 changes: 0 additions & 2 deletions mods/default/blocks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,6 @@ mod:block {
}

server:send_player_change_dimension(client.id, pos.x, pos.y, pos.z, dim, client)
player:set_dimension(dim)
-- player:set_position(pos.x, pos.y, pos.z)
end,
}

Expand Down
4 changes: 2 additions & 2 deletions mods/default/listeners.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ openminer:add_listener(Event.PlayerConnected, function(pos, player, client, serv
player:inventory():add_stack("default:stone_axe", 1)

server:send_chat_message(0, "Welcome to OpenMiner!", client)
server:send_chat_message(0, "Press E to show inventory", client)
server:send_chat_message(0, "Press H to show creative inventory", client)
server:send_chat_message(0, "Press E to open inventory", client)
server:send_chat_message(0, "Press H to open creative inventory", client)
end)

12 changes: 6 additions & 6 deletions source/client/core/ClientApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ bool ClientApplication::init() {

gk::CoreApplication::init();

m_window.addVertexAttribute(VertexAttribute::Coord3d, "coord3d", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, coord3d)));
m_window.addVertexAttribute(VertexAttribute::TexCoord, "texCoord", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, texCoord)));
m_window.addVertexAttribute(VertexAttribute::Color, "color", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, color)));
m_window.addVertexAttribute(VertexAttribute::Normal, "normal", 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, normal)));
m_window.addVertexAttribute(VertexAttribute::LightValue, "lightValue", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, lightValue)));
m_window.addVertexAttribute(VertexAttribute::AmbientOcclusion, "ambientOcclusion", 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, ambientOcclusion)));
m_window.addVertexAttribute(VertexAttribute::Coord3d, 0, "coord3d", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, coord3d)));
m_window.addVertexAttribute(VertexAttribute::TexCoord, 1, "texCoord", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, texCoord)));
m_window.addVertexAttribute(VertexAttribute::Color, 2, "color", 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, color)));
m_window.addVertexAttribute(VertexAttribute::Normal, 3, "normal", 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, normal)));
m_window.addVertexAttribute(VertexAttribute::LightValue, 4, "lightValue", 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, lightValue)));
m_window.addVertexAttribute(VertexAttribute::AmbientOcclusion, 5, "ambientOcclusion", 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<GLvoid *>(offsetof(Vertex, ambientOcclusion)));

if (m_argumentParser.getArgument("help").isFound)
return true;
Expand Down
87 changes: 87 additions & 0 deletions source/client/core/ClientProfiler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <[email protected]>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#include <gk/core/Debug.hpp>
#include <gk/core/GameClock.hpp>

#include "ClientProfiler.hpp"

ClientProfiler *ClientProfiler::s_instance = nullptr;

void ClientProfiler::onBeginTick() {
m_ticks.emplace_back();
m_ticks.back().begin = gk::GameClock::getInstance().getTicks(true);
}

void ClientProfiler::onEndTick() {
m_ticks.back().end = gk::GameClock::getInstance().getTicks(true);
}

void ClientProfiler::startAction(const std::string &name) {
m_ticks.back().actions[name].durations.emplace_back();
m_ticks.back().actions[name].durations.back().first = gk::GameClock::getInstance().getTicks(true);
}

void ClientProfiler::endAction(const std::string &name) {
m_ticks.back().actions[name].durations.back().second = gk::GameClock::getInstance().getTicks(true);
}

void ClientProfiler::dump(u64 tickDurationMin) {
std::unordered_map<std::string, std::pair<u64, u64>> maxActionDuration;

u64 i = 0;
for (auto &tick : m_ticks) {
u64 tickDuration = tick.end - tick.begin;
if (tickDuration < tickDurationMin) continue;

gkDebug() << "Tick" << i++ << "took" << tickDuration << "ms";

if (tickDuration > 0) {
for (auto &[actionName, action] : tick.actions) {
u64 j = 0;
for (auto &[begin, end] : action.durations) {
u64 actionDuration = end - begin;

if (maxActionDuration.find(actionName) == maxActionDuration.end())
maxActionDuration.emplace(actionName, std::make_pair(actionDuration, 0));

maxActionDuration[actionName].first = std::max(maxActionDuration[actionName].first, actionDuration);

float actionPercentTotal = actionDuration / (float)tickDuration * 100.f;

gkDebug() << "Action" << actionName << j++ << "took" << actionDuration << "ms -" << actionPercentTotal << "% of tick";
}

maxActionDuration[actionName].second = std::max(maxActionDuration[actionName].second, j);
}
}
}

for (auto &[actionName, pair] : maxActionDuration) {
gkDebug() << "Max duration for action" << actionName << ":" << pair.first << "ms (" << pair.second << ")";
}
}

65 changes: 65 additions & 0 deletions source/client/core/ClientProfiler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <[email protected]>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#ifndef CLIENTPROFILER_HPP_
#define CLIENTPROFILER_HPP_

#include <deque>
#include <string>
#include <unordered_map>

#include <gk/core/IntTypes.hpp>

struct ClientAction {
std::deque<std::pair<u64, u64>> durations;
};

struct ClientTick {
u64 begin;
u64 end;
std::unordered_map<std::string, ClientAction> actions;
};

class ClientProfiler {
public:
void onBeginTick();
void onEndTick();

void dump(u64 tickDurationMin = 0);

void startAction(const std::string &name);
void endAction(const std::string &name);

static ClientProfiler &getInstance() { return *s_instance; }
static void setInstance(ClientProfiler *instance) { s_instance = instance; }

private:
static ClientProfiler *s_instance;

std::deque<ClientTick> m_ticks;
};

#endif // CLIENTPROFILER_HPP_
3 changes: 3 additions & 0 deletions source/client/core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ u8 Config::mouseSensitivity = 8;

// Debug
bool Config::isChunkMinimapEnabled = false;
bool Config::isLightmapViewerEnabled = false;

// Other
std::string Config::defaultUsername = "";
Expand Down Expand Up @@ -110,6 +111,7 @@ void Config::loadConfigFromFile(const char *filename) {
mouseSensitivity = lua["mouseSensitivity"].get_or(mouseSensitivity);

isChunkMinimapEnabled = lua["isChunkMinimapEnabled"].get_or(isChunkMinimapEnabled);
isLightmapViewerEnabled = lua["isLightmapViewerEnabled"].get_or(isLightmapViewerEnabled);

defaultUsername = lua["defaultUsername"].get_or(defaultUsername);
defaultServerAddress = lua["defaultServerAddress"].get_or(defaultServerAddress);
Expand Down Expand Up @@ -150,6 +152,7 @@ void Config::saveConfigToFile(const char *filename) {
file << "mouseSensitivity = " << (u16)mouseSensitivity << std::endl;
file << std::endl;
file << "isChunkMinimapEnabled = " << (isChunkMinimapEnabled ? "true" : "false") << std::endl;
file << "isLightmapViewerEnabled = " << (isLightmapViewerEnabled ? "true" : "false") << std::endl;
file << std::endl;
file << "defaultUsername = \"" << defaultUsername << "\"" << std::endl;
file << "defaultServerAddress = \"" << defaultServerAddress << "\"" << std::endl;
Expand Down
1 change: 1 addition & 0 deletions source/client/core/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace Config {

// Debug
extern bool isChunkMinimapEnabled;
extern bool isLightmapViewerEnabled;

// Other
extern std::string defaultUsername;
Expand Down
Loading