Sandbox Lua files into ram, namespace them, parse conf.json, show_menu
* Lua show_menu function to show inventories. WIP * Copy all lua mods & their files into a series of structs, stored in LuaMod, LuaModFile, and LuaModConfig classes. * Sandbox SandboxedDoFile further by making it only open LuaModFiles * Recursive mod searching which identifies conf.json as a mod root * Read conf.json for name, description, version, and dependencies * Organize mods to load in order of their dependenciesmaster
parent
d0ae343543
commit
e637622aa8
|
@ -11,11 +11,12 @@ project (${PROJECT_NAME})
|
|||
# Include Header only Libraries
|
||||
set (HEADER_LIBRARIES
|
||||
lib/header/catch2/include # Catch2 unit testing library.
|
||||
lib/header/gzip/include # GZip Compression header library
|
||||
lib/header/gzip/include # GZip Compression header library.
|
||||
lib/header/glm/include # OpenGL Mathematics Library.
|
||||
lib/header/sol2/include # Sol2 Lua Parser library
|
||||
lib/header/sol2/include # Sol2 Lua Parser library.
|
||||
lib/header/cute_files/include # Cute file traversal header library.
|
||||
lib/header/stb_image/include # STB Image processor header library.
|
||||
lib/header/json/include # JSON header library.
|
||||
)
|
||||
|
||||
include_directories (${HEADER_LIBRARIES})
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2013-2019 Niels Lohmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1 @@
|
|||
https://github.com/nlohmann/json
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +0,0 @@
|
|||
local path = zeus.get_path("default")
|
||||
|
||||
dofile(path .. "blocks/ground.lua")
|
||||
dofile(path .. "blocks/tree.lua")
|
||||
dofile(path .. "blocks/foliage.lua")
|
||||
dofile(path .. "blocks/desert.lua")
|
||||
dofile(path .. "blocks/formspec.lua")
|
|
@ -1,24 +0,0 @@
|
|||
zeus.register_block("default:open_formspec", {
|
||||
name = "Open Formspec Block",
|
||||
model = "default:block",
|
||||
textures = {"default_brick"},
|
||||
on_place_client = function()
|
||||
print("Open Menu")
|
||||
-- zeus.show_menu({
|
||||
-- {
|
||||
-- type = "rect",
|
||||
-- size = {x = 32, y = 24},
|
||||
-- padding = {h = 1, v = 1},
|
||||
-- background_color = "#171717",
|
||||
-- children = {
|
||||
-- {
|
||||
-- type = "text",
|
||||
-- contents = "Hello world",
|
||||
-- color = "#0ff",
|
||||
-- position = {x = 2, y = 0}
|
||||
-- }
|
||||
-- }
|
||||
-- }
|
||||
-- })
|
||||
end
|
||||
})
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "zeus:default",
|
||||
"description": "Default mod for the Zeus subgame.",
|
||||
"version": "0.0.1"
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
print("Hello from default, Zeus " .. (zeus.is_server() and "Server" or "Client") .. "!")
|
||||
|
||||
local path = zeus.get_path("default")
|
||||
|
||||
dofile(path .. "models.lua")
|
||||
dofile(path .. "blocks.lua")
|
|
@ -1,9 +0,0 @@
|
|||
local path = zeus.get_path("default")
|
||||
|
||||
dofile(path .. "models/block.lua")
|
||||
dofile(path .. "models/block_foliage.lua")
|
||||
dofile(path .. "models/plantlike.lua")
|
||||
dofile(path .. "models/leaflike.lua")
|
||||
dofile(path .. "models/halfslab.lua")
|
||||
dofile(path .. "models/halfslab_foliage.lua")
|
||||
dofile(path .. "models/crosslarge.lua")
|
|
@ -0,0 +1,5 @@
|
|||
dofile("zeus:default/blocks/ground")
|
||||
dofile("zeus:default/blocks/tree")
|
||||
dofile("zeus:default/blocks/foliage")
|
||||
dofile("zeus:default/blocks/desert")
|
||||
dofile("zeus:default/blocks/formspec")
|
|
@ -0,0 +1,33 @@
|
|||
zeus.register_block("default:open_formspec", {
|
||||
name = "Open Formspec Block",
|
||||
model = "default:block",
|
||||
textures = {"default_brick"},
|
||||
on_place_client = function()
|
||||
zeus.show_menu({
|
||||
key = "form_root",
|
||||
type = "rect",
|
||||
|
||||
size = "1920px, 1080px",
|
||||
background = "#0004",
|
||||
|
||||
children = {
|
||||
{
|
||||
key = "inv_root",
|
||||
type = "rect",
|
||||
|
||||
position = "202px, 138px",
|
||||
size = "236px, 118px",
|
||||
padding = "20px, 10px, 8px, 10px",
|
||||
background = "inventory"
|
||||
}, {
|
||||
key = "hotwheel_root",
|
||||
type = "rect",
|
||||
|
||||
position = "296px, 268px",
|
||||
size = "52px, 52px",
|
||||
background = "inventory_wheel"
|
||||
}
|
||||
}
|
||||
});
|
||||
end
|
||||
})
|
|
@ -0,0 +1,4 @@
|
|||
print("Hello from default, Zeus " .. (zeus.is_server() and "Server" or "Client") .. "!")
|
||||
|
||||
dofile("zeus:default/models")
|
||||
dofile("zeus:default/blocks")
|
|
@ -0,0 +1,7 @@
|
|||
dofile("zeus:default/models/block")
|
||||
dofile("zeus:default/models/block_foliage")
|
||||
dofile("zeus:default/models/plantlike")
|
||||
dofile("zeus:default/models/leaflike")
|
||||
dofile("zeus:default/models/halfslab")
|
||||
dofile("zeus:default/models/halfslab_foliage")
|
||||
dofile("zeus:default/models/crosslarge")
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "zeus:kinetic",
|
||||
"description": "Kinetic energy for the Zeus subgame.",
|
||||
"version": "0.0.1",
|
||||
"depends": ["zeus:default", "zeus:mapgen"]
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
print("Hello from kinetic")
|
||||
|
||||
local path = zeus.get_path("kinetic")
|
||||
|
||||
dofile(path .. "models/axle.lua")
|
||||
dofile(path .. "blocks/axle.lua")
|
|
@ -0,0 +1,4 @@
|
|||
print("Hello from kinetic")
|
||||
|
||||
dofile("zeus:kinetic/models/axle")
|
||||
dofile("zeus:kinetic/blocks/axle")
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "zeus:mapgen",
|
||||
"description": "Mapgen mod for the Zeus subgame.",
|
||||
"version": "0.0.1",
|
||||
"depends": ["zeus:default"]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
print("Hello from mapgen")
|
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 20 KiB |
|
@ -180,6 +180,7 @@ set(ZEUS_SRC_FILES
|
|||
game/entity/hud/components/GUIComponent.cpp
|
||||
game/entity/hud/components/GUIComponent.h
|
||||
game/entity/hud/components/basic/GUIContainer.cpp
|
||||
game/entity/hud/components/basic/GUIContainer.h)
|
||||
game/entity/hud/components/basic/GUIContainer.h
|
||||
api/client/modules/cShowMenu.h api/LuaModFile.h api/LuaMod.h api/LuaModConfig.h)
|
||||
|
||||
add_library (zeusCore ${ZEUS_SRC_FILES})
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Created by aurailus on 03/08/19.
|
||||
//
|
||||
|
||||
#ifndef ZEUS_LUAMOD_H
|
||||
#define ZEUS_LUAMOD_H
|
||||
|
||||
#include <vector>
|
||||
#include "LuaModFile.h"
|
||||
#include "LuaModConfig.h"
|
||||
|
||||
class LuaMod {
|
||||
public:
|
||||
std::vector<LuaModFile> files {};
|
||||
LuaModConfig config {};
|
||||
};
|
||||
|
||||
#endif //ZEUS_LUAMOD_H
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Created by aurailus on 03/08/19.
|
||||
//
|
||||
|
||||
#ifndef ZEUS_LUAMODCONFIG_H
|
||||
#define ZEUS_LUAMODCONFIG_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct LuaModConfig {
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string version;
|
||||
std::vector<std::string> depends;
|
||||
};
|
||||
|
||||
#endif //ZEUS_LUAMODCONFIG_H
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// Created by aurailus on 03/08/19.
|
||||
//
|
||||
|
||||
#ifndef ZEUS_LUAMODFILE_H
|
||||
#define ZEUS_LUAMODFILE_H
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
struct LuaModFile {
|
||||
std::string path;
|
||||
std::string file;
|
||||
};
|
||||
|
||||
|
||||
#endif //ZEUS_LUAMODFILE_H
|
|
@ -25,15 +25,6 @@ void LuaParser::update() {
|
|||
}
|
||||
}
|
||||
|
||||
int LuaParser::DoFileSandboxed(std::string file) {
|
||||
if (root_path.contains(Path(file))) {
|
||||
lua.script_file(file);
|
||||
}
|
||||
else {
|
||||
std::cout << Log::err << "Error opening \"" + file + "\", access denied." << Log::endl;
|
||||
}
|
||||
}
|
||||
|
||||
sol::table LuaParser::vecToTable(glm::vec3 vec) {
|
||||
return lua.create_table_with("x", vec.x, "y", vec.y, "z", vec.z);
|
||||
}
|
|
@ -43,8 +43,6 @@ public:
|
|||
sol::table zeus;
|
||||
|
||||
std::list<DelayedFunction> delayed_functions;
|
||||
protected:
|
||||
int DoFileSandboxed(std::string file);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "LocalLuaParser.h"
|
||||
#include "LocalRegisterBlocks.h"
|
||||
#include "../../def/LocalDefs.h"
|
||||
#include "../../game/entity/hud/GameGui.h"
|
||||
|
||||
#include "modules/cDump.h"
|
||||
#include "modules/cPrintE.h"
|
||||
|
@ -20,7 +21,9 @@
|
|||
#include "modules/cGetBlock.h"
|
||||
#include "modules/cRemoveBlock.h"
|
||||
|
||||
void LocalLuaParser::init(LocalDefs& defs, LocalWorld& world) {
|
||||
#include "modules/cShowMenu.h"
|
||||
|
||||
void LocalLuaParser::init(LocalDefs& defs, LocalWorld& world, GameGui& gui) {
|
||||
//Load Base Libraries
|
||||
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math);
|
||||
|
||||
|
@ -28,7 +31,7 @@ void LocalLuaParser::init(LocalDefs& defs, LocalWorld& world) {
|
|||
lua_atpanic(lua, sol::c_call<decltype(&LuaParser::override_panic), &LuaParser::override_panic>);
|
||||
|
||||
//Load Modules
|
||||
loadModules(defs, world);
|
||||
loadModules(defs, world, gui);
|
||||
|
||||
//Load Mods
|
||||
loadMods();
|
||||
|
@ -37,7 +40,7 @@ void LocalLuaParser::init(LocalDefs& defs, LocalWorld& world) {
|
|||
registerBlocks(defs);
|
||||
}
|
||||
|
||||
void LocalLuaParser::loadModules(LocalDefs &defs, LocalWorld &world) {
|
||||
void LocalLuaParser::loadModules(LocalDefs &defs, LocalWorld &world, GameGui& gui) {
|
||||
//Create Zeus Table
|
||||
zeus = lua.create_table();
|
||||
lua["zeus"] = zeus;
|
||||
|
@ -56,6 +59,8 @@ void LocalLuaParser::loadModules(LocalDefs &defs, LocalWorld &world) {
|
|||
ClientApi::get_block(zeus, defs, world);
|
||||
ClientApi::set_block(zeus, defs, world);
|
||||
ClientApi::remove_block(zeus, defs, world);
|
||||
|
||||
ClientApi::show_menu(zeus, defs, gui);
|
||||
}
|
||||
|
||||
void LocalLuaParser::loadMods() {
|
||||
|
@ -96,3 +101,12 @@ void LocalLuaParser::loadMods() {
|
|||
void LocalLuaParser::registerBlocks(LocalDefs& defs) {
|
||||
LocalRegisterBlocks(zeus, defs);
|
||||
}
|
||||
|
||||
int LocalLuaParser::DoFileSandboxed(std::string file) {
|
||||
if (root_path.contains(Path(file))) {
|
||||
lua.script_file(file);
|
||||
}
|
||||
else {
|
||||
std::cout << Log::err << "Error opening \"" + file + "\", access denied." << Log::endl;
|
||||
}
|
||||
}
|
|
@ -10,18 +10,21 @@
|
|||
|
||||
class LocalDefs;
|
||||
class LocalWorld;
|
||||
class GameGui;
|
||||
|
||||
class LocalLuaParser : public LuaParser {
|
||||
public:
|
||||
explicit LocalLuaParser(std::string mod_root) : LuaParser(std::move(mod_root)) {};
|
||||
|
||||
void init(LocalDefs& defs, LocalWorld& world);
|
||||
void init(LocalDefs& defs, LocalWorld& world, GameGui& gui);
|
||||
|
||||
void loadModules(LocalDefs& defs, LocalWorld& world);
|
||||
void loadModules(LocalDefs& defs, LocalWorld& world, GameGui& gui);
|
||||
void loadMods();
|
||||
void registerBlocks(LocalDefs& defs);
|
||||
|
||||
~LocalLuaParser() = default;
|
||||
private:
|
||||
int DoFileSandboxed(std::string file);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
//
|
||||
// Created by aurailus on 01/08/19.
|
||||
//
|
||||
|
||||
#ifndef ZEUS_CSHOWMENU_H
|
||||
#define ZEUS_CSHOWMENU_H
|
||||
|
||||
#include "../../../def/LocalDefs.h"
|
||||
#include "../../../game/scene/world/LocalWorld.h"
|
||||
#include "../../../game/entity/hud/GameGui.h"
|
||||
#include "../../../game/entity/hud/components/GUIComponent.h"
|
||||
#include "../../../game/entity/hud/components/basic/GUIContainer.h"
|
||||
#include "../../../game/entity/hud/components/basic/GUIText.h"
|
||||
#include "../../../game/entity/hud/components/basic/GUIRect.h"
|
||||
#include <sol2/sol.hpp>
|
||||
|
||||
const static float scale_modifier = 3;
|
||||
|
||||
float calcNum(std::string input) {
|
||||
if (input.find("px") != string::npos) {
|
||||
return atof(input.substr(0, input.find("px")).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 calc2dVec(std::string input) {
|
||||
glm::vec2 r;
|
||||
size_t count = std::count(input.begin(), input.end(), ',');
|
||||
|
||||
if (count == 0) { //1 value
|
||||
r.x = calcNum(input);
|
||||
r.y = r.x;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (count == 1) { //2 values
|
||||
size_t delim = input.find(',');
|
||||
std::string x = input.substr(0, delim);
|
||||
std::string y = input.substr(delim + 1);
|
||||
|
||||
r.x = calcNum(x);
|
||||
r.y = calcNum(y);
|
||||
return r;
|
||||
}
|
||||
|
||||
std::cout << Log::err << "Invalid dimension string " << input << Log::endl;
|
||||
return r;
|
||||
}
|
||||
|
||||
glm::vec4 calc4dVec(std::string input) {
|
||||
glm::vec4 r;
|
||||
size_t count = std::count(input.begin(), input.end(), ',');
|
||||
|
||||
if (count == 0) { //1 value
|
||||
r = glm::vec4(calcNum(input));
|
||||
return r;
|
||||
}
|
||||
|
||||
if (count == 1) { //2 values
|
||||
size_t delim = input.find(',');
|
||||
std::string x = input.substr(0, delim);
|
||||
std::string y = input.substr(delim + 1);
|
||||
|
||||
r.x = calcNum(x);
|
||||
r.y = calcNum(y);
|
||||
r.z = r.x;
|
||||
r.w = r.y;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (count == 3) { //4 values
|
||||
size_t begin = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
size_t end = input.find(',', begin);
|
||||
r[i] = calcNum(input.substr(begin, end - begin));
|
||||
begin = end + 1;
|
||||
}
|
||||
r[3] = calcNum(input.substr(begin));
|
||||
return r;
|
||||
}
|
||||
|
||||
std::cout << Log::err << "Invalid dimension string " << input << Log::endl;
|
||||
return r;
|
||||
}
|
||||
|
||||
void processElement(LocalDefs& defs, sol::table& element, std::shared_ptr<GUIComponent> parent) {
|
||||
auto key = element.get<std::string>("key");
|
||||
auto type = element.get<std::string>("type");
|
||||
|
||||
std::shared_ptr<GUIComponent> component;
|
||||
|
||||
if (type == "rect") {
|
||||
std::string posStr = element.get<std::string>("position");
|
||||
std::string sizeStr = element.get<std::string>("size");
|
||||
std::string padStr = element.get<std::string>("padding");
|
||||
|
||||
glm::vec2 pos = calc2dVec(posStr) * scale_modifier;
|
||||
glm::vec2 size = calc2dVec(sizeStr) * scale_modifier;
|
||||
glm::vec4 padding = calc4dVec(padStr) * scale_modifier;
|
||||
std::string background = element.get_or<std::string>("background", "#0000");
|
||||
|
||||
std::shared_ptr<GUIRect> rect = std::make_shared<GUIRect>(key);
|
||||
|
||||
if (background[0] == '#') rect->create(size, padding, Util::hexToColorVec(background));
|
||||
else rect->create(size - glm::vec2{padding.y + padding.w, padding.x + padding.z}, padding, defs.textures().getTextureRef(background));
|
||||
|
||||
component = rect;
|
||||
rect->setPos(pos);
|
||||
}
|
||||
else if (type == "text") {
|
||||
std::string posStr = element.get<std::string>("position");
|
||||
std::string sizeStr = element.get<std::string>("size");
|
||||
std::string padStr = element.get<std::string>("padding");
|
||||
|
||||
glm::vec2 pos = calc2dVec(posStr) * scale_modifier;
|
||||
glm::vec2 scale = glm::vec2(scale_modifier);
|
||||
glm::vec4 padding = calc4dVec(padStr) * scale_modifier;
|
||||
glm::vec4 bgcolor = Util::hexToColorVec(element.get_or<std::string>("background_color", "#0000"));
|
||||
glm::vec4 color = Util::hexToColorVec(element.get_or<std::string>("color", "#fff"));
|
||||
std::string contents = element.get<std::string>("contents");
|
||||
|
||||
std::shared_ptr<GUIText> text = std::make_shared<GUIText>(key);
|
||||
text->create(scale, padding, bgcolor, color, defs.textures().getTextureRef("font"));
|
||||
text->setText(contents);
|
||||
component = text;
|
||||
text->setPos(pos);
|
||||
}
|
||||
|
||||
parent->add(component);
|
||||
|
||||
auto children = element.get<sol::optional<sol::table>>("children");
|
||||
if (children) {
|
||||
for (auto &child : *children) {
|
||||
sol::table elem = child.second;
|
||||
processElement(defs, elem, component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ClientApi {
|
||||
void show_menu(sol::table &zeus, LocalDefs& defs, GameGui& gui) {
|
||||
|
||||
zeus.set_function("show_menu", [&](sol::table gui_root) {
|
||||
auto root = std::make_shared<GUIContainer>("root");
|
||||
gui.add(root);
|
||||
|
||||
processElement(defs, gui_root, static_pointer_cast<GUIComponent>(root));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //ZEUS_CSHOWMENU_H
|
|
@ -2,6 +2,7 @@
|
|||
// Created by aurailus on 11/06/19.
|
||||
//
|
||||
|
||||
#include <iomanip>
|
||||
#include "ServerLuaParser.h"
|
||||
#include "ServerRegisterBlocks.h"
|
||||
#include "../../def/ServerDefs.h"
|
||||
|
@ -56,43 +57,212 @@ void ServerLuaParser::loadModules(ServerDefs &defs, ServerWorld &world) {
|
|||
ServerApi::get_block(zeus, defs, world);
|
||||
ServerApi::set_block(zeus, defs, world);
|
||||
ServerApi::remove_block(zeus, defs, world);
|
||||
}
|
||||
|
||||
void ServerLuaParser::loadMods() {
|
||||
//Sandbox the dofile function
|
||||
lua.set_function("dofile", &ServerLuaParser::DoFileSandboxed, this);
|
||||
|
||||
cf_dir_t mods_dir;
|
||||
cf_dir_open(&mods_dir, root.c_str());
|
||||
|
||||
//Iterate through all mod folders
|
||||
while (mods_dir.has_next) {
|
||||
cf_file_t mod_folder_file;
|
||||
cf_read_file(&mods_dir, &mod_folder_file);
|
||||
|
||||
if (mod_folder_file.is_dir && strncmp(mod_folder_file.name, ".", 2) != 0 && strncmp(mod_folder_file.name, "..", 3) != 0) {
|
||||
cf_dir_t mod_dir;
|
||||
cf_dir_open(&mod_dir, mod_folder_file.path);
|
||||
|
||||
//Find main.lua
|
||||
while (mod_dir.has_next) {
|
||||
cf_file_t mod_file;
|
||||
cf_read_file(&mod_dir, &mod_file);
|
||||
|
||||
if (strncmp(mod_file.name, "main.lua", 9) == 0) {
|
||||
//Run main.lua
|
||||
DoFileSandboxed(mod_file.path);
|
||||
break;
|
||||
}
|
||||
|
||||
cf_dir_next(&mod_dir);
|
||||
}
|
||||
}
|
||||
cf_dir_next(&mods_dir);
|
||||
}
|
||||
cf_dir_close(&mods_dir);
|
||||
}
|
||||
|
||||
void ServerLuaParser::registerBlocks(ServerDefs& defs) {
|
||||
ServerRegisterBlocks(zeus, defs);
|
||||
}
|
||||
|
||||
void ServerLuaParser::loadMods() {
|
||||
auto modDirs = findModDirs();
|
||||
mods = createLuaMods(modDirs);
|
||||
handleDependencies();
|
||||
|
||||
for (LuaMod& mod : mods) {
|
||||
DoFileSandboxed(mod.config.name + "/main");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::list<std::string> ServerLuaParser::findModDirs() {
|
||||
//Find Mod Directories
|
||||
std::list<std::string> modDirs {};
|
||||
std::list<std::string> dirsToScan {root};
|
||||
|
||||
cf_dir_t dir;
|
||||
|
||||
while (!dirsToScan.empty()) {
|
||||
std::string dirStr = *dirsToScan.begin();
|
||||
dirsToScan.erase(dirsToScan.begin());
|
||||
bool isModFolder = false;
|
||||
|
||||
cf_dir_open(&dir, dirStr.c_str());
|
||||
|
||||
std::list<std::string> subDirs;
|
||||
|
||||
while (dir.has_next) {
|
||||
// Read through files in the directory
|
||||
cf_file_t scannedFile;
|
||||
cf_read_file(&dir, &scannedFile);
|
||||
|
||||
if (strncmp(scannedFile.name, ".", 1) != 0) {
|
||||
if (scannedFile.is_dir) subDirs.emplace_back(scannedFile.path);
|
||||
else if (strncmp(scannedFile.name, "conf.json", 10) == 0) {
|
||||
isModFolder = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cf_dir_next(&dir);
|
||||
}
|
||||
|
||||
cf_dir_close(&dir);
|
||||
|
||||
if (isModFolder) modDirs.push_back(dirStr);
|
||||
else for (const std::string& s : subDirs) dirsToScan.push_back(s);
|
||||
}
|
||||
|
||||
return std::move(modDirs);
|
||||
}
|
||||
|
||||
std::vector<LuaMod> ServerLuaParser::createLuaMods(std::list<std::string> modDirs) {
|
||||
cf_dir_t dir;
|
||||
|
||||
std::vector<LuaMod> mods;
|
||||
|
||||
for (const std::string& modDir : modDirs) {
|
||||
std::string root = modDir + "/script";
|
||||
|
||||
std::list<std::string> dirsToScan {root};
|
||||
std::list<std::string> luaFiles {};
|
||||
|
||||
while (!dirsToScan.empty()) {
|
||||
std::string dirStr = *dirsToScan.begin();
|
||||
dirsToScan.erase(dirsToScan.begin());
|
||||
|
||||
cf_dir_open(&dir, dirStr.c_str());
|
||||
|
||||
while (dir.has_next) {
|
||||
// Read through files in the directory
|
||||
cf_file_t scannedFile;
|
||||
cf_read_file(&dir, &scannedFile);
|
||||
|
||||
if (strncmp(scannedFile.name, ".", 1) != 0) {
|
||||
if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path);
|
||||
else {
|
||||
char *dot = strrchr(scannedFile.path, '.');
|
||||
if (dot && strncmp(dot, ".lua", 4) == 0) {
|
||||
luaFiles.emplace_back(scannedFile.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cf_dir_next(&dir);
|
||||
}
|
||||
|
||||
cf_dir_close(&dir);
|
||||
}
|
||||
|
||||
LuaMod mod {};
|
||||
auto& conf = mod.config;
|
||||
|
||||
std::ifstream i(modDir + "/conf.json");
|
||||
json j;
|
||||
i >> j;
|
||||
|
||||
auto depends = j["depends"];
|
||||
if (strncmp(depends.type_name(), "array", 5) == 0) {
|
||||
for (auto &it : depends) {
|
||||
if (strncmp(it.type_name(), "string", 6) == 0) {
|
||||
conf.depends.push_back(static_cast<std::string>(it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conf.name = j["name"];
|
||||
conf.description = j["description"];
|
||||
conf.version = j["version"];
|
||||
|
||||
for (std::string& file : luaFiles) {
|
||||
size_t rootPos = file.find(root);
|
||||
std::string modPath = file;
|
||||
assert(rootPos != std::string::npos);
|
||||
|
||||
modPath.erase(rootPos, root.length());
|
||||
modPath.insert(0, conf.name);
|
||||
modPath.resize(modPath.size() - 4);
|
||||
|
||||
std::ifstream t(file);
|
||||
std::string fileStr((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
|
||||
|
||||
LuaModFile f {modPath, fileStr};
|
||||
mod.files.push_back(f);
|
||||
}
|
||||
|
||||
mods.push_back(mod);
|
||||
}
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
void ServerLuaParser::handleDependencies() {
|
||||
// TODO: Detect and crash on cyclic dependencies
|
||||
// Ruben's Pseudocode
|
||||
//
|
||||
// def resolve(package):
|
||||
// for dep in package.dependencies:
|
||||
// if pending[dep]:
|
||||
// throw "dependency cycle"
|
||||
// elsif not loaded[dep]:
|
||||
// pending[dep] = True
|
||||
// resolve(dep, loaded, order, pending)
|
||||
// loaded[dep] = True
|
||||
// order.append(dep)
|
||||
// del pending[dep]
|
||||
//
|
||||
//
|
||||
// order = []
|
||||
// pending = {}
|
||||
// loading = {}
|
||||
//
|
||||
// for package in list:
|
||||
// if not loaded[package]:
|
||||
// resolve(package, loaded, order, pending)
|
||||
|
||||
for (int i = 0; i < mods.size(); i++) {
|
||||
LuaMod& mod = mods[i];
|
||||
auto& deps = mod.config.depends;
|
||||
|
||||
bool modifiedList = false;
|
||||
|
||||
for (std::string& dep : deps) {
|
||||
for (int j = 0; j < mods.size(); j++) {
|
||||
LuaMod& otherMod = mods[j];
|
||||
if (otherMod.config.name == dep) {
|
||||
if (j > i) {
|
||||
LuaMod copy = otherMod;
|
||||
mods.erase(mods.begin() + j);
|
||||
mods.insert(mods.begin() + i, copy);
|
||||
i++;
|
||||
modifiedList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modifiedList) i = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int ServerLuaParser::DoFileSandboxed(std::string file) {
|
||||
size_t modname_length = file.find('/');
|
||||
std::string modname = file.substr(0, modname_length);
|
||||
|
||||
for (LuaMod& mod : mods) {
|
||||
if (strncmp(mod.config.name.c_str(), modname.c_str(), modname_length) == 0) {
|
||||
for (LuaModFile& f : mod.files) {
|
||||
if (f.path == file) {
|
||||
lua.script(f.file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << Log::err << "Error opening \"" + file + "\", not found." << Log::endl;
|
||||
}
|
|
@ -5,15 +5,19 @@
|
|||
#ifndef ZEUS_SERVERLUAPARSER_H
|
||||
#define ZEUS_SERVERLUAPARSER_H
|
||||
|
||||
#include "../LuaMod.h"
|
||||
#include "../LuaParser.h"
|
||||
#include <cute_files/cute_files.h>
|
||||
#include <json/json.hpp>
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
class ServerDefs;
|
||||
class ServerWorld;
|
||||
|
||||
class ServerLuaParser : public LuaParser {
|
||||
public:
|
||||
explicit ServerLuaParser(std::string mod_root) : LuaParser(std::move(mod_root)) {};
|
||||
explicit ServerLuaParser(const std::string& mod_root) : LuaParser(mod_root) {};
|
||||
|
||||
void init(ServerDefs& defs, ServerWorld& world);
|
||||
|
||||
|
@ -22,6 +26,14 @@ public:
|
|||
void registerBlocks(ServerDefs& defs);
|
||||
|
||||
~ServerLuaParser() = default;
|
||||
private:
|
||||
std::list<std::string> findModDirs();
|
||||
std::vector<LuaMod> createLuaMods(std::list<std::string> modDirs);
|
||||
void handleDependencies();
|
||||
|
||||
int DoFileSandboxed(std::string file);
|
||||
|
||||
std::vector<LuaMod> mods;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ LocalDefs::LocalDefs(const std::string& tex_path) :
|
|||
textureAtlas.loadDirectory(tex_path + "/ent");
|
||||
}
|
||||
|
||||
void LocalDefs::initLuaApi(LocalWorld &world) {
|
||||
luaApi.init(*this, world);
|
||||
void LocalDefs::initLuaApi(LocalWorld &world, GameGui& gui) {
|
||||
luaApi.init(*this, world, gui);
|
||||
}
|
||||
|
||||
LocalBlockAtlas &LocalDefs::blocks() {
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
TextureAtlas& textures();
|
||||
LocalLuaParser& lua();
|
||||
|
||||
void initLuaApi(LocalWorld &world);
|
||||
void initLuaApi(LocalWorld &world, GameGui& gui);
|
||||
void update(float delta);
|
||||
|
||||
~LocalDefs() = default;
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
#include "ServerDefs.h"
|
||||
|
||||
ServerDefs::ServerDefs() :
|
||||
luaApi("/home/aurailus/CLion/Zeus/res/lua/") {
|
||||
}
|
||||
luaApi("/home/aurailus/CLion/Zeus/res/lua") {}
|
||||
|
||||
void ServerDefs::init(ServerWorld &world) {
|
||||
luaApi.init(*this, world);
|
||||
|
|
|
@ -72,10 +72,16 @@ void GameGui::bufferResized(glm::vec2 bufferSize) {
|
|||
get<GUIRect>("viginette")->setScale({bufferSize.x, bufferSize.y});
|
||||
}
|
||||
|
||||
void GameGui::setInventoryVisible(bool visible) {
|
||||
get<GUIRect>("root")->setVisible(visible);
|
||||
void GameGui::setVisible(bool visible) {
|
||||
GUIComponent::setVisible(visible);
|
||||
get<GUIRect>("root")->setVisible(invOpen);
|
||||
}
|
||||
|
||||
bool GameGui::isInventoryVisible() {
|
||||
return get<GUIRect>("root")->isVisible();
|
||||
void GameGui::setInvOpen(bool open) {
|
||||
get<GUIRect>("root")->setVisible(open);
|
||||
invOpen = open;
|
||||
}
|
||||
|
||||
bool GameGui::isInvOpen() {
|
||||
return invOpen;
|
||||
}
|
|
@ -7,17 +7,20 @@
|
|||
|
||||
#include "components/basic/GUIRect.h"
|
||||
#include "components/basic/GUIContainer.h"
|
||||
#include "../Entity.h"
|
||||
#include "../../graph/drawable/DrawableGroup.h"
|
||||
#include "../../ClientState.h"
|
||||
#include "../Entity.h"
|
||||
|
||||
class GameGui : public GUIContainer {
|
||||
public:
|
||||
explicit GameGui(glm::vec2 bufferSize, TextureAtlas& atlas);
|
||||
void bufferResized(glm::vec2 bufferSize);
|
||||
|
||||
void setInventoryVisible(bool visible);
|
||||
bool isInventoryVisible();
|
||||
void setVisible(bool visible) override;
|
||||
void setInvOpen(bool open);
|
||||
bool isInvOpen();
|
||||
|
||||
bool invOpen;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ GameScene::GameScene(ClientState& state) : Scene(state),
|
|||
state.renderer.setClearColor(148, 194, 240);
|
||||
state.renderer.getWindow().lockMouse(true);
|
||||
|
||||
defs.initLuaApi(world);
|
||||
defs.initLuaApi(world, gameGui);
|
||||
world.init();
|
||||
|
||||
gui.push_back(&gameGui);
|
||||
|
@ -31,7 +31,6 @@ GameScene::GameScene(ClientState& state) : Scene(state),
|
|||
r.sendTo(state.connection.getPeer(), PacketChannel::CONNECT);
|
||||
}
|
||||
|
||||
|
||||
void GameScene::update() {
|
||||
defs.update(static_cast<float>(state.deltaTime) * 1000);
|
||||
defs.textures().update();
|
||||
|
@ -68,8 +67,8 @@ void GameScene::update() {
|
|||
}
|
||||
|
||||
if (window.input.isKeyPressed(GLFW_KEY_E)) {
|
||||
bool open = !gameGui.isInventoryVisible();
|
||||
gameGui.setInventoryVisible(open);
|
||||
bool open = !gameGui.isInvOpen();
|
||||
gameGui.setInvOpen(open);
|
||||
window.lockMouse(!open);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,10 +114,10 @@ void ServerWorld::sendChunk(glm::vec3 pos, ServerClient &peer) {
|
|||
r.sendTo(peer.getPeer(), PacketChannel::CHUNK);
|
||||
}
|
||||
|
||||
void ServerWorld::setBlock(glm::vec3 pos, int block) {
|
||||
void ServerWorld::setBlock(glm::vec3 pos, unsigned int block) {
|
||||
auto oldBlock = getBlock(pos);
|
||||
|
||||
if (block == 0) {
|
||||
if (block == 1) { //TODO: Get air's data value
|
||||
auto def = defs.blocks().fromIndex(oldBlock);
|
||||
if (def.callbacks.count(Callback::DESTRUCT)) {
|
||||
def.callbacks[Callback::DESTRUCT](defs.lua().vecToTable(pos));
|
||||
|
@ -168,7 +168,7 @@ bool ServerWorld::isInBounds(glm::vec3 cPos, std::pair<glm::vec3, glm::vec3> &bo
|
|||
&& cPos.z >= bounds.first.z && cPos.z <= bounds.second.z);
|
||||
}
|
||||
|
||||
int ServerWorld::getBlock(glm::vec3 pos) {
|
||||
unsigned int ServerWorld::getBlock(glm::vec3 pos) {
|
||||
return dimension.getBlock(pos);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#ifndef ZEUS_WORLD_H
|
||||
#define ZEUS_WORLD_H
|
||||
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "WorldGenStream.h"
|
||||
|
@ -24,8 +23,8 @@ public:
|
|||
void init();
|
||||
void update();
|
||||
|
||||
void setBlock(glm::vec3 pos, int block);
|
||||
int getBlock(glm::vec3 pos);
|
||||
void setBlock(glm::vec3 pos, unsigned int block);
|
||||
unsigned int getBlock(glm::vec3 pos);
|
||||
|
||||
~ServerWorld();
|
||||
private:
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
#include <iostream>
|
||||
#include "Log.h"
|
||||
|
||||
namespace Util {
|
||||
struct EnumClassHash {
|
||||
|
@ -51,6 +54,52 @@ namespace Util {
|
|||
unsigned int packedInt = (charX << 16) | (charY << 8) | charZ;
|
||||
return static_cast<float>(static_cast<double>(packedInt) / static_cast<double>(1 << 24));
|
||||
}
|
||||
|
||||
inline static unsigned int intFromHexSegment(const std::string &t) {
|
||||
unsigned int x;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << t;
|
||||
ss >> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
static glm::vec4 hexToColorVec(std::string hex) {
|
||||
glm::vec4 color {};
|
||||
|
||||
if (hex[0] == '#') hex.erase(0, 1);
|
||||
else std::cout << Log::err << "Color string does not begin with hash!" << Log::endl;
|
||||
|
||||
std::string r, g, b, a;
|
||||
|
||||
if (hex.length() == 3 || hex.length() == 4) {
|
||||
r = hex.substr(0, 1);
|
||||
r += r;
|
||||
g = hex.substr(1, 1);
|
||||
g += g;
|
||||
b = hex.substr(2, 1);
|
||||
b += b;
|
||||
a = (hex.length() == 4) ? hex.substr(3, 1) : "f";
|
||||
a += a;
|
||||
}
|
||||
else if (hex.length() == 6 || hex.length() == 8) {
|
||||
r = hex.substr(0,2);
|
||||
g = hex.substr(2,2);
|
||||
b = hex.substr(4,2);
|
||||
a = (hex.length() == 8) ? hex.substr(6,2) : "ff";
|
||||
}
|
||||
else {
|
||||
std::cout << Log::err << "Color string is of incorrect length!" << Log::endl;
|
||||
return color;
|
||||
}
|
||||
|
||||
color.r = intFromHexSegment(r) / 255.f;
|
||||
color.g = intFromHexSegment(g) / 255.f;
|
||||
color.b = intFromHexSegment(b) / 255.f;
|
||||
color.a = intFromHexSegment(a) / 255.f;
|
||||
|
||||
return color;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ int Dimension::getMeshChunkCount() {
|
|||
return (int)meshChunks.size();
|
||||
}
|
||||
|
||||
void Dimension::setBlock(glm::vec3 pos, int block) {
|
||||
void Dimension::setBlock(glm::vec3 pos, unsigned int block) {
|
||||
auto chunkPos = TransPos::chunkFromVec(TransPos::roundPos(pos));
|
||||
auto local = TransPos::chunkLocalFromVec(TransPos::roundPos(pos));
|
||||
|
||||
|
@ -103,13 +103,13 @@ void Dimension::setBlock(glm::vec3 pos, int block) {
|
|||
if (chunk != nullptr) chunk->setBlock(local, block);
|
||||
}
|
||||
|
||||
int Dimension::getBlock(glm::vec3 pos) {
|
||||
unsigned int Dimension::getBlock(glm::vec3 pos) {
|
||||
auto chunkPos = TransPos::chunkFromVec(TransPos::roundPos(pos));
|
||||
auto local = TransPos::chunkLocalFromVec(TransPos::roundPos(pos));
|
||||
|
||||
auto chunk = getChunk(chunkPos);
|
||||
if (chunk != nullptr) return chunk->getBlock(local);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Dimension::removeMeshChunk(const glm::vec3& pos) {
|
||||
|
|
|
@ -24,8 +24,8 @@ public:
|
|||
void removeMeshChunk(const glm::vec3& pos);
|
||||
|
||||
void update();
|
||||
void setBlock(glm::vec3 pos, int block);
|
||||
int getBlock(glm::vec3 pos);
|
||||
void setBlock(glm::vec3 pos, unsigned int block);
|
||||
unsigned int getBlock(glm::vec3 pos);
|
||||
|
||||
int render(Renderer &renderer);
|
||||
int getMeshChunkCount();
|
||||
|
|
Loading…
Reference in New Issue