WIP
This commit is contained in:
parent
9406265c5e
commit
d355b436e6
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@
|
|||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
|
||||||
/build
|
/build
|
||||||
|
/cache
|
||||||
|
2
3rdparty/c55lib/CMakeLists.txt
vendored
2
3rdparty/c55lib/CMakeLists.txt
vendored
@ -1,3 +1,3 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
project(c55lib)
|
project(c55lib)
|
||||||
add_library(c55lib STATIC c55_getopt.cpp)
|
add_library(c55lib STATIC c55_getopt.cpp c55_filesys.cpp)
|
||||||
|
344
3rdparty/c55lib/c55_filesys.cpp
vendored
Normal file
344
3rdparty/c55lib/c55_filesys.cpp
vendored
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
#include "c55_filesys.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace c55fs
|
||||||
|
{
|
||||||
|
|
||||||
|
/* "image.png", "png" -> TRUE */
|
||||||
|
bool checkFileExtension(const char *path, const char *ext)
|
||||||
|
{
|
||||||
|
int extlen = strlen(ext);
|
||||||
|
int pathlen = strlen(path);
|
||||||
|
if(extlen > pathlen - 1)
|
||||||
|
return false;
|
||||||
|
int i;
|
||||||
|
for(i=0; i<extlen; i++){
|
||||||
|
if(path[pathlen-1-i] != ext[extlen-1-i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(path[pathlen-1-i] != '.')
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string stripFileExtension(const std::string &path)
|
||||||
|
{
|
||||||
|
int pathlen = path.size();
|
||||||
|
int i;
|
||||||
|
for(i=pathlen-1; i>=0; i--){
|
||||||
|
if(path[i] == '.')
|
||||||
|
return path.substr(0, i);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string stripFilename(const std::string &path)
|
||||||
|
{
|
||||||
|
int pathlen = path.size();
|
||||||
|
int i;
|
||||||
|
for(i=pathlen-1; i>=0; i--){
|
||||||
|
if(path[i] == '/' || path[i] == '\\')
|
||||||
|
return path.substr(0, i);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32 // WINDOWS
|
||||||
|
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define BUFSIZE MAX_PATH
|
||||||
|
|
||||||
|
std::vector<DirListNode> GetDirListing(std::string pathstring)
|
||||||
|
{
|
||||||
|
std::vector<DirListNode> listing;
|
||||||
|
|
||||||
|
WIN32_FIND_DATA FindFileData;
|
||||||
|
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD dwError;
|
||||||
|
LPTSTR DirSpec;
|
||||||
|
INT retval;
|
||||||
|
|
||||||
|
DirSpec = (LPTSTR) malloc (BUFSIZE);
|
||||||
|
|
||||||
|
if( DirSpec == NULL )
|
||||||
|
{
|
||||||
|
printf( "Insufficient memory available\n" );
|
||||||
|
retval = 1;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the input is not larger than allowed.
|
||||||
|
if (pathstring.size() > (BUFSIZE - 2))
|
||||||
|
{
|
||||||
|
_tprintf(TEXT("Input directory is too large.\n"));
|
||||||
|
retval = 3;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
//_tprintf (TEXT("Target directory is %s.\n"), pathstring.c_str());
|
||||||
|
|
||||||
|
sprintf(DirSpec, "%s", (pathstring + "\\*").c_str());
|
||||||
|
|
||||||
|
// Find the first file in the directory.
|
||||||
|
hFind = FindFirstFile(DirSpec, &FindFileData);
|
||||||
|
|
||||||
|
if (hFind == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
_tprintf (TEXT("Invalid file handle. Error is %u.\n"),
|
||||||
|
GetLastError());
|
||||||
|
retval = (-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE:
|
||||||
|
// Be very sure to not include '..' in the results, it will
|
||||||
|
// result in an epic failure when deleting stuff.
|
||||||
|
|
||||||
|
DirListNode node;
|
||||||
|
node.name = FindFileData.cFileName;
|
||||||
|
node.dir = FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
if(node.name != "." && node.name != "..")
|
||||||
|
listing.push_back(node);
|
||||||
|
|
||||||
|
// List all the other files in the directory.
|
||||||
|
while (FindNextFile(hFind, &FindFileData) != 0)
|
||||||
|
{
|
||||||
|
DirListNode node;
|
||||||
|
node.name = FindFileData.cFileName;
|
||||||
|
node.dir = FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
if(node.name != "." && node.name != "..")
|
||||||
|
listing.push_back(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
dwError = GetLastError();
|
||||||
|
FindClose(hFind);
|
||||||
|
if (dwError != ERROR_NO_MORE_FILES)
|
||||||
|
{
|
||||||
|
_tprintf (TEXT("FindNextFile error. Error is %u.\n"),
|
||||||
|
dwError);
|
||||||
|
retval = (-1);
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
free(DirSpec);
|
||||||
|
|
||||||
|
if(retval != 0) listing.clear();
|
||||||
|
|
||||||
|
//for(unsigned int i=0; i<listing.size(); i++){
|
||||||
|
// std::cout<<listing[i].name<<(listing[i].dir?" (dir)":" (file)")<<std::endl;
|
||||||
|
//}
|
||||||
|
|
||||||
|
return listing;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateDir(std::string path)
|
||||||
|
{
|
||||||
|
bool r = CreateDirectory(path.c_str(), NULL);
|
||||||
|
if(r == true)
|
||||||
|
return true;
|
||||||
|
if(GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathExists(std::string path)
|
||||||
|
{
|
||||||
|
return (GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RecursiveDelete(std::string path)
|
||||||
|
{
|
||||||
|
std::cerr<<"Removing \""<<path<<"\""<<std::endl;
|
||||||
|
|
||||||
|
//return false;
|
||||||
|
|
||||||
|
// This silly function needs a double-null terminated string...
|
||||||
|
// Well, we'll just make sure it has at least two, then.
|
||||||
|
path += "\0\0";
|
||||||
|
|
||||||
|
SHFILEOPSTRUCT sfo;
|
||||||
|
sfo.hwnd = NULL;
|
||||||
|
sfo.wFunc = FO_DELETE;
|
||||||
|
sfo.pFrom = path.c_str();
|
||||||
|
sfo.pTo = NULL;
|
||||||
|
sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
|
||||||
|
|
||||||
|
int r = SHFileOperation(&sfo);
|
||||||
|
|
||||||
|
if(r != 0)
|
||||||
|
std::cerr<<"SHFileOperation returned "<<r<<std::endl;
|
||||||
|
|
||||||
|
//return (r == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // POSIX
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
std::vector<DirListNode> GetDirListing(std::string pathstring)
|
||||||
|
{
|
||||||
|
std::vector<DirListNode> listing;
|
||||||
|
|
||||||
|
DIR *dp;
|
||||||
|
struct dirent *dirp;
|
||||||
|
if((dp = opendir(pathstring.c_str())) == NULL) {
|
||||||
|
//std::cout<<"Error("<<errno<<") opening "<<pathstring<<std::endl;
|
||||||
|
return listing;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((dirp = readdir(dp)) != NULL) {
|
||||||
|
// NOTE:
|
||||||
|
// Be very sure to not include '..' in the results, it will
|
||||||
|
// result in an epic failure when deleting stuff.
|
||||||
|
if(dirp->d_name[0]!='.'){
|
||||||
|
DirListNode node;
|
||||||
|
node.name = dirp->d_name;
|
||||||
|
if(dirp->d_type == DT_DIR) node.dir = true;
|
||||||
|
else node.dir = false;
|
||||||
|
if(node.name != "." && node.name != "..")
|
||||||
|
listing.push_back(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dp);
|
||||||
|
|
||||||
|
return listing;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateDir(std::string path)
|
||||||
|
{
|
||||||
|
int r = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||||
|
if(r == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If already exists, return true
|
||||||
|
if(errno == EEXIST)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathExists(std::string path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
return (stat(path.c_str(),&st) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RecursiveDelete(std::string path)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Execute the 'rm' command directly, by fork() and execve()
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::cerr<<"Removing \""<<path<<"\""<<std::endl;
|
||||||
|
|
||||||
|
//return false;
|
||||||
|
|
||||||
|
pid_t child_pid = fork();
|
||||||
|
|
||||||
|
if(child_pid == 0)
|
||||||
|
{
|
||||||
|
// Child
|
||||||
|
char argv_data[3][10000];
|
||||||
|
strcpy(argv_data[0], "/bin/rm");
|
||||||
|
strcpy(argv_data[1], "-rf");
|
||||||
|
strncpy(argv_data[2], path.c_str(), 10000);
|
||||||
|
char *argv[4];
|
||||||
|
argv[0] = argv_data[0];
|
||||||
|
argv[1] = argv_data[1];
|
||||||
|
argv[2] = argv_data[2];
|
||||||
|
argv[3] = NULL;
|
||||||
|
|
||||||
|
std::cerr<<"Executing '"<<argv[0]<<"' '"<<argv[1]<<"' '"
|
||||||
|
<<argv[2]<<"'"<<std::endl;
|
||||||
|
|
||||||
|
execv(argv[0], argv);
|
||||||
|
|
||||||
|
// Execv shouldn't return. Failed.
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Parent
|
||||||
|
int child_status;
|
||||||
|
pid_t tpid;
|
||||||
|
do{
|
||||||
|
tpid = wait(&child_status);
|
||||||
|
//if(tpid != child_pid) process_terminated(tpid);
|
||||||
|
}while(tpid != child_pid);
|
||||||
|
return (child_status == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline std::string trim(std::string str, const std::string &whitespace=" \t\n\r")
|
||||||
|
{
|
||||||
|
size_t endpos = str.find_last_not_of(whitespace);
|
||||||
|
if(std::string::npos != endpos)
|
||||||
|
str = str.substr(0, endpos+1);
|
||||||
|
size_t startpos = str.find_first_not_of(whitespace);
|
||||||
|
if(std::string::npos != startpos)
|
||||||
|
str = str.substr(startpos);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RecursiveDeleteContent(std::string path)
|
||||||
|
{
|
||||||
|
std::cerr<<"Removing content of \""<<path<<"\""<<std::endl;
|
||||||
|
std::vector<DirListNode> list = GetDirListing(path);
|
||||||
|
for(unsigned int i=0; i<list.size(); i++)
|
||||||
|
{
|
||||||
|
if(trim(list[i].name) == "." || trim(list[i].name) == "..")
|
||||||
|
continue;
|
||||||
|
std::string childpath = path + DIR_DELIM + list[i].name;
|
||||||
|
bool r = RecursiveDelete(childpath);
|
||||||
|
if(r == false)
|
||||||
|
{
|
||||||
|
std::cerr<<"Removing \""<<childpath<<"\" failed"<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateAllDirs(std::string path)
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t pos;
|
||||||
|
std::vector<std::string> tocreate;
|
||||||
|
std::string basepath = path;
|
||||||
|
while(!PathExists(basepath))
|
||||||
|
{
|
||||||
|
tocreate.push_back(basepath);
|
||||||
|
pos = basepath.rfind(DIR_DELIM_C);
|
||||||
|
if(pos == std::string::npos)
|
||||||
|
return false;
|
||||||
|
basepath = basepath.substr(0,pos);
|
||||||
|
}
|
||||||
|
for(int i=tocreate.size()-1;i>=0;i--)
|
||||||
|
CreateDir(tocreate[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fs
|
||||||
|
|
49
3rdparty/c55lib/c55_filesys.h
vendored
Normal file
49
3rdparty/c55lib/c55_filesys.h
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef FILESYS_HEADER
|
||||||
|
#define FILESYS_HEADER
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef _WIN32 // WINDOWS
|
||||||
|
#define DIR_DELIM "\\"
|
||||||
|
#define DIR_DELIM_C '\\'
|
||||||
|
#else // POSIX
|
||||||
|
#define DIR_DELIM "/"
|
||||||
|
#define DIR_DELIM_C '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace c55fs
|
||||||
|
{
|
||||||
|
|
||||||
|
/* "image.png", "png" -> true */
|
||||||
|
bool checkFileExtension(const char *path, const char *ext);
|
||||||
|
std::string stripFileExtension(const std::string &path);
|
||||||
|
std::string stripFilename(const std::string &path);
|
||||||
|
|
||||||
|
struct DirListNode
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
bool dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<DirListNode> GetDirListing(std::string path);
|
||||||
|
|
||||||
|
// Returns true if already exists
|
||||||
|
bool CreateDir(std::string path);
|
||||||
|
|
||||||
|
// Create all directories on the given path that don't already exist.
|
||||||
|
bool CreateAllDirs(std::string path);
|
||||||
|
|
||||||
|
bool PathExists(std::string path);
|
||||||
|
|
||||||
|
// Only pass full paths to this one. True on success.
|
||||||
|
// NOTE: The WIN32 version returns always true.
|
||||||
|
bool RecursiveDelete(std::string path);
|
||||||
|
|
||||||
|
// Only pass full paths to this one. True on success.
|
||||||
|
bool RecursiveDeleteContent(std::string path);
|
||||||
|
|
||||||
|
}//fs
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -63,9 +63,13 @@ TARGET_LINK_LIBRARIES(${CLIENT_EXE_NAME}
|
|||||||
set(SERVER_EXE_NAME buildat_server)
|
set(SERVER_EXE_NAME buildat_server)
|
||||||
set(SERVER_SRCS
|
set(SERVER_SRCS
|
||||||
src/server/main.cpp
|
src/server/main.cpp
|
||||||
|
src/server/state.cpp
|
||||||
|
src/server/rccpp.cpp
|
||||||
)
|
)
|
||||||
add_executable(${SERVER_EXE_NAME} ${SERVER_SRCS})
|
add_executable(${SERVER_EXE_NAME} ${SERVER_SRCS})
|
||||||
TARGET_LINK_LIBRARIES(${SERVER_EXE_NAME}
|
TARGET_LINK_LIBRARIES(${SERVER_EXE_NAME}
|
||||||
c55lib
|
c55lib
|
||||||
|
dl
|
||||||
)
|
)
|
||||||
|
add_definitions(-DRCCPP_ENABLED=1)
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ Buildat
|
|||||||
=======
|
=======
|
||||||
A Minecraft clone with vast extendability.
|
A Minecraft clone with vast extendability.
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
|
||||||
Client
|
Client
|
||||||
------
|
------
|
||||||
Built using Polycode C++.
|
Built using Polycode C++.
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#include <string>
|
#pragma once
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
struct Config
|
struct Config
|
||||||
{
|
{
|
||||||
std::string server_address;
|
ss_ server_address;
|
||||||
std::string polycode_path = "/home/celeron55/softat/polycode/";
|
ss_ polycode_path = "/home/celeron55/softat/polycode/";
|
||||||
std::string share_path = "../share";
|
ss_ share_path = "../share";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "core/types.h"
|
||||||
#include "client/config.h"
|
#include "client/config.h"
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
@ -13,24 +14,24 @@ using Polycode::SDLCore;
|
|||||||
using Polycode::Logger;
|
using Polycode::Logger;
|
||||||
using Polycode::String;
|
using Polycode::String;
|
||||||
|
|
||||||
client::Config g_config;
|
client::Config g_client_config;
|
||||||
|
|
||||||
int MyLoader(lua_State* pState)
|
int MyLoader(lua_State* pState)
|
||||||
{
|
{
|
||||||
// TODO: Security
|
// TODO: Security
|
||||||
std::string module = lua_tostring(pState, 1);
|
ss_ module = lua_tostring(pState, 1);
|
||||||
|
|
||||||
module += ".lua";
|
module += ".lua";
|
||||||
//Logger::log("Loading custom class: %s\n", module.c_str());
|
//Logger::log("Loading custom class: %s\n", module.c_str());
|
||||||
|
|
||||||
std::vector<std::string> defaultPaths = {
|
std::vector<ss_> defaultPaths = {
|
||||||
g_config.polycode_path+"/Bindings/Contents/LUA/API/",
|
g_client_config.polycode_path+"/Bindings/Contents/LUA/API/",
|
||||||
g_config.polycode_path+"/Modules/Bindings/2DPhysics/API/",
|
g_client_config.polycode_path+"/Modules/Bindings/2DPhysics/API/",
|
||||||
g_config.polycode_path+"/Modules/Bindings/3DPhysics/API/",
|
g_client_config.polycode_path+"/Modules/Bindings/3DPhysics/API/",
|
||||||
g_config.polycode_path+"/Modules/Bindings/UI/API/",
|
g_client_config.polycode_path+"/Modules/Bindings/UI/API/",
|
||||||
};
|
};
|
||||||
|
|
||||||
for(std::string defaultPath : defaultPaths){
|
for(ss_ defaultPath : defaultPaths){
|
||||||
defaultPath.append(module);
|
defaultPath.append(module);
|
||||||
|
|
||||||
const char* fullPath = module.c_str();
|
const char* fullPath = module.c_str();
|
||||||
@ -54,7 +55,7 @@ int MyLoader(lua_State* pState)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string err = "\n\tError - Could could not find ";
|
ss_ err = "\n\tError - Could could not find ";
|
||||||
err += module;
|
err += module;
|
||||||
err += ".";
|
err += ".";
|
||||||
lua_pushstring(pState, err.c_str());
|
lua_pushstring(pState, err.c_str());
|
||||||
@ -191,7 +192,7 @@ HelloPolycodeApp::HelloPolycodeApp(Polycode::PolycodeView *view):
|
|||||||
// SDLCore for Linux
|
// SDLCore for Linux
|
||||||
core = new POLYCODE_CORE(view, 640,480,false,false,0,0,90, 1, true);
|
core = new POLYCODE_CORE(view, 640,480,false,false,0,0,90, 1, true);
|
||||||
|
|
||||||
Polycode::CoreServices::getInstance()->getResourceManager()->addArchive(g_config.share_path+"/default.pak");
|
Polycode::CoreServices::getInstance()->getResourceManager()->addArchive(g_client_config.share_path+"/default.pak");
|
||||||
Polycode::CoreServices::getInstance()->getResourceManager()->addDirResource("default", false);
|
Polycode::CoreServices::getInstance()->getResourceManager()->addDirResource("default", false);
|
||||||
|
|
||||||
scene = new Polycode::Scene(Polycode::Scene::SCENE_2D);
|
scene = new Polycode::Scene(Polycode::Scene::SCENE_2D);
|
||||||
@ -263,7 +264,7 @@ HelloPolycodeApp::HelloPolycodeApp(Polycode::PolycodeView *view):
|
|||||||
//luaopen_Physics3D(L);
|
//luaopen_Physics3D(L);
|
||||||
//luaopen_UI(L);
|
//luaopen_UI(L);
|
||||||
|
|
||||||
int error = luaL_dofile(L, (g_config.share_path+"/init.lua").c_str());
|
int error = luaL_dofile(L, (g_client_config.share_path+"/init.lua").c_str());
|
||||||
if(error){
|
if(error){
|
||||||
Logger::log("luaL_dofile: An error occurred: %s\n", lua_tostring(L, -1));
|
Logger::log("luaL_dofile: An error occurred: %s\n", lua_tostring(L, -1));
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
@ -283,7 +284,7 @@ bool HelloPolycodeApp::Update() {
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
client::Config &config = g_config;
|
client::Config &config = g_client_config;
|
||||||
|
|
||||||
const char opts[100] = "hs:p:P:";
|
const char opts[100] = "hs:p:P:";
|
||||||
const char usagefmt[1000] =
|
const char usagefmt[1000] =
|
||||||
|
120
src/core/types.h
Normal file
120
src/core/types.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <exception>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cinttypes> // PRId64
|
||||||
|
#include <sstream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef std::string ss_;
|
||||||
|
template<typename T> using sv_ = std::vector<T>;
|
||||||
|
template<typename T> using set_ = std::set<T>;
|
||||||
|
template<typename T1, typename T2> using sm_ = std::map<T1, T2>;
|
||||||
|
typedef const char cc_;
|
||||||
|
static inline cc_* cs(const ss_ &s){ return s.c_str(); }
|
||||||
|
template<typename T> using up_ = std::unique_ptr<T>;
|
||||||
|
template<typename T> using sp_ = std::shared_ptr<T>;
|
||||||
|
template<typename T> using sil_ = std::initializer_list<T>;
|
||||||
|
|
||||||
|
#define IDF "%" PRId64
|
||||||
|
struct id_ {
|
||||||
|
int64_t value;
|
||||||
|
|
||||||
|
id_(): value(0) {}
|
||||||
|
id_(int64_t v): value(v) {}
|
||||||
|
|
||||||
|
id_& operator=(int64_t v){
|
||||||
|
value = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
bool operator<(const id_ &other) const{
|
||||||
|
return value < other.value;
|
||||||
|
}
|
||||||
|
bool operator==(const id_ &other) const{
|
||||||
|
return value == other.value;
|
||||||
|
}
|
||||||
|
bool operator!=(const id_ &other) const{
|
||||||
|
return value != other.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static inline std::ostream& operator<<(std::ostream &out, const id_ &v){
|
||||||
|
return (out<<v.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct db_json_ {
|
||||||
|
std::string value;
|
||||||
|
db_json_(){}
|
||||||
|
db_json_(const std::string &value_): value(value_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Exception: public std::exception {
|
||||||
|
ss_ msg;
|
||||||
|
Exception(const ss_ &msg): msg(msg) {}
|
||||||
|
virtual const char* what() const throw(){
|
||||||
|
return msg.c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#define DEFINE_EXCEPTION(name, base) struct name: public base\
|
||||||
|
{ name(const ss_ &msg=""): base(ss_()+#name+msg) {} }
|
||||||
|
|
||||||
|
static inline ss_ itos(int64_t i){
|
||||||
|
char buf[22];
|
||||||
|
snprintf(buf, 22, "%" PRId64, i);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
static inline ss_ itos(id_ id){
|
||||||
|
return itos(id.value);
|
||||||
|
}
|
||||||
|
static inline ss_ ftos(float f){
|
||||||
|
char buf[100];
|
||||||
|
snprintf(buf, 100, "%f", f);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SLEN(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
static inline ss_ dump(const id_ &id){
|
||||||
|
char buf[23];
|
||||||
|
snprintf(buf, 23, "@%" PRId64, id.value);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ss_ dump(const sv_<T> &vs){
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
os<<"[";
|
||||||
|
bool first = true;
|
||||||
|
for(const auto &v : vs){
|
||||||
|
if(!first)
|
||||||
|
os<<", ";
|
||||||
|
first = false;
|
||||||
|
os<<v;
|
||||||
|
}
|
||||||
|
os<<"]";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ss_ dump(const std::set<T> &vs){
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
os<<"(";
|
||||||
|
bool first = true;
|
||||||
|
for(const auto &v : vs){
|
||||||
|
if(!first)
|
||||||
|
os<<", ";
|
||||||
|
first = false;
|
||||||
|
os<<v;
|
||||||
|
}
|
||||||
|
os<<")";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static inline cc_* cs(const T &v){
|
||||||
|
return dump(v).c_str();
|
||||||
|
}
|
26
src/interface/core.h
Normal file
26
src/interface/core.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "server/rccpp.h"
|
||||||
|
|
||||||
|
class TestClass : public RuntimeClass<TestClass> {
|
||||||
|
CLASS_INTERNALS(TestClass)
|
||||||
|
public:
|
||||||
|
TestClass();
|
||||||
|
~TestClass();
|
||||||
|
RUNTIME_VIRTUAL int test_add(int a);
|
||||||
|
|
||||||
|
int m_sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
RUNTIME_EXPORT_CLASS(TestClass)
|
||||||
|
|
||||||
|
/*class Module : public RuntimeClass<Module> {
|
||||||
|
CLASS_INTERNALS(Module)
|
||||||
|
public:
|
||||||
|
Module();
|
||||||
|
~Module();
|
||||||
|
RUNTIME_VIRTUAL int test_add(int a);
|
||||||
|
|
||||||
|
int m_sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
RUNTIME_EXPORT_CLASS(Module)*/
|
12
src/server/config.h
Normal file
12
src/server/config.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
|
namespace server
|
||||||
|
{
|
||||||
|
struct Config
|
||||||
|
{
|
||||||
|
ss_ rccpp_build_path = "../cache/rccpp_build";
|
||||||
|
ss_ interface_path = "../src/interface";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,58 @@
|
|||||||
|
#include "core/types.h"
|
||||||
|
#include "server/config.h"
|
||||||
|
#include "server/state.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <c55_getopt.h>
|
||||||
|
|
||||||
|
server::Config g_server_config;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
server::Config &config = g_server_config;
|
||||||
|
|
||||||
|
std::string module_path;
|
||||||
|
|
||||||
|
const char opts[100] = "hm:r:i:";
|
||||||
|
const char usagefmt[1000] =
|
||||||
|
"Usage: %s [OPTION]...\n"
|
||||||
|
" -h Show this help\n"
|
||||||
|
" -m [module_path] Specify module path (for testing a single module)\n"
|
||||||
|
" -r [rccpp_build_path]Specify runtime compiled C++ build path\n"
|
||||||
|
" -i [interface_path] Specify path to interface headers\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while((c = c55_getopt(argc, argv, opts)) != -1)
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
printf(usagefmt, argv[0]);
|
||||||
|
return 1;
|
||||||
|
case 'm':
|
||||||
|
fprintf(stderr, "INFO: module_path: %s\n", c55_optarg);
|
||||||
|
module_path = c55_optarg;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
fprintf(stderr, "INFO: config.rccpp_build_path: %s\n", c55_optarg);
|
||||||
|
config.rccpp_build_path = c55_optarg;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
fprintf(stderr, "INFO: config.interface_path: %s\n", c55_optarg);
|
||||||
|
config.interface_path = c55_optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "ERROR: Invalid command-line argument\n");
|
||||||
|
fprintf(stderr, usagefmt, argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::cerr<<"Buildat server"<<std::endl;
|
std::cerr<<"Buildat server"<<std::endl;
|
||||||
|
|
||||||
|
up_<server::State> state(server::createState());
|
||||||
|
state->load_module(module_path);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
142
src/server/rccpp.cpp
Normal file
142
src/server/rccpp.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#if defined(RCCPP_ENABLED)
|
||||||
|
#include "rccpp.h"
|
||||||
|
|
||||||
|
// Module interface
|
||||||
|
#include "interface/core.h"
|
||||||
|
|
||||||
|
#include <c55_filesys.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
// linux
|
||||||
|
#if 1
|
||||||
|
static void *library_load(const char *filename) { return dlopen(filename, RTLD_NOW); }
|
||||||
|
static void library_unload(void *module) { dlclose(module); }
|
||||||
|
static void *library_get_address(void *module, const char *name) { return dlsym(module, name); }
|
||||||
|
#elif 0
|
||||||
|
static void *library_load(const char *filename) { return LoadLibrary(filename); }
|
||||||
|
static void library_unload(void *module) { FreeLibrary(module); }
|
||||||
|
static void *library_get_address(void *module, const char *name) { return GetProcAddress(module, name); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RCCPP_Compiler::RCCPP_Compiler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RCCPP_Compiler::compile(const std::string &in_path, const std::string &out_path)
|
||||||
|
{
|
||||||
|
//std::string command = "g++ -g -O0 -fPIC -fvisibility=hidden -shared";
|
||||||
|
std::string command = "g++ -DRCCPP -g -fPIC -fvisibility=hidden -shared";
|
||||||
|
|
||||||
|
command += " -std=c++11";
|
||||||
|
|
||||||
|
for(const std::string &dir : include_directories) command += " -I" + dir;
|
||||||
|
for(const std::string &dir : library_directories) command += " -L" + dir;
|
||||||
|
|
||||||
|
command += " -o" + out_path;
|
||||||
|
command += " " + in_path;
|
||||||
|
|
||||||
|
//std::cout << ">>> " << command << std::endl;
|
||||||
|
|
||||||
|
// Fork for compilation.
|
||||||
|
int f = fork();
|
||||||
|
if(f == 0) {
|
||||||
|
execl("/bin/sh", "sh", "-c", command.c_str(), (const char*)nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the forked process to exit.
|
||||||
|
int exit_status;
|
||||||
|
while(wait(&exit_status) > 0);
|
||||||
|
|
||||||
|
return exit_status == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RCCPP_Compiler::build(const std::string &in_path, const std::string &out_path)
|
||||||
|
{
|
||||||
|
std::cout << "Building " << in_path << " -> " << out_path << "... ";
|
||||||
|
|
||||||
|
std::string out_dir = c55fs::stripFilename(out_path);
|
||||||
|
c55fs::CreateAllDirs(out_dir);
|
||||||
|
|
||||||
|
if(compile(in_path, out_path)) {
|
||||||
|
std::cout << "Success!" << std::endl;
|
||||||
|
|
||||||
|
void *new_module = library_load(out_path.c_str());
|
||||||
|
|
||||||
|
RCCPP_GetInterface GetInterface = (RCCPP_GetInterface)library_get_address(new_module, "rccpp_GetInterface");
|
||||||
|
if(GetInterface == nullptr) {
|
||||||
|
std::cout << "GetInterface is missing from the library" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCCPP_Interface *interface = GetInterface();
|
||||||
|
assert(interface && "Interface is null");
|
||||||
|
RCCPP_Constructor fun_constructor = interface->constructor;
|
||||||
|
RCCPP_Destructor fun_destructor = interface->destructor;
|
||||||
|
RCCPP_PlacementNew fun_placementnew = interface->placementnew;
|
||||||
|
|
||||||
|
if(!(fun_constructor && fun_constructor && fun_placementnew)) {
|
||||||
|
printf("Something failed with the function pointers in the module\n");
|
||||||
|
printf(" constructor: %p (%s)\n", fun_constructor, (fun_constructor != nullptr ? "ok" : "fail"));
|
||||||
|
printf(" destructor: %p (%s)\n", fun_destructor, (fun_destructor != nullptr ? "ok" : "fail"));
|
||||||
|
printf(" placement new: %p (%s)\n", fun_placementnew, (fun_placementnew != nullptr ? "ok" : "fail"));
|
||||||
|
fflush(stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string classname = interface->classname;
|
||||||
|
|
||||||
|
auto it = component_info_.find(classname);
|
||||||
|
if(it != component_info_.end()) {
|
||||||
|
RCCPP_Info &funcs = it->second;
|
||||||
|
funcs.constructor = fun_constructor;
|
||||||
|
funcs.destructor = fun_destructor;
|
||||||
|
funcs.placement_new = fun_placementnew;
|
||||||
|
if(funcs.module_prev) library_unload(funcs.module_prev);
|
||||||
|
funcs.module_prev = funcs.module;
|
||||||
|
funcs.module = new_module;
|
||||||
|
} else {
|
||||||
|
RCCPP_Info funcs;
|
||||||
|
funcs.constructor = fun_constructor;
|
||||||
|
funcs.destructor = fun_destructor;
|
||||||
|
funcs.placement_new = fun_placementnew;
|
||||||
|
funcs.module_prev = nullptr;
|
||||||
|
funcs.module = new_module;
|
||||||
|
funcs.size = interface->original_size;
|
||||||
|
component_info_.emplace(classname, std::move(funcs));
|
||||||
|
}
|
||||||
|
|
||||||
|
changed_classes_.push_back(classname);
|
||||||
|
} else {
|
||||||
|
std::cout << "Failed!" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *RCCPP_Compiler::construct(const char *name) {
|
||||||
|
auto component_info_it = component_info_.find(name);
|
||||||
|
if(component_info_it == component_info_.end()) {
|
||||||
|
assert(nullptr && "Failed to get class info");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCCPP_Info &info = component_info_it->second;
|
||||||
|
RCCPP_Constructor constructor = info.constructor;
|
||||||
|
|
||||||
|
void *result = constructor();
|
||||||
|
|
||||||
|
auto it = constructed_objects.find(std::string(name));
|
||||||
|
|
||||||
|
if(it == constructed_objects.end()) constructed_objects.insert(std::make_pair(name, std::vector<void*>{result}));
|
||||||
|
else it->second.push_back(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
127
src/server/rccpp.h
Normal file
127
src/server/rccpp.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
|
// This is what you get when the RCCPP is not enabled
|
||||||
|
#if !defined(RCCPP_ENABLED) && !defined(RCCPP)
|
||||||
|
#define RUNTIME_EXPORT_CLASS(C)
|
||||||
|
#define RUNTIME_VIRTUAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(RCCPP) || defined(RCCPP_ENABLED)
|
||||||
|
#define RCCPP_USE_SINGLETON_NEWING
|
||||||
|
#define RUNTIME_VIRTUAL virtual
|
||||||
|
#define CLASS_INTERNALS(C) public: constexpr static const char *NAME = #C;
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
struct RCCPP_Interface;
|
||||||
|
|
||||||
|
typedef void *(*RCCPP_Constructor)();
|
||||||
|
typedef void (*RCCPP_Destructor)(void *component);
|
||||||
|
typedef void (*RCCPP_PlacementNew)(void *buffer, size_t size);
|
||||||
|
typedef RCCPP_Interface *(*RCCPP_GetInterface)();
|
||||||
|
|
||||||
|
struct RCCPP_Interface {
|
||||||
|
RCCPP_Constructor constructor;
|
||||||
|
RCCPP_Destructor destructor;
|
||||||
|
RCCPP_PlacementNew placementnew;
|
||||||
|
const char *classname;
|
||||||
|
size_t original_size;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is what the runtime compiler exports for the library.
|
||||||
|
#if defined(RCCPP) && !defined(RCCPP_ENABLED)
|
||||||
|
#include <new>
|
||||||
|
#define EXPORT __attribute__ ((visibility ("default")))
|
||||||
|
#define RUNTIME_EXPORT_CLASS(C) \
|
||||||
|
extern "C" { \
|
||||||
|
static void *rccpp_constructor() { return new C(); } \
|
||||||
|
static void rccpp_destructor(void *c) { delete reinterpret_cast<C*>(c); } \
|
||||||
|
static void rccpp_placementnew(void *buffer, size_t size) { new (buffer) C(*(C*)buffer); } \
|
||||||
|
EXPORT RCCPP_Interface *rccpp_GetInterface() { \
|
||||||
|
static RCCPP_Interface interface; \
|
||||||
|
interface.constructor = &rccpp_constructor; \
|
||||||
|
interface.destructor = &rccpp_destructor; \
|
||||||
|
interface.placementnew = &rccpp_placementnew; \
|
||||||
|
interface.classname = #C; \
|
||||||
|
interface.original_size = sizeof(C); \
|
||||||
|
return &interface; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// And this is what your normal compiler sees when you have actually enabled RCCPP.
|
||||||
|
#if !defined(RCCPP) && defined(RCCPP_ENABLED)
|
||||||
|
|
||||||
|
#define RCCPP_CONSTRUCTOR "rccpp_constructor"
|
||||||
|
#define RCCPP_DESTRUCTOR "rccpp_destructor"
|
||||||
|
#define RCCPP_PLACEMENT_NEW "rccpp_placement_new"
|
||||||
|
#define RCCPP_MOVE "rccpp_move"
|
||||||
|
#define RCCPP_CLASSNAME "rccpp_classname"
|
||||||
|
|
||||||
|
#define RUNTIME_EXPORT_CLASS(C)
|
||||||
|
#define RUNTIME_VIRTUAL virtual
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
struct RCCPP_Info {
|
||||||
|
void *module;
|
||||||
|
void *module_prev;
|
||||||
|
RCCPP_Constructor constructor;
|
||||||
|
RCCPP_Destructor destructor;
|
||||||
|
RCCPP_PlacementNew placement_new;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RuntimeClassBase;
|
||||||
|
|
||||||
|
class RCCPP_Compiler {
|
||||||
|
public:
|
||||||
|
RCCPP_Compiler();
|
||||||
|
|
||||||
|
void build(const std::string &in_path, const std::string &out_path);
|
||||||
|
|
||||||
|
template<typename T> T *construct() { return (T*)construct(T::NAME); }
|
||||||
|
void *construct(const char *name);
|
||||||
|
|
||||||
|
#if defined(RCCPP_USE_SINGLETON_NEWING)
|
||||||
|
static RCCPP_Compiler &instance() {
|
||||||
|
static RCCPP_Compiler i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::vector<std::string> include_directories;
|
||||||
|
std::vector<std::string> library_directories;
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::unordered_map<std::string, RCCPP_Info> component_info_;
|
||||||
|
std::unordered_map<std::string, std::vector<void*>> constructed_objects;
|
||||||
|
|
||||||
|
std::vector<std::string> changed_classes_;
|
||||||
|
bool compile(const std::string &in_path, const std::string &out_path);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(RCCPP_ENABLED)
|
||||||
|
#include <cstddef>
|
||||||
|
template<typename T>
|
||||||
|
class RuntimeClass {
|
||||||
|
public:
|
||||||
|
#ifdef RCCPP_USE_SINGLETON_NEWING
|
||||||
|
void *operator new(size_t size) { return RCCPP_Compiler::instance().construct(T::NAME); }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef RCCPP_USE_SINGLETON_NEWING
|
||||||
|
#define RCCPP_Update() RCCPP_Compiler::instance().update();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
template<typename T> class RuntimeClass { };
|
||||||
|
#endif
|
32
src/server/state.cpp
Normal file
32
src/server/state.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "state.h"
|
||||||
|
#include "rccpp.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
extern server::Config g_server_config;
|
||||||
|
|
||||||
|
namespace server {
|
||||||
|
|
||||||
|
struct CState: public State
|
||||||
|
{
|
||||||
|
RCCPP_Compiler m_compiler;
|
||||||
|
|
||||||
|
CState()
|
||||||
|
{
|
||||||
|
m_compiler.include_directories.push_back(
|
||||||
|
g_server_config.interface_path);
|
||||||
|
m_compiler.include_directories.push_back(
|
||||||
|
g_server_config.interface_path+"/..");
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_module(const ss_ &path)
|
||||||
|
{
|
||||||
|
ss_ build_dst = g_server_config.rccpp_build_path + "/foo.o";
|
||||||
|
m_compiler.build(path+"/server/main.cpp", build_dst);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
State* createState()
|
||||||
|
{
|
||||||
|
return new CState();
|
||||||
|
}
|
||||||
|
}
|
13
src/server/state.h
Normal file
13
src/server/state.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "core/types.h"
|
||||||
|
|
||||||
|
namespace server
|
||||||
|
{
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
virtual ~State(){}
|
||||||
|
virtual void load_module(const ss_ &path) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
State* createState();
|
||||||
|
}
|
3
test/testmodule1/server/main.cpp
Normal file
3
test/testmodule1/server/main.cpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include <core.h>
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user