Asset & Mod management base; PlayerUpdate->MsgTypes; add basic crypto
Fix rendering on compliant GL ES 2.0 implementations.master
parent
dd04f4a968
commit
42ea79d259
|
@ -1,9 +1,12 @@
|
||||||
.kdev4
|
.kdev4
|
||||||
assets-orig
|
assets-orig
|
||||||
build
|
build
|
||||||
|
build-*
|
||||||
*.fossil
|
*.fossil
|
||||||
*.project
|
*.project
|
||||||
*.kdev4
|
*.kdev4
|
||||||
|
*.user
|
||||||
TODO.txt
|
TODO.txt
|
||||||
diggler.cfg
|
diggler.cfg
|
||||||
.kdev_include_paths
|
.kdev_include_paths
|
||||||
|
_*
|
||||||
|
|
|
@ -10,3 +10,6 @@
|
||||||
[submodule "ext/StackTracePlus"]
|
[submodule "ext/StackTracePlus"]
|
||||||
path = ext/StackTracePlus
|
path = ext/StackTracePlus
|
||||||
url = https://github.com/ignacio/StackTracePlus.git
|
url = https://github.com/ignacio/StackTracePlus.git
|
||||||
|
[submodule "ext/Optional"]
|
||||||
|
path = ext/Optional
|
||||||
|
url = https://github.com/akrzemi1/Optional.git
|
||||||
|
|
|
@ -2,6 +2,22 @@ cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
project(Diggler C CXX)
|
project(Diggler C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||||
|
|
||||||
|
if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
|
||||||
|
# Forbid in-tree builds. With CMake, doing an in-tree build breaks out-of-tree ones
|
||||||
|
# when generating from .in files into the source directory, overriding the path of out-of-tree
|
||||||
|
# generated ones.
|
||||||
|
# TL;DR: in-tree build = BAD IDEA.
|
||||||
|
file(REMOVE_RECURSE CMakeFiles CMakeCache.txt)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"You are doing an in-tree build (i.e. the source and binary directories are the same).\
|
||||||
|
In-tree builds aren't supported and will *never* be.\
|
||||||
|
Make a \"build\" directory and run cmake here.
|
||||||
|
\
|
||||||
|
Don't forget to remove CMakeFiles and CMakeCache.txt.")
|
||||||
|
endif()
|
||||||
|
|
||||||
### Find path to build dir, relative if possible, to symlink resources directories
|
### Find path to build dir, relative if possible, to symlink resources directories
|
||||||
file(RELATIVE_PATH REL_BUILD_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
|
file(RELATIVE_PATH REL_BUILD_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
|
||||||
string(FIND "${REL_BUILD_PATH}" ".." RBP_2DOTPOS)
|
string(FIND "${REL_BUILD_PATH}" ".." RBP_2DOTPOS)
|
||||||
|
@ -43,13 +59,13 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
find_package(CXX14)
|
find_package(CXX14)
|
||||||
if (NOT CXX14_FOUND)
|
if (NOT CXX14_FOUND)
|
||||||
message(FATAL_ERROR "C++14 feature support unavailable.
|
message(FATAL_ERROR "C++14 feature support unavailable.\
|
||||||
Please use the latest version of your compiler.
|
Please use the latest version of your compiler.\
|
||||||
|
\
|
||||||
Here are the minimum requirements:
|
Here are the minimum requirements:\
|
||||||
- GCC version 5 (on Debian Jessie, enable Stretch/testing repos and get GCC from there)
|
- GCC version 5 (on Debian Jessie, enable Stretch/testing repos and get GCC from there)\
|
||||||
- clang version 3.4
|
- clang version 3.4\
|
||||||
- MSVC: wait until Microsoft goes bankrupt, and use another compiler in the meantime
|
- MSVC: wait until Microsoft goes bankrupt, and use another compiler in the meantime\
|
||||||
- ICC: ICC 17.0 Beta doesn't yet support all required C++14 features")
|
- ICC: ICC 17.0 Beta doesn't yet support all required C++14 features")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_CXX_FLAGS "${CXX14_FLAGS} ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CXX14_FLAGS} ${CMAKE_CXX_FLAGS}")
|
||||||
|
@ -71,6 +87,8 @@ endif()
|
||||||
|
|
||||||
pkg_search_module(EPOXY REQUIRED epoxy)
|
pkg_search_module(EPOXY REQUIRED epoxy)
|
||||||
pkg_search_module(GLFW REQUIRED glfw3)
|
pkg_search_module(GLFW REQUIRED glfw3)
|
||||||
|
pkg_search_module(SQLITE3 REQUIRED sqlite3)
|
||||||
|
pkg_search_module(LIBSODIUM REQUIRED libsodium)
|
||||||
include_directories(
|
include_directories(
|
||||||
${ETC_INCLUDE_DIRS}
|
${ETC_INCLUDE_DIRS}
|
||||||
${LUA_INCLUDE_DIR}
|
${LUA_INCLUDE_DIR}
|
||||||
|
@ -78,6 +96,8 @@ include_directories(
|
||||||
${ENET_INCLUDE_DIRS}
|
${ENET_INCLUDE_DIRS}
|
||||||
${EPOXY_INCLUDE_DIRS}
|
${EPOXY_INCLUDE_DIRS}
|
||||||
${GLFW_INCLUDE_DIRS}
|
${GLFW_INCLUDE_DIRS}
|
||||||
|
${LIBSODIUM_INCLUDE_DIRS}
|
||||||
|
${SQLITE3_INCLUDE_DIRS}
|
||||||
${OPENAL_INCLUDE_DIR}
|
${OPENAL_INCLUDE_DIR}
|
||||||
${MSGPACK_INCLUDE_DIR}
|
${MSGPACK_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
@ -94,6 +114,8 @@ target_link_libraries(diggler
|
||||||
${ENET_LIBRARIES}
|
${ENET_LIBRARIES}
|
||||||
${EPOXY_LIBRARIES}
|
${EPOXY_LIBRARIES}
|
||||||
${GLFW_LIBRARIES}
|
${GLFW_LIBRARIES}
|
||||||
|
${LIBSODIUM_LIBRARIES}
|
||||||
|
${SQLITE3_LIBRARIES}
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
pthread)
|
pthread)
|
||||||
|
|
||||||
|
|
|
@ -26,3 +26,5 @@ You should already have OpenGL available thanks to Mesa or proprietary drivers.
|
||||||
Arch: `pacman -S glm openal libepoxy glfw luajit`
|
Arch: `pacman -S glm openal libepoxy glfw luajit`
|
||||||
|
|
||||||
Debian (Jessie **w/ testing**, or up) & derivatives: `apt-get install libglm-dev libopenal-dev libepoxy-dev libglfw3-dev libx{i,randr}-dev libluajit-5.1-dev`
|
Debian (Jessie **w/ testing**, or up) & derivatives: `apt-get install libglm-dev libopenal-dev libepoxy-dev libglfw3-dev libx{i,randr}-dev libluajit-5.1-dev`
|
||||||
|
|
||||||
|
Fedora (tested on F24): `dnf install glm-devel openal-soft-devel libepoxy-devel glfw-devel luajit-devel`
|
||||||
|
|
|
@ -12,11 +12,11 @@ include(CheckCXXSourceCompiles)
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
set(CXX14_FLAG_CANDIDATES
|
set(CXX14_FLAG_CANDIDATES
|
||||||
#Gnu and Intel Linux
|
# GCC 6+ and everything that automatically accepts C++14
|
||||||
"-std=c++14"
|
|
||||||
#Microsoft Visual Studio, and everything that automatically accepts C++14
|
|
||||||
" "
|
" "
|
||||||
#Intel windows
|
# GCC < 6 and Intel Linux
|
||||||
|
"-std=c++14"
|
||||||
|
# Intel Windows
|
||||||
"/Qstd=c++14"
|
"/Qstd=c++14"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@ set(CXX14_TEST_SOURCE
|
||||||
"
|
"
|
||||||
[[deprecated]] void unused() {}
|
[[deprecated]] void unused() {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T pi = T(3.1415926535897932385);
|
||||||
|
|
||||||
constexpr int numberwang(int n) {
|
constexpr int numberwang(int n) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
return 0b1'1001'0101;
|
return 0b1'1001'0101;
|
||||||
|
@ -31,7 +34,7 @@ constexpr int numberwang(int n) {
|
||||||
return n - 1;
|
return n - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lambda = [](auto a, auto b) { return a * b; };
|
auto lambda = [v = 0](auto a, auto b) { return v + a * b; };
|
||||||
|
|
||||||
auto square(int n) {
|
auto square(int n) {
|
||||||
return lambda(n, n) * numberwang(2);
|
return lambda(n, n) * numberwang(2);
|
||||||
|
@ -39,6 +42,7 @@ auto square(int n) {
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int s = square(3);
|
int s = square(3);
|
||||||
|
double pie = pi<double>;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
")
|
")
|
||||||
|
@ -47,7 +51,7 @@ foreach(FLAG ${CXX14_FLAG_CANDIDATES})
|
||||||
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||||
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
|
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
|
||||||
unset(CXX14_FLAG_DETECTED CACHE)
|
unset(CXX14_FLAG_DETECTED CACHE)
|
||||||
message(STATUS "Try C++14 flag = [${FLAG}]")
|
message(STATUS "Trying C++14 flag '${FLAG}'")
|
||||||
check_cxx_source_compiles("${CXX14_TEST_SOURCE}" CXX14_FLAG_DETECTED)
|
check_cxx_source_compiles("${CXX14_TEST_SOURCE}" CXX14_FLAG_DETECTED)
|
||||||
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
|
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
|
||||||
if(CXX14_FLAG_DETECTED)
|
if(CXX14_FLAG_DETECTED)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 3922965396fc455c6b1770374b9b4111799588a9
|
|
@ -5,7 +5,7 @@ local grassBlock = {
|
||||||
variabilty = {'static'},
|
variabilty = {'static'},
|
||||||
textures = {
|
textures = {
|
||||||
grass = {
|
grass = {
|
||||||
path = 'tex/grass.png',
|
path = 'self:/tex/grass.png',
|
||||||
['repeat'] = {
|
['repeat'] = {
|
||||||
xdiv = 8,
|
xdiv = 8,
|
||||||
ydiv = 8
|
ydiv = 8
|
||||||
|
|
|
@ -16,6 +16,8 @@ set(SRCS
|
||||||
${CSD}/Chunk.cpp
|
${CSD}/Chunk.cpp
|
||||||
${CSD}/Clouds.cpp
|
${CSD}/Clouds.cpp
|
||||||
${CSD}/Config.cpp
|
${CSD}/Config.cpp
|
||||||
|
${CSD}/content/AssetManager.cpp
|
||||||
|
${CSD}/content/ModManager.cpp
|
||||||
${CSD}/content/Registry.cpp
|
${CSD}/content/Registry.cpp
|
||||||
${CSD}/EscMenu.cpp
|
${CSD}/EscMenu.cpp
|
||||||
${CSD}/Frustum.cpp
|
${CSD}/Frustum.cpp
|
||||||
|
@ -34,6 +36,8 @@ set(SRCS
|
||||||
${CSD}/network/msgtypes/BlockUpdate.cpp
|
${CSD}/network/msgtypes/BlockUpdate.cpp
|
||||||
${CSD}/network/msgtypes/Chat.cpp
|
${CSD}/network/msgtypes/Chat.cpp
|
||||||
${CSD}/network/msgtypes/ChunkTransfer.cpp
|
${CSD}/network/msgtypes/ChunkTransfer.cpp
|
||||||
|
${CSD}/network/msgtypes/ConnectionParam.cpp
|
||||||
|
${CSD}/network/msgtypes/PlayerUpdate.cpp
|
||||||
${CSD}/network/msgtypes/ServerInfo.cpp
|
${CSD}/network/msgtypes/ServerInfo.cpp
|
||||||
${CSD}/network/ClientMessageHandler.cpp
|
${CSD}/network/ClientMessageHandler.cpp
|
||||||
${CSD}/network/NetHelper.cpp
|
${CSD}/network/NetHelper.cpp
|
||||||
|
|
|
@ -92,7 +92,7 @@ Chunk::Chunk(Game *G, WorldRef W, int X, int Y, int Z) :
|
||||||
calcMemUsage();
|
calcMemUsage();
|
||||||
|
|
||||||
if (GlobalProperties::IsClient) {
|
if (GlobalProperties::IsClient) {
|
||||||
G->R->WR->registerChunk(this);
|
G->R->renderers.world->registerChunk(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ Chunk::~Chunk() {
|
||||||
std::free(imcData);
|
std::free(imcData);
|
||||||
#endif
|
#endif
|
||||||
if (GlobalProperties::IsClient) {
|
if (GlobalProperties::IsClient) {
|
||||||
G->R->WR->unregisterChunk(this);
|
G->R->renderers.world->unregisterChunk(this);
|
||||||
}
|
}
|
||||||
// getDebugStream() << W->id << '.' << wcx << ',' << wcy << ',' << wcz << " destruct" << std::endl;
|
// getDebugStream() << W->id << '.' << wcx << ',' << wcy << ',' << wcz << " destruct" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -442,7 +442,7 @@ void Chunk::updateClient() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
G->R->WR->updateChunk(this, vertex, v, idxOpaque, io, idxTransp, it);
|
G->R->renderers.world->updateChunk(this, vertex, v, idxOpaque, io, idxTransp, it);
|
||||||
dirty = false;
|
dirty = false;
|
||||||
mut.unlock();
|
mut.unlock();
|
||||||
}
|
}
|
||||||
|
|
69
src/Game.cpp
69
src/Game.cpp
|
@ -1,6 +1,8 @@
|
||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
|
|
||||||
#include "Audio.hpp"
|
#include "Audio.hpp"
|
||||||
|
#include "content/AssetManager.hpp"
|
||||||
|
#include "content/ModManager.hpp"
|
||||||
#include "content/Registry.hpp"
|
#include "content/Registry.hpp"
|
||||||
#include "GlobalProperties.hpp"
|
#include "GlobalProperties.hpp"
|
||||||
#include "KeyBinds.hpp"
|
#include "KeyBinds.hpp"
|
||||||
|
@ -20,42 +22,67 @@ Game::Game() :
|
||||||
|
|
||||||
void Game::init() {
|
void Game::init() {
|
||||||
CR = new Content::Registry;
|
CR = new Content::Registry;
|
||||||
|
AM = std::make_unique<Content::AssetManager>(this);
|
||||||
|
MM = std::make_unique<Content::ModManager>(this);
|
||||||
LS = new Scripting::Lua::State(this);
|
LS = new Scripting::Lua::State(this);
|
||||||
if (GlobalProperties::IsClient) {
|
if (GlobalProperties::IsClient) {
|
||||||
PM = new ProgramManager(*this);
|
initClient();
|
||||||
LP = new LocalPlayer(this);
|
|
||||||
RP = new RenderProperties; { // TODO move somewhere else?
|
|
||||||
RP->bloom = true;
|
|
||||||
RP->wavingLiquids = !true;
|
|
||||||
RP->fogStart = 16;
|
|
||||||
RP->fogEnd = 24;
|
|
||||||
}
|
|
||||||
R = new Render::gl::GLRenderer(this);
|
|
||||||
A = new Audio(*this);
|
|
||||||
KB = new KeyBinds;
|
|
||||||
PlayerPosUpdateFreq = 4;
|
|
||||||
}
|
}
|
||||||
if (GlobalProperties::IsServer) {
|
if (GlobalProperties::IsServer) {
|
||||||
|
initServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::~Game() {
|
void Game::initClient() {
|
||||||
delete CR;
|
PM = new ProgramManager(*this);
|
||||||
|
LP = new LocalPlayer(this);
|
||||||
|
RP = new RenderProperties; { // TODO move somewhere else?
|
||||||
|
RP->bloom = true;
|
||||||
|
RP->wavingLiquids = !true;
|
||||||
|
RP->fogStart = 16;
|
||||||
|
RP->fogEnd = 24;
|
||||||
|
}
|
||||||
|
R = new Render::gl::GLRenderer(this);
|
||||||
|
A = new Audio(*this);
|
||||||
|
KB = new KeyBinds;
|
||||||
|
PlayerPosUpdateFreq = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::initServer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::finalize() {
|
||||||
if (GlobalProperties::IsClient) {
|
if (GlobalProperties::IsClient) {
|
||||||
delete KB;
|
finalizeClient();
|
||||||
delete A;
|
|
||||||
delete R;
|
|
||||||
delete RP;
|
|
||||||
delete LP;
|
|
||||||
delete PM;
|
|
||||||
}
|
}
|
||||||
if (GlobalProperties::IsServer) {
|
if (GlobalProperties::IsServer) {
|
||||||
|
finalizeServer();
|
||||||
}
|
}
|
||||||
|
delete LS; LS = nullptr;
|
||||||
|
MM.reset();
|
||||||
|
AM.reset();
|
||||||
|
delete CR; CR = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::finalizeClient() {
|
||||||
|
delete KB; KB = nullptr;
|
||||||
|
delete A; A = nullptr;
|
||||||
|
delete R; R = nullptr;
|
||||||
|
delete RP; RP = nullptr;
|
||||||
|
delete LP; LP = nullptr;
|
||||||
|
delete PM; PM = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::finalizeServer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::~Game() {
|
||||||
|
finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::updateTime(double time) {
|
void Game::updateTime(double time) {
|
||||||
Time = time;
|
Time = time;
|
||||||
TimeMs = (int64)(time * 1000);
|
TimeMs = static_cast<int64>(time * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
26
src/Game.hpp
26
src/Game.hpp
|
@ -1,6 +1,8 @@
|
||||||
#ifndef GAME_HPP
|
#ifndef DIGGLER_GAME_HPP
|
||||||
#define GAME_HPP
|
#define DIGGLER_GAME_HPP
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "ui/FontManager.hpp"
|
#include "ui/FontManager.hpp"
|
||||||
#include "Universe.hpp"
|
#include "Universe.hpp"
|
||||||
#include "PlayerList.hpp"
|
#include "PlayerList.hpp"
|
||||||
|
@ -12,6 +14,8 @@ using std::shared_ptr;
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
|
|
||||||
namespace Content {
|
namespace Content {
|
||||||
|
class AssetManager;
|
||||||
|
class ModManager;
|
||||||
class Registry;
|
class Registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +39,11 @@ class GameWindow;
|
||||||
class KeyBinds;
|
class KeyBinds;
|
||||||
class Server;
|
class Server;
|
||||||
|
|
||||||
class Game {
|
class Game final {
|
||||||
|
private:
|
||||||
|
template<typename T>
|
||||||
|
using ptr = std::unique_ptr<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Shared
|
// Shared
|
||||||
double Time; uint64 TimeMs;
|
double Time; uint64 TimeMs;
|
||||||
|
@ -43,6 +51,8 @@ public:
|
||||||
Universe *U;
|
Universe *U;
|
||||||
PlayerList players;
|
PlayerList players;
|
||||||
Content::Registry *CR;
|
Content::Registry *CR;
|
||||||
|
ptr<Content::AssetManager> AM;
|
||||||
|
ptr<Content::ModManager> MM;
|
||||||
Scripting::Lua::State *LS;
|
Scripting::Lua::State *LS;
|
||||||
|
|
||||||
// Server
|
// Server
|
||||||
|
@ -61,16 +71,22 @@ public:
|
||||||
float fogStart, fogEnd;
|
float fogStart, fogEnd;
|
||||||
} *RP;
|
} *RP;
|
||||||
Audio *A;
|
Audio *A;
|
||||||
Net::Peer NS;
|
Net::Peer *NS;
|
||||||
KeyBinds *KB;
|
KeyBinds *KB;
|
||||||
int PlayerPosUpdateFreq;
|
int PlayerPosUpdateFreq;
|
||||||
|
|
||||||
Game();
|
Game();
|
||||||
void init();
|
void init();
|
||||||
|
void initClient();
|
||||||
|
void initServer();
|
||||||
|
void finalize();
|
||||||
|
void finalizeClient();
|
||||||
|
void finalizeServer();
|
||||||
|
|
||||||
void updateTime(double time);
|
void updateTime(double time);
|
||||||
~Game();
|
~Game();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif /* DIGGLER_GAME_HPP */
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "network/NetHelper.hpp"
|
#include "network/NetHelper.hpp"
|
||||||
#include "Particles.hpp"
|
#include "Particles.hpp"
|
||||||
|
|
||||||
|
#include "network/msgtypes/PlayerUpdate.hpp"
|
||||||
#include "network/msgtypes/BlockUpdate.hpp"
|
#include "network/msgtypes/BlockUpdate.hpp"
|
||||||
#include "content/Registry.hpp"
|
#include "content/Registry.hpp"
|
||||||
|
|
||||||
|
@ -95,6 +96,10 @@ GameState::GameState(GameWindow *GW, const std::string &servHost, int servPort)
|
||||||
m_highlightBox.att_coord = m_highlightBox.program->att("coord");
|
m_highlightBox.att_coord = m_highlightBox.program->att("coord");
|
||||||
m_highlightBox.uni_unicolor = m_highlightBox.program->uni("unicolor");
|
m_highlightBox.uni_unicolor = m_highlightBox.program->uni("unicolor");
|
||||||
m_highlightBox.uni_mvp = m_highlightBox.program->uni("mvp");
|
m_highlightBox.uni_mvp = m_highlightBox.program->uni("mvp");
|
||||||
|
{ Render::gl::VAO::Config cfg = m_highlightBox.vao.configure();
|
||||||
|
cfg.vertexAttrib(m_highlightBox.vbo, m_highlightBox.att_coord, 3, GL_FLOAT, 0);
|
||||||
|
cfg.commit();
|
||||||
|
}
|
||||||
|
|
||||||
m_3dFbo = new Render::gl::FBO(w, h, Texture::PixelFormat::RGB, true);
|
m_3dFbo = new Render::gl::FBO(w, h, Texture::PixelFormat::RGB, true);
|
||||||
m_3dRenderVBO = new Render::gl::VBO();
|
m_3dRenderVBO = new Render::gl::VBO();
|
||||||
|
@ -388,7 +393,7 @@ void GameState::updateViewport() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameState::sendMsg(Net::OutMessage &msg, Net::Tfer mode, Net::Channels chan) {
|
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::run() {
|
||||||
|
@ -402,13 +407,15 @@ bool GameState::connectLoop() {
|
||||||
std::string &serverHost = m_serverHost;
|
std::string &serverHost = m_serverHost;
|
||||||
int serverPort = m_serverPort;
|
int serverPort = m_serverPort;
|
||||||
bool finished = false, success = false; Game *G = this->G;
|
bool finished = false, success = false; Game *G = this->G;
|
||||||
m_networkThread = std::thread([G, &success, &finished, &serverHost, serverPort]() {
|
std::string failureStr;
|
||||||
|
m_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(serverHost, serverPort, 5000);
|
||||||
success = true;
|
success = true;
|
||||||
} catch (const Net::Exception &e) {
|
} catch (const Net::Exception &e) {
|
||||||
success = false;
|
success = false;
|
||||||
|
failureStr = e.what();
|
||||||
}
|
}
|
||||||
finished = true;
|
finished = true;
|
||||||
});
|
});
|
||||||
|
@ -447,9 +454,7 @@ bool GameState::connectLoop() {
|
||||||
if (GW->shouldClose())
|
if (GW->shouldClose())
|
||||||
return true;
|
return true;
|
||||||
if (!success) {
|
if (!success) {
|
||||||
std::ostringstream oss;
|
GW->showMessage("Could not connect to server", failureStr);
|
||||||
oss << serverHost << ':' << serverPort << " did not respond";
|
|
||||||
GW->showMessage("Could not connect to server", oss.str());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +474,7 @@ bool GameState::connectLoop() {
|
||||||
switch (m_msg.getType()) {
|
switch (m_msg.getType()) {
|
||||||
case Net::MessageType::PlayerJoin: {
|
case Net::MessageType::PlayerJoin: {
|
||||||
G->U = new Universe(G, true);
|
G->U = new Universe(G, true);
|
||||||
LP.id = m_msg.readU32();
|
LP.sessId = m_msg.readU32();
|
||||||
LP.W = G->U->createWorld(m_msg.readI16());
|
LP.W = G->U->createWorld(m_msg.readI16());
|
||||||
} break;
|
} break;
|
||||||
case Net::MessageType::PlayerQuit: {
|
case Net::MessageType::PlayerQuit: {
|
||||||
|
@ -488,7 +493,7 @@ bool GameState::connectLoop() {
|
||||||
G->LS->setGameLuaRuntimePath(gameLuaRuntimePath);
|
G->LS->setGameLuaRuntimePath(gameLuaRuntimePath);
|
||||||
G->LS->dofile(gameLuaRuntimePath + "/Diggler.lua");
|
G->LS->dofile(gameLuaRuntimePath + "/Diggler.lua");
|
||||||
|
|
||||||
getDebugStream() << "Joined as " << LP.name << '/' << LP.id << std::endl;
|
getDebugStream() << "Joined as " << LP.name << '/' << LP.sessId << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,11 +525,14 @@ void GameState::gameLoop() {
|
||||||
|
|
||||||
if (G->LP->isAlive) {
|
if (G->LP->isAlive) {
|
||||||
if (T > nextNetUpdate) {
|
if (T > nextNetUpdate) {
|
||||||
Net::OutMessage msg(Net::MessageType::PlayerUpdate, Net::PlayerUpdateType::Move);
|
Net::MsgTypes::PlayerUpdateMove pum;
|
||||||
msg.writeVec3(LP->position);
|
pum.position = LP->position;
|
||||||
msg.writeVec3(LP->velocity);
|
if (LP->velocity != glm::vec3()) {
|
||||||
msg.writeVec3(LP->accel);
|
pum.velocity = LP->velocity;
|
||||||
msg.writeFloat(LP->angle);
|
pum.accel = LP->accel;
|
||||||
|
}
|
||||||
|
pum.angle = LP->angle;
|
||||||
|
Net::OutMessage msg; pum.writeToMsg(msg);
|
||||||
sendMsg(msg, Net::Tfer::Unrel, Net::Channels::Movement);
|
sendMsg(msg, Net::Tfer::Unrel, Net::Channels::Movement);
|
||||||
nextNetUpdate = T+1.0/G->PlayerPosUpdateFreq;
|
nextNetUpdate = T+1.0/G->PlayerPosUpdateFreq;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +568,7 @@ void GameState::gameLoop() {
|
||||||
rp.world = WR.get();
|
rp.world = WR.get();
|
||||||
rp.transform = m_transform;
|
rp.transform = m_transform;
|
||||||
rp.frustum = G->LP->camera.frustum;
|
rp.frustum = G->LP->camera.frustum;
|
||||||
G->R->WR->render(rp);
|
G->R->renderers.world->render(rp);
|
||||||
for (Player &p : G->players) {
|
for (Player &p : G->players) {
|
||||||
p.update(deltaT);
|
p.update(deltaT);
|
||||||
if (G->LP->camera.frustum.sphereInFrustum(p.position, 2))
|
if (G->LP->camera.frustum.sphereInFrustum(p.position, 2))
|
||||||
|
@ -591,16 +599,14 @@ void GameState::gameLoop() {
|
||||||
// TODO: replace harcoded 32 viewdistance
|
// TODO: replace harcoded 32 viewdistance
|
||||||
if (G->LP->raytracePointed(32, &m_pointedBlock, &m_pointedFacing)) {
|
if (G->LP->raytracePointed(32, &m_pointedBlock, &m_pointedFacing)) {
|
||||||
m_highlightBox.program->bind();
|
m_highlightBox.program->bind();
|
||||||
glEnableVertexAttribArray(m_highlightBox.att_coord);
|
m_highlightBox.vao.bind();
|
||||||
m_highlightBox.vbo.bind();
|
|
||||||
glVertexAttribPointer(m_highlightBox.att_coord, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
|
||||||
|
|
||||||
glUniform4f(m_highlightBox.uni_unicolor, 1.f, 1.f, 1.f, .1f);
|
glUniform4f(m_highlightBox.uni_unicolor, 1.f, 1.f, 1.f, .1f);
|
||||||
glUniformMatrix4fv(m_highlightBox.uni_mvp, 1, GL_FALSE, glm::value_ptr(
|
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))));
|
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);
|
glDrawArrays(GL_TRIANGLES, 0, 6*2*3);
|
||||||
|
|
||||||
glDisableVertexAttribArray(m_highlightBox.att_coord);
|
m_highlightBox.vao.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
@ -622,7 +628,7 @@ void GameState::gameLoop() {
|
||||||
glEnableVertexAttribArray(bloom.extractor.att_texcoord);
|
glEnableVertexAttribArray(bloom.extractor.att_texcoord);
|
||||||
m_3dRenderVBO->bind();
|
m_3dRenderVBO->bind();
|
||||||
glUniformMatrix4fv(bloom.extractor.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
glUniformMatrix4fv(bloom.extractor.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
||||||
glVertexAttribPointer(bloom.extractor.att_coord, 2, GL_INT, GL_FALSE, sizeof(Coord2DTex), 0);
|
glVertexAttribPointer(bloom.extractor.att_coord, 2, GL_SHORT, GL_FALSE, sizeof(Coord2DTex), 0);
|
||||||
glVertexAttribPointer(bloom.extractor.att_texcoord, 2, GL_BYTE, GL_FALSE, sizeof(Coord2DTex), (GLvoid*)offsetof(Coord2DTex, u));
|
glVertexAttribPointer(bloom.extractor.att_texcoord, 2, GL_BYTE, GL_FALSE, sizeof(Coord2DTex), (GLvoid*)offsetof(Coord2DTex, u));
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
glDisableVertexAttribArray(bloom.extractor.att_texcoord);
|
glDisableVertexAttribArray(bloom.extractor.att_texcoord);
|
||||||
|
@ -639,7 +645,7 @@ void GameState::gameLoop() {
|
||||||
m_3dRenderVBO->bind();
|
m_3dRenderVBO->bind();
|
||||||
glUniformMatrix4fv(bloom.renderer.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
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));
|
glUniform2f(bloom.renderer.uni_pixshift, 1.f/(GW->getW()/bloom.scale), 1.f/(GW->getH()/bloom.scale));
|
||||||
glVertexAttribPointer(bloom.renderer.att_coord, 2, GL_INT, GL_FALSE, sizeof(Coord2DTex), 0);
|
glVertexAttribPointer(bloom.renderer.att_coord, 2, GL_SHORT, GL_FALSE, sizeof(Coord2DTex), 0);
|
||||||
glVertexAttribPointer(bloom.renderer.att_texcoord, 2, GL_BYTE, GL_FALSE, sizeof(Coord2DTex), (GLvoid*)offsetof(Coord2DTex, u));
|
glVertexAttribPointer(bloom.renderer.att_texcoord, 2, GL_BYTE, GL_FALSE, sizeof(Coord2DTex), (GLvoid*)offsetof(Coord2DTex, u));
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
glDisableVertexAttribArray(bloom.renderer.att_texcoord);
|
glDisableVertexAttribArray(bloom.renderer.att_texcoord);
|
||||||
|
@ -656,7 +662,7 @@ void GameState::gameLoop() {
|
||||||
glEnableVertexAttribArray(bloom.renderer.att_texcoord);
|
glEnableVertexAttribArray(bloom.renderer.att_texcoord);
|
||||||
m_3dRenderVBO->bind();
|
m_3dRenderVBO->bind();
|
||||||
glUniformMatrix4fv(bloom.renderer.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
glUniformMatrix4fv(bloom.renderer.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
||||||
glVertexAttribPointer(bloom.renderer.att_coord, 2, GL_INT, GL_FALSE, sizeof(Coord2DTex), 0);
|
glVertexAttribPointer(bloom.renderer.att_coord, 2, GL_SHORT, GL_FALSE, sizeof(Coord2DTex), 0);
|
||||||
glVertexAttribPointer(bloom.renderer.att_texcoord, 2, GL_BYTE, GL_FALSE, sizeof(Coord2DTex), (GLvoid*)offsetof(Coord2DTex, u));
|
glVertexAttribPointer(bloom.renderer.att_texcoord, 2, GL_BYTE, GL_FALSE, sizeof(Coord2DTex), (GLvoid*)offsetof(Coord2DTex, u));
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
glDisableVertexAttribArray(bloom.renderer.att_texcoord);
|
glDisableVertexAttribArray(bloom.renderer.att_texcoord);
|
||||||
|
@ -675,8 +681,9 @@ void GameState::gameLoop() {
|
||||||
}
|
}
|
||||||
if (!G->LP->deathSent) {
|
if (!G->LP->deathSent) {
|
||||||
G->LP->deathSent = true;
|
G->LP->deathSent = true;
|
||||||
Net::OutMessage out(Net::MessageType::PlayerUpdate, Net::PlayerUpdateType::Die);
|
Net::MsgTypes::PlayerUpdateDie pud;
|
||||||
out.writeU8((uint8)G->LP->deathReason);
|
pud.reason = G->LP->deathReason;
|
||||||
|
Net::OutMessage out; pud.writeToMsg(out);
|
||||||
sendMsg(out, Net::Tfer::Rel, Net::Channels::Life);
|
sendMsg(out, Net::Tfer::Rel, Net::Channels::Life);
|
||||||
}
|
}
|
||||||
renderDeathScreen();
|
renderDeathScreen();
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "GameWindow.hpp"
|
#include "GameWindow.hpp"
|
||||||
#include "render/gl/FBO.hpp"
|
#include "render/gl/FBO.hpp"
|
||||||
#include "render/gl/VBO.hpp"
|
#include "render/gl/VBO.hpp"
|
||||||
|
#include "render/gl/VAO.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "network/Network.hpp"
|
#include "network/Network.hpp"
|
||||||
#include "network/ClientMessageHandler.hpp"
|
#include "network/ClientMessageHandler.hpp"
|
||||||
|
@ -69,7 +70,7 @@ private:
|
||||||
} bloom;
|
} bloom;
|
||||||
|
|
||||||
Render::gl::VBO *m_3dRenderVBO;
|
Render::gl::VBO *m_3dRenderVBO;
|
||||||
struct Coord2DTex { int x, y; uint8 u, v; };
|
struct Coord2DTex { int16 x, y; uint8 u, v; };
|
||||||
Clouds *m_clouds;
|
Clouds *m_clouds;
|
||||||
Skybox *m_sky;
|
Skybox *m_sky;
|
||||||
|
|
||||||
|
@ -80,6 +81,7 @@ private:
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
Render::gl::VBO vbo;
|
Render::gl::VBO vbo;
|
||||||
|
Render::gl::VAO vao;
|
||||||
const Program *program;
|
const Program *program;
|
||||||
GLuint att_coord, uni_unicolor, uni_mvp;
|
GLuint att_coord, uni_unicolor, uni_mvp;
|
||||||
} m_highlightBox;
|
} m_highlightBox;
|
||||||
|
|
|
@ -116,7 +116,7 @@ GameWindow::GameWindow(Game *G) : G(G) {
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||||
glfwWindowHint(GLFW_SAMPLES, 0); // Gimme aliasing everywhere
|
glfwWindowHint(GLFW_SAMPLES, 0); // Gimme aliasing everywhere
|
||||||
//glfwWindowHint(GLFW_STENCIL_BITS, 8);
|
//glfwWindowHint(GLFW_STENCIL_BITS, 8);
|
||||||
|
|
||||||
|
@ -190,6 +190,8 @@ GameWindow::GameWindow(Game *G) : G(G) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GameWindow::~GameWindow() {
|
GameWindow::~GameWindow() {
|
||||||
|
m_currentState.reset();
|
||||||
|
m_nextState.reset();
|
||||||
delete UIM;
|
delete UIM;
|
||||||
|
|
||||||
glfwDestroyWindow(m_window);
|
glfwDestroyWindow(m_window);
|
||||||
|
@ -243,13 +245,13 @@ void GameWindow::cbResize(int w, int h) {
|
||||||
m_currentState->onResize(w, h);
|
m_currentState->onResize(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameWindow::setNextState(const shared_ptr<State> next) {
|
void GameWindow::setNextState(std::unique_ptr<State> &&next) {
|
||||||
m_nextState = next;
|
m_nextState = std::move(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameWindow::run() {
|
void GameWindow::run() {
|
||||||
while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
|
while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
|
||||||
m_currentState = m_nextState;
|
m_currentState = std::move(m_nextState);
|
||||||
m_nextState = nullptr;
|
m_nextState = nullptr;
|
||||||
UIM->clear();
|
UIM->clear();
|
||||||
m_currentState->run();
|
m_currentState->run();
|
||||||
|
@ -257,7 +259,7 @@ void GameWindow::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameWindow::showMessage(const std::string &msg, const std::string &submsg) {
|
void GameWindow::showMessage(const std::string &msg, const std::string &submsg) {
|
||||||
setNextState(std::make_shared<MessageState>(this, msg, submsg));
|
setNextState(std::move(std::make_unique<MessageState>(this, msg, submsg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#include "Platform.hpp"
|
#include "Platform.hpp"
|
||||||
#include "ui/Manager.hpp"
|
#include "ui/Manager.hpp"
|
||||||
|
|
||||||
using std::shared_ptr;
|
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
|
|
||||||
class Game;
|
class Game;
|
||||||
|
@ -22,7 +20,7 @@ private:
|
||||||
GLFWwindow *m_window;
|
GLFWwindow *m_window;
|
||||||
int m_w, m_h;
|
int m_w, m_h;
|
||||||
|
|
||||||
shared_ptr<State> m_currentState, m_nextState;
|
std::unique_ptr<State> m_currentState, m_nextState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UI::Manager *UIM;
|
UI::Manager *UIM;
|
||||||
|
@ -52,7 +50,7 @@ public:
|
||||||
|
|
||||||
void updateViewport();
|
void updateViewport();
|
||||||
|
|
||||||
void setNextState(const shared_ptr<State> next);
|
void setNextState(std::unique_ptr<State> &&next);
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
void showMessage(const std::string &msg, const std::string &submsg = "");
|
void showMessage(const std::string &msg, const std::string &submsg = "");
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Audio.hpp"
|
#include "Audio.hpp"
|
||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
#include "network/NetHelper.hpp"
|
#include "network/NetHelper.hpp"
|
||||||
|
#include "render/gl/VAO.hpp"
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
|
|
||||||
|
@ -174,14 +175,11 @@ void LocalPlayer::update(float delta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::render(const glm::mat4 &transform) const {
|
void LocalPlayer::render(const glm::mat4 &transform) const {
|
||||||
const Program *P = G->PM->getProgram(PM_3D | PM_COLORED);
|
|
||||||
P->bind();
|
|
||||||
glEnableVertexAttribArray(P->att("coord"));
|
|
||||||
glEnableVertexAttribArray(P->att("color"));
|
|
||||||
glUniformMatrix4fv(P->uni("mvp"), 1, GL_FALSE, glm::value_ptr(transform));
|
|
||||||
static Render::gl::VBO vbo;
|
static Render::gl::VBO vbo;
|
||||||
const glm::ivec3 &min = aabbmin, &max = aabbmax;
|
static Render::gl::VAO vao;
|
||||||
struct Coord { int x, y, z; uint8 r, g, b; } pts[] = {
|
static bool vaoConfigured = false;
|
||||||
|
const glm::f32vec3 min = aabbmin, max = aabbmax;
|
||||||
|
struct Coord { float x, y, z; uint8 r, g, b; } pts[] = {
|
||||||
{ min.x, min.y, min.z, 0, 1, 0 },
|
{ min.x, min.y, min.z, 0, 1, 0 },
|
||||||
{ max.x, min.y, min.z, 0, 1, 0 },
|
{ max.x, min.y, min.z, 0, 1, 0 },
|
||||||
{ min.x, min.y, min.z, 0, 1, 0 },
|
{ min.x, min.y, min.z, 0, 1, 0 },
|
||||||
|
@ -209,12 +207,19 @@ void LocalPlayer::render(const glm::mat4 &transform) const {
|
||||||
{ min.x, min.y, max.z, 0, 1, 0 },
|
{ min.x, min.y, max.z, 0, 1, 0 },
|
||||||
};
|
};
|
||||||
vbo.setDataKeepSize(pts, sizeof(pts)/sizeof(Coord), GL_STREAM_DRAW);
|
vbo.setDataKeepSize(pts, sizeof(pts)/sizeof(Coord), GL_STREAM_DRAW);
|
||||||
vbo.bind();
|
const Program &P = *G->PM->getProgram(PM_3D | PM_COLORED);
|
||||||
glVertexAttribPointer(P->att("coord"), 3, GL_INT, GL_FALSE, sizeof(Coord), 0);
|
if (!vaoConfigured) {
|
||||||
glVertexAttribPointer(P->att("color"), 3, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Coord), (GLvoid*)(offsetof(Coord, r)));
|
vaoConfigured = true;
|
||||||
|
Render::gl::VAO::Config cfg = vao.configure();
|
||||||
|
cfg.vertexAttrib(vbo, P.att("coord"), 3, GL_FLOAT, sizeof(Coord), 0);
|
||||||
|
cfg.vertexAttrib(vbo, P.att("color"), 3, GL_UNSIGNED_BYTE, sizeof(Coord), offsetof(Coord, r));
|
||||||
|
cfg.commit();
|
||||||
|
}
|
||||||
|
P.bind();
|
||||||
|
glUniformMatrix4fv(P.uni("mvp"), 1, GL_FALSE, glm::value_ptr(transform));
|
||||||
|
vao.bind();
|
||||||
glDrawArrays(GL_LINES, 0, sizeof(pts)/sizeof(Coord));
|
glDrawArrays(GL_LINES, 0, sizeof(pts)/sizeof(Coord));
|
||||||
glDisableVertexAttribArray(P->att("color"));
|
vao.unbind();
|
||||||
glDisableVertexAttribArray(P->att("coord"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::forceCameraUpdate() {
|
void LocalPlayer::forceCameraUpdate() {
|
||||||
|
|
|
@ -8,11 +8,11 @@ namespace Diggler {
|
||||||
|
|
||||||
ParticleEmitter::ParticleEmitter(Game *G) :
|
ParticleEmitter::ParticleEmitter(Game *G) :
|
||||||
G(G) {
|
G(G) {
|
||||||
G->R->PR->registerEmitter(this);
|
G->R->renderers.particles->registerEmitter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleEmitter::~ParticleEmitter() {
|
ParticleEmitter::~ParticleEmitter() {
|
||||||
G->R->PR->unregisterEmitter(this);
|
G->R->renderers.particles->unregisterEmitter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEmitter::setMaxCount(uint count) {
|
void ParticleEmitter::setMaxCount(uint count) {
|
||||||
|
@ -35,7 +35,7 @@ void ParticleEmitter::emit(Particle &p) {
|
||||||
void ParticleEmitter::update(double delta) {
|
void ParticleEmitter::update(double delta) {
|
||||||
ParticleRenderData *data = new ParticleRenderData[maxCount];
|
ParticleRenderData *data = new ParticleRenderData[maxCount];
|
||||||
float deltaF = delta;
|
float deltaF = delta;
|
||||||
for (int i=0; i < maxCount; ++i) {
|
for (uint i = 0; i < maxCount; ++i) {
|
||||||
Particle &p = particles[i];
|
Particle &p = particles[i];
|
||||||
p.vel += p.accel * deltaF;
|
p.vel += p.accel * deltaF;
|
||||||
p.pos += p.vel * deltaF;
|
p.pos += p.vel * deltaF;
|
||||||
|
@ -44,7 +44,7 @@ void ParticleEmitter::update(double delta) {
|
||||||
emit(p);
|
emit(p);
|
||||||
data[i] = { p.pos.x, p.pos.y, p.pos.z, p.color.r, p.color.g, p.color.b, p.color.a, p.size };
|
data[i] = { p.pos.x, p.pos.y, p.pos.z, p.color.r, p.color.g, p.color.b, p.color.a, p.size };
|
||||||
}
|
}
|
||||||
G->R->PR->updateParticleData(this, data, maxCount);
|
G->R->renderers.particles->updateParticleData(this, data, maxCount);
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,14 @@
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
|
|
||||||
Player::Renderer Player::R = {0};
|
Player::Renderer Player::R = {};
|
||||||
|
|
||||||
Player::Player(Game *G) :
|
Player::Player(Game *G) :
|
||||||
G(G), position(0), velocity(0), accel(0), angle(0), toolUseTime(0),
|
G(G),
|
||||||
isAlive(true) {
|
angle(0),
|
||||||
|
toolUseTime(0),
|
||||||
|
isAlive(true),
|
||||||
|
peer(nullptr) {
|
||||||
if (GlobalProperties::IsClient) {
|
if (GlobalProperties::IsClient) {
|
||||||
if (R.prog == nullptr) {
|
if (R.prog == nullptr) {
|
||||||
R.prog = G->PM->getProgram(PM_3D | PM_FOG);
|
R.prog = G->PM->getProgram(PM_3D | PM_FOG);
|
||||||
|
@ -31,34 +34,12 @@ Player::Player(Game *G) :
|
||||||
-sz, .0f, 0.0f,
|
-sz, .0f, 0.0f,
|
||||||
sz, szH, 0.0f,
|
sz, szH, 0.0f,
|
||||||
};
|
};
|
||||||
R.vbo = new Render::gl::VBO;
|
R.vbo = std::make_unique<Render::gl::VBO>();
|
||||||
R.vbo->setData(coords, 6*3);
|
R.vbo->setData(coords, 6*3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using std::swap;
|
|
||||||
Player::Player(Player &&p) {
|
|
||||||
*this = std::move(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
Player& Player::operator=(Player &&p) {
|
|
||||||
swap(direction, p.direction);
|
|
||||||
swap(G, p.G);
|
|
||||||
swap(position, p.position);
|
|
||||||
swap(velocity, p.velocity);
|
|
||||||
swap(accel, p.accel);
|
|
||||||
swap(name, p.name);
|
|
||||||
swap(id, p.id);
|
|
||||||
swap(P, p.P);
|
|
||||||
swap(isAlive, p.isAlive);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player::~Player() {
|
|
||||||
delete R.vbo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::setPosVel(const glm::vec3 &pos, const glm::vec3 &vel, const glm::vec3 &acc) {
|
void Player::setPosVel(const glm::vec3 &pos, const glm::vec3 &vel, const glm::vec3 &acc) {
|
||||||
lastPosition = m_predictPos;
|
lastPosition = m_predictPos;
|
||||||
position = m_predictPos = pos;
|
position = m_predictPos = pos;
|
||||||
|
|
|
@ -2,11 +2,14 @@
|
||||||
#define PLAYER_HPP
|
#define PLAYER_HPP
|
||||||
#include "Platform.hpp"
|
#include "Platform.hpp"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <epoxy/gl.h>
|
#include <epoxy/gl.h>
|
||||||
|
|
||||||
|
#include "platform/PreprocUtils.hpp"
|
||||||
#include "network/Network.hpp"
|
#include "network/Network.hpp"
|
||||||
#include "World.hpp"
|
#include "World.hpp"
|
||||||
|
|
||||||
|
@ -14,6 +17,7 @@ namespace Diggler {
|
||||||
|
|
||||||
class Program;
|
class Program;
|
||||||
namespace Render {
|
namespace Render {
|
||||||
|
class PlayerRenderer;
|
||||||
namespace gl {
|
namespace gl {
|
||||||
class VBO;
|
class VBO;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +29,9 @@ using PlayerGameID = uint32;
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
protected:
|
protected:
|
||||||
|
friend class Render::PlayerRenderer;
|
||||||
|
uintptr_t rendererData;
|
||||||
|
|
||||||
static struct Renderer {
|
static struct Renderer {
|
||||||
const Program *prog;
|
const Program *prog;
|
||||||
GLint att_coord,
|
GLint att_coord,
|
||||||
|
@ -32,13 +39,10 @@ protected:
|
||||||
uni_unicolor,
|
uni_unicolor,
|
||||||
uni_fogStart,
|
uni_fogStart,
|
||||||
uni_fogEnd;
|
uni_fogEnd;
|
||||||
Render::gl::VBO *vbo;
|
std::unique_ptr<Render::gl::VBO> vbo;
|
||||||
} R;
|
} R;
|
||||||
double m_lastPosTime;
|
double m_lastPosTime;
|
||||||
glm::vec3 m_predictPos;
|
glm::vec3 m_predictPos;
|
||||||
|
|
||||||
Player(const Player&) = delete;
|
|
||||||
Player& operator=(const Player&) = delete;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Direction : uint8 {
|
enum class Direction : uint8 {
|
||||||
|
@ -60,15 +64,15 @@ public:
|
||||||
glm::vec3 position, lastPosition, velocity, accel;
|
glm::vec3 position, lastPosition, velocity, accel;
|
||||||
float angle; double toolUseTime;
|
float angle; double toolUseTime;
|
||||||
std::string name;
|
std::string name;
|
||||||
uint32 id;
|
using SessionID = uint32;
|
||||||
|
SessionID sessId;
|
||||||
bool isAlive;
|
bool isAlive;
|
||||||
Net::Peer P;
|
Net::Peer *peer;
|
||||||
std::list<ChunkRef> pendingChunks;
|
std::list<ChunkRef> pendingChunks;
|
||||||
|
|
||||||
Player(Game *G = nullptr);
|
Player(Game *G = nullptr);
|
||||||
Player(Player&&);
|
nocopy(Player);
|
||||||
Player& operator=(Player&&);
|
defaultmove(Player);
|
||||||
~Player();
|
|
||||||
|
|
||||||
void setPosVel(const glm::vec3 &pos, const glm::vec3 &vel, const glm::vec3 &acc = glm::vec3());
|
void setPosVel(const glm::vec3 &pos, const glm::vec3 &vel, const glm::vec3 &acc = glm::vec3());
|
||||||
void update(const float &delta);
|
void update(const float &delta);
|
||||||
|
|
|
@ -31,12 +31,12 @@ void PlayerList::remove(const Player &plr) {
|
||||||
throw std::out_of_range("Can't remove player: not in list");
|
throw std::out_of_range("Can't remove player: not in list");
|
||||||
}
|
}
|
||||||
|
|
||||||
Player* PlayerList::getByGameId(uint32 id) {
|
Player* PlayerList::getBySessId(Player::SessionID sid) {
|
||||||
if (G->LP && id == G->LP->id)
|
if (G->LP && sid == G->LP->sessId)
|
||||||
return G->LP;
|
return G->LP;
|
||||||
for (auto it = begin();
|
for (auto it = begin();
|
||||||
it != end(); ++it) {
|
it != end(); ++it) {
|
||||||
if (it->id == id) {
|
if (it->sessId == sid) {
|
||||||
return &*it;
|
return &*it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ Player* PlayerList::getByName(const std::string &name) {
|
||||||
Player* PlayerList::getByPeer(const Net::Peer &peer) {
|
Player* PlayerList::getByPeer(const Net::Peer &peer) {
|
||||||
for (auto it = begin();
|
for (auto it = begin();
|
||||||
it != end(); ++it) {
|
it != end(); ++it) {
|
||||||
if (it->P == peer) {
|
if (*it->peer == peer) {
|
||||||
return &*it;
|
return &*it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
* @brief Gets a Player using its game session ID
|
* @brief Gets a Player using its game session ID
|
||||||
* @return Pointer to Player, may be nullptr if not found
|
* @return Pointer to Player, may be nullptr if not found
|
||||||
*/
|
*/
|
||||||
Player* getByGameId(uint32);
|
Player* getBySessId(Player::SessionID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a Player using its name
|
* @brief Gets a Player using its name
|
||||||
|
|
106
src/Server.cpp
106
src/Server.cpp
|
@ -11,6 +11,7 @@
|
||||||
#include "network/msgtypes/BlockUpdate.hpp"
|
#include "network/msgtypes/BlockUpdate.hpp"
|
||||||
#include "network/msgtypes/Chat.hpp"
|
#include "network/msgtypes/Chat.hpp"
|
||||||
#include "network/msgtypes/ChunkTransfer.hpp"
|
#include "network/msgtypes/ChunkTransfer.hpp"
|
||||||
|
#include "network/msgtypes/PlayerUpdate.hpp"
|
||||||
#include "network/Network.hpp"
|
#include "network/Network.hpp"
|
||||||
#include "network/NetHelper.hpp"
|
#include "network/NetHelper.hpp"
|
||||||
#include "scripting/lua/State.hpp"
|
#include "scripting/lua/State.hpp"
|
||||||
|
@ -27,8 +28,8 @@ namespace Diggler {
|
||||||
inline Player* Server::getPlayerByPeer(const Peer &peer) {
|
inline Player* Server::getPlayerByPeer(const Peer &peer) {
|
||||||
return G.players.getByPeer(peer);
|
return G.players.getByPeer(peer);
|
||||||
}
|
}
|
||||||
inline Player* Server::getPlayerById(uint32 id) {
|
inline Player *Server::getPlayerBySessId(uint32 id) {
|
||||||
return G.players.getByGameId(id);
|
return G.players.getBySessId(id);
|
||||||
}
|
}
|
||||||
inline Player* Server::getPlayerByName(const std::string &name) {
|
inline Player* Server::getPlayerByName(const std::string &name) {
|
||||||
return G.players.getByName(name);
|
return G.players.getByName(name);
|
||||||
|
@ -36,7 +37,7 @@ inline Player* Server::getPlayerByName(const std::string &name) {
|
||||||
|
|
||||||
void Server::handlePlayerJoin(InMessage &msg, Peer &peer) {
|
void Server::handlePlayerJoin(InMessage &msg, Peer &peer) {
|
||||||
std::string name = msg.readString();
|
std::string name = msg.readString();
|
||||||
getOutputStream() << peer.getHost() << " is joining as " << name << std::endl;
|
getOutputStream() << peer.peerHost() << " is joining as " << name << std::endl;
|
||||||
|
|
||||||
// TODO: ban list
|
// TODO: ban list
|
||||||
Player *possible = getPlayerByName(name);
|
Player *possible = getPlayerByName(name);
|
||||||
|
@ -45,42 +46,42 @@ void Server::handlePlayerJoin(InMessage &msg, Peer &peer) {
|
||||||
OutMessage kick(MessageType::PlayerQuit, QuitReason::UsernameAlreadyUsed);
|
OutMessage kick(MessageType::PlayerQuit, QuitReason::UsernameAlreadyUsed);
|
||||||
kick.writeString("You are \faalready\f0 playing on this server");
|
kick.writeString("You are \faalready\f0 playing on this server");
|
||||||
H.send(peer, kick, Tfer::Rel);
|
H.send(peer, kick, Tfer::Rel);
|
||||||
getOutputStream() << peer.getHost() << " tried to connect as " << name << ": name is taken" << endl;
|
getOutputStream() << peer.peerHost() << " tried to connect as " << name << ": name is taken" << endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Player &plr = G.players.add();
|
Player &plr = G.players.add();
|
||||||
plr.name = name;
|
plr.name = name;
|
||||||
plr.id = FastRand();
|
plr.sessId = FastRand();
|
||||||
plr.P = peer;
|
plr.peer = &peer;
|
||||||
plr.W = G.U->getLoadWorld(0);
|
plr.W = G.U->getLoadWorld(0);
|
||||||
|
|
||||||
// Confirm successful join
|
// Confirm successful join
|
||||||
OutMessage join(MessageType::PlayerJoin);
|
OutMessage join(MessageType::PlayerJoin);
|
||||||
join.writeU32(plr.id);
|
join.writeU32(plr.sessId);
|
||||||
join.writeI16(plr.W->id);
|
join.writeI16(plr.W->id);
|
||||||
H.send(peer, join, Tfer::Rel);
|
H.send(peer, join, Tfer::Rel);
|
||||||
|
|
||||||
// Send the player list
|
// Send the player list
|
||||||
for (Player &p : G.players) {
|
for (Player &p : G.players) {
|
||||||
if (p.id == plr.id)
|
if (p.sessId == plr.sessId)
|
||||||
continue; // ok, he knows he's here
|
continue; // ok, he knows he's here
|
||||||
OutMessage playerMsg(MessageType::PlayerJoin);
|
OutMessage playerMsg(MessageType::PlayerJoin);
|
||||||
playerMsg.writeU32(p.id);
|
playerMsg.writeU32(p.sessId);
|
||||||
playerMsg.writeString(p.name);
|
playerMsg.writeString(p.name);
|
||||||
H.send(peer, playerMsg, Tfer::Rel);
|
H.send(peer, playerMsg, Tfer::Rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast player's join
|
// Broadcast player's join
|
||||||
OutMessage broadcast(MessageType::PlayerJoin);
|
OutMessage broadcast(MessageType::PlayerJoin);
|
||||||
broadcast.writeU32(plr.id);
|
broadcast.writeU32(plr.sessId);
|
||||||
broadcast.writeString(plr.name);
|
broadcast.writeString(plr.name);
|
||||||
for (Player &p : G.players) {
|
for (Player &p : G.players) {
|
||||||
if (p.id == plr.id)
|
if (p.sessId == plr.sessId)
|
||||||
continue; // don't send broadcast to the player
|
continue; // don't send broadcast to the player
|
||||||
H.send(p.P, broadcast, Tfer::Rel);
|
H.send(*p.peer, broadcast, Tfer::Rel);
|
||||||
}
|
}
|
||||||
getOutputStream() << plr.name << " joined from " << peer.getHost() << endl;
|
getOutputStream() << plr.name << " joined from " << peer.peerHost() << endl;
|
||||||
for (int x = -2; x < 2; ++x)
|
for (int x = -2; x < 2; ++x)
|
||||||
for (int y = -2; y < 2; ++y)
|
for (int y = -2; y < 2; ++y)
|
||||||
for (int z = -2; z < 2; ++z)
|
for (int z = -2; z < 2; ++z)
|
||||||
|
@ -93,16 +94,16 @@ void Server::handlePlayerQuit(Peer &peer, QuitReason reason) {
|
||||||
Player &plr = *plrPtr;
|
Player &plr = *plrPtr;
|
||||||
// Broadcast disconnection
|
// Broadcast disconnection
|
||||||
OutMessage broadcast(MessageType::PlayerQuit, reason);
|
OutMessage broadcast(MessageType::PlayerQuit, reason);
|
||||||
broadcast.writeU32(plr.id);
|
broadcast.writeU32(plr.sessId);
|
||||||
for (Player &p : G.players) {
|
for (Player &p : G.players) {
|
||||||
if (p.id == plr.id)
|
if (p.sessId == plr.sessId)
|
||||||
continue; // dont send broadcast to the player
|
continue; // dont send broadcast to the player
|
||||||
H.send(p.P, broadcast, Tfer::Rel);
|
H.send(*p.peer, broadcast, Tfer::Rel);
|
||||||
}
|
}
|
||||||
getOutputStream() << plr.name << " disconnected" << endl;
|
getOutputStream() << plr.name << " disconnected" << endl;
|
||||||
G.players.remove(plr);
|
G.players.remove(plr);
|
||||||
} else {
|
} else {
|
||||||
getOutputStream() << peer.getHost() << " disconnected" << endl;
|
getOutputStream() << peer.peerHost() << " disconnected" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +120,7 @@ void Server::handleChat(InMessage &msg, Player *plr) {
|
||||||
cs.readFromMsg(msg);
|
cs.readFromMsg(msg);
|
||||||
|
|
||||||
ChatPlayerTalk cpt;
|
ChatPlayerTalk cpt;
|
||||||
cpt.player.id = plr->id;
|
cpt.player.id = plr->sessId;
|
||||||
cpt.msg = cs.msg;
|
cpt.msg = cs.msg;
|
||||||
OutMessage omsg;
|
OutMessage omsg;
|
||||||
cpt.writeToMsg(omsg);
|
cpt.writeToMsg(omsg);
|
||||||
|
@ -137,28 +138,23 @@ void Server::handleCommand(Player *plr, const std::string &command, const std::v
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handlePlayerUpdate(InMessage &msg, Player &plr) {
|
void Server::handlePlayerUpdate(InMessage &msg, Player &plr) {
|
||||||
switch (msg.getSubtype()) {
|
using namespace Net::MsgTypes;
|
||||||
case PlayerUpdateType::Move: {
|
using S = PlayerUpdateSubtype;
|
||||||
|
switch (static_cast<S>(msg.getSubtype())) {
|
||||||
|
case S::Move: {
|
||||||
|
PlayerUpdateMove pum;
|
||||||
|
pum.readFromMsg(msg);
|
||||||
|
pum.plrSessId = plr.sessId;
|
||||||
// Broadcast movement
|
// Broadcast movement
|
||||||
OutMessage bcast(MessageType::PlayerUpdate, PlayerUpdateType::Move);
|
OutMessage bcast; pum.writeToMsg(bcast);
|
||||||
bcast.writeU32(plr.id);
|
|
||||||
glm::vec3 pos = msg.readVec3(),
|
|
||||||
vel = msg.readVec3(),
|
|
||||||
acc = msg.readVec3();
|
|
||||||
plr.setPosVel(pos, vel, acc);
|
|
||||||
plr.angle = msg.readFloat();
|
|
||||||
bcast.writeVec3(pos);
|
|
||||||
bcast.writeVec3(vel);
|
|
||||||
bcast.writeVec3(acc);
|
|
||||||
bcast.writeFloat(plr.angle);
|
|
||||||
for (Player &p : G.players) {
|
for (Player &p : G.players) {
|
||||||
if (p.id == plr.id)
|
if (p.sessId == plr.sessId)
|
||||||
continue; // dont send broadcast to the player
|
continue; // dont send broadcast to the player
|
||||||
// TODO: confirm position to player
|
// TODO: confirm position to player
|
||||||
H.send(p.P, bcast, Tfer::Unrel);
|
H.send(*p.peer, bcast, Tfer::Unrel);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case PlayerUpdateType::Die:
|
case S::Die:
|
||||||
handlePlayerDeath(msg, plr);
|
handlePlayerDeath(msg, plr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -188,7 +184,7 @@ void Server::sendChunks(const std::list<ChunkRef> &cs, Player &P) {
|
||||||
}
|
}
|
||||||
OutMessage msg;
|
OutMessage msg;
|
||||||
ctr.writeToMsg(msg);
|
ctr.writeToMsg(msg);
|
||||||
H.send(P.P, msg, Tfer::Rel, Channels::MapTransfer);
|
H.send(*P.peer, msg, Tfer::Rel, Channels::MapTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handlePlayerChunkRequest(InMessage &msg, Player &plr) {
|
void Server::handlePlayerChunkRequest(InMessage &msg, Player &plr) {
|
||||||
|
@ -263,26 +259,27 @@ void Server::handlePlayerMapUpdate(InMessage &msg, Player &plr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handlePlayerDeath(InMessage &msg, Player &plr) {
|
void Server::handlePlayerDeath(InMessage &msg, Player &plr) {
|
||||||
uint8 drb = msg.readU8();
|
using namespace Net::MsgTypes;
|
||||||
Player::DeathReason dr = (Player::DeathReason)drb;
|
PlayerUpdateDie pud;
|
||||||
plr.setDead(false, dr);
|
pud.readFromMsg(msg);
|
||||||
OutMessage out(MessageType::PlayerUpdate, PlayerUpdateType::Die);
|
pud.plrSessId = plr.sessId;
|
||||||
out.writeU32(plr.id);
|
plr.setDead(false, pud.reason);
|
||||||
out.writeU8(drb);
|
OutMessage out; pud.writeToMsg(out);
|
||||||
for (Player &p : G.players) {
|
for (Player &p : G.players) {
|
||||||
if (p.id != plr.id)
|
if (p.sessId != plr.sessId)
|
||||||
H.send(p.P, out, Tfer::Rel, Channels::Life);
|
H.send(*p.peer, out, Tfer::Rel, Channels::Life);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Respawn player later
|
// Respawn player later
|
||||||
Game *G = &this->G; uint32 id = plr.id;
|
Game *G = &this->G; Player::SessionID sid = plr.sessId;
|
||||||
std::thread respawn([G, id] {
|
std::thread respawn([G, sid] {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
Player *plr = G->S->getPlayerById(id);
|
Player *plr = G->S->getPlayerBySessId(sid);
|
||||||
if (plr) {
|
if (plr) {
|
||||||
plr->setDead(false);
|
plr->setDead(false);
|
||||||
OutMessage out(MessageType::PlayerUpdate, PlayerUpdateType::Respawn);
|
PlayerUpdateRespawn pur;
|
||||||
out.writeU32(id);
|
pur.plrSessId = sid;
|
||||||
|
OutMessage out; pur.writeToMsg(out);
|
||||||
NetHelper::Broadcast(G, out, Tfer::Rel, Channels::Life);
|
NetHelper::Broadcast(G, out, Tfer::Rel, Channels::Life);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -380,12 +377,13 @@ void Server::chunkUpdater(WorldRef WR, bool &continueUpdate) {
|
||||||
|
|
||||||
void Server::run() {
|
void Server::run() {
|
||||||
InMessage msg;
|
InMessage msg;
|
||||||
Peer peer;
|
Peer *peerPtr;
|
||||||
bool continueUpdate = true;
|
bool continueUpdate = true;
|
||||||
std::thread upd(&Server::chunkUpdater, this, G.U->getWorld(0), std::ref(continueUpdate));
|
std::thread upd(&Server::chunkUpdater, this, G.U->getWorld(0), std::ref(continueUpdate));
|
||||||
Player *plr;
|
Player *plr;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (H.recv(msg, peer, 100)) {
|
if (H.recv(msg, &peerPtr, 100)) {
|
||||||
|
Peer &peer = *peerPtr;
|
||||||
plr = getPlayerByPeer(peer);
|
plr = getPlayerByPeer(peer);
|
||||||
if (plr != nullptr) {
|
if (plr != nullptr) {
|
||||||
switch (msg.getType()) {
|
switch (msg.getType()) {
|
||||||
|
@ -408,7 +406,7 @@ void Server::run() {
|
||||||
}
|
}
|
||||||
switch (msg.getType()) {
|
switch (msg.getType()) {
|
||||||
case MessageType::NetConnect:
|
case MessageType::NetConnect:
|
||||||
getOutputStream() << peer.getHost() << " NEWCONN" << std::endl;
|
getOutputStream() << peer.peerHost() << " NEWCONN" << std::endl;
|
||||||
break;
|
break;
|
||||||
case MessageType::NetDisconnect:
|
case MessageType::NetDisconnect:
|
||||||
handleDisconnect(peer);
|
handleDisconnect(peer);
|
||||||
|
@ -441,10 +439,10 @@ bool Server::isPlayerOnline(const std::string &playername) const {
|
||||||
|
|
||||||
void Server::kick(Player &p, Net::QuitReason r, const std::string &message) {
|
void Server::kick(Player &p, Net::QuitReason r, const std::string &message) {
|
||||||
OutMessage msg(MessageType::PlayerQuit, r);
|
OutMessage msg(MessageType::PlayerQuit, r);
|
||||||
msg.writeU32(p.id);
|
msg.writeU32(p.sessId);
|
||||||
msg.writeString(message);
|
msg.writeString(message);
|
||||||
H.send(p.P, msg, Tfer::Rel);
|
H.send(*p.peer, msg, Tfer::Rel);
|
||||||
p.P.disconnect();
|
p.peer->disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server() {
|
Server::~Server() {
|
||||||
|
|
|
@ -50,7 +50,7 @@ public:
|
||||||
|
|
||||||
bool isPlayerOnline(const std::string &playername) const;
|
bool isPlayerOnline(const std::string &playername) const;
|
||||||
bool isIPOnline(const std::string &ip) const;
|
bool isIPOnline(const std::string &ip) const;
|
||||||
Player* getPlayerById(uint32 id);
|
Player* getPlayerBySessId(uint32 id);
|
||||||
Player* getPlayerByPeer(const Net::Peer &peer);
|
Player* getPlayerByPeer(const Net::Peer &peer);
|
||||||
Player* getPlayerByName(const std::string &name);
|
Player* getPlayerByName(const std::string &name);
|
||||||
void kick(Player &p, Net::QuitReason r = Net::QuitReason::Kicked, const std::string& message = "");
|
void kick(Player &p, Net::QuitReason r = Net::QuitReason::Kicked, const std::string& message = "");
|
||||||
|
|
|
@ -102,10 +102,14 @@ void Texture::setFiltering(Filter min, Filter mag) {
|
||||||
|
|
||||||
static GLenum getWrapGlConstant(Texture::Wrapping wrap) {
|
static GLenum getWrapGlConstant(Texture::Wrapping wrap) {
|
||||||
switch (wrap) {
|
switch (wrap) {
|
||||||
case Texture::Wrapping::Clamp:
|
case Texture::Wrapping::ClampEdge:
|
||||||
return GL_CLAMP;
|
return GL_CLAMP_TO_EDGE;
|
||||||
|
case Texture::Wrapping::ClampBorder:
|
||||||
|
return GL_CLAMP_TO_BORDER;
|
||||||
case Texture::Wrapping::Repeat:
|
case Texture::Wrapping::Repeat:
|
||||||
return GL_REPEAT;
|
return GL_REPEAT;
|
||||||
|
case Texture::Wrapping::MirroredRepeat:
|
||||||
|
return GL_MIRRORED_REPEAT;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,10 @@ public:
|
||||||
Linear
|
Linear
|
||||||
};
|
};
|
||||||
enum class Wrapping {
|
enum class Wrapping {
|
||||||
|
ClampEdge,
|
||||||
|
ClampBorder,
|
||||||
Repeat,
|
Repeat,
|
||||||
Clamp
|
MirroredRepeat
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
GLuint m_id;
|
GLuint m_id;
|
||||||
|
@ -54,7 +56,9 @@ public:
|
||||||
void setSubTexture(int x, int y, uint w, uint h, const uint8_t *data, PixelFormat format = PixelFormat::RGB);
|
void setSubTexture(int x, int y, uint w, uint h, const uint8_t *data, PixelFormat format = PixelFormat::RGB);
|
||||||
void setFiltering(Filter min, Filter mag);
|
void setFiltering(Filter min, Filter mag);
|
||||||
void setWrapping(Wrapping s, Wrapping t);
|
void setWrapping(Wrapping s, Wrapping t);
|
||||||
|
inline void setWrapping(Wrapping w) {
|
||||||
|
setWrapping(w, w);
|
||||||
|
}
|
||||||
|
|
||||||
void bind() const {
|
void bind() const {
|
||||||
glBindTexture(GL_TEXTURE_2D, m_id);
|
glBindTexture(GL_TEXTURE_2D, m_id);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef VERSION_INFO_HPP
|
#ifndef DIGGLER_VERSION_INFO_HPP
|
||||||
#define VERSION_INFO_HPP
|
#define DIGGLER_VERSION_INFO_HPP
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
const char* VersionString = "0.1.0";
|
const char* VersionString = "0.1.0";
|
||||||
|
@ -8,4 +8,4 @@ namespace Diggler {
|
||||||
int VersionRevision = 0;
|
int VersionRevision = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif /* DIGGLER_VERSION_INFO_HPP */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef WORLD_GENERATOR_HPP
|
#ifndef DIGGLER_WORLD_GENERATOR_HPP
|
||||||
#define WORLD_GENERATOR_HPP
|
#define DIGGLER_WORLD_GENERATOR_HPP
|
||||||
|
|
||||||
#include <glm/vec3.hpp>
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
|
@ -13,4 +14,4 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif /* DIGGLER_WORLD_GENERATOR_HPP */
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef DIGGLER_CONTENT_ASSET_HPP
|
||||||
|
#define DIGGLER_CONTENT_ASSET_HPP
|
||||||
|
|
||||||
|
#include <msgpack.hpp>
|
||||||
|
|
||||||
|
#include "../crypto/SHA256.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Content {
|
||||||
|
|
||||||
|
class Asset {
|
||||||
|
public:
|
||||||
|
enum class Type {
|
||||||
|
Texture,
|
||||||
|
Sound,
|
||||||
|
Music,
|
||||||
|
Schematic,
|
||||||
|
Model,
|
||||||
|
VoxelModel
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Crypto::SHA256::Digest m_hash;
|
||||||
|
Type m_type;
|
||||||
|
msgpack::object m_info;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const Crypto::SHA256::Digest& hash() const {
|
||||||
|
return m_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type() const {
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgpack::object& info() const {
|
||||||
|
return m_info;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CONTENT_ASSET_HPP */
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "AssetManager.hpp"
|
||||||
|
|
||||||
|
#include "../Game.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Content {
|
||||||
|
|
||||||
|
AssetManager::AssetManager(Game *G) :
|
||||||
|
G(G) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef DIGGLER_CONTENT_ASSET_MANAGER_HPP
|
||||||
|
#define DIGGLER_CONTENT_ASSET_MANAGER_HPP
|
||||||
|
|
||||||
|
#include "Asset.hpp"
|
||||||
|
#include "Mod.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
|
||||||
|
class Game;
|
||||||
|
|
||||||
|
namespace Content {
|
||||||
|
|
||||||
|
class AssetManager final {
|
||||||
|
private:
|
||||||
|
Game *G;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AssetManager(Game*);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CONTENT_ASSET_MANAGER_HPP */
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef DIGGLER_CONTENT_MOD_HPP
|
||||||
|
#define DIGGLER_CONTENT_MOD_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../Platform.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Content {
|
||||||
|
|
||||||
|
using ModId = byte[32];
|
||||||
|
|
||||||
|
class Mod {
|
||||||
|
public:
|
||||||
|
ModId id;
|
||||||
|
std::string name, fsPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CONTENT_MOD_HPP */
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "ModManager.hpp"
|
||||||
|
|
||||||
|
#include "../Game.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Content {
|
||||||
|
|
||||||
|
ModManager::ModManager(Game *G) :
|
||||||
|
G(G) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
#ifndef DIGGLER_CONTENT_MOD_MANAGER_HPP
|
||||||
|
#define DIGGLER_CONTENT_MOD_MANAGER_HPP
|
||||||
|
|
||||||
|
#include "Mod.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
|
||||||
|
class Game;
|
||||||
|
|
||||||
|
namespace Content {
|
||||||
|
|
||||||
|
class ModManager final {
|
||||||
|
private:
|
||||||
|
Game *G;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ModManager(Game*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resolves a mod-relative or absolute path into a filesystem path
|
||||||
|
* Accepted schemes: builtin, mod:*, self
|
||||||
|
* @param mod Mod context
|
||||||
|
* @param path Mod-relative or absolute path
|
||||||
|
* @return Resolved filesystem path
|
||||||
|
*/
|
||||||
|
std::string filesystemPath(const Mod &mod, const std::string &path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resolves an absolute path into a filesystem path
|
||||||
|
* Accepted schemes: builtin, mod:*
|
||||||
|
* @param path Absolute path
|
||||||
|
* @return Resolved filesystem path
|
||||||
|
*/
|
||||||
|
std::string filesystemPath(const std::string &path);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determines if the path is absolute or mod-relative (i.e. requires a mod context to be
|
||||||
|
* resolved)
|
||||||
|
* @param path Path to check
|
||||||
|
* @return true if path is absolute, false otherwise
|
||||||
|
*/
|
||||||
|
static bool isAbsolutePath(const std::string &path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resolves a mod-relative path into an absolute path
|
||||||
|
* Accepted schemes: builtin, mod:*, self
|
||||||
|
* @param path Mod-relative path
|
||||||
|
* @return Resolved filesystem path
|
||||||
|
*/
|
||||||
|
std::string absolutePath(const Mod &mod, const std::string &path);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CONTENT_MOD_MANAGER_HPP */
|
|
@ -0,0 +1,70 @@
|
||||||
|
#ifndef DIGGLER_CRYPTO_CRYPTODATA_HPP
|
||||||
|
#define DIGGLER_CRYPTO_CRYPTODATA_HPP
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Crypto {
|
||||||
|
|
||||||
|
template<size_t B>
|
||||||
|
struct CryptoData {
|
||||||
|
constexpr static size_t Length = B;
|
||||||
|
|
||||||
|
union {
|
||||||
|
unsigned char data[Length], bytes[Length];
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const CryptoData<B> &o) const {
|
||||||
|
return sodium_memcmp(data, o.data, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const CryptoData<B> &o) const {
|
||||||
|
return !operator==(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char& operator[](size_t idx) {
|
||||||
|
return data[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char operator[](size_t idx) const {
|
||||||
|
return data[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
void zerofill() {
|
||||||
|
memset(data, 0, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string hex(bool caps = false) const {
|
||||||
|
std::string hex(Length * 2, '\0');
|
||||||
|
const char *hextab = caps ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||||
|
for (size_t i = 0; i < Length; ++i) {
|
||||||
|
hex[i * 2 + 0] = hextab[data[i] >> 4];
|
||||||
|
hex[i * 2 + 1] = hextab[data[i] & 0xF];
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t B>
|
||||||
|
struct MlockedCryptoData : CryptoData<B> {
|
||||||
|
MlockedCryptoData() {
|
||||||
|
sodium_mlock(this->data, this->Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
MlockedCryptoData(MlockedCryptoData<B> &o) {
|
||||||
|
sodium_mlock(this->data, this->Length);
|
||||||
|
memcpy(this->data, o.data, this->Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
~MlockedCryptoData() {
|
||||||
|
sodium_munlock(this->data, this->Length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CRYPTO_CRYPTODATA_HPP */
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef DIGGLER_CRYPTO_DIFFIE_HELLMAN_HPP
|
||||||
|
#define DIGGLER_CRYPTO_DIFFIE_HELLMAN_HPP
|
||||||
|
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
|
#include "CryptoData.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Crypto {
|
||||||
|
namespace DiffieHellman {
|
||||||
|
|
||||||
|
constexpr static size_t ScalarBytes = crypto_scalarmult_SCALARBYTES;
|
||||||
|
constexpr static size_t Bytes = crypto_scalarmult_BYTES;
|
||||||
|
|
||||||
|
struct SecretKey : MlockedCryptoData<ScalarBytes> {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PublicKey : CryptoData<Bytes> {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SharedSecret : MlockedCryptoData<Bytes> {
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void scalarmultBase(const SecretKey &sk, PublicKey &pk) {
|
||||||
|
crypto_scalarmult_base(pk.bytes, sk.bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[gnu::warn_unused_result]]
|
||||||
|
inline bool scalarmult(const SecretKey &sk, const PublicKey &pk, SharedSecret &ss) {
|
||||||
|
return crypto_scalarmult(ss.bytes, sk.bytes, pk.bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CRYPTO_DIFFIE_HELLMAN_HPP */
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef DIGGLER_CRYPTO_RANDOM_HPP
|
||||||
|
#define DIGGLER_CRYPTO_RANDOM_HPP
|
||||||
|
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
|
#include "CryptoData.hpp"
|
||||||
|
#include "../platform/Types.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Crypto {
|
||||||
|
namespace Random {
|
||||||
|
|
||||||
|
uint32 random() {
|
||||||
|
return randombytes_random();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 uniform(const uint32 upperBound) {
|
||||||
|
return randombytes_uniform(upperBound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void buf(void *const buf, const size_t size) {
|
||||||
|
randombytes_buf(buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t B>
|
||||||
|
void randomData(CryptoData<B> &cd) {
|
||||||
|
randombytes_buf(cd.bytes, cd.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stir() {
|
||||||
|
randombytes_stir();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CRYPTO_RANDOM_HPP */
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef DIGGLER_CRYPTO_SHA256_HPP
|
||||||
|
#define DIGGLER_CRYPTO_SHA256_HPP
|
||||||
|
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
|
#include "CryptoData.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Crypto {
|
||||||
|
|
||||||
|
struct SHA256 {
|
||||||
|
constexpr static size_t DigestBytes = crypto_hash_sha256_BYTES;
|
||||||
|
|
||||||
|
struct Digest : CryptoData<SHA256::DigestBytes> {
|
||||||
|
};
|
||||||
|
|
||||||
|
crypto_hash_sha256_state state;
|
||||||
|
|
||||||
|
SHA256() {
|
||||||
|
crypto_hash_sha256_init(&state);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void update(const T *data, size_t len) {
|
||||||
|
crypto_hash_sha256_update(&state, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void finalize(unsigned char *digest) {
|
||||||
|
crypto_hash_sha256_final(&state, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
Digest finalize() {
|
||||||
|
Digest digest;
|
||||||
|
crypto_hash_sha256_final(&state, digest.bytes);
|
||||||
|
return digest;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CRYPTO_SHA256_HPP */
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef DIGGLER_CRYPTO_SIGN_HPP
|
||||||
|
#define DIGGLER_CRYPTO_SIGN_HPP
|
||||||
|
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
|
#include "CryptoData.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Crypto {
|
||||||
|
namespace Sign {
|
||||||
|
|
||||||
|
constexpr size_t PublicKeyBytes = crypto_sign_PUBLICKEYBYTES;
|
||||||
|
constexpr size_t SecretKeyBytes = crypto_sign_SECRETKEYBYTES;
|
||||||
|
constexpr size_t SignatureBytes = crypto_sign_BYTES;
|
||||||
|
|
||||||
|
struct PublicKey : CryptoData<PublicKeyBytes> {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SecretKey : MlockedCryptoData<SecretKeyBytes> {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Signature : CryptoData<SignatureBytes> {
|
||||||
|
};
|
||||||
|
|
||||||
|
void keypair(PublicKey &pk, SecretKey &sk) {
|
||||||
|
crypto_sign_keypair(pk.bytes, sk.bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sign(const unsigned char *m, unsigned long long mlen, const SecretKey &sk, Signature &sig) {
|
||||||
|
crypto_sign_detached(sig.bytes, nullptr, m, mlen, sk.bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verify(const unsigned char *m, unsigned long long mlen, Signature &sig, const PublicKey &pk) {
|
||||||
|
return crypto_sign_verify_detached(sig.bytes, m, mlen, pk.bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CRYPTO_SIGN_HPP */
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef DIGGLER_CRYPTO_SODIUM_HPP
|
||||||
|
#define DIGGLER_CRYPTO_SODIUM_HPP
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Crypto {
|
||||||
|
|
||||||
|
class Sodium {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_CRYPTO_SODIUM_HPP */
|
|
@ -134,12 +134,13 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
/*/GW.setNextState(std::make_shared<UITestState>(&GW));/*/
|
/*/GW.setNextState(std::make_shared<UITestState>(&GW));/*/
|
||||||
if (networkSuccess)
|
if (networkSuccess)
|
||||||
GW.setNextState(std::make_shared<GameState>(&GW, host, port));
|
GW.setNextState(std::move(std::make_unique<GameState>(&GW, host, port)));
|
||||||
else
|
else
|
||||||
GW.showMessage("Network init failed!");
|
GW.showMessage("Network init failed!");
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
GW.run();
|
GW.run();
|
||||||
|
G->finalizeClient();
|
||||||
}
|
}
|
||||||
G.reset();
|
G.reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "msgtypes/BlockUpdate.hpp"
|
#include "msgtypes/BlockUpdate.hpp"
|
||||||
#include "msgtypes/Chat.hpp"
|
#include "msgtypes/Chat.hpp"
|
||||||
#include "msgtypes/ChunkTransfer.hpp"
|
#include "msgtypes/ChunkTransfer.hpp"
|
||||||
|
#include "msgtypes/PlayerUpdate.hpp"
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
namespace Net {
|
namespace Net {
|
||||||
|
@ -65,7 +66,7 @@ bool ClientMessageHandler::handleMessage(InMessage &msg) {
|
||||||
if (cpt.msg.type == msgpack::type::STR) {
|
if (cpt.msg.type == msgpack::type::STR) {
|
||||||
std::string playerName;
|
std::string playerName;
|
||||||
if (cpt.player.display.type == msgpack::type::NIL) {
|
if (cpt.player.display.type == msgpack::type::NIL) {
|
||||||
const Player *blabbermouth = GS.G->players.getByGameId(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 {
|
||||||
|
@ -81,14 +82,14 @@ bool ClientMessageHandler::handleMessage(InMessage &msg) {
|
||||||
} break;
|
} break;
|
||||||
case MessageType::PlayerJoin: {
|
case MessageType::PlayerJoin: {
|
||||||
Player &plr = GS.G->players.add();
|
Player &plr = GS.G->players.add();
|
||||||
plr.id = msg.readU32();
|
plr.sessId = msg.readU32();
|
||||||
plr.name = msg.readString();
|
plr.name = msg.readString();
|
||||||
getDebugStream() << "Player " << plr.name << '(' << plr.id << ") joined the party!" << std::endl;
|
getDebugStream() << "Player " << plr.name << '(' << plr.sessId << ") joined the party!" << std::endl;
|
||||||
} break;
|
} break;
|
||||||
case MessageType::PlayerQuit: {
|
case MessageType::PlayerQuit: {
|
||||||
uint32 id = msg.readU32();
|
uint32 id = msg.readU32();
|
||||||
try {
|
try {
|
||||||
Player *plr = GS.G->players.getByGameId(id);
|
Player *plr = GS.G->players.getBySessId(id);
|
||||||
if (plr != nullptr) {
|
if (plr != nullptr) {
|
||||||
getOutputStream() << plr->name << " is gone :(" << std::endl;
|
getOutputStream() << plr->name << " is gone :(" << std::endl;
|
||||||
GS.G->players.remove(*plr);
|
GS.G->players.remove(*plr);
|
||||||
|
@ -98,30 +99,51 @@ bool ClientMessageHandler::handleMessage(InMessage &msg) {
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case MessageType::PlayerUpdate: {
|
case MessageType::PlayerUpdate: {
|
||||||
uint32 id = msg.readU32();
|
using S = PlayerUpdateSubtype;
|
||||||
try {
|
switch (static_cast<S>(msg.getSubtype())) {
|
||||||
Player *plr = GS.G->players.getByGameId(id);
|
case S::Move: {
|
||||||
if (plr != nullptr) {
|
PlayerUpdateMove pum;
|
||||||
switch (msg.getSubtype()) {
|
pum.readFromMsg(msg);
|
||||||
case PlayerUpdateType::Move: {
|
if (!pum.plrSessId) {
|
||||||
glm::vec3 pos = msg.readVec3(),
|
getOutputStream() << "PlayerUpdateMove without player session ID" << std::endl;
|
||||||
vel = msg.readVec3(),
|
return true;
|
||||||
acc = msg.readVec3();
|
|
||||||
plr->setPosVel(pos, vel, acc);
|
|
||||||
plr->angle = msg.readFloat();
|
|
||||||
} break;
|
|
||||||
case PlayerUpdateType::Die:
|
|
||||||
plr->setDead(false, (Player::DeathReason)msg.readU8());
|
|
||||||
break;
|
|
||||||
case PlayerUpdateType::Respawn:
|
|
||||||
plr->setDead(false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
Player *plr = GS.G->players.getBySessId(*pum.plrSessId);
|
||||||
} catch (const std::out_of_range &e) {
|
if (!plr) {
|
||||||
getOutputStream() << "Invalid player update: #" << id << " is not on server" << std::endl;
|
getOutputStream() << "PlayerUpdateMove: sess#" << *pum.plrSessId <<
|
||||||
|
" is not on server" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
glm::vec3 pos = pum.position ? *pum.position : plr->position,
|
||||||
|
vel = pum.velocity ? *pum.velocity : plr->velocity,
|
||||||
|
acc = pum.accel ? *pum.accel : plr->accel;
|
||||||
|
plr->setPosVel(pos, vel, acc);
|
||||||
|
plr->angle = pum.angle;
|
||||||
|
} break;
|
||||||
|
case S::Die: {
|
||||||
|
PlayerUpdateDie pud;
|
||||||
|
pud.readFromMsg(msg);
|
||||||
|
Player *plr = GS.G->players.getBySessId(pud.plrSessId);
|
||||||
|
if (!plr) {
|
||||||
|
getOutputStream() << "PlayerUpdateDie: sess#" << pud.plrSessId <<
|
||||||
|
" is not on server" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
plr->setDead(false, pud.reason);
|
||||||
|
} break;
|
||||||
|
case S::Respawn: {
|
||||||
|
PlayerUpdateRespawn pur;
|
||||||
|
pur.readFromMsg(msg);
|
||||||
|
Player *plr = GS.G->players.getBySessId(pur.plrSessId);
|
||||||
|
if (!plr) {
|
||||||
|
getOutputStream() << "PlayerUpdateRespawn: sess#" << pur.plrSessId <<
|
||||||
|
" is not on server" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
plr->setDead(false);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case MessageType::BlockUpdate: {
|
case MessageType::BlockUpdate: {
|
||||||
|
|
|
@ -17,7 +17,7 @@ void Broadcast(Game *G, const OutMessage &msg, Tfer tfer, Channels chan) {
|
||||||
|
|
||||||
void Broadcast(Game &G, const OutMessage &msg, Tfer tfer, Channels chan) {
|
void Broadcast(Game &G, const OutMessage &msg, Tfer tfer, Channels chan) {
|
||||||
for (Player &p : G.players) {
|
for (Player &p : G.players) {
|
||||||
G.S->H.send(p.P, msg, tfer, chan);
|
G.S->H.send(*p.peer, msg, tfer, chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,20 +27,7 @@ void SendChat(Game *G, const std::string &str) {
|
||||||
|
|
||||||
OutMessage msg;
|
OutMessage msg;
|
||||||
cs.writeToMsg(msg);
|
cs.writeToMsg(msg);
|
||||||
G->H.send(G->NS, msg, Tfer::Unseq);
|
G->H.send(*G->NS, msg, Tfer::Unseq);
|
||||||
}
|
|
||||||
|
|
||||||
void SendToolUse(Game *G, int x, int y, int z) {
|
|
||||||
OutMessage msg(MessageType::PlayerUpdate, PlayerUpdateType::ToolUse);
|
|
||||||
msg.writeBool(true);
|
|
||||||
msg.writeIVec3(x, y, z);
|
|
||||||
G->H.send(G->NS, msg, Tfer::Rel, Channels::PlayerInteract);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendToolUse(Game *G) {
|
|
||||||
OutMessage msg(MessageType::PlayerUpdate, PlayerUpdateType::ToolUse);
|
|
||||||
msg.writeBool(false);
|
|
||||||
G->H.send(G->NS, msg, Tfer::Rel, Channels::PlayerInteract);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,8 @@ void MakeEvent(Net::OutMessage&, Net::EventType, const Player&);
|
||||||
void SendEvent(Game*, Net::EventType);
|
void SendEvent(Game*, Net::EventType);
|
||||||
|
|
||||||
void SendChat(Game*, const std::string&);
|
void SendChat(Game*, const std::string&);
|
||||||
void SendToolUse(Game*);
|
|
||||||
void SendToolUse(Game*, int x, int y, int z);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
#include "Network.hpp"
|
#include "Network.hpp"
|
||||||
#include <enet/enet.h>
|
|
||||||
|
#include <chrono>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include <enet/enet.h>
|
||||||
|
|
||||||
|
#include "../crypto/Random.hpp"
|
||||||
|
#include "msgtypes/ConnectionParam.hpp"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
|
@ -53,8 +59,7 @@ Message::Message(MessageType t, uint8 s) :
|
||||||
|
|
||||||
InMessage::InMessage() :
|
InMessage::InMessage() :
|
||||||
Message(MessageType::Null, 0),
|
Message(MessageType::Null, 0),
|
||||||
m_chan(Channels::Base),
|
m_chan(Channels::Base) {
|
||||||
m_packet(nullptr) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InMessage::~InMessage() {
|
InMessage::~InMessage() {
|
||||||
|
@ -79,36 +84,17 @@ void InMessage::fromData(const void *data, SizeT len, Channels chan) {
|
||||||
m_length = len;
|
m_length = len;
|
||||||
m_type = static_cast<MessageType>(bytes[0]);
|
m_type = static_cast<MessageType>(bytes[0]);
|
||||||
m_subtype = bytes[1];
|
m_subtype = bytes[1];
|
||||||
m_data = static_cast<uint8*>(std::malloc(len-HeaderSize));
|
// m_data/bytes is guaranteed never to be written to, so we can const_cast it
|
||||||
std::memcpy(m_data, &(bytes[HeaderSize]), len-HeaderSize);
|
m_data = const_cast<uint8*>(bytes) + HeaderSize;
|
||||||
}
|
|
||||||
|
|
||||||
void InMessage::fromPacket(void *packet, Channels chan) {
|
|
||||||
ENetPacket *enpkt = static_cast<ENetPacket*>(packet);
|
|
||||||
SizeT len = enpkt->dataLength;
|
|
||||||
if (len < HeaderSize) {
|
|
||||||
throw std::invalid_argument("Message length is smaller than message header");
|
|
||||||
}
|
|
||||||
uint8 *const bytes = static_cast<uint8*>(enpkt->data);
|
|
||||||
free();
|
|
||||||
m_packet = packet;
|
|
||||||
m_chan = chan;
|
|
||||||
m_cursor = 0;
|
|
||||||
m_length = len;
|
|
||||||
m_type = static_cast<MessageType>(bytes[0]);
|
|
||||||
m_subtype = bytes[1];
|
|
||||||
m_data = &(bytes[HeaderSize]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InMessage::free() {
|
void InMessage::free() {
|
||||||
if (m_packet != nullptr) {
|
if (m_data != nullptr) {
|
||||||
enet_packet_destroy(static_cast<ENetPacket*>(m_packet));
|
delete[] (m_data - HeaderSize);
|
||||||
} else {
|
|
||||||
std::free(m_data);
|
|
||||||
}
|
}
|
||||||
m_type = MessageType::Null;
|
m_type = MessageType::Null;
|
||||||
m_subtype = m_length = m_cursor = 0;
|
m_subtype = m_length = m_cursor = 0;
|
||||||
m_packet = m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,6 +146,14 @@ Channels InMessage::getChannel() const {
|
||||||
return m_chan;
|
return m_chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Peer::Peer(Host &host, void *peer) :
|
||||||
|
host(host),
|
||||||
|
peer(peer) {
|
||||||
|
reinterpret_cast<ENetPeer*>(this->peer)->data = this;
|
||||||
|
Crypto::Random::randomData(connectionPk);
|
||||||
|
Crypto::DiffieHellman::scalarmultBase(connectionSk, connectionPk);
|
||||||
|
}
|
||||||
|
|
||||||
bool Peer::operator==(const Peer &other) const {
|
bool Peer::operator==(const Peer &other) const {
|
||||||
return peer == other.peer;
|
return peer == other.peer;
|
||||||
}
|
}
|
||||||
|
@ -168,13 +162,13 @@ bool Peer::operator!=(const Peer &other) const {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Peer::disconnect() {
|
void Peer::disconnect(uint32 data) {
|
||||||
ENetPeer *const peer = static_cast<ENetPeer*>(this->peer);
|
ENetPeer *const peer = reinterpret_cast<ENetPeer*>(this->peer);
|
||||||
enet_peer_disconnect(peer, 0);
|
enet_peer_disconnect(peer, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Peer::getHost() {
|
std::string Peer::peerHost() {
|
||||||
const ENetPeer *const peer = static_cast<const ENetPeer*>(this->peer);
|
const ENetPeer *const peer = reinterpret_cast<const ENetPeer*>(this->peer);
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
char *chars = new char[512];
|
char *chars = new char[512];
|
||||||
enet_address_get_host_ip(&peer->host->address, chars, 512);
|
enet_address_get_host_ip(&peer->host->address, chars, 512);
|
||||||
|
@ -184,8 +178,8 @@ std::string Peer::getHost() {
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Peer::getIp() {
|
std::string Peer::peerIP() {
|
||||||
const ENetPeer *const peer = static_cast<const ENetPeer*>(this->peer);
|
const ENetPeer *const peer = reinterpret_cast<const ENetPeer*>(this->peer);
|
||||||
char *chars = new char[512];
|
char *chars = new char[512];
|
||||||
enet_address_get_host_ip(&peer->host->address, chars, 512);
|
enet_address_get_host_ip(&peer->host->address, chars, 512);
|
||||||
std::string str(chars);
|
std::string str(chars);
|
||||||
|
@ -193,8 +187,8 @@ std::string Peer::getIp() {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
Port Peer::getPort() {
|
Port Peer::peerPort() {
|
||||||
const ENetPeer *const peer = static_cast<const ENetPeer*>(this->peer);
|
const ENetPeer *const peer = reinterpret_cast<const ENetPeer*>(this->peer);
|
||||||
return peer->host->address.port;
|
return peer->host->address.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +200,11 @@ Host::Host() :
|
||||||
txBytes(0) {
|
txBytes(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Host::~Host() {
|
||||||
|
ENetHost *const host = reinterpret_cast<ENetHost*>(this->host);
|
||||||
|
enet_host_destroy(host);
|
||||||
|
}
|
||||||
|
|
||||||
void Host::create(Port port, uint maxconn) {
|
void Host::create(Port port, uint maxconn) {
|
||||||
if (port == 0) { // Client
|
if (port == 0) { // Client
|
||||||
host = enet_host_create(nullptr, 1, static_cast<size_t>(Channels::MAX), 0, 0);
|
host = enet_host_create(nullptr, 1, static_cast<size_t>(Channels::MAX), 0, 0);
|
||||||
|
@ -220,8 +219,8 @@ void Host::create(Port port, uint maxconn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Peer Host::connect(const std::string &hostAddr, Port port, Timeout timeout) {
|
Peer& Host::connect(const std::string &hostAddr, Port port, Timeout timeout) {
|
||||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
ENetHost *const host = reinterpret_cast<ENetHost*>(this->host);
|
||||||
ENetAddress address;
|
ENetAddress address;
|
||||||
ENetEvent event;
|
ENetEvent event;
|
||||||
ENetPeer *peer;
|
ENetPeer *peer;
|
||||||
|
@ -236,102 +235,140 @@ Peer Host::connect(const std::string &hostAddr, Port port, Timeout timeout) {
|
||||||
|
|
||||||
if (enet_host_service(host, &event, timeout) > 0 &&
|
if (enet_host_service(host, &event, timeout) > 0 &&
|
||||||
event.type == ENET_EVENT_TYPE_CONNECT) {
|
event.type == ENET_EVENT_TYPE_CONNECT) {
|
||||||
Peer p; p.peer = peer;
|
Peer *p = new Peer(*this, peer);
|
||||||
return p;
|
sendKeyExchange(*p);
|
||||||
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
enet_peer_reset(peer);
|
enet_peer_reset(peer);
|
||||||
throw Exception();
|
throw Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
Host::~Host() {
|
void Host::processPeersToDelete() {
|
||||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
for (Peer *peer : m_peersToDelete) {
|
||||||
enet_host_destroy(host);
|
delete peer;
|
||||||
|
}
|
||||||
|
m_peersToDelete.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static void hexDump(char in, uint8 *buf, int len) {
|
void Host::sendKeyExchange(Peer &p) {
|
||||||
|
MsgTypes::ConnectionParamDHKeyExchange dhke;
|
||||||
|
dhke.pk = p.connectionPk;
|
||||||
|
OutMessage keMsg;
|
||||||
|
dhke.writeToMsg(keMsg);
|
||||||
|
send(p, keMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hexDump(char in, uint8 *buf, int len) {
|
||||||
std::cout << in << ": " << std::setiosflags(std::ios::internal);
|
std::cout << in << ": " << std::setiosflags(std::ios::internal);
|
||||||
for (int i=0; i < len; ++i) {
|
for (int i=0; i < len; ++i) {
|
||||||
std::cout << std::setfill('0') << std::setw(2) << std::hex << (int)buf[i] << ' ';
|
std::cout << std::setfill('0') << std::setw(2) << std::hex << (int)buf[i] << ' ';
|
||||||
}
|
}
|
||||||
std::cout << std::dec << std::endl;
|
std::cout << std::dec << std::endl;
|
||||||
}*/
|
|
||||||
|
|
||||||
bool Host::recv(InMessage &msg, Peer &peer, Timeout timeout) {
|
|
||||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
|
||||||
ENetEvent event;
|
|
||||||
if (enet_host_service(host, &event, timeout) >= 0){
|
|
||||||
switch (event.type) {
|
|
||||||
case ENET_EVENT_TYPE_NONE:
|
|
||||||
return false;
|
|
||||||
case ENET_EVENT_TYPE_CONNECT:
|
|
||||||
peer.peer = event.peer;
|
|
||||||
msg.setType(MessageType::NetConnect);
|
|
||||||
break;
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
|
||||||
peer.peer = event.peer;
|
|
||||||
//hexDump('R', event.packet->data, event.packet->dataLength);
|
|
||||||
// Packet "ownership" is transferred to msg
|
|
||||||
msg.fromPacket(event.packet, static_cast<Channels>(event.channelID));
|
|
||||||
rxBytes += event.packet->dataLength;
|
|
||||||
break;
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
|
||||||
peer.peer = event.peer;
|
|
||||||
msg.setType(MessageType::NetDisconnect);
|
|
||||||
enet_peer_reset(event.peer);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
throw Exception();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Host::recv(InMessage &msg, Timeout timeout) {
|
bool Host::recv(InMessage &msg, Peer **peer, Timeout timeout) {
|
||||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
ENetHost *const host = reinterpret_cast<ENetHost*>(this->host);
|
||||||
|
processPeersToDelete();
|
||||||
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
ENetEvent event;
|
ENetEvent event;
|
||||||
if (enet_host_service(host, &event, timeout) >= 0){
|
while (true) {
|
||||||
switch (event.type) {
|
auto now = std::chrono::steady_clock::now();
|
||||||
case ENET_EVENT_TYPE_NONE:
|
enet_uint32 elapsed = static_cast<enet_uint32>(
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count());
|
||||||
|
if (enet_host_service(host, &event, timeout - elapsed) > 0) {
|
||||||
|
Peer *peerPtr = event.peer == nullptr ? nullptr :
|
||||||
|
reinterpret_cast<Peer*>(event.peer->data);
|
||||||
|
switch (event.type) {
|
||||||
|
case ENET_EVENT_TYPE_NONE:
|
||||||
|
break;
|
||||||
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
|
peerPtr = new Peer(*this, event.peer);
|
||||||
|
*peer = peerPtr;
|
||||||
|
sendKeyExchange(*peerPtr);
|
||||||
|
msg.setType(MessageType::NetConnect);
|
||||||
|
return true;
|
||||||
|
case ENET_EVENT_TYPE_RECEIVE: {
|
||||||
|
if (peer) {
|
||||||
|
*peer = peerPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Message::SizeT pktLen = event.packet->dataLength;
|
||||||
|
const Channels pktChannel = static_cast<Channels>(event.channelID);
|
||||||
|
const bool decrypt = (pktChannel == Channels::ConnectionMetaPlain);
|
||||||
|
byte *rcvData = new uint8[pktLen];
|
||||||
|
if (decrypt) {
|
||||||
|
// TODO: decryption
|
||||||
|
std::memcpy(rcvData, event.packet->data, pktLen);
|
||||||
|
} else {
|
||||||
|
std::memcpy(rcvData, event.packet->data, pktLen);
|
||||||
|
}
|
||||||
|
// pktData's ownership is transferred to msg
|
||||||
|
msg.fromData(rcvData, pktLen, pktChannel);
|
||||||
|
rxBytes += event.packet->dataLength;
|
||||||
|
|
||||||
|
if (msg.getType() == MessageType::ConnectionParam &&
|
||||||
|
msg.getSubtype() == static_cast<int>(MsgTypes::ConnectionParamSubtype::DHKeyExchange)) {
|
||||||
|
MsgTypes::ConnectionParamDHKeyExchange dhke; dhke.readFromMsg(msg);
|
||||||
|
peerPtr->remotePk = dhke.pk;
|
||||||
|
if (Crypto::DiffieHellman::scalarmult(peerPtr->connectionSk, peerPtr->remotePk,
|
||||||
|
peerPtr->sharedSecret) != 0) {
|
||||||
|
// TODO: properly handle key exchange failure
|
||||||
|
throw std::runtime_error("DH key exchange failed");
|
||||||
|
}
|
||||||
|
getDebugStream() << "hello DH! " << peerPtr->sharedSecret.hex() << std::endl;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
|
if (peer) {
|
||||||
|
*peer = peerPtr;
|
||||||
|
}
|
||||||
|
msg.setType(MessageType::NetDisconnect);
|
||||||
|
m_peersToDelete.emplace_back(peerPtr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
case ENET_EVENT_TYPE_CONNECT:
|
|
||||||
msg.setType(MessageType::NetConnect);
|
|
||||||
break;
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
|
||||||
//hexDump('R', event.packet->data, event.packet->dataLength);
|
|
||||||
// Packet "ownership" is transferred to msg
|
|
||||||
msg.fromPacket(event.packet, static_cast<Channels>(event.channelID));
|
|
||||||
rxBytes += event.packet->dataLength;
|
|
||||||
break;
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
|
||||||
msg.setType(MessageType::NetDisconnect);
|
|
||||||
enet_peer_reset(event.peer);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
throw Exception();
|
throw Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::send(Peer &peer, const OutMessage &msg, Tfer mode, Channels chan) {
|
void Host::send(Peer &peer, const OutMessage &msg, Tfer mode, Channels chan) {
|
||||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
ENetHost *const host = reinterpret_cast<ENetHost*>(this->host);
|
||||||
|
const bool encrypt = (chan == Channels::ConnectionMetaPlain);
|
||||||
|
|
||||||
const uint8 header[Message::HeaderSize] = {
|
const byte header[Message::HeaderSize] = {
|
||||||
static_cast<uint8>(msg.m_type),
|
static_cast<byte>(msg.m_type),
|
||||||
msg.m_subtype
|
msg.m_subtype
|
||||||
};
|
};
|
||||||
|
|
||||||
ENetPacket *packet;
|
size_t pktLen = Message::HeaderSize + (msg.m_actualData == nullptr ? 0 : msg.m_length);
|
||||||
|
ENetPacket *packet = enet_packet_create(nullptr, pktLen, TferToFlags(mode));
|
||||||
|
byte *pktData = packet->data;
|
||||||
|
txBytes += pktLen;
|
||||||
if (msg.m_actualData != nullptr) {
|
if (msg.m_actualData != nullptr) {
|
||||||
std::memcpy(msg.m_actualData, header, Message::HeaderSize);
|
std::memcpy(msg.m_actualData, header, Message::HeaderSize);
|
||||||
packet = enet_packet_create(msg.m_actualData,
|
if (encrypt) {
|
||||||
Message::HeaderSize + msg.m_length, TferToFlags(mode));
|
// TODO: don't memcpy, encrypt!
|
||||||
txBytes += Message::HeaderSize + msg.m_length;
|
std::memcpy(pktData, msg.m_actualData, pktLen);
|
||||||
|
} else {
|
||||||
|
std::memcpy(pktData, msg.m_actualData, pktLen);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
packet = enet_packet_create(header,
|
if (encrypt) {
|
||||||
Message::HeaderSize, TferToFlags(mode));
|
// TODO: don't memcpy, encrypt!
|
||||||
txBytes += Message::HeaderSize;
|
std::memcpy(pktData, header, pktLen);
|
||||||
|
} else {
|
||||||
|
std::memcpy(pktData, header, pktLen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//hexDump('S', packet->data, 2+msg.m_length);
|
hexDump('S', pktData, pktLen);
|
||||||
enet_peer_send(static_cast<ENetPeer*>(peer.peer), static_cast<uint8>(chan), packet);
|
enet_peer_send(reinterpret_cast<ENetPeer*>(peer.peer), static_cast<uint8>(chan), packet);
|
||||||
enet_host_flush(host);
|
enet_host_flush(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
#ifndef NETWORK_HPP
|
#ifndef NETWORK_HPP
|
||||||
#define NETWORK_HPP
|
#define NETWORK_HPP
|
||||||
#include "../Platform.hpp"
|
|
||||||
#include "../io/MemoryStream.hpp"
|
|
||||||
#include <glm/vec3.hpp>
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
|
#include "../Platform.hpp"
|
||||||
|
#include "../platform/PreprocUtils.hpp"
|
||||||
|
#include "../crypto/DiffieHellman.hpp"
|
||||||
|
#include "../io/MemoryStream.hpp"
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
namespace Net {
|
namespace Net {
|
||||||
|
|
||||||
|
@ -20,6 +25,8 @@ enum class Tfer {
|
||||||
|
|
||||||
enum class Channels : uint8 {
|
enum class Channels : uint8 {
|
||||||
Base = 0,
|
Base = 0,
|
||||||
|
ConnectionMeta,
|
||||||
|
ConnectionMetaPlain,
|
||||||
Chat,
|
Chat,
|
||||||
Life,
|
Life,
|
||||||
Movement,
|
Movement,
|
||||||
|
@ -35,6 +42,8 @@ enum class MessageType : uint8 {
|
||||||
|
|
||||||
ServerInfo = 220,
|
ServerInfo = 220,
|
||||||
|
|
||||||
|
ConnectionParam = 200,
|
||||||
|
|
||||||
PlayerJoin = 1,
|
PlayerJoin = 1,
|
||||||
PlayerUpdate,
|
PlayerUpdate,
|
||||||
PlayerQuit,
|
PlayerQuit,
|
||||||
|
@ -46,16 +55,6 @@ enum class MessageType : uint8 {
|
||||||
NetDisconnect
|
NetDisconnect
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PlayerUpdateType : uint8 {
|
|
||||||
Move,
|
|
||||||
ChangeTool,
|
|
||||||
ChangeClass,
|
|
||||||
ChangeTeam,
|
|
||||||
Die,
|
|
||||||
Respawn,
|
|
||||||
ToolUse
|
|
||||||
};
|
|
||||||
|
|
||||||
enum QuitReason : uint8 {
|
enum QuitReason : uint8 {
|
||||||
Quit,
|
Quit,
|
||||||
Timeout,
|
Timeout,
|
||||||
|
@ -82,6 +81,8 @@ protected:
|
||||||
public:
|
public:
|
||||||
static constexpr uint HeaderSize = 2;
|
static constexpr uint HeaderSize = 2;
|
||||||
|
|
||||||
|
virtual ~Message() {}
|
||||||
|
|
||||||
inline MessageType getType() const { return m_type; }
|
inline MessageType getType() const { return m_type; }
|
||||||
inline uint8 getSubtype() const { return m_subtype; }
|
inline uint8 getSubtype() const { return m_subtype; }
|
||||||
|
|
||||||
|
@ -94,10 +95,8 @@ class InMessage : public Message, public InMemoryStream {
|
||||||
protected:
|
protected:
|
||||||
friend class Host;
|
friend class Host;
|
||||||
Channels m_chan;
|
Channels m_chan;
|
||||||
void *m_packet;
|
|
||||||
void setType(MessageType type);
|
void setType(MessageType type);
|
||||||
void fromData(const void *data, SizeT len, Channels chan = Channels::Base);
|
void fromData(const void *data, SizeT, Channels);
|
||||||
void fromPacket(void *packet, Channels chan = Channels::Base);
|
|
||||||
void free();
|
void free();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -166,20 +165,43 @@ class Exception : public std::exception {
|
||||||
|
|
||||||
using Port = uint16;
|
using Port = uint16;
|
||||||
|
|
||||||
|
class Host;
|
||||||
|
|
||||||
struct Peer {
|
struct Peer {
|
||||||
void *peer;
|
Crypto::DiffieHellman::SecretKey connectionSk;
|
||||||
|
Crypto::DiffieHellman::PublicKey connectionPk;
|
||||||
|
|
||||||
|
Crypto::DiffieHellman::PublicKey remotePk;
|
||||||
|
Crypto::DiffieHellman::SharedSecret sharedSecret;
|
||||||
|
|
||||||
|
Host &host;
|
||||||
|
void *const peer;
|
||||||
|
|
||||||
|
Peer(Host&, void*);
|
||||||
|
nocopy(Peer);
|
||||||
|
nomove(Peer);
|
||||||
|
|
||||||
bool operator==(const Peer&) const;
|
bool operator==(const Peer&) const;
|
||||||
bool operator!=(const Peer&) const;
|
bool operator!=(const Peer&) const;
|
||||||
|
|
||||||
void disconnect();
|
/**
|
||||||
std::string getHost();
|
* @brief Disconnects the peer.
|
||||||
std::string getIp();
|
* @param data
|
||||||
Port getPort();
|
* Adds the peer for pending disconnection. A NetDisconnect event will be generated once the
|
||||||
|
* peer has successfully disconnected, and the current Peer object will be deallocated as per
|
||||||
|
* Host::recv's rules.
|
||||||
|
*/
|
||||||
|
void disconnect(uint32 data = 0);
|
||||||
|
std::string peerHost();
|
||||||
|
std::string peerIP();
|
||||||
|
Port peerPort();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Host {
|
class Host {
|
||||||
private:
|
private:
|
||||||
|
std::vector<Peer*> m_peersToDelete;
|
||||||
|
void processPeersToDelete();
|
||||||
|
|
||||||
void *host;
|
void *host;
|
||||||
uint64 rxBytes, txBytes;
|
uint64 rxBytes, txBytes;
|
||||||
|
|
||||||
|
@ -187,17 +209,27 @@ private:
|
||||||
Host& operator=(Host&) = delete;
|
Host& operator=(Host&) = delete;
|
||||||
Host& operator=(const Host&) = delete;
|
Host& operator=(const Host&) = delete;
|
||||||
|
|
||||||
|
void sendKeyExchange(Peer&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Timeout = uint32;
|
using Timeout = uint32;
|
||||||
|
|
||||||
|
public:
|
||||||
Host();
|
Host();
|
||||||
~Host();
|
~Host();
|
||||||
void create(Port port = 0, uint maxconn = 64);
|
void create(Port port = 0, uint maxconn = 64);
|
||||||
Peer connect(const std::string &hostAddr, Port port, Timeout timeout);
|
Peer& connect(const std::string &hostAddr, Port port, Timeout timeout);
|
||||||
|
|
||||||
void send(Peer &peer, const OutMessage &msg, Tfer mode = Tfer::Rel, Channels chan = Channels::Base);
|
void send(Peer &peer, const OutMessage &msg, Tfer mode = Tfer::Rel, Channels chan = Channels::Base);
|
||||||
bool recv(InMessage &msg, Peer &peer, Timeout timeout);
|
|
||||||
bool recv(InMessage &msg, Timeout timeout = 0);
|
// Returns true if a message is available, and put it in msg.
|
||||||
|
// msg may be modified even if recv returns false.
|
||||||
|
// If the msg is a NetDisconnect, returned peer object is put on a deletion list and will be
|
||||||
|
// freed upon the next call to recv.
|
||||||
|
bool recv(InMessage &msg, Peer **peer, Timeout timeout);
|
||||||
|
inline bool recv(InMessage &msg, Timeout timeout) {
|
||||||
|
return recv(msg, nullptr, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
inline uint64 getRxBytes() const {
|
inline uint64 getRxBytes() const {
|
||||||
return rxBytes;
|
return rxBytes;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include "ConnectionParam.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Net {
|
||||||
|
namespace MsgTypes {
|
||||||
|
|
||||||
|
void ConnectionParamDHKeyExchange::writeToMsg(OutMessage &msg) const {
|
||||||
|
msg.setType(MessageType::ConnectionParam, ConnectionParamSubtype::DHKeyExchange);
|
||||||
|
|
||||||
|
msg.writeData(reinterpret_cast<const char*>(&pk.bytes), pk.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectionParamDHKeyExchange::readFromMsg(InMessage &msg) {
|
||||||
|
msg.readData(&pk.bytes, pk.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef DIGGLER_NET_MSGTYPES_CONNECTIONPARAM_HPP
|
||||||
|
#define DIGGLER_NET_MSGTYPES_CONNECTIONPARAM_HPP
|
||||||
|
|
||||||
|
#include "MsgType.hpp"
|
||||||
|
|
||||||
|
#include "../../crypto/DiffieHellman.hpp"
|
||||||
|
|
||||||
|
namespace Diggler {
|
||||||
|
namespace Net {
|
||||||
|
namespace MsgTypes {
|
||||||
|
|
||||||
|
enum class ConnectionParamSubtype : uint8 {
|
||||||
|
DHKeyExchange
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConnectionParamDHKeyExchange : public MsgType {
|
||||||
|
Crypto::DiffieHellman::PublicKey pk;
|
||||||
|
|
||||||
|
void writeToMsg(OutMessage&) const override;
|
||||||
|
void readFromMsg(InMessage&) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DIGGLER_NET_MSGTYPES_CONNECTIONPARAM_HPP */
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef DIGGLER_PLATFORM_PREPROC_UTILS_HPP
|
||||||
|
#define DIGGLER_PLATFORM_PREPROC_UTILS_HPP
|
||||||
|
|
||||||
|
#define nocopy(c) c(const c&)=delete;c& operator=(const c&)=delete
|
||||||
|
#define nomove(c) c(c&&)=delete;c& operator=(c&&)=delete
|
||||||
|
#define nocopymove(c) nocopy(c);nomove(c)
|
||||||
|
|
||||||
|
#define defaultcopy(c) c(const c&)=default;c& operator=(const c&)=default
|
||||||
|
#define defaultmove(c) c(c&&)=default;c& operator=(c&&)=default
|
||||||
|
#define defaultcopymove(c) defaultcopy(c);defaultmove(c)
|
||||||
|
|
||||||
|
#endif /* DIGGLER_PLATFORM_PREPROC_UTILS_HPP */
|
|
@ -1,18 +1,21 @@
|
||||||
#ifndef DIGGLER_PLATFORM_TYPES_HPP
|
#ifndef DIGGLER_PLATFORM_TYPES_HPP
|
||||||
#define DIGGLER_PLATFORM_TYPES_HPP
|
#define DIGGLER_PLATFORM_TYPES_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
|
|
||||||
using int32 = int32_t;
|
using uint = std::uint32_t;
|
||||||
using uint = uint32_t;
|
using uint32 = std::uint32_t;
|
||||||
using uint32 = uint32_t;
|
using uint64 = std::uint64_t;
|
||||||
using uint64 = uint64_t;
|
using uint16 = std::uint16_t;
|
||||||
using uint16 = uint16_t;
|
using uint8 = std::uint8_t;
|
||||||
using uint8 = uint8_t;
|
using int64 = std::int64_t;
|
||||||
using int64 = int64_t;
|
using int32 = std::int32_t;
|
||||||
using int16 = int16_t;
|
using int16 = std::int16_t;
|
||||||
using int8 = int8_t;
|
using int8 = std::int8_t;
|
||||||
using byte = uint8_t;
|
using byte = std::uint8_t;
|
||||||
using char32 = char32_t;
|
using char32 = char32_t;
|
||||||
using char16 = char16_t;
|
using char16 = char16_t;
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,10 @@ protected:
|
||||||
public:
|
public:
|
||||||
virtual ~Renderer() = 0;
|
virtual ~Renderer() = 0;
|
||||||
|
|
||||||
ParticlesRenderer *PR;
|
struct Renderers {
|
||||||
WorldRenderer *WR;
|
ParticlesRenderer *particles;
|
||||||
|
WorldRenderer *world;
|
||||||
|
} renderers;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Renderer::~Renderer() {}
|
inline Renderer::~Renderer() {}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "FBO.hpp"
|
#include "FBO.hpp"
|
||||||
|
|
||||||
|
#include "FeatureSupport.hpp"
|
||||||
#include "Util.hpp"
|
#include "Util.hpp"
|
||||||
|
|
||||||
#ifdef IN_IDE_PARSER
|
#ifdef IN_IDE_PARSER
|
||||||
|
@ -32,13 +33,25 @@ FBO::FBO(int w, int h, Texture::PixelFormat format, bool stencil) : m_hasStencil
|
||||||
// Set up renderbuffer to which depth/stencil will be written to
|
// Set up renderbuffer to which depth/stencil will be written to
|
||||||
glGenRenderbuffers(1, &rboId);
|
glGenRenderbuffers(1, &rboId);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
|
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
|
||||||
if (stencil)
|
if (stencil) {
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
|
glRenderbufferStorage(GL_RENDERBUFFER, FeatureSupport::FBO_ARB ? GL_DEPTH24_STENCIL8 :
|
||||||
else
|
GL_DEPTH24_STENCIL8_OES, w, h);
|
||||||
|
} else {
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, w, h);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex, 0);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
|
if (stencil) {
|
||||||
|
if (FeatureSupport::FBO_ARB) {
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||||
|
rboId);
|
||||||
|
} else {
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
|
||||||
|
}
|
||||||
|
|
||||||
glCheck();
|
glCheck();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "FeatureSupport.hpp"
|
#include "FeatureSupport.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Diggler {
|
namespace Diggler {
|
||||||
namespace Render {
|
namespace Render {
|
||||||
namespace gl {
|
namespace gl {
|
||||||
|
@ -11,17 +13,32 @@ bool
|
||||||
F::DSA_ARB,
|
F::DSA_ARB,
|
||||||
F::DSA_EXT,
|
F::DSA_EXT,
|
||||||
F::DSA,
|
F::DSA,
|
||||||
F::shader_image_load_store;
|
F::shader_image_load_store,
|
||||||
|
F::FBO_ARB;
|
||||||
|
|
||||||
void F::probe() {
|
void F::probe() {
|
||||||
VAO = epoxy_has_gl_extension("GL_ARB_vertex_array_object") or
|
VAO = epoxy_has_gl_extension("GL_ARB_vertex_array_object") or
|
||||||
epoxy_has_gl_extension("GL_OES_vertex_array_object");
|
epoxy_has_gl_extension("GL_OES_vertex_array_object");
|
||||||
DSA_ARB = epoxy_has_gl_extension("ARB_direct_state_access");
|
DSA_ARB = epoxy_has_gl_extension("GL_ARB_direct_state_access");
|
||||||
DSA_EXT = epoxy_has_gl_extension("EXT_direct_state_access");
|
DSA_EXT = epoxy_has_gl_extension("GL_EXT_direct_state_access");
|
||||||
DSA = DSA_ARB or DSA_EXT;
|
DSA = DSA_ARB or DSA_EXT;
|
||||||
shader_image_load_store = epoxy_has_gl_extension("ARB_shader_image_load_store");
|
shader_image_load_store = epoxy_has_gl_extension("GL_ARB_shader_image_load_store");
|
||||||
|
FBO_ARB = epoxy_has_gl_extension("GL_ARB_framebuffer_object");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define feature(x) if(x){oss<<#x<<std::endl;}
|
||||||
|
std::string F::supported() {
|
||||||
|
std::ostringstream oss;
|
||||||
|
feature(VAO);
|
||||||
|
feature(DSA_ARB);
|
||||||
|
feature(DSA_EXT);
|
||||||
|
feature(DSA);
|
||||||
|
feature(shader_image_load_store);
|
||||||
|
feature(FBO_ARB);
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
#undef feature
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,11 @@ public:
|
||||||
DSA_ARB /* Direct State Access, ARB version */,
|
DSA_ARB /* Direct State Access, ARB version */,
|
||||||
DSA_EXT /* Direct State Access, EXT version */,
|
DSA_EXT /* Direct State Access, EXT version */,
|
||||||
DSA /* Direct State Access, one or move of above */,
|
DSA /* Direct State Access, one or move of above */,
|
||||||
shader_image_load_store;
|
shader_image_load_store,
|
||||||
|
FBO_ARB /* FrameBuffer Obects, ARB version */;
|
||||||
|
|
||||||
static void probe();
|
static void probe();
|
||||||
|
static std::string supported();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,9 @@ public:
|
||||||
GLRenderer(Game *G) :
|
GLRenderer(Game *G) :
|
||||||
Renderer(G) {
|
Renderer(G) {
|
||||||
FeatureSupport::probe();
|
FeatureSupport::probe();
|
||||||
PR = new GLParticlesRenderer(G);
|
getDebugStream() << "GLRenderer, using features: " << FeatureSupport::supported() << std::endl;
|
||||||
WR = new GLWorldRenderer(G);
|
renderers.particles = new GLParticlesRenderer(G);
|
||||||
|
renderers.world = new GLWorldRenderer(G);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,11 @@ public:
|
||||||
m_id(0),
|
m_id(0),
|
||||||
m_size(0),
|
m_size(0),
|
||||||
m_usage(GL_STATIC_DRAW) {
|
m_usage(GL_STATIC_DRAW) {
|
||||||
glGenBuffers(1, &m_id);
|
if (FeatureSupport::DSA_ARB) {
|
||||||
|
glCreateBuffers(1, &m_id);
|
||||||
|
} else {
|
||||||
|
glGenBuffers(1, &m_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~VBO() {
|
~VBO() {
|
||||||
|
|
|
@ -64,7 +64,7 @@ Font::Font(Game *G, const std::string& path) : G(G) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Vertex { int x, y; float tx, ty; float r, g, b ,a; };
|
struct Vertex { int16 x, y; float tx, ty; float r, g, b ,a; };
|
||||||
|
|
||||||
#define eraseCurChar() elements -= 6;
|
#define eraseCurChar() elements -= 6;
|
||||||
|
|
||||||
|
@ -121,16 +121,16 @@ int Font::updateVBO(Render::gl::VBO &vbo, const std::string &text, GLenum usage)
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::draw(const Render::gl::VBO &vbo, int count, const glm::mat4& matrix) const {
|
void Font::draw(const Render::gl::VBO &vbo, int count, const glm::mat4 &matrix) const {
|
||||||
|
R.prog->bind();
|
||||||
glEnableVertexAttribArray(R.att_coord);
|
glEnableVertexAttribArray(R.att_coord);
|
||||||
glEnableVertexAttribArray(R.att_texcoord);
|
glEnableVertexAttribArray(R.att_texcoord);
|
||||||
glEnableVertexAttribArray(R.att_color);
|
glEnableVertexAttribArray(R.att_color);
|
||||||
|
|
||||||
R.prog->bind();
|
|
||||||
m_texture->bind();
|
m_texture->bind();
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
glUniformMatrix4fv(R.uni_mvp, 1, GL_FALSE, glm::value_ptr(matrix));
|
glUniformMatrix4fv(R.uni_mvp, 1, GL_FALSE, glm::value_ptr(matrix));
|
||||||
glVertexAttribPointer(R.att_coord, 2, GL_INT, GL_FALSE, sizeof(Vertex), 0);
|
glVertexAttribPointer(R.att_coord, 2, GL_SHORT, GL_FALSE, sizeof(Vertex), 0);
|
||||||
glVertexAttribPointer(R.att_texcoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, tx));
|
glVertexAttribPointer(R.att_texcoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, tx));
|
||||||
glVertexAttribPointer(R.att_color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, r));
|
glVertexAttribPointer(R.att_color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, r));
|
||||||
glDrawArrays(GL_TRIANGLES, 0, count);
|
glDrawArrays(GL_TRIANGLES, 0, count);
|
||||||
|
|
Loading…
Reference in New Issue