Replace goodform with meiose; refactor game state management

master
Dorian Wouters 2018-01-11 20:04:15 +01:00
parent 46082b5d01
commit 071db06f2b
No known key found for this signature in database
GPG Key ID: 6E9DA8063322434B
39 changed files with 726 additions and 357 deletions

6
.gitmodules vendored
View File

@ -7,9 +7,6 @@
[submodule "ext/enet"] [submodule "ext/enet"]
path = ext/enet path = ext/enet
url = https://github.com/freeminer/enet.git url = https://github.com/freeminer/enet.git
[submodule "ext/goodform"]
path = ext/goodform
url = https://github.com/ElementW/goodform.git
[submodule "ext/torch7"] [submodule "ext/torch7"]
path = ext/torch7 path = ext/torch7
url = https://github.com/torch/torch7.git url = https://github.com/torch/torch7.git
@ -25,3 +22,6 @@
[submodule "assets/lua/modules/lds"] [submodule "assets/lua/modules/lds"]
path = assets/lua/modules/lds path = assets/lua/modules/lds
url = https://github.com/neomantra/lds.git url = https://github.com/neomantra/lds.git
[submodule "ext/meiose"]
path = ext/meiose
url = https://github.com/ElementW/meiose.git

View File

@ -69,6 +69,12 @@ find_package(OpenGL REQUIRED)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
find_package(LuaJIT REQUIRED) find_package(LuaJIT REQUIRED)
find_package(meiose REQUIRED)
if(NOT MPACK_FOUND)
message(FATAL_ERROR "Bundled meiose not found. Have you checked out submodules?
git submodule update --init")
endif()
find_package(Optional REQUIRED) find_package(Optional REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3) pkg_search_module(GLFW REQUIRED glfw3)
@ -77,6 +83,7 @@ pkg_search_module(LIBSODIUM REQUIRED libsodium)
include_directories(BEFORE include_directories(BEFORE
"${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include"
${ETC_INCLUDE_DIRS} ${ETC_INCLUDE_DIRS}
${MEIOSE_INCLUDE_DIR}
${LUA_INCLUDE_DIR} ${LUA_INCLUDE_DIR}
${LZFX_INCLUDE_DIRS} ${LZFX_INCLUDE_DIRS}
${ENET_INCLUDE_DIRS} ${ENET_INCLUDE_DIRS}
@ -87,10 +94,6 @@ include_directories(BEFORE
${OPTIONAL_INCLUDE_DIR} ${OPTIONAL_INCLUDE_DIR}
) )
# Glob all source files so they show up in Qt Creator
#file(GLOB_RECURSE FILELIST "*.h" "*.hpp" "*.cpp")
#add_custom_target(files SOURCES ${FILELIST})
### Allow subdirs to add params to the `diggler` target ### Allow subdirs to add params to the `diggler` target
# Sources # Sources
set_property(GLOBAL PROPERTY DIGGLER_SOURCE_FILES "") set_property(GLOBAL PROPERTY DIGGLER_SOURCE_FILES "")
@ -146,6 +149,7 @@ get_property(LIBS GLOBAL PROPERTY DIGGLER_LINK_LIBRARIES)
target_link_libraries(diggler target_link_libraries(diggler
${LIBS} ${LIBS}
${ETC_LIBRARIES} ${ETC_LIBRARIES}
${MEIOSE_LIBRARY}
${LUA_LIBRARY} ${LUA_LIBRARY}
${LZFX_LIBRARIES} ${LZFX_LIBRARIES}
${ENET_LIBRARIES} ${ENET_LIBRARIES}

55
cmake/FindJemalloc.cmake Normal file
View File

@ -0,0 +1,55 @@
#
# Find the JEMALLOC client includes and library
#
# This module defines
# JEMALLOC_INCLUDE_DIR, where to find jemalloc.h
# JEMALLOC_LIBRARIES, the libraries to link against
# JEMALLOC_FOUND, if false, you cannot build anything that requires JEMALLOC
# also defined, but not for general use are
# JEMALLOC_LIBRARY, where to find the JEMALLOC library.
set( JEMALLOC_FOUND 0 )
if ( UNIX )
FIND_PATH( JEMALLOC_INCLUDE_DIR
NAMES
jemalloc/jemalloc.h
PATHS
/usr/include
/usr/include/jemalloc
/usr/local/include
/usr/local/include/jemalloc
$ENV{JEMALLOC_ROOT}
$ENV{JEMALLOC_ROOT}/include
${CMAKE_SOURCE_DIR}/externals/jemalloc
DOC
"Specify include-directories that might contain jemalloc.h here."
)
FIND_LIBRARY( JEMALLOC_LIBRARY
NAMES
jemalloc libjemalloc JEMALLOC
PATHS
/usr/lib
/usr/lib/jemalloc
/usr/local/lib
/usr/local/lib/jemalloc
/usr/local/jemalloc/lib
$ENV{JEMALLOC_ROOT}/lib
$ENV{JEMALLOC_ROOT}
DOC "Specify library-locations that might contain the jemalloc library here."
)
if ( JEMALLOC_LIBRARY )
if ( JEMALLOC_INCLUDE_DIR )
set( JEMALLOC_FOUND 1 )
message( STATUS "Found JEMALLOC library: ${JEMALLOC_LIBRARY}")
message( STATUS "Found JEMALLOC headers: ${JEMALLOC_INCLUDE_DIR}")
else ( JEMALLOC_INCLUDE_DIR )
message(FATAL_ERROR "Could not find jemalloc headers! Please install jemalloc libraries and headers")
endif ( JEMALLOC_INCLUDE_DIR )
endif ( JEMALLOC_LIBRARY )
mark_as_advanced( JEMALLOC_FOUND JEMALLOC_LIBRARY JEMALLOC_EXTRA_LIBRARIES JEMALLOC_INCLUDE_DIR )
endif (UNIX)

17
cmake/Findmeiose.cmake Normal file
View File

@ -0,0 +1,17 @@
set(MEIOSE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/meiose")
set(MEIOSE_INCLUDE_DIR "${MEIOSE_ROOT_DIR}/include/")
if(NOT EXISTS "${MEIOSE_INCLUDE_DIR}")
unset(MEIOSE_INCLUDE_DIR)
endif()
add_subdirectory("${MEIOSE_ROOT_DIR}")
target_include_directories(meiose-static PRIVATE "${MPACK_INCLUDE_DIR}")
set(MEIOSE_LIBRARY "meiose-static")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MPACK
REQUIRED_VARS MEIOSE_INCLUDE_DIR MEIOSE_LIBRARY)
mark_as_advanced(MEIOSE_INCLUDE_DIR MEIOSE_LIBRARY)

View File

@ -374,7 +374,8 @@ struct ServerInfoResponse {
The client asks for a list of information, and the server simply replies. Different infos are identified by a short string describing both what it is and optional parameters, separated by dot characters (`.`, U+002E). The client asks for a list of information, and the server simply replies. Different infos are identified by a short string describing both what it is and optional parameters, separated by dot characters (`.`, U+002E).
The server may reply to the client with only some of the requested information, and/or information with different parameters, but is expected to do its best effort to send back the most appropriate information. It is up to the client to choose what to do with this data and put it to best use. The server may reply to the client with only some of the requested information, and/or information with different parameters, but is expected to do its best effort to send back the most appropriate information. It is up to the client to choose what to do with this data and put it to best use.
Parameters that expresses languages are substituted by `XXX` in the following table, and are expected to be ISO 639-3 alpha-3-*type* codes. Language codes that are not part of ISO 639-3 are considered **valid** and may very well be used for alternative languages, such as `zls` for 1337$P34|< ([leetspeak](https://en.wikipedia.org/wiki/Leet)). Parameters that expresses languages are substituted by `XXXX` in the following table, and are expected to be ISO 639-3 alpha-3-*like* codes for "real" languages (which can be fictive and constructed, like Klingon). Language codes that are not part of ISO 639-3 are considered **valid**.
For other languages, a code of the form `!ABC` where `ABC` is the language code. For example, for 1337$P34|< ([leetspeak](https://en.wikipedia.org/wiki/Leet)), the code could be `!lts`.
When that language specification is shown between parentheses, it is optional and the server is free to return said information in any language if unspecified, whichever is the most appropriate (e.g. according to the server's homeland or client location guessed from its IP address). When that language specification is shown between parentheses, it is optional and the server is free to return said information in any language if unspecified, whichever is the most appropriate (e.g. according to the server's homeland or client location guessed from its IP address).
Info name | Reply type | Reply data Info name | Reply type | Reply data

@ -1 +0,0 @@
Subproject commit 0791e58e1bf20f486a14c3a86d5ba2f231bb8b8f

View File

@ -35,6 +35,8 @@
#define LZFX_HSIZE (1 << (LZFX_HLOG)) #define LZFX_HSIZE (1 << (LZFX_HLOG))
#include <stdint.h>
/* We need this for memset */ /* We need this for memset */
#ifdef __cplusplus #ifdef __cplusplus
# include <cstring> # include <cstring>
@ -105,7 +107,7 @@ int lzfx_compress(const void *const ibuf, const unsigned int ilen,
int lit; /* # of bytes in current literal run */ int lit; /* # of bytes in current literal run */
#if defined (WIN32) && defined (_M_X64) #if defined (WIN32) && defined (_M_X64)
unsigned _int64 off; /* workaround for missing POSIX compliance */ uint64_t off; /* workaround for missing POSIX compliance */
#else #else
unsigned long off; unsigned long off;
#endif #endif

1
ext/meiose Submodule

@ -0,0 +1 @@
Subproject commit f04d826bd236c92c4ae492d2503f250ce9f0323a

View File

@ -49,13 +49,18 @@ public:
const int wcx, wcy, wcz; const int wcx, wcy, wcz;
/**
* @brief Struct holding the Chunk's block contents.
* @note This structure must be a Plain Old Data struct.
*/
struct Data { struct Data {
static constexpr FourCC MagicMarker = MakeFourCC("CKDT"); static constexpr FourCC MagicMarker = MakeFourCC("CKDT");
FourCC magic; FourCC magic; /**< Magic marker. Used for Chunk eviction checking. */
// Keep me Plain Old Data!
BlockId id[CX*CY*CZ]; BlockId id[CX*CY*CZ]; /**< Block IDs. */
BlockData data[CX*CY*CZ]; BlockData data[CX*CY*CZ]; /**< Block data. */
LightData light[CX*CY*CZ]; LightData light[CX*CY*CZ]; /**< Block light info. */
void clear(); void clear();
}; };

View File

@ -45,115 +45,116 @@ void ConnectingState::setupUI() {
void ConnectingState::updateViewport() { void ConnectingState::updateViewport() {
} }
void ConnectingState::onResize(int w, int h) { void ConnectingState::onStart() {
updateViewport(); finished = success = false;
}
void ConnectingState::run() {
std::string &serverHost = m_serverHost;
int serverPort = m_serverPort;
bool finished = false, success = false;
Game *const G = W->G; Game *const G = W->G;
std::string failureStr; m_networkThread = std::thread([this, G]() {
std::thread networkThread = std::thread([G, &success, &finished, &serverHost, serverPort, &failureStr]() {
try { try {
G->H.create(); G->H.create();
G->NS = &G->H.connect(serverHost, serverPort, 5000); G->NS = &G->H.connect(m_serverHost, m_serverPort, 5000);
success = true; success = true;
} catch (const std::exception &e) { } catch (const std::exception &e) {
success = false; success = false;
failureStr = e.what(); m_infoStr = e.what();
} }
finished = true; finished = true;
}); });
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
}
void ConnectingState::onLogicTick() {
Game *const G = W->G;
G->updateTime(runTime());
if (finished) {
if (success) {
LocalPlayer &LP = *G->LP;
LP.name = GlobalProperties::PlayerName;
Net::MsgTypes::PlayerJoinRequest pjr;
pjr.name = G->LP->name;
Net::OutMessage join; pjr.writeToMsg(join);
G->H.send(*G->NS, join, Net::Tfer::Rel, Net::Channels::Base);
Net::InMessage m_msg;
bool received = G->H.recv(m_msg, 5000);
if (!received) {
W->showMessage("Connected but got no response", "after 5 seconds");
return;
}
bool msgGood = false;
if (m_msg.getType() == Net::MessageType::PlayerJoin) {
using PJS = Net::MsgTypes::PlayerJoinSubtype;
switch (m_msg.getSubtype<PJS>()) {
case PJS::Success:
msgGood = true;
G->U = new Universe(G, true);
LP.sessId = m_msg.readU32();
LP.W = G->U->createWorld(m_msg.readI16());
break;
case PJS::Failure: {
// TODO be able to display a custom message
W->showMessage("Disconnected", "while joining");
} return;
default:
break;
}
}
if (!msgGood) {
std::ostringstream sstm;
sstm << "Type: " << static_cast<int>(m_msg.getType()) <<
" Subtype: " << static_cast<int>(m_msg.getSubtype());
W->showMessage("Received unexpected packet", sstm.str());
return;
}
// TODO: move elsewhere
G->LS->initialize();
const std::string gameLuaRuntimePath(getAssetsDirectory() + "/lua");
G->LS->setGameLuaRuntimePath(gameLuaRuntimePath);
G->LS->dofile(gameLuaRuntimePath + "/Diggler.lua");
Log(Info, TAG) << "Joined as " << LP.name << '/' << LP.sessId;
W->setNextState(std::make_unique<GameState>(W));
} else {
W->showMessage("Could not connect to server", m_infoStr);
}
}
}
void ConnectingState::onFrameTick() {
Game *const G = W->G;
glm::mat4 mat; glm::mat4 mat;
UI::Text::Size sz = txtConnecting->getSize(); UI::Text::Size sz = txtConnecting->getSize();
const glm::mat4 textMat = glm::scale(glm::translate(*G->UIM->PM, glm::vec3(W->getW()/2-sz.x, const glm::mat4 textMat = glm::scale(glm::translate(*G->UIM->PM, glm::vec3(W->getW()/2-sz.x,
W->getH()/2, 0.f)), glm::vec3(2.f, 2.f, 1.f)); W->getH()/2, 0.f)), glm::vec3(2.f, 2.f, 1.f));
while (!finished && !W->shouldClose()) { // Infinite loop \o/
const double T = glfwGetTime();
G->updateTime(T);
G->R->beginFrame(); G->R->beginFrame();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
txtConnecting->render(textMat); txtConnecting->render(textMat);
for (int i=0; i < 6; ++i) { for (int i=0; i < 6; ++i) {
const float t = T * 3 + 0.3f * i; const double t = G->Time * 3 + 0.3 * i;
mat = glm::scale(glm::translate(*G->UIM->PM, mat = glm::scale(glm::translate(*G->UIM->PM,
glm::vec3(W->getW()/2 - 1 + std::sin(t)*sz.x, W->getH()/2-sz.y, 0.f)), glm::vec3(W->getW()/2 - 1 + std::sin(t)*sz.x, W->getH()/2-sz.y, 0.f)),
glm::vec3(2.f, 2.f, 1.f)); glm::vec3(2.f, 2.f, 1.f));
txtDot->render(mat); txtDot->render(mat);
}
G->R->endFrame();
glfwSwapBuffers(*W);
glfwPollEvents();
}
if (W->shouldClose())
W->setVisible(false);
networkThread.join();
if (W->shouldClose())
return;
if (!success) {
W->showMessage("Could not connect to server", failureStr);
return;
} }
LocalPlayer &LP = *G->LP; G->R->endFrame();
LP.name = GlobalProperties::PlayerName; }
Net::MsgTypes::PlayerJoinRequest pjr; void ConnectingState::onStop() {
pjr.name = G->LP->name; if (m_networkThread.joinable()) {
Net::OutMessage join; pjr.writeToMsg(join); m_networkThread.join();
G->H.send(*G->NS, join, Net::Tfer::Rel, Net::Channels::Base);
Net::InMessage m_msg;
bool received = G->H.recv(m_msg, 5000);
if (!received) {
W->showMessage("Connected but got no response", "after 5 seconds");
return;
}
bool msgGood = false;
if (m_msg.getType() == Net::MessageType::PlayerJoin) {
using PJS = Net::MsgTypes::PlayerJoinSubtype;
switch (m_msg.getSubtype<PJS>()) {
case PJS::Success:
msgGood = true;
G->U = new Universe(G, true);
LP.sessId = m_msg.readU32();
LP.W = G->U->createWorld(m_msg.readI16());
break;
case PJS::Failure: {
// TODO be able to display a custom message
W->showMessage("Disconnected", "while joining");
} return;
default:
break;
}
}
if (!msgGood) {
std::ostringstream sstm;
sstm << "Type: " << static_cast<int>(m_msg.getType()) <<
" Subtype: " << static_cast<int>(m_msg.getSubtype());
W->showMessage("Received unexpected packet", sstm.str());
return;
} }
}
// TODO: move elsewhere void ConnectingState::onResize(int w, int h) {
G->LS->initialize(); updateViewport();
const std::string gameLuaRuntimePath(getAssetsDirectory() + "/lua");
G->LS->setGameLuaRuntimePath(gameLuaRuntimePath);
G->LS->dofile(gameLuaRuntimePath + "/Diggler.lua");
Log(Info, TAG) << "Joined as " << LP.name << '/' << LP.sessId;
W->setNextState(std::make_unique<GameState>(W));
} }
} }

View File

@ -1,6 +1,10 @@
#ifndef DIGGLER_CONNECTING_STATE_HPP #ifndef DIGGLER_CONNECTING_STATE_HPP
#define DIGGLER_CONNECTING_STATE_HPP #define DIGGLER_CONNECTING_STATE_HPP
#include <memory>
#include <string>
#include <thread>
#include "State.hpp" #include "State.hpp"
#include "GameWindow.hpp" #include "GameWindow.hpp"
#include "ui/Text.hpp" #include "ui/Text.hpp"
@ -20,16 +24,24 @@ private:
std::string m_serverHost; std::string m_serverHost;
int m_serverPort; int m_serverPort;
std::thread m_networkThread;
bool finished, success;
std::string m_infoStr;
void setupUI(); void setupUI();
public: public:
ConnectingState(GameWindow *W, const std::string &servHost, int servPort); ConnectingState(GameWindow *W, const std::string &servHost, int servPort);
~ConnectingState(); ~ConnectingState();
void onStart() override;
void onLogicTick() override;
void onFrameTick() override;
void onStop() override;
//void onMouseButton(int key, int action, int mods); //void onMouseButton(int key, int action, int mods);
//void onCursorPos(double x, double y); //void onCursorPos(double x, double y);
void onResize(int w, int h); void onResize(int w, int h);
void run();
void updateViewport(); void updateViewport();
}; };

View File

@ -5,6 +5,10 @@
#include "platform/types/vec3.hpp" #include "platform/types/vec3.hpp"
// The following, courtesy of the Windows developer experience™
#undef NEAR
#undef FAR
namespace Diggler { namespace Diggler {
class Frustum { class Frustum {

View File

@ -413,13 +413,12 @@ void GameState::sendMsg(Net::OutMessage &msg, Net::Tfer mode, Net::Channels chan
G->H.send(*G->NS, msg, mode, chan); G->H.send(*G->NS, msg, mode, chan);
} }
void GameState::run() { void GameState::onStart() {
setupUI(); setupUI();
gameLoop();
}
void GameState::gameLoop() { fpsCounter = 0;
double lastT, deltaT, T, fpsT = 0; int frames = 0; fpsNextSampling = 1.;
LocalPlayer *LP = G->LP; LocalPlayer *LP = G->LP;
LP->position = glm::vec3(-2, 2, -2); LP->position = glm::vec3(-2, 2, -2);
angles.x = M_PI/4; angles.y = M_PI/4; angles.x = M_PI/4; angles.y = M_PI/4;
@ -430,169 +429,178 @@ void GameState::gameLoop() {
LP->forceCameraUpdate(); LP->forceCameraUpdate();
G->A->update(); G->A->update();
LP->setHasNoclip(true); LP->setHasNoclip(true);
}
std::chrono::time_point<std::chrono::steady_clock> frameStart, frameEnd; void GameState::onLogicTick() {
while (!GW->shouldClose()) { if (!processNetwork()) return;
if (!processNetwork()) return;
T = glfwGetTime(); deltaT = T - lastT; G->updateTime(runTime());
G->updateTime(T); if (runTime() > fpsNextSampling) {
if (T > fpsT) { char str[10]; std::snprintf(str, 10, "FPS: %-4d", fpsCounter);
char str[10]; std::snprintf(str, 10, "FPS: %-4d", frames); UI.FPS->setText(std::string(str));
UI.FPS->setText(std::string(str)); fpsNextSampling = runTime() + 1;
fpsT = T+1; fpsCounter = 0;
frames = 0;
}
G->R->beginFrame();
frameStart = std::chrono::steady_clock::now();
if (T > nextNetUpdate) {
Net::MsgTypes::PlayerUpdateMove pum;
pum.position = LP->position;
if (LP->velocity != glm::vec3()) {
pum.velocity = LP->velocity;
pum.accel = LP->accel;
}
pum.angle = LP->angle;
Net::OutMessage msg; pum.writeToMsg(msg);
sendMsg(msg, Net::Tfer::Unrel, Net::Channels::Movement);
nextNetUpdate = T+1.0/G->PlayerPosUpdateFreq;
}
if (bloom.enable) {
m_3dFbo->bind();
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
LP->update(deltaT);
glm::mat4 m_transform = LP->getPVMatrix();
/*** 3D PART ***/
// TODO: multiworld
WorldRef WR = G->U->getWorld(0);
World &W = *WR;
/*glm::mat4 cloudmat = glm::scale(glm::translate(m_transform, glm::vec3(0.f, W.cloudsHeight, 0.f)), glm::vec3(4*CX, 1, 4*CZ));
m_clouds->render(cloudmat);*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
Render::RenderParams rp;
rp.world = WR.get();
rp.transform = m_transform;
rp.frustum = G->LP->camera.frustum;
G->R->renderers.world->render(rp);
for (Player &p : G->players) {
p.update(deltaT);
if (G->LP->camera.frustum.sphereInFrustum(p.position, 2))
p.render(m_transform);
}
//W.renderTransparent(m_transform);
/*static ParticleEmitter pe(G);
pe.posAmpl = glm::vec3(1, 1, 1);
pe.pTemplate.color = glm::vec4(0, 0.4, 0.9, 1);
pe.pTemplate.size = 0.07;
pe.velAmpl = glm::vec3(0, 1, 0);
pe.pTemplate.accel = glm::vec3(0, -.7, 0);
pe.pTemplate.decay = 4;
pe.decayAmpl = 2;
pe.setMaxCount(4*4*800);
pe.posAmpl = glm::vec3(2*16, 1, 2*16);
pe.pos = glm::vec3(2*16, 4*16+4, 2*16);
pe.pTemplate.vel = glm::vec3(0, -4, 0);
pe.velAmpl = glm::vec3(0, 2, 0); rain
pe.update(deltaT);
Render::RenderParams rp;
rp.transform = m_transform;
G->R->PR->render(rp);*/
// TODO: replace harcoded 32 viewdistance
if (G->LP->raytracePointed(32, &m_pointedBlock, &m_pointedFacing)) {
m_highlightBox.program->bind();
m_highlightBox.vao.bind();
glUniform4f(m_highlightBox.uni_unicolor, 1.f, 1.f, 1.f, .1f);
glUniformMatrix4fv(m_highlightBox.uni_mvp, 1, GL_FALSE, glm::value_ptr(
glm::scale(glm::translate(m_transform, glm::vec3(m_pointedBlock)+glm::vec3(.5f)), glm::vec3(0.5f*1.03f))));
glDrawArrays(GL_TRIANGLES, 0, 6*2*3);
m_highlightBox.vao.unbind();
}
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
LP->render(m_transform);
if (bloom.enable) {
m_3dFbo->unbind();
G->UIM->drawFullTexV(*m_3dFbo->tex);
m_3dFbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
bloom.extractor.fbo->bind();
glViewport(0, 0, GW->getW()/bloom.scale, GW->getH()/bloom.scale);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (!bloom.vao) {
bloom.vao = std::make_unique<Render::gl::VAO>();
Render::gl::VAO::Config cfg = bloom.vao->configure();
cfg.vertexAttrib(*m_3dRenderVBO, bloom.extractor.att_coord, 2, GL_SHORT, sizeof(Coord2DTex), 0);
cfg.vertexAttrib(*m_3dRenderVBO, bloom.extractor.att_texcoord, 2, GL_BYTE, sizeof(Coord2DTex), offsetof(Coord2DTex, u));
cfg.commit();
}
bloom.extractor.prog->bind();
bloom.vao->bind();
glUniformMatrix4fv(bloom.extractor.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
glDrawArrays(GL_TRIANGLES, 0, 6);
m_3dFbo->tex->setFiltering(Texture::Filter::Nearest, Texture::Filter::Nearest);
bloom.renderer.fbo->bind();
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bloom.extractor.fbo->tex->bind();
bloom.renderer.prog->bind();
glUniformMatrix4fv(bloom.renderer.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
glUniform2f(bloom.renderer.uni_pixshift, 1.f/(GW->getW()/bloom.scale), 1.f/(GW->getH()/bloom.scale));
glDrawArrays(GL_TRIANGLES, 0, 6);
bloom.renderer.fbo->unbind();
// render to real surface
glViewport(0, 0, GW->getW(), GW->getH());
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
bloom.extractor.fbo->tex->bind();
bloom.extractor.fbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
glDrawArrays(GL_TRIANGLES, 0, 6);
bloom.vao->unbind();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
/*** 2D PART ***/
G->UIM->drawFullRect(glm::vec4(1.f, 0.f, 0.f, 1-G->LP->health));
updateUI();
drawUI();
G->R->endFrame();
frameEnd = std::chrono::steady_clock::now();
frameTime = std::chrono::duration_cast<std::chrono::duration<uint64, std::micro>>(frameEnd - frameStart).count();
glfwSwapBuffers(*GW);
glfwPollEvents();
lastT = T;
frames++;
} }
}
void GameState::onFrameTick() {
std::chrono::time_point<std::chrono::steady_clock> frameStart, frameEnd;
G->R->beginFrame();
frameStart = std::chrono::steady_clock::now();
LocalPlayer *LP = G->LP;
double T = G->Time;
if (runTime() > nextNetUpdate) {
Net::MsgTypes::PlayerUpdateMove pum;
pum.position = LP->position;
if (LP->velocity != glm::vec3()) {
pum.velocity = LP->velocity;
pum.accel = LP->accel;
}
pum.angle = LP->angle;
Net::OutMessage msg; pum.writeToMsg(msg);
sendMsg(msg, Net::Tfer::Unrel, Net::Channels::Movement);
nextNetUpdate = T+1.0/G->PlayerPosUpdateFreq;
}
if (bloom.enable) {
m_3dFbo->bind();
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
double deltaT = deltaTime();
LP->update(deltaT);
glm::mat4 m_transform = LP->getPVMatrix();
/*** 3D PART ***/
// TODO: multiworld
WorldRef WR = G->U->getWorld(0);
World &W = *WR;
/*glm::mat4 cloudmat = glm::scale(glm::translate(m_transform, glm::vec3(0.f, W.cloudsHeight, 0.f)), glm::vec3(4*CX, 1, 4*CZ));
m_clouds->render(cloudmat);*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
Render::RenderParams rp;
rp.world = WR.get();
rp.transform = m_transform;
rp.frustum = G->LP->camera.frustum;
G->R->renderers.world->render(rp);
for (Player &p : G->players) {
p.update(deltaT);
if (G->LP->camera.frustum.sphereInFrustum(p.position, 2))
p.render(m_transform);
}
//W.renderTransparent(m_transform);
/*static ParticleEmitter pe(G);
pe.posAmpl = glm::vec3(1, 1, 1);
pe.pTemplate.color = glm::vec4(0, 0.4, 0.9, 1);
pe.pTemplate.size = 0.07;
pe.velAmpl = glm::vec3(0, 1, 0);
pe.pTemplate.accel = glm::vec3(0, -.7, 0);
pe.pTemplate.decay = 4;
pe.decayAmpl = 2;
pe.setMaxCount(4*4*800);
pe.posAmpl = glm::vec3(2*16, 1, 2*16);
pe.pos = glm::vec3(2*16, 4*16+4, 2*16);
pe.pTemplate.vel = glm::vec3(0, -4, 0);
pe.velAmpl = glm::vec3(0, 2, 0); rain
pe.update(deltaT);
Render::RenderParams rp;
rp.transform = m_transform;
G->R->PR->render(rp);*/
// TODO: replace harcoded 32 viewdistance
if (G->LP->raytracePointed(32, &m_pointedBlock, &m_pointedFacing)) {
m_highlightBox.program->bind();
m_highlightBox.vao.bind();
glUniform4f(m_highlightBox.uni_unicolor, 1.f, 1.f, 1.f, .1f);
glUniformMatrix4fv(m_highlightBox.uni_mvp, 1, GL_FALSE, glm::value_ptr(
glm::scale(glm::translate(m_transform, glm::vec3(m_pointedBlock)+glm::vec3(.5f)), glm::vec3(0.5f*1.03f))));
glDrawArrays(GL_TRIANGLES, 0, 6*2*3);
m_highlightBox.vao.unbind();
}
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
G->LP->render(m_transform);
if (bloom.enable) {
m_3dFbo->unbind();
G->UIM->drawFullTexV(*m_3dFbo->tex);
m_3dFbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
bloom.extractor.fbo->bind();
glViewport(0, 0, GW->getW()/bloom.scale, GW->getH()/bloom.scale);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (!bloom.vao) {
bloom.vao = std::make_unique<Render::gl::VAO>();
Render::gl::VAO::Config cfg = bloom.vao->configure();
cfg.vertexAttrib(*m_3dRenderVBO, bloom.extractor.att_coord, 2, GL_SHORT, sizeof(Coord2DTex), 0);
cfg.vertexAttrib(*m_3dRenderVBO, bloom.extractor.att_texcoord, 2, GL_BYTE, sizeof(Coord2DTex), offsetof(Coord2DTex, u));
cfg.commit();
}
bloom.extractor.prog->bind();
bloom.vao->bind();
glUniformMatrix4fv(bloom.extractor.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
glDrawArrays(GL_TRIANGLES, 0, 6);
m_3dFbo->tex->setFiltering(Texture::Filter::Nearest, Texture::Filter::Nearest);
bloom.renderer.fbo->bind();
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bloom.extractor.fbo->tex->bind();
bloom.renderer.prog->bind();
glUniformMatrix4fv(bloom.renderer.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
glUniform2f(bloom.renderer.uni_pixshift, 1.f/(GW->getW()/bloom.scale), 1.f/(GW->getH()/bloom.scale));
glDrawArrays(GL_TRIANGLES, 0, 6);
bloom.renderer.fbo->unbind();
// render to real surface
glViewport(0, 0, GW->getW(), GW->getH());
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
bloom.extractor.fbo->tex->bind();
bloom.extractor.fbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
glDrawArrays(GL_TRIANGLES, 0, 6);
bloom.vao->unbind();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
/*** 2D PART ***/
G->UIM->drawFullRect(glm::vec4(1.f, 0.f, 0.f, 1-G->LP->health));
updateUI();
drawUI();
G->R->endFrame();
frameEnd = std::chrono::steady_clock::now();
frameTime = std::chrono::duration_cast<std::chrono::duration<uint64, std::micro>>(frameEnd - frameStart).count();
fpsCounter++;
}
void GameState::onStop() {
Net::OutMessage quit(Net::MessageType::PlayerQuit); Net::OutMessage quit(Net::MessageType::PlayerQuit);
sendMsg(quit, Net::Tfer::Rel); sendMsg(quit, Net::Tfer::Rel);
G->LS->finalize(); G->LS->finalize();
} }
void GameState::gameLoop() {
double lastT, deltaT, T, fpsT = 0; int frames = 0;
LocalPlayer *LP = G->LP;
}
void GameState::renderDeathScreen() { void GameState::renderDeathScreen() {
double red = std::max(1-(G->Time-G->LP->deathTime), 0.0); double red = std::max(1-(G->Time-G->LP->deathTime), 0.0);
glClearColor(red, 0.0, 0.0, 1.0); glClearColor(red, 0.0, 0.0, 1.0);

View File

@ -114,6 +114,8 @@ private:
std::shared_ptr<class EscMenu> EM; std::shared_ptr<class EscMenu> EM;
} UI; } UI;
int fpsCounter;
double fpsNextSampling;
uint64 frameTime; uint64 frameTime;
void setupUI(); void setupUI();
@ -128,12 +130,17 @@ public:
GameState(GameWindow *W); GameState(GameWindow *W);
~GameState(); ~GameState();
void onMouseButton(int key, int action, int mods); void onStart() override;
void onCursorPos(double x, double y); void onLogicTick() override;
void onMouseScroll(double x, double y); void onFrameTick() override;
void onKey(int key, int scancode, int action, int mods); void onStop() override;
void onChar(char32 unichar);
void onResize(int w, int h); void onMouseButton(int key, int action, int mods) override;
void onCursorPos(double x, double y) override;
void onMouseScroll(double x, double y) override;
void onKey(int key, int scancode, int action, int mods) override;
void onChar(char32 unichar) override;
void onResize(int w, int h) override;
void run(); void run();
void updateViewport(); void updateViewport();

View File

@ -211,7 +211,20 @@ void GameWindow::run() {
while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) { while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
m_currentState = std::move(m_nextState); m_currentState = std::move(m_nextState);
m_nextState = nullptr; m_nextState = nullptr;
m_currentState->run(); m_currentState->onCreate();
m_currentState->onStart();
m_currentState->m_runTime = glfwGetTime();
while (m_nextState == nullptr && !glfwWindowShouldClose(m_window)) {
double newTime = glfwGetTime();
m_currentState->m_deltaTime = newTime - m_currentState->m_runTime;
m_currentState->m_runTime = newTime;
glfwPollEvents();
m_currentState->onLogicTick();
m_currentState->onFrameTick();
glfwSwapBuffers(m_window);
}
m_currentState->onStop();
m_currentState->onDestroy();
m_currentState.reset(); m_currentState.reset();
} }
} }

View File

@ -11,6 +11,7 @@
#include <glm/detail/type_mat.hpp> #include <glm/detail/type_mat.hpp>
#include "StateMachine.hpp"
#include "Platform.hpp" #include "Platform.hpp"
namespace Diggler { namespace Diggler {
@ -22,7 +23,7 @@ namespace UI {
class Manager; class Manager;
} }
class GameWindow { class GameWindow : public StateMachine {
private: private:
static int InstanceCount; static int InstanceCount;
@ -59,7 +60,7 @@ public:
void updateViewport(); void updateViewport();
void setNextState(std::unique_ptr<State> &&next); void setNextState(std::unique_ptr<State> &&next) override;
void run(); void run();
void showMessage(const std::string &msg, const std::string &submsg = ""); void showMessage(const std::string &msg, const std::string &submsg = "");

View File

@ -20,10 +20,13 @@ MessageState::MessageState(GameWindow *W, const std::string &msg, const std::str
MessageState::~MessageState() { MessageState::~MessageState() {
} }
void MessageState::setupUI() { void MessageState::onStart() {
txtMsg = W->G->UIM->add<UI::Text>(msg, 2, 2); txtMsg = W->G->UIM->add<UI::Text>(msg, 2, 2);
txtSubMsg = W->G->UIM->add<UI::Text>(subMsg); txtSubMsg = W->G->UIM->add<UI::Text>(subMsg);
updateViewport(); updateViewport();
if (GlobalProperties::IsSoundEnabled) {
W->G->A->playSound("click-quiet");
}
} }
void MessageState::updateViewport() { void MessageState::updateViewport() {
@ -38,23 +41,16 @@ void MessageState::onResize(int w, int h) {
updateViewport(); updateViewport();
} }
void MessageState::run() { void MessageState::onLogicTick() {}
setupUI();
if (GlobalProperties::IsSoundEnabled) {
W->G->A->playSound("click-quiet");
}
while (!glfwWindowShouldClose(*W)) {
W->G->R->beginFrame();
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
W->G->UIM->render(); void MessageState::onFrameTick() {
W->G->R->beginFrame();
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
W->G->R->endFrame(); W->G->UIM->render();
glfwSwapBuffers(*W); W->G->R->endFrame();
glfwPollEvents();
}
} }
} }

View File

@ -16,12 +16,15 @@ private:
public: public:
MessageState(GameWindow *W, const std::string &msg, const std::string &submsg = ""); MessageState(GameWindow *W, const std::string &msg, const std::string &submsg = "");
~MessageState(); ~MessageState() override;
void onStart() override;
void onLogicTick() override;
void onFrameTick() override;
//void onMouseButton(int key, int action, int mods); //void onMouseButton(int key, int action, int mods);
//void onCursorPos(double x, double y); //void onCursorPos(double x, double y);
void onResize(int w, int h); void onResize(int w, int h) override;
void run();
void updateViewport(); void updateViewport();
}; };

View File

@ -4,17 +4,42 @@
namespace Diggler { namespace Diggler {
class GameWindow;
class State { class State {
private:
friend GameWindow;
double m_runTime, m_deltaTime;
protected:
inline double runTime() const {
return m_runTime;
}
inline double deltaTime() const {
return m_deltaTime;
}
public: public:
virtual ~State() {} virtual ~State() {}
// Lifecycle
virtual void onCreate() {}
virtual void onStart() {}
// virtual void onResume() {}
virtual void onLogicTick() = 0;
virtual void onFrameTick() = 0;
// virtual void onPause() {}
virtual void onStop() {}
virtual void onDestroy() {}
// Input
virtual void onMouseButton(int key, int action, int mods) {} virtual void onMouseButton(int key, int action, int mods) {}
virtual void onCursorPos(double x, double y) {} virtual void onCursorPos(double x, double y) {}
virtual void onMouseScroll(double x, double y) {} virtual void onMouseScroll(double x, double y) {}
virtual void onKey(int key, int scancode, int action, int mods) {} virtual void onKey(int key, int scancode, int action, int mods) {}
virtual void onChar(char32 unichar) {} virtual void onChar(char32 unichar) {}
virtual void onResize(int w, int h) {} virtual void onResize(int w, int h) {}
virtual void run() = 0;
}; };
} }

17
src/StateMachine.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef DIGGLER_STATE_MACHINE_HPP
#define DIGGLER_STATE_MACHINE_HPP
#include <memory>
#include "State.hpp"
namespace Diggler {
class StateMachine {
public:
virtual void setNextState(std::unique_ptr<State> &&next) = 0;
};
}
#endif /* DIGGLER_STATE_MACHINE_HPP */

View File

@ -21,28 +21,28 @@ public:
Universe(Game *G, bool remote); Universe(Game *G, bool remote);
~Universe(); ~Universe();
/// /**
/// @brief Gets a reference to a world. * @brief Gets a reference to a world.
/// Gets a world using its ID. If the world doesn't exist, returns an empty reference. * Gets a world using its ID. If the world doesn't exist, returns an empty reference.
/// @returns Reference to the world. * @returns Reference to the world.
/// */
WorldRef getWorld(WorldId id); WorldRef getWorld(WorldId id);
/// /**
/// @brief Gets a reference to a world. * @brief Gets a reference to a world.
/// Gets a world using its ID. If the world doesn't exist in memory, creates it or * Gets a world using its ID. If the world doesn't exist in memory, creates it or
/// *synchronously* loads it. * *synchronously* loads it.
/// @returns Reference to the world. * @returns Reference to the world.
/// */
WorldRef getLoadWorld(WorldId id); WorldRef getLoadWorld(WorldId id);
/// /**
/// @brief Creates a world. * @brief Creates a world.
/// Creates a world with the specified ID. The World instance is constructed with * Creates a world with the specified ID. The World instance is constructed with
/// default parameters. * default parameters.
/// @note If a world with the same ID exists, an empty reference is returned. * @note If a world with the same ID exists, an empty reference is returned.
/// @returns Reference to the newly created world. * @returns Reference to the newly created world.
/// */
WorldRef createWorld(WorldId id); WorldRef createWorld(WorldId id);
/* ============ Serialization ============ */ /* ============ Serialization ============ */

17
src/content/Asset.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "Asset.hpp"
#include <meiose/variant.hpp>
#include "AssetManager.hpp"
namespace Diggler {
namespace Content {
Asset::Asset(const std::shared_ptr<AssetContentMetadata> &acm) :
m_contentMetadata(acm) {
}
}
}

View File

@ -1,7 +1,7 @@
#ifndef DIGGLER_CONTENT_ASSET_HPP #ifndef DIGGLER_CONTENT_ASSET_HPP
#define DIGGLER_CONTENT_ASSET_HPP #define DIGGLER_CONTENT_ASSET_HPP
#include <goodform/variant.hpp> #include <memory>
#include "../crypto/SHA256.hpp" #include "../crypto/SHA256.hpp"
#include "AssetContentMetadata.hpp" #include "AssetContentMetadata.hpp"
@ -26,11 +26,10 @@ protected:
friend class AssetManager; friend class AssetManager;
Crypto::SHA256::Digest m_contentHash; Crypto::SHA256::Digest m_contentHash;
AssetContentMetadata &m_contentMetadata; std::shared_ptr<AssetContentMetadata> m_contentMetadata;
Type m_type; Type m_type;
goodform::object m_info;
Asset(AssetContentMetadata&); Asset(const std::shared_ptr<AssetContentMetadata>&);
public: public:
const Crypto::SHA256::Digest& contentHash() const { const Crypto::SHA256::Digest& contentHash() const {
@ -38,16 +37,12 @@ public:
} }
const AssetContentMetadata& contentMetadata() const { const AssetContentMetadata& contentMetadata() const {
return m_contentMetadata; return *m_contentMetadata;
} }
Type type() const { Type type() const {
return m_type; return m_type;
} }
const goodform::object& info() const {
return m_info;
}
}; };
} }

View File

@ -0,0 +1,97 @@
#include "AssetContentMetadata.hpp"
#include <algorithm>
#include <goodform/variant.hpp>
namespace Diggler {
namespace Content {
AssetContentMetadata::AssetContentMetadata(AssetManager &am) :
m_assetManager(am) {
}
AssetContentMetadata::~AssetContentMetadata() {
}
bool AssetContentMetadata::validSchemeVersion(SchemeVersion v) {
return v == 0;
}
bool AssetContentMetadata::validSerialized(InMemoryStream &ims) {
try {
SchemeVersion schemeVersion = ims.readU32();
if (not validSchemeVersion(schemeVersion)) {
return false;
}
const uint64 fileSize = ims.readU64();
/* if (fileSize > MaxFileSize) {
return false;
} */
const uint32 blockSize = ims.readU32();
if (blockSize < MinBlockSize or
blockSize > MaxBlockSize) {
return false;
}
const uint64 blockCount = (fileSize + (blockSize - 1)) / blockSize;
ims.seek(static_cast<Stream::OffT>(blockCount * Crypto::SHA256::Digest::Length),
MemoryStream::Current);
} catch (const std::underflow_error&) {
return false;
}
return true;
}
bool AssetContentMetadata::validSerializedDB(InMemoryStream &ims) {
if (not validSerialized(ims)) {
return false;
}
/* Enable when useful:
Stream::PosT pos = ims.tell();
ims.rewind();
const SchemeVersion schemeVersion = ims.readU32();
ims.seek(pos); */
try {
uint8 contentFileStatus = ims.readU8();
if (contentFileStatus >= static_cast<uint8>(ContentFileStatus::MAX)) {
return false;
}
} catch (const std::underflow_error&) {
return false;
}
return true;
}
void AssetContentMetadata::fromSerialized(InMemoryStream &ims) {
m_schemeVersion = ims.readU32();
m_fileSize = ims.readU64();
m_blockSize = ims.readU32();
const size_t blockCount = static_cast<size_t>((m_fileSize + (m_blockSize - 1)) / m_blockSize);
m_blockHashes = decltype(m_blockHashes)(blockCount);
for (size_t i = 0; i < blockCount; ++i) {
ims.readData(m_blockHashes[i].data, decltype(m_blockHashes)::value_type::Length);
}
}
void AssetContentMetadata::fromSerializedDB(InMemoryStream &ims) {
fromSerialized(ims);
m_contentFileStatus = static_cast<ContentFileStatus>(ims.readU8());
}
void AssetContentMetadata::toSerialized(OutMemoryStream &oms) const {
oms.writeU32(m_schemeVersion);
oms.writeU64(m_fileSize);
oms.writeU32(m_blockSize);
for (const Crypto::SHA256::Digest &blockHash : m_blockHashes) {
oms.writeData(blockHash.data, decltype(m_blockHashes)::value_type::Length);
}
}
void AssetContentMetadata::toSerializedDB(OutMemoryStream &oms) const {
toSerialized(oms);
oms.writeU8(static_cast<uint8>(m_contentFileStatus));
}
}
}

View File

@ -6,6 +6,8 @@ add_subdirectory("texture")
set(CSD ${CMAKE_CURRENT_SOURCE_DIR}) set(CSD ${CMAKE_CURRENT_SOURCE_DIR})
diggler_add_sources( diggler_add_sources(
#${CSD}/Asset.cpp
#${CSD}/AssetContentMetadata.cpp
${CSD}/AssetManager.cpp ${CSD}/AssetManager.cpp
${CSD}/ModManager.cpp ${CSD}/ModManager.cpp
${CSD}/Registry.cpp ${CSD}/Registry.cpp

View File

@ -3,7 +3,6 @@
#include <memory> #include <memory>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <sys/signal.h>
#include "ConnectingState.hpp" #include "ConnectingState.hpp"
#include "Game.hpp" #include "Game.hpp"

View File

@ -1,5 +1,7 @@
#include "NetHelper.hpp" #include "NetHelper.hpp"
#include <meiose/variant.hpp>
#include "msgtypes/Chat.hpp" #include "msgtypes/Chat.hpp"
#include "../Game.hpp" #include "../Game.hpp"
#include "../Player.hpp" #include "../Player.hpp"
@ -23,7 +25,7 @@ void Broadcast(Game &G, const OutMessage &msg, Tfer tfer, Channels chan) {
void SendChat(Game *G, const std::string &str) { void SendChat(Game *G, const std::string &str) {
Net::MsgTypes::ChatSend cs; Net::MsgTypes::ChatSend cs;
cs.msg = goodform::object { cs.msg = meiose::variant::map {
{"plaintext", str} {"plaintext", str}
}; };

View File

@ -8,7 +8,8 @@
#include <enet/enet.h> #include <enet/enet.h>
#include <goodform/msgpack.hpp> #include <meiose/msgpack.hpp>
#include <meiose/variant.hpp>
#include "../crypto/Random.hpp" #include "../crypto/Random.hpp"
#include "../util/Log.hpp" #include "../util/Log.hpp"
@ -16,6 +17,31 @@
#include <iomanip> #include <iomanip>
struct membuf : std::streambuf {
membuf(char* begin, char* end) {
setg(begin, begin, end);
}
membuf(void* begin, void* end) :
membuf(reinterpret_cast<char*>(begin), reinterpret_cast<char*>(end)) {}
membuf(const void* begin, const void* end) :
membuf(const_cast<void*>(begin), const_cast<void*>(end)) {}
};
class omsgbuf : public std::streambuf {
protected:
Diggler::Net::OutMessage &omsg;
public:
omsgbuf(Diggler::Net::OutMessage &o) : omsg(o) {}
protected:
std::streamsize xsputn(const char_type* s, std::streamsize n) override {
omsg.writeData(s, n);
return n;
}
int_type overflow(int_type ch) override {
omsg.writeI8(ch);
return 1;
}
};
namespace Diggler { namespace Diggler {
namespace Net { namespace Net {
@ -105,16 +131,15 @@ void InMessage::free() {
m_data = nullptr; m_data = nullptr;
} }
void InMessage::readMsgpack(goodform::variant &var) { void InMessage::readMsgpack(meiose::variant &var) {
uint32 len = readU32(); uint32 len = readU32();
if (len > remaining()) { if (len > remaining()) {
throw std::runtime_error("Not enough bytes available for reported msgpack length"); throw std::runtime_error("Not enough bytes available for reported msgpack length");
} }
InMemoryStream ims(getCursorPtr(len), len); const void *start = getCursorPtr(len);
goodform::msgpack::deserialize(ims, var); membuf sbuf(start, getCursorPtr());
/*if (var.type() != goodform::variant_type::object) { std::istream in(&sbuf);
throw std::runtime_error("Read msgpack is not an object / map"); meiose::msgpack::read(in, var);
}*/
} }
@ -149,13 +174,12 @@ void OutMessage::fit(SizeT len) {
m_allocated = targetSize; m_allocated = targetSize;
} }
void OutMessage::writeMsgpack(const goodform::variant &var) { void OutMessage::writeMsgpack(const meiose::variant &var) {
/*if (var.type() != goodform::variant_type::object) {
throw std::runtime_error("msgpack to write is not an object / map");
}*/
PosT pos = tell(); PosT pos = tell();
writeU32(0); writeU32(0);
goodform::msgpack::serialize(var, *this); omsgbuf sbuf(*this);
std::ostream out(&sbuf);
meiose::msgpack::write(out, var);
PosT posWritten = tell(); PosT posWritten = tell();
seek(pos); seek(pos);
writeU32(static_cast<uint32>(posWritten - (pos + sizeof(uint32)))); writeU32(static_cast<uint32>(posWritten - (pos + sizeof(uint32))));

View File

@ -11,6 +11,10 @@
#include "../crypto/DiffieHellman.hpp" #include "../crypto/DiffieHellman.hpp"
#include "../io/MemoryStream.hpp" #include "../io/MemoryStream.hpp"
namespace meiose {
class variant;
}
namespace Diggler { namespace Diggler {
namespace Net { namespace Net {
@ -113,6 +117,7 @@ public:
glm::vec3 readVec3(); glm::vec3 readVec3();
glm::ivec3 readIVec3(); glm::ivec3 readIVec3();
void readMsgpack(meiose::variant&);
Channels getChannel() const; Channels getChannel() const;
}; };
@ -153,6 +158,7 @@ public:
writeI32(vec.y); writeI32(vec.y);
writeI32(vec.z); writeI32(vec.z);
} }
void writeMsgpack(const meiose::variant&);
}; };
class Exception : public std::exception { class Exception : public std::exception {

View File

@ -21,27 +21,27 @@ bool ChatHandler::handle(GameState &GS, InMessage &msg) {
ChatAnnouncement ca; ChatAnnouncement ca;
ca.readFromMsg(msg); ca.readFromMsg(msg);
// TODO better formatting abilities // TODO better formatting abilities
if (ca.msg.is<goodform::object>()) { if (ca.msg.isMap()) {
GS.m_chatBox->addChatEntry(ca.msg["plaintext"].get<std::string>()); GS.m_chatBox->addChatEntry(ca.msg["plaintext"].getStr());
} }
} break; } break;
case S::PlayerTalk: { case S::PlayerTalk: {
ChatPlayerTalk cpt; ChatPlayerTalk cpt;
cpt.readFromMsg(msg); cpt.readFromMsg(msg);
// TODO better formatting abilities // TODO better formatting abilities
if (cpt.msg.is<std::string>()) { if (cpt.msg.isStr()) {
std::string playerName; std::string playerName;
if (cpt.player.display.is<std::nullptr_t>()) { if (cpt.player.display.isNil()) {
const Player *blabbermouth = GS.G->players.getBySessId(cpt.player.id); const Player *blabbermouth = GS.G->players.getBySessId(cpt.player.id);
if (blabbermouth != nullptr) { if (blabbermouth != nullptr) {
playerName = blabbermouth->name + "> "; playerName = blabbermouth->name + "> ";
} else { } else {
playerName = "?> "; playerName = "?> ";
} }
} else if (cpt.player.display.is<std::string>()) { } else if (cpt.player.display.isStr()) {
cpt.player.display.get<std::string>(playerName); playerName = cpt.player.display.getStr();
} }
GS.m_chatBox->addChatEntry(playerName + cpt.msg.get<std::string>()); GS.m_chatBox->addChatEntry(playerName + cpt.msg.getStr());
} }
} break; } break;
} }

View File

@ -3,6 +3,8 @@
#include "MsgType.hpp" #include "MsgType.hpp"
#include <meiose/variant.hpp>
#include "../../content/Content.hpp" #include "../../content/Content.hpp"
#include "../../World.hpp" #include "../../World.hpp"
@ -26,7 +28,7 @@ struct BlockUpdateNotify : public MsgType {
glm::ivec3 pos; glm::ivec3 pos;
BlockId id; BlockId id;
BlockData data; BlockData data;
//goodform::variant extdata; meiose::variant extdata;
LightData light; LightData light;
enum Cause : uint8 { enum Cause : uint8 {
Unspecified = 0, Unspecified = 0,
@ -45,7 +47,7 @@ struct BlockUpdatePlace : public MsgType {
glm::ivec3 pos; glm::ivec3 pos;
BlockId id; BlockId id;
BlockData data; BlockData data;
//goodform::variant extdata; meiose::variant extdata;
void writeToMsg(OutMessage&) const override; void writeToMsg(OutMessage&) const override;
void readFromMsg(InMessage&) override; void readFromMsg(InMessage&) override;

View File

@ -3,7 +3,7 @@
#include "MsgType.hpp" #include "MsgType.hpp"
#include <goodform/variant.hpp> #include <meiose/variant.hpp>
#include "../../Player.hpp" #include "../../Player.hpp"
@ -18,7 +18,7 @@ enum class ChatSubtype : uint8 {
}; };
struct ChatSend : public MsgType { struct ChatSend : public MsgType {
goodform::variant msg; meiose::variant msg;
void writeToMsg(OutMessage&) const override; void writeToMsg(OutMessage&) const override;
void readFromMsg(InMessage&) override; void readFromMsg(InMessage&) override;
@ -28,9 +28,9 @@ struct ChatAnnouncement : public MsgType {
std::string announcementType; std::string announcementType;
struct Origin { struct Origin {
std::string name; std::string name;
goodform::variant display; meiose::variant display;
} origin; } origin;
goodform::variant msg; meiose::variant msg;
void writeToMsg(OutMessage&) const override; void writeToMsg(OutMessage&) const override;
void readFromMsg(InMessage&) override; void readFromMsg(InMessage&) override;
@ -39,9 +39,9 @@ struct ChatAnnouncement : public MsgType {
struct ChatPlayerTalk : public MsgType { struct ChatPlayerTalk : public MsgType {
struct ChatPlayer { struct ChatPlayer {
PlayerGameID id; PlayerGameID id;
goodform::variant display; meiose::variant display;
} player; } player;
goodform::variant msg; meiose::variant msg;
void writeToMsg(OutMessage&) const override; void writeToMsg(OutMessage&) const override;
void readFromMsg(InMessage&) override; void readFromMsg(InMessage&) override;

View File

@ -3,7 +3,7 @@
#include "MsgType.hpp" #include "MsgType.hpp"
#include <goodform/variant.hpp> #include <meiose/variant.hpp>
namespace Diggler { namespace Diggler {
namespace Net { namespace Net {
@ -16,14 +16,14 @@ enum class ServerInfoSubtype : uint8 {
struct ServerInfoRequest : public MsgType { struct ServerInfoRequest : public MsgType {
std::vector<std::string> infos; std::vector<std::string> infos;
goodform::variant params; meiose::variant params;
void writeToMsg(OutMessage&) const override; void writeToMsg(OutMessage&) const override;
void readFromMsg(InMessage&) override; void readFromMsg(InMessage&) override;
}; };
struct ServerInfoResponse : public MsgType { struct ServerInfoResponse : public MsgType {
goodform::variant infos; meiose::variant infos;
void writeToMsg(OutMessage&) const override; void writeToMsg(OutMessage&) const override;
void readFromMsg(InMessage&) override; void readFromMsg(InMessage&) override;

View File

@ -6,17 +6,33 @@
namespace Diggler { namespace Diggler {
constexpr uint16_t byteSwap16(uint16_t x) { constexpr uint16_t byteSwap16(uint16_t x) {
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
return __builtin_bswap16(x);
#else
return static_cast<uint16_t>((x >> 8) | (x << 8)); return static_cast<uint16_t>((x >> 8) | (x << 8));
#endif
} }
constexpr uint32_t byteSwap32(uint32_t x) { constexpr uint32_t byteSwap32(uint32_t x) {
return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24);; #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
return __builtin_bswap32(x);
#elif defined(__ICC) || defined(__INTEL_COMPILER)
return _bswap(x);
#else
return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24);
#endif
} }
constexpr uint64_t byteSwap64(uint64_t x) { constexpr uint64_t byteSwap64(uint64_t x) {
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
return __builtin_bswap64(x);
#elif defined(__ICC) || defined(__INTEL_COMPILER)
return _bswap64(x);
#else
return (x>>56) | ((x<<40) & 0x00FF000000000000UL) | ((x<<24) & 0x0000FF0000000000UL) | return (x>>56) | ((x<<40) & 0x00FF000000000000UL) | ((x<<24) & 0x0000FF0000000000UL) |
((x<<8) & 0x000000FF00000000UL) | ((x>>8) & 0x00000000FF000000UL) | ((x<<8) & 0x000000FF00000000UL) | ((x>>8) & 0x00000000FF000000UL) |
((x>>24) & 0x0000000000FF0000UL) | ((x>>40) & 0x000000000000FF00UL) | (x<<56); ((x>>24) & 0x0000000000FF0000UL) | ((x>>40) & 0x000000000000FF00UL) | (x<<56);
#endif
} }
enum class Endianness : uint8_t { enum class Endianness : uint8_t {
@ -27,9 +43,11 @@ enum class Endianness : uint8_t {
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \ #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \
defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
defined(__BIG_ENDIAN__) || \ defined(__BIG_ENDIAN__) || \
defined(__ARMEB__) || \ defined(__sparc) || defined(__sparc__) || \
defined(__THUMBEB__) || \ defined(_POWER) || defined(__powerpc__) || \
defined(__AARCH64EB__) || \ defined(__ppc__) || defined(__hpux) || \
defined(__s390__) || \
defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
constexpr Endianness SystemEndianness = Endianness::Big; constexpr Endianness SystemEndianness = Endianness::Big;
@ -51,9 +69,13 @@ constexpr uint64_t fromLe64(uint64_t x) { return byteSwap64(x); }
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \ #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
defined(__LITTLE_ENDIAN__) || \ defined(__LITTLE_ENDIAN__) || \
defined(__ARMEL__) || \ defined(__i386__) || defined(__alpha__) || \
defined(__THUMBEL__) || \ defined(__ia64) || defined(__ia64__) || \
defined(__AARCH64EL__) || \ defined(_M_IX86) || defined(_M_IA64) || \
defined(_M_ALPHA) || defined(__amd64) || \
defined(__amd64__) || defined(_M_AMD64) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
constexpr Endianness SystemEndianness = Endianness::Little; constexpr Endianness SystemEndianness = Endianness::Little;

View File

@ -10,6 +10,7 @@ using uint = std::uint32_t;
using uint32 = std::uint32_t; using uint32 = std::uint32_t;
using uint64 = std::uint64_t; using uint64 = std::uint64_t;
using uint16 = std::uint16_t; using uint16 = std::uint16_t;
using ushort = uint16;
using uint8 = std::uint8_t; using uint8 = std::uint8_t;
using int64 = std::int64_t; using int64 = std::int64_t;
using int32 = std::int32_t; using int32 = std::int32_t;

View File

@ -1,6 +1,7 @@
#ifndef DIGGLER_RENDER_GL_DELEGATE_GL_HPP #ifndef DIGGLER_RENDER_GL_DELEGATE_GL_HPP
#define DIGGLER_RENDER_GL_DELEGATE_GL_HPP #define DIGGLER_RENDER_GL_DELEGATE_GL_HPP
#include <future>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
@ -38,6 +39,16 @@ public:
GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei width, GLsizei height, GLenum format, GLenum type,
std::unique_ptr<const uint8[]> &&data); std::unique_ptr<const uint8[]> &&data);
template<typename Func>
static std::future<decltype(std::declval<Func>()())> run(Func &&func) {
std::promise<decltype(std::declval<Func>()())> promise;
auto future = promise.get_future();
push([func { std::move(func) }, promise { std::move(promise) }] {
promise.set_value_at_thread_exit(func());
});
return future;
}
static void execute(); static void execute();
}; };

View File

@ -6,6 +6,7 @@
#include "OpenGL.hpp" #include "OpenGL.hpp"
#include "../../platform/PreprocUtils.hpp" #include "../../platform/PreprocUtils.hpp"
#include "../../platform/Types.hpp"
namespace Diggler { namespace Diggler {
namespace Render { namespace Render {

View File

@ -37,10 +37,12 @@ else()
endif() endif()
if (DIGGLER_ENABLE_JEMALLOC) if (DIGGLER_ENABLE_JEMALLOC)
find_package(Jemalloc REQUIRED)
diggler_add_definition( diggler_add_definition(
-DDIGGLER_ENABLE_JEMALLOC=1 -DDIGGLER_ENABLE_JEMALLOC=1
) )
diggler_link_libraries( diggler_link_libraries(
jemalloc ${JEMALLOC_LIBRARIES}
) )
endif() endif()

View File

@ -0,0 +1,17 @@
#include "MemoryTracker.hpp"
namespace Diggler {
namespace Util {
namespace MemoryTracker {
void init() {}
void setCategory(const char*, uint_fast32_t) {}
std::vector<CategoryStats> categoryStats() {
return {};
}
}
}
}