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
|
||||
assets-orig
|
||||
build
|
||||
build-*
|
||||
*.fossil
|
||||
*.project
|
||||
*.kdev4
|
||||
*.user
|
||||
TODO.txt
|
||||
diggler.cfg
|
||||
.kdev_include_paths
|
||||
.kdev_include_paths
|
||||
_*
|
||||
|
|
|
@ -10,3 +10,6 @@
|
|||
[submodule "ext/StackTracePlus"]
|
||||
path = ext/StackTracePlus
|
||||
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)
|
||||
|
||||
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
|
||||
file(RELATIVE_PATH REL_BUILD_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
|
||||
string(FIND "${REL_BUILD_PATH}" ".." RBP_2DOTPOS)
|
||||
|
@ -43,13 +59,13 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
|||
|
||||
find_package(CXX14)
|
||||
if (NOT CXX14_FOUND)
|
||||
message(FATAL_ERROR "C++14 feature support unavailable.
|
||||
Please use the latest version of your compiler.
|
||||
|
||||
Here are the minimum requirements:
|
||||
- GCC version 5 (on Debian Jessie, enable Stretch/testing repos and get GCC from there)
|
||||
- clang version 3.4
|
||||
- MSVC: wait until Microsoft goes bankrupt, and use another compiler in the meantime
|
||||
message(FATAL_ERROR "C++14 feature support unavailable.\
|
||||
Please use the latest version of your compiler.\
|
||||
\
|
||||
Here are the minimum requirements:\
|
||||
- GCC version 5 (on Debian Jessie, enable Stretch/testing repos and get GCC from there)\
|
||||
- clang version 3.4\
|
||||
- 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")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CXX14_FLAGS} ${CMAKE_CXX_FLAGS}")
|
||||
|
@ -71,6 +87,8 @@ endif()
|
|||
|
||||
pkg_search_module(EPOXY REQUIRED epoxy)
|
||||
pkg_search_module(GLFW REQUIRED glfw3)
|
||||
pkg_search_module(SQLITE3 REQUIRED sqlite3)
|
||||
pkg_search_module(LIBSODIUM REQUIRED libsodium)
|
||||
include_directories(
|
||||
${ETC_INCLUDE_DIRS}
|
||||
${LUA_INCLUDE_DIR}
|
||||
|
@ -78,6 +96,8 @@ include_directories(
|
|||
${ENET_INCLUDE_DIRS}
|
||||
${EPOXY_INCLUDE_DIRS}
|
||||
${GLFW_INCLUDE_DIRS}
|
||||
${LIBSODIUM_INCLUDE_DIRS}
|
||||
${SQLITE3_INCLUDE_DIRS}
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
${MSGPACK_INCLUDE_DIR}
|
||||
)
|
||||
|
@ -94,6 +114,8 @@ target_link_libraries(diggler
|
|||
${ENET_LIBRARIES}
|
||||
${EPOXY_LIBRARIES}
|
||||
${GLFW_LIBRARIES}
|
||||
${LIBSODIUM_LIBRARIES}
|
||||
${SQLITE3_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
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`
|
||||
|
||||
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)
|
||||
|
||||
set(CXX14_FLAG_CANDIDATES
|
||||
#Gnu and Intel Linux
|
||||
"-std=c++14"
|
||||
#Microsoft Visual Studio, and everything that automatically accepts C++14
|
||||
# GCC 6+ and everything that automatically accepts C++14
|
||||
" "
|
||||
#Intel windows
|
||||
# GCC < 6 and Intel Linux
|
||||
"-std=c++14"
|
||||
# Intel Windows
|
||||
"/Qstd=c++14"
|
||||
)
|
||||
|
||||
|
@ -24,6 +24,9 @@ set(CXX14_TEST_SOURCE
|
|||
"
|
||||
[[deprecated]] void unused() {}
|
||||
|
||||
template<typename T>
|
||||
constexpr T pi = T(3.1415926535897932385);
|
||||
|
||||
constexpr int numberwang(int n) {
|
||||
if (n < 0) {
|
||||
return 0b1'1001'0101;
|
||||
|
@ -31,7 +34,7 @@ constexpr int numberwang(int n) {
|
|||
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) {
|
||||
return lambda(n, n) * numberwang(2);
|
||||
|
@ -39,6 +42,7 @@ auto square(int n) {
|
|||
|
||||
int main() {
|
||||
int s = square(3);
|
||||
double pie = pi<double>;
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
|
@ -47,7 +51,7 @@ foreach(FLAG ${CXX14_FLAG_CANDIDATES})
|
|||
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
|
||||
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)
|
||||
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
|
||||
if(CXX14_FLAG_DETECTED)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 3922965396fc455c6b1770374b9b4111799588a9
|
|
@ -5,7 +5,7 @@ local grassBlock = {
|
|||
variabilty = {'static'},
|
||||
textures = {
|
||||
grass = {
|
||||
path = 'tex/grass.png',
|
||||
path = 'self:/tex/grass.png',
|
||||
['repeat'] = {
|
||||
xdiv = 8,
|
||||
ydiv = 8
|
||||
|
|
|
@ -16,6 +16,8 @@ set(SRCS
|
|||
${CSD}/Chunk.cpp
|
||||
${CSD}/Clouds.cpp
|
||||
${CSD}/Config.cpp
|
||||
${CSD}/content/AssetManager.cpp
|
||||
${CSD}/content/ModManager.cpp
|
||||
${CSD}/content/Registry.cpp
|
||||
${CSD}/EscMenu.cpp
|
||||
${CSD}/Frustum.cpp
|
||||
|
@ -34,6 +36,8 @@ set(SRCS
|
|||
${CSD}/network/msgtypes/BlockUpdate.cpp
|
||||
${CSD}/network/msgtypes/Chat.cpp
|
||||
${CSD}/network/msgtypes/ChunkTransfer.cpp
|
||||
${CSD}/network/msgtypes/ConnectionParam.cpp
|
||||
${CSD}/network/msgtypes/PlayerUpdate.cpp
|
||||
${CSD}/network/msgtypes/ServerInfo.cpp
|
||||
${CSD}/network/ClientMessageHandler.cpp
|
||||
${CSD}/network/NetHelper.cpp
|
||||
|
|
|
@ -92,7 +92,7 @@ Chunk::Chunk(Game *G, WorldRef W, int X, int Y, int Z) :
|
|||
calcMemUsage();
|
||||
|
||||
if (GlobalProperties::IsClient) {
|
||||
G->R->WR->registerChunk(this);
|
||||
G->R->renderers.world->registerChunk(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ Chunk::~Chunk() {
|
|||
std::free(imcData);
|
||||
#endif
|
||||
if (GlobalProperties::IsClient) {
|
||||
G->R->WR->unregisterChunk(this);
|
||||
G->R->renderers.world->unregisterChunk(this);
|
||||
}
|
||||
// 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;
|
||||
mut.unlock();
|
||||
}
|
||||
|
|
69
src/Game.cpp
69
src/Game.cpp
|
@ -1,6 +1,8 @@
|
|||
#include "Game.hpp"
|
||||
|
||||
#include "Audio.hpp"
|
||||
#include "content/AssetManager.hpp"
|
||||
#include "content/ModManager.hpp"
|
||||
#include "content/Registry.hpp"
|
||||
#include "GlobalProperties.hpp"
|
||||
#include "KeyBinds.hpp"
|
||||
|
@ -20,42 +22,67 @@ Game::Game() :
|
|||
|
||||
void Game::init() {
|
||||
CR = new Content::Registry;
|
||||
AM = std::make_unique<Content::AssetManager>(this);
|
||||
MM = std::make_unique<Content::ModManager>(this);
|
||||
LS = new Scripting::Lua::State(this);
|
||||
if (GlobalProperties::IsClient) {
|
||||
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;
|
||||
initClient();
|
||||
}
|
||||
if (GlobalProperties::IsServer) {
|
||||
initServer();
|
||||
}
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
delete CR;
|
||||
void Game::initClient() {
|
||||
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) {
|
||||
delete KB;
|
||||
delete A;
|
||||
delete R;
|
||||
delete RP;
|
||||
delete LP;
|
||||
delete PM;
|
||||
finalizeClient();
|
||||
}
|
||||
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) {
|
||||
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
|
||||
#define GAME_HPP
|
||||
#ifndef DIGGLER_GAME_HPP
|
||||
#define DIGGLER_GAME_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ui/FontManager.hpp"
|
||||
#include "Universe.hpp"
|
||||
#include "PlayerList.hpp"
|
||||
|
@ -12,6 +14,8 @@ using std::shared_ptr;
|
|||
namespace Diggler {
|
||||
|
||||
namespace Content {
|
||||
class AssetManager;
|
||||
class ModManager;
|
||||
class Registry;
|
||||
}
|
||||
|
||||
|
@ -35,7 +39,11 @@ class GameWindow;
|
|||
class KeyBinds;
|
||||
class Server;
|
||||
|
||||
class Game {
|
||||
class Game final {
|
||||
private:
|
||||
template<typename T>
|
||||
using ptr = std::unique_ptr<T>;
|
||||
|
||||
public:
|
||||
// Shared
|
||||
double Time; uint64 TimeMs;
|
||||
|
@ -43,6 +51,8 @@ public:
|
|||
Universe *U;
|
||||
PlayerList players;
|
||||
Content::Registry *CR;
|
||||
ptr<Content::AssetManager> AM;
|
||||
ptr<Content::ModManager> MM;
|
||||
Scripting::Lua::State *LS;
|
||||
|
||||
// Server
|
||||
|
@ -61,16 +71,22 @@ public:
|
|||
float fogStart, fogEnd;
|
||||
} *RP;
|
||||
Audio *A;
|
||||
Net::Peer NS;
|
||||
Net::Peer *NS;
|
||||
KeyBinds *KB;
|
||||
int PlayerPosUpdateFreq;
|
||||
|
||||
Game();
|
||||
void init();
|
||||
void initClient();
|
||||
void initServer();
|
||||
void finalize();
|
||||
void finalizeClient();
|
||||
void finalizeServer();
|
||||
|
||||
void updateTime(double time);
|
||||
~Game();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* DIGGLER_GAME_HPP */
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "network/NetHelper.hpp"
|
||||
#include "Particles.hpp"
|
||||
|
||||
#include "network/msgtypes/PlayerUpdate.hpp"
|
||||
#include "network/msgtypes/BlockUpdate.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.uni_unicolor = m_highlightBox.program->uni("unicolor");
|
||||
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_3dRenderVBO = new Render::gl::VBO();
|
||||
|
@ -388,7 +393,7 @@ void GameState::updateViewport() {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
@ -402,13 +407,15 @@ bool GameState::connectLoop() {
|
|||
std::string &serverHost = m_serverHost;
|
||||
int serverPort = m_serverPort;
|
||||
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 {
|
||||
G->H.create();
|
||||
G->NS = G->H.connect(serverHost, serverPort, 5000);
|
||||
G->NS = &G->H.connect(serverHost, serverPort, 5000);
|
||||
success = true;
|
||||
} catch (const Net::Exception &e) {
|
||||
success = false;
|
||||
failureStr = e.what();
|
||||
}
|
||||
finished = true;
|
||||
});
|
||||
|
@ -447,9 +454,7 @@ bool GameState::connectLoop() {
|
|||
if (GW->shouldClose())
|
||||
return true;
|
||||
if (!success) {
|
||||
std::ostringstream oss;
|
||||
oss << serverHost << ':' << serverPort << " did not respond";
|
||||
GW->showMessage("Could not connect to server", oss.str());
|
||||
GW->showMessage("Could not connect to server", failureStr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -469,7 +474,7 @@ bool GameState::connectLoop() {
|
|||
switch (m_msg.getType()) {
|
||||
case Net::MessageType::PlayerJoin: {
|
||||
G->U = new Universe(G, true);
|
||||
LP.id = m_msg.readU32();
|
||||
LP.sessId = m_msg.readU32();
|
||||
LP.W = G->U->createWorld(m_msg.readI16());
|
||||
} break;
|
||||
case Net::MessageType::PlayerQuit: {
|
||||
|
@ -488,7 +493,7 @@ bool GameState::connectLoop() {
|
|||
G->LS->setGameLuaRuntimePath(gameLuaRuntimePath);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -520,11 +525,14 @@ void GameState::gameLoop() {
|
|||
|
||||
if (G->LP->isAlive) {
|
||||
if (T > nextNetUpdate) {
|
||||
Net::OutMessage msg(Net::MessageType::PlayerUpdate, Net::PlayerUpdateType::Move);
|
||||
msg.writeVec3(LP->position);
|
||||
msg.writeVec3(LP->velocity);
|
||||
msg.writeVec3(LP->accel);
|
||||
msg.writeFloat(LP->angle);
|
||||
Net::MsgTypes::PlayerUpdateMove pum;
|
||||
pum.position = LP->position;
|
||||
if (LP->velocity != glm::vec3()) {
|
||||
pum.velocity = LP->velocity;
|
||||
pum.accel = LP->accel;
|
||||
}
|
||||
pum.angle = LP->angle;
|
||||
Net::OutMessage msg; pum.writeToMsg(msg);
|
||||
sendMsg(msg, Net::Tfer::Unrel, Net::Channels::Movement);
|
||||
nextNetUpdate = T+1.0/G->PlayerPosUpdateFreq;
|
||||
}
|
||||
|
@ -560,7 +568,7 @@ void GameState::gameLoop() {
|
|||
rp.world = WR.get();
|
||||
rp.transform = m_transform;
|
||||
rp.frustum = G->LP->camera.frustum;
|
||||
G->R->WR->render(rp);
|
||||
G->R->renderers.world->render(rp);
|
||||
for (Player &p : G->players) {
|
||||
p.update(deltaT);
|
||||
if (G->LP->camera.frustum.sphereInFrustum(p.position, 2))
|
||||
|
@ -591,16 +599,14 @@ void GameState::gameLoop() {
|
|||
// TODO: replace harcoded 32 viewdistance
|
||||
if (G->LP->raytracePointed(32, &m_pointedBlock, &m_pointedFacing)) {
|
||||
m_highlightBox.program->bind();
|
||||
glEnableVertexAttribArray(m_highlightBox.att_coord);
|
||||
m_highlightBox.vbo.bind();
|
||||
glVertexAttribPointer(m_highlightBox.att_coord, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
m_highlightBox.vao.bind();
|
||||
|
||||
glUniform4f(m_highlightBox.uni_unicolor, 1.f, 1.f, 1.f, .1f);
|
||||
glUniformMatrix4fv(m_highlightBox.uni_mvp, 1, GL_FALSE, glm::value_ptr(
|
||||
glm::scale(glm::translate(m_transform, glm::vec3(m_pointedBlock)+glm::vec3(.5f)), glm::vec3(0.5f*1.03f))));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6*2*3);
|
||||
|
||||
glDisableVertexAttribArray(m_highlightBox.att_coord);
|
||||
m_highlightBox.vao.unbind();
|
||||
}
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
@ -622,7 +628,7 @@ void GameState::gameLoop() {
|
|||
glEnableVertexAttribArray(bloom.extractor.att_texcoord);
|
||||
m_3dRenderVBO->bind();
|
||||
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));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glDisableVertexAttribArray(bloom.extractor.att_texcoord);
|
||||
|
@ -639,7 +645,7 @@ void GameState::gameLoop() {
|
|||
m_3dRenderVBO->bind();
|
||||
glUniformMatrix4fv(bloom.renderer.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
||||
glUniform2f(bloom.renderer.uni_pixshift, 1.f/(GW->getW()/bloom.scale), 1.f/(GW->getH()/bloom.scale));
|
||||
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));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glDisableVertexAttribArray(bloom.renderer.att_texcoord);
|
||||
|
@ -656,7 +662,7 @@ void GameState::gameLoop() {
|
|||
glEnableVertexAttribArray(bloom.renderer.att_texcoord);
|
||||
m_3dRenderVBO->bind();
|
||||
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));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glDisableVertexAttribArray(bloom.renderer.att_texcoord);
|
||||
|
@ -675,8 +681,9 @@ void GameState::gameLoop() {
|
|||
}
|
||||
if (!G->LP->deathSent) {
|
||||
G->LP->deathSent = true;
|
||||
Net::OutMessage out(Net::MessageType::PlayerUpdate, Net::PlayerUpdateType::Die);
|
||||
out.writeU8((uint8)G->LP->deathReason);
|
||||
Net::MsgTypes::PlayerUpdateDie pud;
|
||||
pud.reason = G->LP->deathReason;
|
||||
Net::OutMessage out; pud.writeToMsg(out);
|
||||
sendMsg(out, Net::Tfer::Rel, Net::Channels::Life);
|
||||
}
|
||||
renderDeathScreen();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "GameWindow.hpp"
|
||||
#include "render/gl/FBO.hpp"
|
||||
#include "render/gl/VBO.hpp"
|
||||
#include "render/gl/VAO.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "network/Network.hpp"
|
||||
#include "network/ClientMessageHandler.hpp"
|
||||
|
@ -69,7 +70,7 @@ private:
|
|||
} bloom;
|
||||
|
||||
Render::gl::VBO *m_3dRenderVBO;
|
||||
struct Coord2DTex { int x, y; uint8 u, v; };
|
||||
struct Coord2DTex { int16 x, y; uint8 u, v; };
|
||||
Clouds *m_clouds;
|
||||
Skybox *m_sky;
|
||||
|
||||
|
@ -80,6 +81,7 @@ private:
|
|||
|
||||
struct {
|
||||
Render::gl::VBO vbo;
|
||||
Render::gl::VAO vao;
|
||||
const Program *program;
|
||||
GLuint att_coord, uni_unicolor, uni_mvp;
|
||||
} m_highlightBox;
|
||||
|
|
|
@ -116,7 +116,7 @@ GameWindow::GameWindow(Game *G) : G(G) {
|
|||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
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_STENCIL_BITS, 8);
|
||||
|
||||
|
@ -190,6 +190,8 @@ GameWindow::GameWindow(Game *G) : G(G) {
|
|||
}
|
||||
|
||||
GameWindow::~GameWindow() {
|
||||
m_currentState.reset();
|
||||
m_nextState.reset();
|
||||
delete UIM;
|
||||
|
||||
glfwDestroyWindow(m_window);
|
||||
|
@ -243,13 +245,13 @@ void GameWindow::cbResize(int w, int h) {
|
|||
m_currentState->onResize(w, h);
|
||||
}
|
||||
|
||||
void GameWindow::setNextState(const shared_ptr<State> next) {
|
||||
m_nextState = next;
|
||||
void GameWindow::setNextState(std::unique_ptr<State> &&next) {
|
||||
m_nextState = std::move(next);
|
||||
}
|
||||
|
||||
void GameWindow::run() {
|
||||
while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
|
||||
m_currentState = m_nextState;
|
||||
m_currentState = std::move(m_nextState);
|
||||
m_nextState = nullptr;
|
||||
UIM->clear();
|
||||
m_currentState->run();
|
||||
|
@ -257,7 +259,7 @@ void GameWindow::run() {
|
|||
}
|
||||
|
||||
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 "ui/Manager.hpp"
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
namespace Diggler {
|
||||
|
||||
class Game;
|
||||
|
@ -22,7 +20,7 @@ private:
|
|||
GLFWwindow *m_window;
|
||||
int m_w, m_h;
|
||||
|
||||
shared_ptr<State> m_currentState, m_nextState;
|
||||
std::unique_ptr<State> m_currentState, m_nextState;
|
||||
|
||||
public:
|
||||
UI::Manager *UIM;
|
||||
|
@ -52,7 +50,7 @@ public:
|
|||
|
||||
void updateViewport();
|
||||
|
||||
void setNextState(const shared_ptr<State> next);
|
||||
void setNextState(std::unique_ptr<State> &&next);
|
||||
void run();
|
||||
|
||||
void showMessage(const std::string &msg, const std::string &submsg = "");
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Audio.hpp"
|
||||
#include "Game.hpp"
|
||||
#include "network/NetHelper.hpp"
|
||||
#include "render/gl/VAO.hpp"
|
||||
|
||||
namespace Diggler {
|
||||
|
||||
|
@ -174,14 +175,11 @@ void LocalPlayer::update(float delta) {
|
|||
}
|
||||
|
||||
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;
|
||||
const glm::ivec3 &min = aabbmin, &max = aabbmax;
|
||||
struct Coord { int x, y, z; uint8 r, g, b; } pts[] = {
|
||||
static Render::gl::VAO vao;
|
||||
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 },
|
||||
{ max.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 },
|
||||
};
|
||||
vbo.setDataKeepSize(pts, sizeof(pts)/sizeof(Coord), GL_STREAM_DRAW);
|
||||
vbo.bind();
|
||||
glVertexAttribPointer(P->att("coord"), 3, GL_INT, GL_FALSE, sizeof(Coord), 0);
|
||||
glVertexAttribPointer(P->att("color"), 3, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Coord), (GLvoid*)(offsetof(Coord, r)));
|
||||
const Program &P = *G->PM->getProgram(PM_3D | PM_COLORED);
|
||||
if (!vaoConfigured) {
|
||||
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));
|
||||
glDisableVertexAttribArray(P->att("color"));
|
||||
glDisableVertexAttribArray(P->att("coord"));
|
||||
vao.unbind();
|
||||
}
|
||||
|
||||
void LocalPlayer::forceCameraUpdate() {
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Diggler {
|
|||
|
||||
ParticleEmitter::ParticleEmitter(Game *G) :
|
||||
G(G) {
|
||||
G->R->PR->registerEmitter(this);
|
||||
G->R->renderers.particles->registerEmitter(this);
|
||||
}
|
||||
|
||||
ParticleEmitter::~ParticleEmitter() {
|
||||
G->R->PR->unregisterEmitter(this);
|
||||
G->R->renderers.particles->unregisterEmitter(this);
|
||||
}
|
||||
|
||||
void ParticleEmitter::setMaxCount(uint count) {
|
||||
|
@ -35,7 +35,7 @@ void ParticleEmitter::emit(Particle &p) {
|
|||
void ParticleEmitter::update(double delta) {
|
||||
ParticleRenderData *data = new ParticleRenderData[maxCount];
|
||||
float deltaF = delta;
|
||||
for (int i=0; i < maxCount; ++i) {
|
||||
for (uint i = 0; i < maxCount; ++i) {
|
||||
Particle &p = particles[i];
|
||||
p.vel += p.accel * deltaF;
|
||||
p.pos += p.vel * deltaF;
|
||||
|
@ -44,7 +44,7 @@ void ParticleEmitter::update(double delta) {
|
|||
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 };
|
||||
}
|
||||
G->R->PR->updateParticleData(this, data, maxCount);
|
||||
G->R->renderers.particles->updateParticleData(this, data, maxCount);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,14 @@
|
|||
|
||||
namespace Diggler {
|
||||
|
||||
Player::Renderer Player::R = {0};
|
||||
Player::Renderer Player::R = {};
|
||||
|
||||
Player::Player(Game *G) :
|
||||
G(G), position(0), velocity(0), accel(0), angle(0), toolUseTime(0),
|
||||
isAlive(true) {
|
||||
G(G),
|
||||
angle(0),
|
||||
toolUseTime(0),
|
||||
isAlive(true),
|
||||
peer(nullptr) {
|
||||
if (GlobalProperties::IsClient) {
|
||||
if (R.prog == nullptr) {
|
||||
R.prog = G->PM->getProgram(PM_3D | PM_FOG);
|
||||
|
@ -31,34 +34,12 @@ Player::Player(Game *G) :
|
|||
-sz, .0f, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
lastPosition = m_predictPos;
|
||||
position = m_predictPos = pos;
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
#define PLAYER_HPP
|
||||
#include "Platform.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
#include "platform/PreprocUtils.hpp"
|
||||
#include "network/Network.hpp"
|
||||
#include "World.hpp"
|
||||
|
||||
|
@ -14,6 +17,7 @@ namespace Diggler {
|
|||
|
||||
class Program;
|
||||
namespace Render {
|
||||
class PlayerRenderer;
|
||||
namespace gl {
|
||||
class VBO;
|
||||
}
|
||||
|
@ -25,6 +29,9 @@ using PlayerGameID = uint32;
|
|||
|
||||
class Player {
|
||||
protected:
|
||||
friend class Render::PlayerRenderer;
|
||||
uintptr_t rendererData;
|
||||
|
||||
static struct Renderer {
|
||||
const Program *prog;
|
||||
GLint att_coord,
|
||||
|
@ -32,13 +39,10 @@ protected:
|
|||
uni_unicolor,
|
||||
uni_fogStart,
|
||||
uni_fogEnd;
|
||||
Render::gl::VBO *vbo;
|
||||
std::unique_ptr<Render::gl::VBO> vbo;
|
||||
} R;
|
||||
double m_lastPosTime;
|
||||
glm::vec3 m_predictPos;
|
||||
|
||||
Player(const Player&) = delete;
|
||||
Player& operator=(const Player&) = delete;
|
||||
|
||||
public:
|
||||
enum class Direction : uint8 {
|
||||
|
@ -60,15 +64,15 @@ public:
|
|||
glm::vec3 position, lastPosition, velocity, accel;
|
||||
float angle; double toolUseTime;
|
||||
std::string name;
|
||||
uint32 id;
|
||||
using SessionID = uint32;
|
||||
SessionID sessId;
|
||||
bool isAlive;
|
||||
Net::Peer P;
|
||||
Net::Peer *peer;
|
||||
std::list<ChunkRef> pendingChunks;
|
||||
|
||||
Player(Game *G = nullptr);
|
||||
Player(Player&&);
|
||||
Player& operator=(Player&&);
|
||||
~Player();
|
||||
nocopy(Player);
|
||||
defaultmove(Player);
|
||||
|
||||
void setPosVel(const glm::vec3 &pos, const glm::vec3 &vel, const glm::vec3 &acc = glm::vec3());
|
||||
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");
|
||||
}
|
||||
|
||||
Player* PlayerList::getByGameId(uint32 id) {
|
||||
if (G->LP && id == G->LP->id)
|
||||
Player* PlayerList::getBySessId(Player::SessionID sid) {
|
||||
if (G->LP && sid == G->LP->sessId)
|
||||
return G->LP;
|
||||
for (auto it = begin();
|
||||
it != end(); ++it) {
|
||||
if (it->id == id) {
|
||||
if (it->sessId == sid) {
|
||||
return &*it;
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ Player* PlayerList::getByName(const std::string &name) {
|
|||
Player* PlayerList::getByPeer(const Net::Peer &peer) {
|
||||
for (auto it = begin();
|
||||
it != end(); ++it) {
|
||||
if (it->P == peer) {
|
||||
if (*it->peer == peer) {
|
||||
return &*it;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
* @brief Gets a Player using its game session ID
|
||||
* @return Pointer to Player, may be nullptr if not found
|
||||
*/
|
||||
Player* getByGameId(uint32);
|
||||
Player* getBySessId(Player::SessionID);
|
||||
|
||||
/**
|
||||
* @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/Chat.hpp"
|
||||
#include "network/msgtypes/ChunkTransfer.hpp"
|
||||
#include "network/msgtypes/PlayerUpdate.hpp"
|
||||
#include "network/Network.hpp"
|
||||
#include "network/NetHelper.hpp"
|
||||
#include "scripting/lua/State.hpp"
|
||||
|
@ -27,8 +28,8 @@ namespace Diggler {
|
|||
inline Player* Server::getPlayerByPeer(const Peer &peer) {
|
||||
return G.players.getByPeer(peer);
|
||||
}
|
||||
inline Player* Server::getPlayerById(uint32 id) {
|
||||
return G.players.getByGameId(id);
|
||||
inline Player *Server::getPlayerBySessId(uint32 id) {
|
||||
return G.players.getBySessId(id);
|
||||
}
|
||||
inline Player* Server::getPlayerByName(const std::string &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) {
|
||||
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
|
||||
Player *possible = getPlayerByName(name);
|
||||
|
@ -45,42 +46,42 @@ void Server::handlePlayerJoin(InMessage &msg, Peer &peer) {
|
|||
OutMessage kick(MessageType::PlayerQuit, QuitReason::UsernameAlreadyUsed);
|
||||
kick.writeString("You are \faalready\f0 playing on this server");
|
||||
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;
|
||||
}
|
||||
|
||||
Player &plr = G.players.add();
|
||||
plr.name = name;
|
||||
plr.id = FastRand();
|
||||
plr.P = peer;
|
||||
plr.sessId = FastRand();
|
||||
plr.peer = &peer;
|
||||
plr.W = G.U->getLoadWorld(0);
|
||||
|
||||
// Confirm successful join
|
||||
OutMessage join(MessageType::PlayerJoin);
|
||||
join.writeU32(plr.id);
|
||||
join.writeU32(plr.sessId);
|
||||
join.writeI16(plr.W->id);
|
||||
H.send(peer, join, Tfer::Rel);
|
||||
|
||||
// Send the player list
|
||||
for (Player &p : G.players) {
|
||||
if (p.id == plr.id)
|
||||
if (p.sessId == plr.sessId)
|
||||
continue; // ok, he knows he's here
|
||||
OutMessage playerMsg(MessageType::PlayerJoin);
|
||||
playerMsg.writeU32(p.id);
|
||||
playerMsg.writeU32(p.sessId);
|
||||
playerMsg.writeString(p.name);
|
||||
H.send(peer, playerMsg, Tfer::Rel);
|
||||
}
|
||||
|
||||
// Broadcast player's join
|
||||
OutMessage broadcast(MessageType::PlayerJoin);
|
||||
broadcast.writeU32(plr.id);
|
||||
broadcast.writeU32(plr.sessId);
|
||||
broadcast.writeString(plr.name);
|
||||
for (Player &p : G.players) {
|
||||
if (p.id == plr.id)
|
||||
if (p.sessId == plr.sessId)
|
||||
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 y = -2; y < 2; ++y)
|
||||
for (int z = -2; z < 2; ++z)
|
||||
|
@ -93,16 +94,16 @@ void Server::handlePlayerQuit(Peer &peer, QuitReason reason) {
|
|||
Player &plr = *plrPtr;
|
||||
// Broadcast disconnection
|
||||
OutMessage broadcast(MessageType::PlayerQuit, reason);
|
||||
broadcast.writeU32(plr.id);
|
||||
broadcast.writeU32(plr.sessId);
|
||||
for (Player &p : G.players) {
|
||||
if (p.id == plr.id)
|
||||
if (p.sessId == plr.sessId)
|
||||
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;
|
||||
G.players.remove(plr);
|
||||
} 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);
|
||||
|
||||
ChatPlayerTalk cpt;
|
||||
cpt.player.id = plr->id;
|
||||
cpt.player.id = plr->sessId;
|
||||
cpt.msg = cs.msg;
|
||||
OutMessage 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) {
|
||||
switch (msg.getSubtype()) {
|
||||
case PlayerUpdateType::Move: {
|
||||
using namespace Net::MsgTypes;
|
||||
using S = PlayerUpdateSubtype;
|
||||
switch (static_cast<S>(msg.getSubtype())) {
|
||||
case S::Move: {
|
||||
PlayerUpdateMove pum;
|
||||
pum.readFromMsg(msg);
|
||||
pum.plrSessId = plr.sessId;
|
||||
// Broadcast movement
|
||||
OutMessage bcast(MessageType::PlayerUpdate, PlayerUpdateType::Move);
|
||||
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);
|
||||
OutMessage bcast; pum.writeToMsg(bcast);
|
||||
for (Player &p : G.players) {
|
||||
if (p.id == plr.id)
|
||||
if (p.sessId == plr.sessId)
|
||||
continue; // dont send broadcast to the player
|
||||
// TODO: confirm position to player
|
||||
H.send(p.P, bcast, Tfer::Unrel);
|
||||
H.send(*p.peer, bcast, Tfer::Unrel);
|
||||
}
|
||||
} break;
|
||||
case PlayerUpdateType::Die:
|
||||
case S::Die:
|
||||
handlePlayerDeath(msg, plr);
|
||||
break;
|
||||
default:
|
||||
|
@ -188,7 +184,7 @@ void Server::sendChunks(const std::list<ChunkRef> &cs, Player &P) {
|
|||
}
|
||||
OutMessage 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) {
|
||||
|
@ -263,26 +259,27 @@ void Server::handlePlayerMapUpdate(InMessage &msg, Player &plr) {
|
|||
}
|
||||
|
||||
void Server::handlePlayerDeath(InMessage &msg, Player &plr) {
|
||||
uint8 drb = msg.readU8();
|
||||
Player::DeathReason dr = (Player::DeathReason)drb;
|
||||
plr.setDead(false, dr);
|
||||
OutMessage out(MessageType::PlayerUpdate, PlayerUpdateType::Die);
|
||||
out.writeU32(plr.id);
|
||||
out.writeU8(drb);
|
||||
using namespace Net::MsgTypes;
|
||||
PlayerUpdateDie pud;
|
||||
pud.readFromMsg(msg);
|
||||
pud.plrSessId = plr.sessId;
|
||||
plr.setDead(false, pud.reason);
|
||||
OutMessage out; pud.writeToMsg(out);
|
||||
for (Player &p : G.players) {
|
||||
if (p.id != plr.id)
|
||||
H.send(p.P, out, Tfer::Rel, Channels::Life);
|
||||
if (p.sessId != plr.sessId)
|
||||
H.send(*p.peer, out, Tfer::Rel, Channels::Life);
|
||||
}
|
||||
|
||||
// Respawn player later
|
||||
Game *G = &this->G; uint32 id = plr.id;
|
||||
std::thread respawn([G, id] {
|
||||
Game *G = &this->G; Player::SessionID sid = plr.sessId;
|
||||
std::thread respawn([G, sid] {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
Player *plr = G->S->getPlayerById(id);
|
||||
Player *plr = G->S->getPlayerBySessId(sid);
|
||||
if (plr) {
|
||||
plr->setDead(false);
|
||||
OutMessage out(MessageType::PlayerUpdate, PlayerUpdateType::Respawn);
|
||||
out.writeU32(id);
|
||||
PlayerUpdateRespawn pur;
|
||||
pur.plrSessId = sid;
|
||||
OutMessage out; pur.writeToMsg(out);
|
||||
NetHelper::Broadcast(G, out, Tfer::Rel, Channels::Life);
|
||||
}
|
||||
});
|
||||
|
@ -380,12 +377,13 @@ void Server::chunkUpdater(WorldRef WR, bool &continueUpdate) {
|
|||
|
||||
void Server::run() {
|
||||
InMessage msg;
|
||||
Peer peer;
|
||||
Peer *peerPtr;
|
||||
bool continueUpdate = true;
|
||||
std::thread upd(&Server::chunkUpdater, this, G.U->getWorld(0), std::ref(continueUpdate));
|
||||
Player *plr;
|
||||
while (true) {
|
||||
if (H.recv(msg, peer, 100)) {
|
||||
if (H.recv(msg, &peerPtr, 100)) {
|
||||
Peer &peer = *peerPtr;
|
||||
plr = getPlayerByPeer(peer);
|
||||
if (plr != nullptr) {
|
||||
switch (msg.getType()) {
|
||||
|
@ -408,7 +406,7 @@ void Server::run() {
|
|||
}
|
||||
switch (msg.getType()) {
|
||||
case MessageType::NetConnect:
|
||||
getOutputStream() << peer.getHost() << " NEWCONN" << std::endl;
|
||||
getOutputStream() << peer.peerHost() << " NEWCONN" << std::endl;
|
||||
break;
|
||||
case MessageType::NetDisconnect:
|
||||
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) {
|
||||
OutMessage msg(MessageType::PlayerQuit, r);
|
||||
msg.writeU32(p.id);
|
||||
msg.writeU32(p.sessId);
|
||||
msg.writeString(message);
|
||||
H.send(p.P, msg, Tfer::Rel);
|
||||
p.P.disconnect();
|
||||
H.send(*p.peer, msg, Tfer::Rel);
|
||||
p.peer->disconnect();
|
||||
}
|
||||
|
||||
Server::~Server() {
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
|
||||
bool isPlayerOnline(const std::string &playername) const;
|
||||
bool isIPOnline(const std::string &ip) const;
|
||||
Player* getPlayerById(uint32 id);
|
||||
Player* getPlayerBySessId(uint32 id);
|
||||
Player* getPlayerByPeer(const Net::Peer &peer);
|
||||
Player* getPlayerByName(const std::string &name);
|
||||
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) {
|
||||
switch (wrap) {
|
||||
case Texture::Wrapping::Clamp:
|
||||
return GL_CLAMP;
|
||||
case Texture::Wrapping::ClampEdge:
|
||||
return GL_CLAMP_TO_EDGE;
|
||||
case Texture::Wrapping::ClampBorder:
|
||||
return GL_CLAMP_TO_BORDER;
|
||||
case Texture::Wrapping::Repeat:
|
||||
return GL_REPEAT;
|
||||
case Texture::Wrapping::MirroredRepeat:
|
||||
return GL_MIRRORED_REPEAT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,10 @@ public:
|
|||
Linear
|
||||
};
|
||||
enum class Wrapping {
|
||||
ClampEdge,
|
||||
ClampBorder,
|
||||
Repeat,
|
||||
Clamp
|
||||
MirroredRepeat
|
||||
};
|
||||
private:
|
||||
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 setFiltering(Filter min, Filter mag);
|
||||
void setWrapping(Wrapping s, Wrapping t);
|
||||
|
||||
inline void setWrapping(Wrapping w) {
|
||||
setWrapping(w, w);
|
||||
}
|
||||
|
||||
void bind() const {
|
||||
glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef VERSION_INFO_HPP
|
||||
#define VERSION_INFO_HPP
|
||||
#ifndef DIGGLER_VERSION_INFO_HPP
|
||||
#define DIGGLER_VERSION_INFO_HPP
|
||||
|
||||
namespace Diggler {
|
||||
const char* VersionString = "0.1.0";
|
||||
|
@ -8,4 +8,4 @@ namespace Diggler {
|
|||
int VersionRevision = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* DIGGLER_VERSION_INFO_HPP */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef WORLD_GENERATOR_HPP
|
||||
#define WORLD_GENERATOR_HPP
|
||||
#ifndef DIGGLER_WORLD_GENERATOR_HPP
|
||||
#define DIGGLER_WORLD_GENERATOR_HPP
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
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));/*/
|
||||
if (networkSuccess)
|
||||
GW.setNextState(std::make_shared<GameState>(&GW, host, port));
|
||||
GW.setNextState(std::move(std::make_unique<GameState>(&GW, host, port)));
|
||||
else
|
||||
GW.showMessage("Network init failed!");
|
||||
/**/
|
||||
|
||||
GW.run();
|
||||
G->finalizeClient();
|
||||
}
|
||||
G.reset();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "msgtypes/BlockUpdate.hpp"
|
||||
#include "msgtypes/Chat.hpp"
|
||||
#include "msgtypes/ChunkTransfer.hpp"
|
||||
#include "msgtypes/PlayerUpdate.hpp"
|
||||
|
||||
namespace Diggler {
|
||||
namespace Net {
|
||||
|
@ -65,7 +66,7 @@ bool ClientMessageHandler::handleMessage(InMessage &msg) {
|
|||
if (cpt.msg.type == msgpack::type::STR) {
|
||||
std::string playerName;
|
||||
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) {
|
||||
playerName = blabbermouth->name + "> ";
|
||||
} else {
|
||||
|
@ -81,14 +82,14 @@ bool ClientMessageHandler::handleMessage(InMessage &msg) {
|
|||
} break;
|
||||
case MessageType::PlayerJoin: {
|
||||
Player &plr = GS.G->players.add();
|
||||
plr.id = msg.readU32();
|
||||
plr.sessId = msg.readU32();
|
||||
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;
|
||||
case MessageType::PlayerQuit: {
|
||||
uint32 id = msg.readU32();
|
||||
try {
|
||||
Player *plr = GS.G->players.getByGameId(id);
|
||||
Player *plr = GS.G->players.getBySessId(id);
|
||||
if (plr != nullptr) {
|
||||
getOutputStream() << plr->name << " is gone :(" << std::endl;
|
||||
GS.G->players.remove(*plr);
|
||||
|
@ -98,30 +99,51 @@ bool ClientMessageHandler::handleMessage(InMessage &msg) {
|
|||
}
|
||||
} break;
|
||||
case MessageType::PlayerUpdate: {
|
||||
uint32 id = msg.readU32();
|
||||
try {
|
||||
Player *plr = GS.G->players.getByGameId(id);
|
||||
if (plr != nullptr) {
|
||||
switch (msg.getSubtype()) {
|
||||
case PlayerUpdateType::Move: {
|
||||
glm::vec3 pos = msg.readVec3(),
|
||||
vel = msg.readVec3(),
|
||||
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;
|
||||
using S = PlayerUpdateSubtype;
|
||||
switch (static_cast<S>(msg.getSubtype())) {
|
||||
case S::Move: {
|
||||
PlayerUpdateMove pum;
|
||||
pum.readFromMsg(msg);
|
||||
if (!pum.plrSessId) {
|
||||
getOutputStream() << "PlayerUpdateMove without player session ID" << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (const std::out_of_range &e) {
|
||||
getOutputStream() << "Invalid player update: #" << id << " is not on server" << std::endl;
|
||||
Player *plr = GS.G->players.getBySessId(*pum.plrSessId);
|
||||
if (!plr) {
|
||||
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;
|
||||
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) {
|
||||
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;
|
||||
cs.writeToMsg(msg);
|
||||
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);
|
||||
G->H.send(*G->NS, msg, Tfer::Unseq);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,10 +20,8 @@ void MakeEvent(Net::OutMessage&, Net::EventType, const Player&);
|
|||
void SendEvent(Game*, Net::EventType);
|
||||
|
||||
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 <enet/enet.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
#include <enet/enet.h>
|
||||
|
||||
#include "../crypto/Random.hpp"
|
||||
#include "msgtypes/ConnectionParam.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
namespace Diggler {
|
||||
|
@ -53,8 +59,7 @@ Message::Message(MessageType t, uint8 s) :
|
|||
|
||||
InMessage::InMessage() :
|
||||
Message(MessageType::Null, 0),
|
||||
m_chan(Channels::Base),
|
||||
m_packet(nullptr) {
|
||||
m_chan(Channels::Base) {
|
||||
}
|
||||
|
||||
InMessage::~InMessage() {
|
||||
|
@ -79,36 +84,17 @@ void InMessage::fromData(const void *data, SizeT len, Channels chan) {
|
|||
m_length = len;
|
||||
m_type = static_cast<MessageType>(bytes[0]);
|
||||
m_subtype = bytes[1];
|
||||
m_data = static_cast<uint8*>(std::malloc(len-HeaderSize));
|
||||
std::memcpy(m_data, &(bytes[HeaderSize]), len-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]);
|
||||
// m_data/bytes is guaranteed never to be written to, so we can const_cast it
|
||||
m_data = const_cast<uint8*>(bytes) + HeaderSize;
|
||||
}
|
||||
|
||||
void InMessage::free() {
|
||||
if (m_packet != nullptr) {
|
||||
enet_packet_destroy(static_cast<ENetPacket*>(m_packet));
|
||||
} else {
|
||||
std::free(m_data);
|
||||
if (m_data != nullptr) {
|
||||
delete[] (m_data - HeaderSize);
|
||||
}
|
||||
m_type = MessageType::Null;
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
return peer == other.peer;
|
||||
}
|
||||
|
@ -168,13 +162,13 @@ bool Peer::operator!=(const Peer &other) const {
|
|||
return !(*this == other);
|
||||
}
|
||||
|
||||
void Peer::disconnect() {
|
||||
ENetPeer *const peer = static_cast<ENetPeer*>(this->peer);
|
||||
enet_peer_disconnect(peer, 0);
|
||||
void Peer::disconnect(uint32 data) {
|
||||
ENetPeer *const peer = reinterpret_cast<ENetPeer*>(this->peer);
|
||||
enet_peer_disconnect(peer, data);
|
||||
}
|
||||
|
||||
std::string Peer::getHost() {
|
||||
const ENetPeer *const peer = static_cast<const ENetPeer*>(this->peer);
|
||||
std::string Peer::peerHost() {
|
||||
const ENetPeer *const peer = reinterpret_cast<const ENetPeer*>(this->peer);
|
||||
std::ostringstream oss;
|
||||
char *chars = new char[512];
|
||||
enet_address_get_host_ip(&peer->host->address, chars, 512);
|
||||
|
@ -184,8 +178,8 @@ std::string Peer::getHost() {
|
|||
return oss.str();
|
||||
}
|
||||
|
||||
std::string Peer::getIp() {
|
||||
const ENetPeer *const peer = static_cast<const ENetPeer*>(this->peer);
|
||||
std::string Peer::peerIP() {
|
||||
const ENetPeer *const peer = reinterpret_cast<const ENetPeer*>(this->peer);
|
||||
char *chars = new char[512];
|
||||
enet_address_get_host_ip(&peer->host->address, chars, 512);
|
||||
std::string str(chars);
|
||||
|
@ -193,8 +187,8 @@ std::string Peer::getIp() {
|
|||
return str;
|
||||
}
|
||||
|
||||
Port Peer::getPort() {
|
||||
const ENetPeer *const peer = static_cast<const ENetPeer*>(this->peer);
|
||||
Port Peer::peerPort() {
|
||||
const ENetPeer *const peer = reinterpret_cast<const ENetPeer*>(this->peer);
|
||||
return peer->host->address.port;
|
||||
}
|
||||
|
||||
|
@ -206,6 +200,11 @@ Host::Host() :
|
|||
txBytes(0) {
|
||||
}
|
||||
|
||||
Host::~Host() {
|
||||
ENetHost *const host = reinterpret_cast<ENetHost*>(this->host);
|
||||
enet_host_destroy(host);
|
||||
}
|
||||
|
||||
void Host::create(Port port, uint maxconn) {
|
||||
if (port == 0) { // Client
|
||||
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) {
|
||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
||||
Peer& Host::connect(const std::string &hostAddr, Port port, Timeout timeout) {
|
||||
ENetHost *const host = reinterpret_cast<ENetHost*>(this->host);
|
||||
ENetAddress address;
|
||||
ENetEvent event;
|
||||
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 &&
|
||||
event.type == ENET_EVENT_TYPE_CONNECT) {
|
||||
Peer p; p.peer = peer;
|
||||
return p;
|
||||
Peer *p = new Peer(*this, peer);
|
||||
sendKeyExchange(*p);
|
||||
return *p;
|
||||
}
|
||||
|
||||
enet_peer_reset(peer);
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
Host::~Host() {
|
||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
||||
enet_host_destroy(host);
|
||||
void Host::processPeersToDelete() {
|
||||
for (Peer *peer : m_peersToDelete) {
|
||||
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);
|
||||
for (int i=0; i < len; ++i) {
|
||||
std::cout << std::setfill('0') << std::setw(2) << std::hex << (int)buf[i] << ' ';
|
||||
}
|
||||
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) {
|
||||
ENetHost *const host = static_cast<ENetHost*>(this->host);
|
||||
bool Host::recv(InMessage &msg, Peer **peer, Timeout timeout) {
|
||||
ENetHost *const host = reinterpret_cast<ENetHost*>(this->host);
|
||||
processPeersToDelete();
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
ENetEvent event;
|
||||
if (enet_host_service(host, &event, timeout) >= 0){
|
||||
switch (event.type) {
|
||||
case ENET_EVENT_TYPE_NONE:
|
||||
while (true) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
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;
|
||||
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();
|
||||
}
|
||||
|
||||
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] = {
|
||||
static_cast<uint8>(msg.m_type),
|
||||
const byte header[Message::HeaderSize] = {
|
||||
static_cast<byte>(msg.m_type),
|
||||
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) {
|
||||
std::memcpy(msg.m_actualData, header, Message::HeaderSize);
|
||||
packet = enet_packet_create(msg.m_actualData,
|
||||
Message::HeaderSize + msg.m_length, TferToFlags(mode));
|
||||
txBytes += Message::HeaderSize + msg.m_length;
|
||||
if (encrypt) {
|
||||
// TODO: don't memcpy, encrypt!
|
||||
std::memcpy(pktData, msg.m_actualData, pktLen);
|
||||
} else {
|
||||
std::memcpy(pktData, msg.m_actualData, pktLen);
|
||||
}
|
||||
} else {
|
||||
packet = enet_packet_create(header,
|
||||
Message::HeaderSize, TferToFlags(mode));
|
||||
txBytes += Message::HeaderSize;
|
||||
if (encrypt) {
|
||||
// TODO: don't memcpy, encrypt!
|
||||
std::memcpy(pktData, header, pktLen);
|
||||
} else {
|
||||
std::memcpy(pktData, header, pktLen);
|
||||
}
|
||||
}
|
||||
|
||||
//hexDump('S', packet->data, 2+msg.m_length);
|
||||
enet_peer_send(static_cast<ENetPeer*>(peer.peer), static_cast<uint8>(chan), packet);
|
||||
hexDump('S', pktData, pktLen);
|
||||
enet_peer_send(reinterpret_cast<ENetPeer*>(peer.peer), static_cast<uint8>(chan), packet);
|
||||
enet_host_flush(host);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
#ifndef NETWORK_HPP
|
||||
#define NETWORK_HPP
|
||||
#include "../Platform.hpp"
|
||||
#include "../io/MemoryStream.hpp"
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "../Platform.hpp"
|
||||
#include "../platform/PreprocUtils.hpp"
|
||||
#include "../crypto/DiffieHellman.hpp"
|
||||
#include "../io/MemoryStream.hpp"
|
||||
|
||||
namespace Diggler {
|
||||
namespace Net {
|
||||
|
||||
|
@ -20,6 +25,8 @@ enum class Tfer {
|
|||
|
||||
enum class Channels : uint8 {
|
||||
Base = 0,
|
||||
ConnectionMeta,
|
||||
ConnectionMetaPlain,
|
||||
Chat,
|
||||
Life,
|
||||
Movement,
|
||||
|
@ -35,6 +42,8 @@ enum class MessageType : uint8 {
|
|||
|
||||
ServerInfo = 220,
|
||||
|
||||
ConnectionParam = 200,
|
||||
|
||||
PlayerJoin = 1,
|
||||
PlayerUpdate,
|
||||
PlayerQuit,
|
||||
|
@ -46,16 +55,6 @@ enum class MessageType : uint8 {
|
|||
NetDisconnect
|
||||
};
|
||||
|
||||
enum PlayerUpdateType : uint8 {
|
||||
Move,
|
||||
ChangeTool,
|
||||
ChangeClass,
|
||||
ChangeTeam,
|
||||
Die,
|
||||
Respawn,
|
||||
ToolUse
|
||||
};
|
||||
|
||||
enum QuitReason : uint8 {
|
||||
Quit,
|
||||
Timeout,
|
||||
|
@ -82,6 +81,8 @@ protected:
|
|||
public:
|
||||
static constexpr uint HeaderSize = 2;
|
||||
|
||||
virtual ~Message() {}
|
||||
|
||||
inline MessageType getType() const { return m_type; }
|
||||
inline uint8 getSubtype() const { return m_subtype; }
|
||||
|
||||
|
@ -94,10 +95,8 @@ class InMessage : public Message, public InMemoryStream {
|
|||
protected:
|
||||
friend class Host;
|
||||
Channels m_chan;
|
||||
void *m_packet;
|
||||
void setType(MessageType type);
|
||||
void fromData(const void *data, SizeT len, Channels chan = Channels::Base);
|
||||
void fromPacket(void *packet, Channels chan = Channels::Base);
|
||||
void fromData(const void *data, SizeT, Channels);
|
||||
void free();
|
||||
|
||||
public:
|
||||
|
@ -166,20 +165,43 @@ class Exception : public std::exception {
|
|||
|
||||
using Port = uint16;
|
||||
|
||||
class Host;
|
||||
|
||||
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;
|
||||
|
||||
void disconnect();
|
||||
std::string getHost();
|
||||
std::string getIp();
|
||||
Port getPort();
|
||||
/**
|
||||
* @brief Disconnects the peer.
|
||||
* @param data
|
||||
* 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 {
|
||||
private:
|
||||
std::vector<Peer*> m_peersToDelete;
|
||||
void processPeersToDelete();
|
||||
|
||||
void *host;
|
||||
uint64 rxBytes, txBytes;
|
||||
|
||||
|
@ -187,17 +209,27 @@ private:
|
|||
Host& operator=(Host&) = delete;
|
||||
Host& operator=(const Host&) = delete;
|
||||
|
||||
void sendKeyExchange(Peer&);
|
||||
|
||||
public:
|
||||
using Timeout = uint32;
|
||||
|
||||
public:
|
||||
Host();
|
||||
~Host();
|
||||
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);
|
||||
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 {
|
||||
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
|
||||
#define DIGGLER_PLATFORM_TYPES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace Diggler {
|
||||
|
||||
using int32 = int32_t;
|
||||
using uint = uint32_t;
|
||||
using uint32 = uint32_t;
|
||||
using uint64 = uint64_t;
|
||||
using uint16 = uint16_t;
|
||||
using uint8 = uint8_t;
|
||||
using int64 = int64_t;
|
||||
using int16 = int16_t;
|
||||
using int8 = int8_t;
|
||||
using byte = uint8_t;
|
||||
using uint = std::uint32_t;
|
||||
using uint32 = std::uint32_t;
|
||||
using uint64 = std::uint64_t;
|
||||
using uint16 = std::uint16_t;
|
||||
using uint8 = std::uint8_t;
|
||||
using int64 = std::int64_t;
|
||||
using int32 = std::int32_t;
|
||||
using int16 = std::int16_t;
|
||||
using int8 = std::int8_t;
|
||||
using byte = std::uint8_t;
|
||||
using char32 = char32_t;
|
||||
using char16 = char16_t;
|
||||
|
||||
|
|
|
@ -21,8 +21,10 @@ protected:
|
|||
public:
|
||||
virtual ~Renderer() = 0;
|
||||
|
||||
ParticlesRenderer *PR;
|
||||
WorldRenderer *WR;
|
||||
struct Renderers {
|
||||
ParticlesRenderer *particles;
|
||||
WorldRenderer *world;
|
||||
} renderers;
|
||||
};
|
||||
|
||||
inline Renderer::~Renderer() {}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "FBO.hpp"
|
||||
|
||||
#include "FeatureSupport.hpp"
|
||||
#include "Util.hpp"
|
||||
|
||||
#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
|
||||
glGenRenderbuffers(1, &rboId);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
|
||||
if (stencil)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
|
||||
else
|
||||
if (stencil) {
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, FeatureSupport::FBO_ARB ? GL_DEPTH24_STENCIL8 :
|
||||
GL_DEPTH24_STENCIL8_OES, w, h);
|
||||
} else {
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, w, h);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "FeatureSupport.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace Diggler {
|
||||
namespace Render {
|
||||
namespace gl {
|
||||
|
@ -11,17 +13,32 @@ bool
|
|||
F::DSA_ARB,
|
||||
F::DSA_EXT,
|
||||
F::DSA,
|
||||
F::shader_image_load_store;
|
||||
F::shader_image_load_store,
|
||||
F::FBO_ARB;
|
||||
|
||||
void F::probe() {
|
||||
VAO = epoxy_has_gl_extension("GL_ARB_vertex_array_object") or
|
||||
epoxy_has_gl_extension("GL_OES_vertex_array_object");
|
||||
DSA_ARB = epoxy_has_gl_extension("ARB_direct_state_access");
|
||||
DSA_EXT = epoxy_has_gl_extension("EXT_direct_state_access");
|
||||
DSA_ARB = epoxy_has_gl_extension("GL_ARB_direct_state_access");
|
||||
DSA_EXT = epoxy_has_gl_extension("GL_EXT_direct_state_access");
|
||||
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_EXT /* Direct State Access, EXT version */,
|
||||
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 std::string supported();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,9 @@ public:
|
|||
GLRenderer(Game *G) :
|
||||
Renderer(G) {
|
||||
FeatureSupport::probe();
|
||||
PR = new GLParticlesRenderer(G);
|
||||
WR = new GLWorldRenderer(G);
|
||||
getDebugStream() << "GLRenderer, using features: " << FeatureSupport::supported() << std::endl;
|
||||
renderers.particles = new GLParticlesRenderer(G);
|
||||
renderers.world = new GLWorldRenderer(G);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -25,7 +25,11 @@ public:
|
|||
m_id(0),
|
||||
m_size(0),
|
||||
m_usage(GL_STATIC_DRAW) {
|
||||
glGenBuffers(1, &m_id);
|
||||
if (FeatureSupport::DSA_ARB) {
|
||||
glCreateBuffers(1, &m_id);
|
||||
} else {
|
||||
glGenBuffers(1, &m_id);
|
||||
}
|
||||
}
|
||||
|
||||
~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;
|
||||
|
||||
|
@ -121,16 +121,16 @@ int Font::updateVBO(Render::gl::VBO &vbo, const std::string &text, GLenum usage)
|
|||
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_texcoord);
|
||||
glEnableVertexAttribArray(R.att_color);
|
||||
|
||||
R.prog->bind();
|
||||
m_texture->bind();
|
||||
vbo.bind();
|
||||
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_color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, r));
|
||||
glDrawArrays(GL_TRIANGLES, 0, count);
|
||||
|
|
Loading…
Reference in New Issue