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"]
path = ext/enet
url = https://github.com/freeminer/enet.git
[submodule "ext/goodform"]
path = ext/goodform
url = https://github.com/ElementW/goodform.git
[submodule "ext/torch7"]
path = ext/torch7
url = https://github.com/torch/torch7.git
@ -25,3 +22,6 @@
[submodule "assets/lua/modules/lds"]
path = assets/lua/modules/lds
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(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)
pkg_search_module(GLFW REQUIRED glfw3)
@ -77,6 +83,7 @@ pkg_search_module(LIBSODIUM REQUIRED libsodium)
include_directories(BEFORE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
${ETC_INCLUDE_DIRS}
${MEIOSE_INCLUDE_DIR}
${LUA_INCLUDE_DIR}
${LZFX_INCLUDE_DIRS}
${ENET_INCLUDE_DIRS}
@ -87,10 +94,6 @@ include_directories(BEFORE
${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
# Sources
set_property(GLOBAL PROPERTY DIGGLER_SOURCE_FILES "")
@ -146,6 +149,7 @@ get_property(LIBS GLOBAL PROPERTY DIGGLER_LINK_LIBRARIES)
target_link_libraries(diggler
${LIBS}
${ETC_LIBRARIES}
${MEIOSE_LIBRARY}
${LUA_LIBRARY}
${LZFX_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 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).
Info name | Reply type | Reply data

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

View File

@ -35,6 +35,8 @@
#define LZFX_HSIZE (1 << (LZFX_HLOG))
#include <stdint.h>
/* We need this for memset */
#ifdef __cplusplus
# 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 */
#if defined (WIN32) && defined (_M_X64)
unsigned _int64 off; /* workaround for missing POSIX compliance */
uint64_t off; /* workaround for missing POSIX compliance */
#else
unsigned long off;
#endif

1
ext/meiose Submodule

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

View File

@ -49,13 +49,18 @@ public:
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 {
static constexpr FourCC MagicMarker = MakeFourCC("CKDT");
FourCC magic;
// Keep me Plain Old Data!
BlockId id[CX*CY*CZ];
BlockData data[CX*CY*CZ];
LightData light[CX*CY*CZ];
FourCC magic; /**< Magic marker. Used for Chunk eviction checking. */
BlockId id[CX*CY*CZ]; /**< Block IDs. */
BlockData data[CX*CY*CZ]; /**< Block data. */
LightData light[CX*CY*CZ]; /**< Block light info. */
void clear();
};

View File

@ -45,115 +45,116 @@ void ConnectingState::setupUI() {
void ConnectingState::updateViewport() {
}
void ConnectingState::onResize(int w, int h) {
updateViewport();
}
void ConnectingState::run() {
std::string &serverHost = m_serverHost;
int serverPort = m_serverPort;
bool finished = false, success = false;
void ConnectingState::onStart() {
finished = success = false;
Game *const G = W->G;
std::string failureStr;
std::thread networkThread = std::thread([G, &success, &finished, &serverHost, serverPort, &failureStr]() {
m_networkThread = std::thread([this, G]() {
try {
G->H.create();
G->NS = &G->H.connect(serverHost, serverPort, 5000);
G->NS = &G->H.connect(m_serverHost, m_serverPort, 5000);
success = true;
} catch (const std::exception &e) {
success = false;
failureStr = e.what();
m_infoStr = e.what();
}
finished = true;
});
glDisable(GL_CULL_FACE);
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;
UI::Text::Size sz = txtConnecting->getSize();
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));
while (!finished && !W->shouldClose()) { // Infinite loop \o/
const double T = glfwGetTime();
G->updateTime(T);
G->R->beginFrame();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
G->R->beginFrame();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
txtConnecting->render(textMat);
for (int i=0; i < 6; ++i) {
const float t = T * 3 + 0.3f * i;
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(2.f, 2.f, 1.f));
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;
txtConnecting->render(textMat);
for (int i=0; i < 6; ++i) {
const double t = G->Time * 3 + 0.3 * i;
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(2.f, 2.f, 1.f));
txtDot->render(mat);
}
LocalPlayer &LP = *G->LP;
LP.name = GlobalProperties::PlayerName;
G->R->endFrame();
}
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;
void ConnectingState::onStop() {
if (m_networkThread.joinable()) {
m_networkThread.join();
}
}
// 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));
void ConnectingState::onResize(int w, int h) {
updateViewport();
}
}

View File

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

View File

@ -5,6 +5,10 @@
#include "platform/types/vec3.hpp"
// The following, courtesy of the Windows developer experience™
#undef NEAR
#undef FAR
namespace Diggler {
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);
}
void GameState::run() {
void GameState::onStart() {
setupUI();
gameLoop();
}
void GameState::gameLoop() {
double lastT, deltaT, T, fpsT = 0; int frames = 0;
fpsCounter = 0;
fpsNextSampling = 1.;
LocalPlayer *LP = G->LP;
LP->position = glm::vec3(-2, 2, -2);
angles.x = M_PI/4; angles.y = M_PI/4;
@ -430,169 +429,178 @@ void GameState::gameLoop() {
LP->forceCameraUpdate();
G->A->update();
LP->setHasNoclip(true);
}
std::chrono::time_point<std::chrono::steady_clock> frameStart, frameEnd;
while (!GW->shouldClose()) {
if (!processNetwork()) return;
void GameState::onLogicTick() {
if (!processNetwork()) return;
T = glfwGetTime(); deltaT = T - lastT;
G->updateTime(T);
if (T > fpsT) {
char str[10]; std::snprintf(str, 10, "FPS: %-4d", frames);
UI.FPS->setText(std::string(str));
fpsT = T+1;
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++;
G->updateTime(runTime());
if (runTime() > fpsNextSampling) {
char str[10]; std::snprintf(str, 10, "FPS: %-4d", fpsCounter);
UI.FPS->setText(std::string(str));
fpsNextSampling = runTime() + 1;
fpsCounter = 0;
}
}
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);
sendMsg(quit, Net::Tfer::Rel);
G->LS->finalize();
}
void GameState::gameLoop() {
double lastT, deltaT, T, fpsT = 0; int frames = 0;
LocalPlayer *LP = G->LP;
}
void GameState::renderDeathScreen() {
double red = std::max(1-(G->Time-G->LP->deathTime), 0.0);
glClearColor(red, 0.0, 0.0, 1.0);

View File

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

View File

@ -211,7 +211,20 @@ void GameWindow::run() {
while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
m_currentState = std::move(m_nextState);
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();
}
}

View File

@ -11,6 +11,7 @@
#include <glm/detail/type_mat.hpp>
#include "StateMachine.hpp"
#include "Platform.hpp"
namespace Diggler {
@ -22,7 +23,7 @@ namespace UI {
class Manager;
}
class GameWindow {
class GameWindow : public StateMachine {
private:
static int InstanceCount;
@ -59,7 +60,7 @@ public:
void updateViewport();
void setNextState(std::unique_ptr<State> &&next);
void setNextState(std::unique_ptr<State> &&next) override;
void run();
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() {
}
void MessageState::setupUI() {
void MessageState::onStart() {
txtMsg = W->G->UIM->add<UI::Text>(msg, 2, 2);
txtSubMsg = W->G->UIM->add<UI::Text>(subMsg);
updateViewport();
if (GlobalProperties::IsSoundEnabled) {
W->G->A->playSound("click-quiet");
}
}
void MessageState::updateViewport() {
@ -38,23 +41,16 @@ void MessageState::onResize(int w, int h) {
updateViewport();
}
void MessageState::run() {
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);
void MessageState::onLogicTick() {}
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);
glfwPollEvents();
}
W->G->R->endFrame();
}
}

View File

@ -16,12 +16,15 @@ private:
public:
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 onCursorPos(double x, double y);
void onResize(int w, int h);
void run();
void onResize(int w, int h) override;
void updateViewport();
};

View File

@ -4,17 +4,42 @@
namespace Diggler {
class GameWindow;
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:
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 onCursorPos(double x, double y) {}
virtual void onMouseScroll(double x, double y) {}
virtual void onKey(int key, int scancode, int action, int mods) {}
virtual void onChar(char32 unichar) {}
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();
///
/// @brief Gets a reference to a world.
/// Gets a world using its ID. If the world doesn't exist, returns an empty reference.
/// @returns Reference to the world.
///
/**
* @brief Gets a reference to a world.
* Gets a world using its ID. If the world doesn't exist, returns an empty reference.
* @returns Reference to the world.
*/
WorldRef getWorld(WorldId id);
///
/// @brief Gets a reference to a world.
/// Gets a world using its ID. If the world doesn't exist in memory, creates it or
/// *synchronously* loads it.
/// @returns Reference to the 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
* *synchronously* loads it.
* @returns Reference to the world.
*/
WorldRef getLoadWorld(WorldId id);
///
/// @brief Creates a world.
/// Creates a world with the specified ID. The World instance is constructed with
/// default parameters.
/// @note If a world with the same ID exists, an empty reference is returned.
/// @returns Reference to the newly created world.
///
/**
* @brief Creates a world.
* Creates a world with the specified ID. The World instance is constructed with
* default parameters.
* @note If a world with the same ID exists, an empty reference is returned.
* @returns Reference to the newly created world.
*/
WorldRef createWorld(WorldId id);
/* ============ 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
#define DIGGLER_CONTENT_ASSET_HPP
#include <goodform/variant.hpp>
#include <memory>
#include "../crypto/SHA256.hpp"
#include "AssetContentMetadata.hpp"
@ -26,11 +26,10 @@ protected:
friend class AssetManager;
Crypto::SHA256::Digest m_contentHash;
AssetContentMetadata &m_contentMetadata;
std::shared_ptr<AssetContentMetadata> m_contentMetadata;
Type m_type;
goodform::object m_info;
Asset(AssetContentMetadata&);
Asset(const std::shared_ptr<AssetContentMetadata>&);
public:
const Crypto::SHA256::Digest& contentHash() const {
@ -38,16 +37,12 @@ public:
}
const AssetContentMetadata& contentMetadata() const {
return m_contentMetadata;
return *m_contentMetadata;
}
Type type() const {
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})
diggler_add_sources(
#${CSD}/Asset.cpp
#${CSD}/AssetContentMetadata.cpp
${CSD}/AssetManager.cpp
${CSD}/ModManager.cpp
${CSD}/Registry.cpp

View File

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

View File

@ -1,5 +1,7 @@
#include "NetHelper.hpp"
#include <meiose/variant.hpp>
#include "msgtypes/Chat.hpp"
#include "../Game.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) {
Net::MsgTypes::ChatSend cs;
cs.msg = goodform::object {
cs.msg = meiose::variant::map {
{"plaintext", str}
};

View File

@ -8,7 +8,8 @@
#include <enet/enet.h>
#include <goodform/msgpack.hpp>
#include <meiose/msgpack.hpp>
#include <meiose/variant.hpp>
#include "../crypto/Random.hpp"
#include "../util/Log.hpp"
@ -16,6 +17,31 @@
#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 Net {
@ -105,16 +131,15 @@ void InMessage::free() {
m_data = nullptr;
}
void InMessage::readMsgpack(goodform::variant &var) {
void InMessage::readMsgpack(meiose::variant &var) {
uint32 len = readU32();
if (len > remaining()) {
throw std::runtime_error("Not enough bytes available for reported msgpack length");
}
InMemoryStream ims(getCursorPtr(len), len);
goodform::msgpack::deserialize(ims, var);
/*if (var.type() != goodform::variant_type::object) {
throw std::runtime_error("Read msgpack is not an object / map");
}*/
const void *start = getCursorPtr(len);
membuf sbuf(start, getCursorPtr());
std::istream in(&sbuf);
meiose::msgpack::read(in, var);
}
@ -149,13 +174,12 @@ void OutMessage::fit(SizeT len) {
m_allocated = targetSize;
}
void OutMessage::writeMsgpack(const goodform::variant &var) {
/*if (var.type() != goodform::variant_type::object) {
throw std::runtime_error("msgpack to write is not an object / map");
}*/
void OutMessage::writeMsgpack(const meiose::variant &var) {
PosT pos = tell();
writeU32(0);
goodform::msgpack::serialize(var, *this);
omsgbuf sbuf(*this);
std::ostream out(&sbuf);
meiose::msgpack::write(out, var);
PosT posWritten = tell();
seek(pos);
writeU32(static_cast<uint32>(posWritten - (pos + sizeof(uint32))));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,17 +6,33 @@
namespace Diggler {
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));
#endif
}
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) {
#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) |
((x<<8) & 0x000000FF00000000UL) | ((x>>8) & 0x00000000FF000000UL) |
((x>>24) & 0x0000000000FF0000UL) | ((x>>40) & 0x000000000000FF00UL) | (x<<56);
#endif
}
enum class Endianness : uint8_t {
@ -27,9 +43,11 @@ enum class Endianness : uint8_t {
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \
defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
defined(__BIG_ENDIAN__) || \
defined(__ARMEB__) || \
defined(__THUMBEB__) || \
defined(__AARCH64EB__) || \
defined(__sparc) || defined(__sparc__) || \
defined(_POWER) || defined(__powerpc__) || \
defined(__ppc__) || defined(__hpux) || \
defined(__s390__) || \
defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
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__ || \
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
defined(__LITTLE_ENDIAN__) || \
defined(__ARMEL__) || \
defined(__THUMBEL__) || \
defined(__AARCH64EL__) || \
defined(__i386__) || defined(__alpha__) || \
defined(__ia64) || defined(__ia64__) || \
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__)
constexpr Endianness SystemEndianness = Endianness::Little;

View File

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

View File

@ -1,6 +1,7 @@
#ifndef DIGGLER_RENDER_GL_DELEGATE_GL_HPP
#define DIGGLER_RENDER_GL_DELEGATE_GL_HPP
#include <future>
#include <memory>
#include <mutex>
#include <thread>
@ -38,6 +39,16 @@ public:
GLsizei width, GLsizei height, GLenum format, GLenum type,
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();
};

View File

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

View File

@ -37,10 +37,12 @@ else()
endif()
if (DIGGLER_ENABLE_JEMALLOC)
find_package(Jemalloc REQUIRED)
diggler_add_definition(
-DDIGGLER_ENABLE_JEMALLOC=1
)
diggler_link_libraries(
jemalloc
${JEMALLOC_LIBRARIES}
)
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 {};
}
}
}
}