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 dependencies
master
Nicole Collings 2019-08-03 18:18:05 -07:00
parent d0ae343543
commit e637622aa8
54 changed files with 23307 additions and 131 deletions

View File

@ -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})

View File

@ -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.

1
lib/header/json/REPO.md Normal file
View File

@ -0,0 +1 @@
https://github.com/nlohmann/json

File diff suppressed because it is too large Load Diff

View File

@ -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")

View File

@ -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
})

View File

@ -0,0 +1,5 @@
{
"name": "zeus:default",
"description": "Default mod for the Zeus subgame.",
"version": "0.0.1"
}

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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
})

View File

@ -0,0 +1,4 @@
print("Hello from default, Zeus " .. (zeus.is_server() and "Server" or "Client") .. "!")
dofile("zeus:default/models")
dofile("zeus:default/blocks")

View File

@ -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")

View File

@ -0,0 +1,6 @@
{
"name": "zeus:kinetic",
"description": "Kinetic energy for the Zeus subgame.",
"version": "0.0.1",
"depends": ["zeus:default", "zeus:mapgen"]
}

View File

@ -1,6 +0,0 @@
print("Hello from kinetic")
local path = zeus.get_path("kinetic")
dofile(path .. "models/axle.lua")
dofile(path .. "blocks/axle.lua")

View File

@ -0,0 +1,4 @@
print("Hello from kinetic")
dofile("zeus:kinetic/models/axle")
dofile("zeus:kinetic/blocks/axle")

7
res/lua/mapgen/conf.json Normal file
View File

@ -0,0 +1,7 @@
{
"name": "zeus:mapgen",
"description": "Mapgen mod for the Zeus subgame.",
"version": "0.0.1",
"depends": ["zeus:default"]
}

View File

@ -0,0 +1 @@
print("Hello from mapgen")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -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})

18
src/api/LuaMod.h Normal file
View File

@ -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

18
src/api/LuaModConfig.h Normal file
View File

@ -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

17
src/api/LuaModFile.h Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -43,8 +43,6 @@ public:
sol::table zeus;
std::list<DelayedFunction> delayed_functions;
protected:
int DoFileSandboxed(std::string file);
};

View 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;
}
}

View File

@ -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);
};

View 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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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() {

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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:

View File

@ -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;
}
};

View File

@ -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) {

View File

@ -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();