Client and Server both run Lua code under separate APIs + sandboxing.

* Seperate Lua API into a Client API and a Server API
* LuaApi split into 2 files and named ClientLuaParser & ServerLuaParser
* ModuleServerRegisterBlock modified to work with ServerDefs
* Lua Parsers now find mods in the mod root directory
* Path class to sandbox included lua files
* Move util.lua code into ModuleClientUtils / ModuleServerUtils
* MapGen uses block names instead of hard-coded IDs
* Moved header-only-libs implementations into Main.cpp
* Two test mods with only main.lua to test mod loading
master
aurailus 2019-06-12 00:15:47 -07:00
parent 709eda6eb2
commit b590e57b4e
50 changed files with 646 additions and 348 deletions

1
res/lua/admin/main.lua Normal file
View File

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

View File

@ -1,39 +1,6 @@
local path = zeus.get_path("default");
--Grass, dirt, stone
dofile(path .. "blocks/ground.lua");
--Leaves, wood
dofile(path .. "blocks/tree.lua");
--Tallgrass, Flowers
dofile(path .. "blocks/foliage.lua");
--Sand, sandstone
dofile(path .. "blocks/desert.lua");
-- Grass Slab
zeus.register_block("default:grass_slab", {
name = "Grass",
model = "default:halfslab_foliage",
culls = false,
textures = {
"default_grass_top",
"default_dirt",
"default_grass_side",
"default_grass_side",
"default_grass_side",
"default_grass_side",
"default_grass_float",
},
lowdef_textures = {
"default_grass_top",
"default_dirt",
"default_grass_side"
},
selection_box = {
{0, 0, 0, 1, 0.5, 1}
},
toughness = {
hand = 3,
shovel = 1,
pick = 2
},
})
dofile(path .. "blocks/desert.lua");

View File

@ -1,4 +1,3 @@
-- Sand [ID 19]
zeus.register_block('default:sand', {
name = "Sand",
model = "default:block",
@ -10,7 +9,6 @@ zeus.register_block('default:sand', {
},
})
-- Sandstone [ID 20]
zeus.register_block('default:sandstone', {
name = "Sandstone",
model = "default:block",

View File

@ -1,4 +1,3 @@
-- TallGrass [ID 6..10]
for i=1,5,1 do
zeus.register_block("default:tallgrass_" .. i, {
culls = false,
@ -18,7 +17,6 @@ for i=1,5,1 do
})
end
-- Flowers [ID 11..18]
local flowers = {
"rose",
"tulip",

View File

@ -1,4 +1,3 @@
-- Grass [ID 1]
zeus.register_block("default:grass", {
name = "Grass",
model = "default:block_foliage",
@ -23,7 +22,6 @@ zeus.register_block("default:grass", {
},
})
-- Dirt [ID 2]
zeus.register_block('default:dirt', {
name = "Dirt",
model = "default:block",
@ -35,7 +33,6 @@ zeus.register_block('default:dirt', {
},
})
-- Stone [ID 3]
zeus.register_block('default:stone', {
name = "Stone",
model = "default:block",

View File

@ -1,4 +1,3 @@
-- Leaves [ID 4]
zeus.register_block('default:leaves', {
visible = true,
culls = false,
@ -17,7 +16,6 @@ zeus.register_block('default:leaves', {
},
})
-- Wood [ID 5]
zeus.register_block('default:wood', {
name = "Log",
model = "default:block",

View File

@ -1,4 +0,0 @@
local path = zeus.get_path("default");
dofile(path .. "models.lua");
dofile(path .. "blocks.lua");

41
res/lua/default/main.lua Normal file
View File

@ -0,0 +1,41 @@
print([[----------------------
LUA API Starting
Hello Zeus ]] .. (zeus.is_server() and "Server" or "Client") .. [[!
----------------------]]);
local path = zeus.get_path("default");
dofile(path .. "models.lua");
dofile(path .. "blocks.lua");
-- API DOCUMENTATION --
-- # Register LocalBlockModel
-- `zeus.register_blockmodel(string identifier, table definition)`
--
-- Definition is stored as `zeus.registered_blockmodels[identifier] = definition`.
-- There are no requirements for the contents of the definition table in this function, but for it to be well
-- formed and usable in `register_block`, it should be an array-table of face tables, which contain the following
-- information:
--
-- face: One of "left", "right", "front", "back", "top", "bottom", or "nocull". Used when determining which parts
-- of the model to cull.
--
-- tex: The texture index which this face uses. What textures these refer to are defined in the `register_block`
-- `textures` table. The index must be greater than or equal to 1.
--
-- points: An array of integers that define one or more quads. Each quad is defined by 20 numbers or 4 vertices,
-- in the format of x, y, z, tex_coord_x, tex_coord_y. The vertices are indexed in the order
-- 0, 1, 2, 2, 3, 0.
--
-- ## Example
-- {
-- face = "left"
-- tex = 3,
-- points = {
-- 0, 0, 0, 0, 1,
-- 0, 0, 1, 1, 1,
-- 0, 1, 1, 1, 0,
-- 0, 1, 0, 0, 0
-- }
-- }

1
res/lua/test/main.lua Normal file
View File

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

View File

@ -1,20 +0,0 @@
-- Dump function
function dump(tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
if type(k) == "number" then
k = "[" .. k .. "]"
end
local indentString = string.rep(" ", indent)
local formatting = indentString .. k .. " = "
if type(v) == "table" then
print(formatting .. "{")
dump(v, indent+1)
print(indentString .. "}")
elseif type(v) == 'boolean' then
print(formatting .. tostring(v))
else
print(formatting .. v)
end
end
end

View File

@ -35,10 +35,10 @@ set(ZEUS_SRC_FILES
game/scene/GameScene.h
game/graph/Renderer.cpp
game/graph/Renderer.h
api/LuaApi.cpp
api/LuaApi.h
api/func/LModuleRegister.cpp
api/func/LModuleRegister.h
api/client/LocalLuaParser.cpp
api/client/LocalLuaParser.h
api/client/ModuleClientRegisterBlock.cpp
api/client/ModuleClientRegisterBlock.h
game/entity/hud/TextEntity.cpp
game/entity/hud/TextEntity.h
game/entity/hud/DebugGui.cpp
@ -119,13 +119,13 @@ set(ZEUS_SRC_FILES
def/texture/AtlasRef.h
world/region/MapBlock.h def/LocalDefs.cpp
def/LocalDefs.h
api/func/LModuleUtil.cpp
api/func/LModuleUtil.h
api/client/ModuleClientUtils.cpp
api/client/ModuleClientUtils.h
world/region/Region.cpp
world/region/MapBlock.cpp
game/entity/hud/StatGraph.cpp
game/entity/hud/StatGraph.h
util/Util.h
world/block/PointedThing.h game/entity/world/ParticleEntity.cpp game/entity/world/ParticleEntity.h def/ServerDefs.cpp def/ServerDefs.h def/block/server/ServerBlockAtlas.cpp def/block/server/ServerBlockAtlas.h def/block/server/ServerBlockDef.cpp def/block/server/ServerBlockDef.h def/block/server/ServerBlockModel.cpp def/block/server/ServerBlockModel.h util/Dir.h def/block/server/ServerMeshPart.cpp def/block/server/ServerMeshPart.h)
world/block/PointedThing.h game/entity/world/ParticleEntity.cpp game/entity/world/ParticleEntity.h def/ServerDefs.cpp def/ServerDefs.h def/block/server/ServerBlockAtlas.cpp def/block/server/ServerBlockAtlas.h def/block/server/ServerBlockDef.cpp def/block/server/ServerBlockDef.h def/block/server/ServerBlockModel.cpp def/block/server/ServerBlockModel.h util/Dir.h def/block/server/ServerMeshPart.cpp def/block/server/ServerMeshPart.h def/block/BlockAtlas.h def/block/BlockDef.h api/LuaParser.cpp api/LuaParser.h api/server/ServerLuaParser.cpp api/server/ServerLuaParser.h api/server/ModuleServerUtils.cpp api/server/ModuleServerUtils.h api/server/ModuleServerRegisterBlock.cpp api/server/ModuleServerRegisterBlock.h util/Path.cpp util/Path.h)
add_library (zeusCore ${ZEUS_SRC_FILES})

View File

@ -1,6 +1,8 @@
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#define STB_IMAGE_IMPLEMENTATION
#define CUTE_FILES_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#pragma clang diagnostic pop
#include "game/Game.h"

View File

@ -1,30 +0,0 @@
//
// Created by aurailus on 17/12/18.
//
#include "LuaApi.h"
#include "../def/LocalDefs.h"
//todo: add security using doFileSandboxed
void LuaApi::init(LocalDefs& defs) {
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math);
lua.script_file("/home/aurailus/C++/GlProject/res/lua/util.lua");
zeus = lua.create_table();
lua["zeus"] = zeus;
lua.set_function("dofile", &LuaApi::DoFileSandboxed, this);
LModuleRegister(lua, zeus, defs);
LModuleUtil(lua, zeus, defs);
}
void LuaApi::loadMod(std::string file) {
lua.script_file(file);
}
int LuaApi::DoFileSandboxed(std::string file) {
std::cout << file << std::endl;
lua.script_file(file);
}

View File

@ -1,35 +0,0 @@
//
// Created by aurailus on 17/12/18.
//
#ifndef ZEUS_LUAPARSER_H
#define ZEUS_LUAPARSER_H
#include <string>
#include <sol.hpp>
#include <iostream>
#include "func/LModuleRegister.h"
#include "func/LModuleUtil.h"
class LocalDefs;
class LuaApi {
public:
LuaApi() = default;
void init(LocalDefs& defs);
void loadMod(std::string file);
sol::state lua;
sol::table zeus;
int DoFileSandboxed(std::string file);
~LuaApi() = default;
private:
};
#endif //ZEUS_LUAPARSER_H

18
src/api/LuaParser.cpp Normal file
View File

@ -0,0 +1,18 @@
//
// Created by aurailus on 11/06/19.
//
#include "LuaParser.h"
LuaParser::LuaParser(std::string root) :
root(std::move(root)),
root_path(this->root) {}
int LuaParser::DoFileSandboxed(std::string file) {
if (root_path.contains(Path(file))) {
lua.script_file(file);
}
else {
std::cerr << "\"" + file + "\" is outside of the sandbox and cannot be loaded!" << std::endl;
}
}

25
src/api/LuaParser.h Normal file
View File

@ -0,0 +1,25 @@
//
// Created by aurailus on 11/06/19.
//
#ifndef ZEUS_LUAPARSER_H
#define ZEUS_LUAPARSER_H
#include <sol.hpp>
#include <iostream>
#include "../util/Path.h"
class LuaParser {
public:
explicit LuaParser(std::string root);
std::string root;
Path root_path;
protected:
sol::state lua;
sol::table zeus;
int DoFileSandboxed(std::string file);
};
#endif //ZEUS_LUAPARSER_H

View File

@ -0,0 +1,53 @@
//
// Created by aurailus on 17/12/18.
//
#include "LocalLuaParser.h"
#include "../../def/LocalDefs.h"
LocalLuaParser::LocalLuaParser(std::string mod_root) : LuaParser(std::move(mod_root)) {}
void LocalLuaParser::init(LocalDefs& defs) {
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math);
zeus = lua.create_table();
lua["zeus"] = zeus;
lua.set_function("dofile", &LocalLuaParser::DoFileSandboxed, this);
ModuleClientUtils(lua, zeus, defs);
ModuleClientRegisterBlock(lua, zeus, defs);
//LOAD MODS
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);
}

View File

@ -0,0 +1,28 @@
//
// Created by aurailus on 17/12/18.
//
#ifndef ZEUS_LOCALLUAPARSER_H
#define ZEUS_LOCALLUAPARSER_H
#include <string>
#include <iostream>
#include <cute_files.h>
#include "../LuaParser.h"
#include "ModuleClientRegisterBlock.h"
#include "ModuleClientUtils.h"
class LocalDefs;
class LocalLuaParser : public LuaParser {
public:
explicit LocalLuaParser(std::string mod_root);
void init(LocalDefs& defs);
~LocalLuaParser() = default;
};
#endif //ZEUS_LOCALLUAPARSER_H

View File

@ -2,46 +2,14 @@
// Created by aurailus on 18/12/18.
//
#include "LModuleRegister.h"
#include "ModuleClientRegisterBlock.h"
#include "../../def/LocalDefs.h"
LModuleRegister::LModuleRegister(sol::state &lua, sol::table &zeus, LocalDefs &defs) {
ModuleClientRegisterBlock::ModuleClientRegisterBlock(sol::state &lua, sol::table &zeus, LocalDefs &defs) {
//Define registered_blockmodels table
zeus["registered_blockmodels"] = lua.create_table();
//
// # Register LocalBlockModel
// `zeus.register_blockmodel(string identifier, table definition)`
//
// Definition is stored as `zeus.registered_blockmodels[identifier] = definition`.
// There are no requirements for the contents of the definition table in this function, but for it to be well
// formed and usable in `register_block`, it should be an array-table of face tables, which contain the following
// information:
//
// face: One of "left", "right", "front", "back", "top", "bottom", or "nocull". Used when determining which parts
// of the model to cull.
//
// tex: The texture index which this face uses. What textures these refer to are defined in the `register_block`
// `textures` table. The index must be greater than or equal to 1.
//
// points: An array of integers that define one or more quads. Each quad is defined by 20 numbers or 4 vertices,
// in the format of x, y, z, tex_coord_x, tex_coord_y. The vertices are indexed in the order
// 0, 1, 2, 2, 3, 0.
//
// ## Example
// {
// face = "left"
// tex = 3,
// points = {
// 0, 0, 0, 0, 1,
// 0, 0, 1, 1, 1,
// 0, 1, 1, 1, 0,
// 0, 1, 0, 0, 0
// }
// }
//
zeus.set_function("register_blockmodel", [&](std::string identifier, sol::table data) {
try {
if (identifier.length() == 0) throw "No Identifier";
@ -52,12 +20,6 @@ LModuleRegister::LModuleRegister(sol::state &lua, sol::table &zeus, LocalDefs &d
}
});
//
// # Register Block
// `zeus.register_block(string identifier, table definition)`
//
//
//
zeus.set_function("register_block", [&](std::string identifier, sol::table data) {
try {
if (identifier.length() == 0) throw "No Identifier";
@ -98,7 +60,7 @@ LModuleRegister::LModuleRegister(sol::state &lua, sol::table &zeus, LocalDefs &d
}
LocalBlockModel blockModel = LocalBlockModel::create(*model, texturesVector, defs.textures(), visible, culls);
LocalBlockDef def(identifier, std::move(blockModel), solid, sbox);
LocalBlockDef def(identifier, defs.blocks().definitionsSize(), std::move(blockModel), solid, sbox);
defs.blocks().registerBlock(std::move(def));
}

View File

@ -12,9 +12,9 @@
class LocalDefs;
class LModuleRegister {
class ModuleClientRegisterBlock {
public:
LModuleRegister(sol::state& lua, sol::table& zeus, LocalDefs& defs);
ModuleClientRegisterBlock(sol::state& lua, sol::table& zeus, LocalDefs& defs);
};

View File

@ -0,0 +1,49 @@
//
// Created by aurailus on 21/04/19.
//
#include "ModuleClientUtils.h"
ModuleClientUtils::ModuleClientUtils(sol::state &lua, sol::table &zeus, LocalDefs &defs) {
//Dump function
lua.script(R"(
local function dump(tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
if type(k) == "number" then
k = "[" .. k .. "]"
end
local indentString = string.rep(" ", indent)
local formatting = indentString .. k .. " = "
if type(v) == "table" then
print(formatting .. "{")
dump(v, indent+1)
print(indentString .. "}")
elseif type(v) == 'boolean' then
print(formatting .. tostring(v))
else
print(formatting .. v)
end
end
end
zeus.dump = dump
)");
//Get Path for mod
zeus.set_function("get_path", [&](std::string modname) {
try {
if (modname.length() == 0) throw "No mod name specified!";
return "/home/aurailus/C++/GlProject/res/lua/" + modname + "/";
}
catch (const std::string& e) {
std::cerr << "Exception on get_path: " << e << std::endl;
}
});
//Get if the interpreter is the server or the client
zeus.set_function("is_server", []() {
return false;
});
}

View File

@ -12,11 +12,9 @@
class LocalDefs;
class LModuleUtil {
class ModuleClientUtils {
public:
LModuleUtil(sol::state& lua, sol::table& zeus, LocalDefs& defs);
ModuleClientUtils(sol::state& lua, sol::table& zeus, LocalDefs& defs);
};
#endif //ZEUS_LMODULEUTIL_H

View File

@ -1,17 +0,0 @@
//
// Created by aurailus on 21/04/19.
//
#include "LModuleUtil.h"
LModuleUtil::LModuleUtil(sol::state &lua, sol::table &zeus, LocalDefs &defs) {
zeus.set_function("get_path", [&](std::string modname) {
try {
if (modname.length() == 0) throw "No mod name specified!";
return "/home/aurailus/C++/GlProject/res/lua/" + modname + "/";
}
catch (const std::string& e) {
std::cerr << "Exception on get_path: " << e << std::endl;
}
});
}

View File

@ -0,0 +1,71 @@
//
// Created by aurailus on 11/06/19.
//
#include "ModuleServerRegisterBlock.h"
#include "../../def/ServerDefs.h"
ModuleServerRegisterBlock::ModuleServerRegisterBlock(sol::state &lua, sol::table &zeus, ServerDefs &defs) {
//Define registered_blockmodels table
zeus["registered_blockmodels"] = lua.create_table();
zeus.set_function("register_blockmodel", [&](std::string identifier, sol::table data) {
try {
if (identifier.length() == 0) throw "No Identifier";
zeus["registered_blockmodels"][identifier] = data;
}
catch (const std::string& e) {
std::cerr << "Exception on register_blockmodel: " << e << std::endl;
}
});
zeus.set_function("register_block", [&](std::string identifier, sol::table data) {
try {
if (identifier.length() == 0) throw "No Identifier";
auto name = data.get<sol::optional<std::string>>("name");
auto textures = data.get<sol::optional<sol::table>>("textures");
auto modelStr = data.get_or<std::string>("model", "default:cube");
auto selection = data.get<sol::optional<sol::table>>("selection_box");
bool visible = data.get_or("visible", true);
bool culls = data.get_or("culls", true);
bool solid = data.get_or("solid", true);
if (!name) throw "No name property";
if (!textures) throw "No textures table";
//Convert textures to a std::vector
std::vector<std::string> texturesVector;
textures->for_each([&](sol::object key, sol::object value) {
if (!value.is<std::string>()) throw "Non string texture value.";
std::string str = value.as<std::string>();
texturesVector.push_back(str);
});
if (texturesVector.size() == 0) texturesVector.push_back("_missing");
//TODO: In register_blockmodel, store these models in C++ somewhere so that I don't need to reference the
//lua data to register a model.
sol::table models = zeus["registered_blockmodels"];
auto model = models.get<sol::optional<sol::table>>(modelStr);
if (!model) throw "Undefined model";
//TODO: Validate and allow multiple selection boxes
SelectionBox sbox = {{0, 0, 0}, {1, 1, 1}};
if (selection) {
sol::table def = (*selection)[1];
sbox = {{def[1], def[2], def[3]}, {def[4], def[5], def[6]}};
}
ServerBlockModel blockModel = ServerBlockModel::create(*model, texturesVector, visible, culls);
ServerBlockDef def(identifier, defs.blocks().definitionsSize(), std::move(blockModel), solid, sbox);
defs.blocks().registerBlock(std::move(def));
}
catch (const std::string& e) {
std::cerr << "Exception on register_block: " << e << std::endl;
}
});
}

View File

@ -0,0 +1,21 @@
//
// Created by aurailus on 11/06/19.
//
#ifndef ZEUS_MODULESERVERREGISTERBLOCK_H
#define ZEUS_MODULESERVERREGISTERBLOCK_H
#include "../../def/block/SelectionBox.h"
#include "../../def/block/client/LocalBlockDef.h"
#include "../../def/block/client/LocalBlockAtlas.h"
#include <sol.hpp>
class ServerDefs;
class ModuleServerRegisterBlock {
public:
ModuleServerRegisterBlock(sol::state& lua, sol::table& zeus, ServerDefs& defs);
};
#endif //ZEUS_MODULESERVERREGISTERBLOCK_H

View File

@ -0,0 +1,49 @@
//
// Created by aurailus on 11/06/19.
//
#include "ModuleServerUtils.h"
ModuleServerUtils::ModuleServerUtils(sol::state &lua, sol::table &zeus, ServerDefs &defs) {
//Dump function
lua.script(R"(
local function dump(tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
if type(k) == "number" then
k = "[" .. k .. "]"
end
local indentString = string.rep(" ", indent)
local formatting = indentString .. k .. " = "
if type(v) == "table" then
print(formatting .. "{")
dump(v, indent+1)
print(indentString .. "}")
elseif type(v) == 'boolean' then
print(formatting .. tostring(v))
else
print(formatting .. v)
end
end
end
zeus.dump = dump
)");
//Get path for mod
zeus.set_function("get_path", [&](std::string modname) {
try {
if (modname.length() == 0) throw "No mod name specified!";
return "/home/aurailus/C++/GlProject/res/lua/" + modname + "/";
}
catch (const std::string& e) {
std::cerr << "Exception on get_path: " << e << std::endl;
}
});
//Get if the interpreter is the server or the client
zeus.set_function("is_server", []() {
return true;
});
}

View File

@ -0,0 +1,20 @@
//
// Created by aurailus on 11/06/19.
//
#ifndef ZEUS_SMODULEUTILS_H
#define ZEUS_SMODULEUTILS_H
#include "../../def/block/SelectionBox.h"
#include "../../def/block/server/ServerBlockDef.h"
#include "../../def/block/server/ServerBlockAtlas.h"
#include <sol.hpp>
class ServerDefs;
class ModuleServerUtils {
public:
ModuleServerUtils(sol::state& lua, sol::table& zeus, ServerDefs& defs);
};
#endif //ZEUS_SMODULEUTILS_H

View File

@ -0,0 +1,53 @@
//
// Created by aurailus on 11/06/19.
//
#include "ServerLuaParser.h"
#include "../../def/ServerDefs.h"
ServerLuaParser::ServerLuaParser(std::string mod_root) : LuaParser(std::move(mod_root)) {}
void ServerLuaParser::init(ServerDefs& defs) {
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math);
zeus = lua.create_table();
lua["zeus"] = zeus;
lua.set_function("dofile", &ServerLuaParser::DoFileSandboxed, this);
ModuleServerUtils(lua, zeus, defs);
ModuleServerRegisterBlock(lua, zeus, defs);
//LOAD MODS
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);
}

View File

@ -0,0 +1,26 @@
//
// Created by aurailus on 11/06/19.
//
#ifndef ZEUS_SERVERLUAPARSER_H
#define ZEUS_SERVERLUAPARSER_H
#include "../LuaParser.h"
#include <cute_files.h>
#include "ModuleServerRegisterBlock.h"
#include "ModuleServerUtils.h"
class ServerDefs;
class ServerLuaParser : public LuaParser {
public:
explicit ServerLuaParser(std::string mod_root);
void init(ServerDefs& defs);
~ServerLuaParser() = default;
};
#endif //ZEUS_SERVERLUAPARSER_H

View File

@ -4,7 +4,9 @@
#include "LocalDefs.h"
LocalDefs::LocalDefs(std::string tex_path) {
LocalDefs::LocalDefs(std::string tex_path) :
lua("/home/aurailus/C++/GlProject/res/lua/") {
textureAtlas = TextureAtlas(1024);
textureAtlas.loadDirectory(tex_path + "/game");
textureAtlas.loadDirectory(tex_path + "/gui");
@ -12,8 +14,7 @@ LocalDefs::LocalDefs(std::string tex_path) {
blockAtlas = LocalBlockAtlas();
luaApi.init(*this);
luaApi.loadMod("../res/lua/default/init.lua");
lua.init(*this);
}
LocalBlockAtlas &LocalDefs::blocks() {

View File

@ -7,7 +7,7 @@
#include "texture/TextureAtlas.h"
#include "block/client/LocalBlockAtlas.h"
#include "../api/LuaApi.h"
#include "../api/client/LocalLuaParser.h"
class LocalDefs {
public:
@ -21,7 +21,7 @@ public:
private:
TextureAtlas textureAtlas;
LocalBlockAtlas blockAtlas;
LuaApi luaApi;
LocalLuaParser lua;
};

View File

@ -4,12 +4,13 @@
#include "ServerDefs.h"
ServerDefs::ServerDefs() {
ServerDefs::ServerDefs() :
lua("/home/aurailus/C++/GlProject/res/lua/") {
blockAtlas = ServerBlockAtlas();
// luaApi.init(*this);
// luaApi.loadMod("../res/lua/default/init.lua");
lua.init(*this);
// lua.loadMod("../res/lua/default/init.lua");
}
ServerBlockAtlas &ServerDefs::blocks() {

View File

@ -5,8 +5,9 @@
#ifndef ZEUS_SERVERDEFS_H
#define ZEUS_SERVERDEFS_H
#include "block/server/ServerBlockAtlas.h"
#include "../api/LuaApi.h"
#include "../api/server/ServerLuaParser.h"
class ServerDefs {
public:
@ -17,7 +18,7 @@ public:
~ServerDefs() = default;
private:
ServerBlockAtlas blockAtlas;
// LuaApi luaApi;
ServerLuaParser lua;
};

View File

@ -0,0 +1,19 @@
//
// Created by aurailus on 10/06/19.
//
#ifndef ZEUS_BLOCKATLAS_H
#define ZEUS_BLOCKATLAS_H
#include <string>
#include "BlockDef.h"
class BlockAtlas {
public:
virtual int definitionsSize() = 0;
virtual BlockDef& fromIndex(int index) = 0;
virtual BlockDef& fromIdentifier(std::string identifier) = 0;
};
#endif //ZEUS_BLOCKATLAS_H

40
src/def/block/BlockDef.h Normal file
View File

@ -0,0 +1,40 @@
//
// Created by aurailus on 10/06/19.
//
#ifndef ZEUS_BLOCKDEF_H
#define ZEUS_BLOCKDEF_H
#include <string>
#include "SelectionBox.h"
class BlockDef {
public:
BlockDef() = default;
BlockDef(std::string identifier, int index, bool culls, bool solid, SelectionBox selectionBox) :
identifier(std::move(identifier)),
index(index),
culls(culls),
solid(solid),
selectionBox(selectionBox) {}
std::string getIdentifier() { return identifier; };
int getIndex() { return index; }
bool isCulling() { return culls; };
bool isSolid() { return solid; };
SelectionBox getSelectionBox() { return selectionBox; };
protected:
std::string identifier;
int index;
bool culls = false;
bool solid = false;
SelectionBox selectionBox;
};
#endif //ZEUS_BLOCKDEF_H

View File

@ -7,17 +7,22 @@
LocalBlockAtlas::LocalBlockAtlas() {
//Register Air Node
LocalBlockModel nullModel; nullModel.visible = false, nullModel.culls = false;
LocalBlockDef air("builtin:air", nullModel, false, {{0, 0, 0}, {1, 1, 1}});
LocalBlockDef air("builtin:air", static_cast<int>(definitions.size()), nullModel, false, {{0, 0, 0}, {1, 1, 1}});
registerBlock(std::move(air));
}
int LocalBlockAtlas::definitionsSize() {
return static_cast<int>(definitions.size());
}
void LocalBlockAtlas::registerBlock(LocalBlockDef def) {
definitions.push_back(def);
identifierIndexTable.insert({def.getIdentifier(), def.getIndex()});
}
LocalBlockDef& LocalBlockAtlas::fromIndex(int id) {
if (id >= 0 && id < definitions.size()) {
return definitions.at((unsigned long)id);
return definitions.at(static_cast<unsigned long>(id));
}
std::cerr << "Block ID #" << id << " (undefined) requested! Returning air." << std::endl;

View File

@ -9,15 +9,18 @@
#include <vector>
#include "LocalBlockDef.h"
#include "../../texture/TextureAtlas.h"
#include "../BlockAtlas.h"
class LocalBlockAtlas {
class LocalBlockAtlas : public BlockAtlas {
public:
LocalBlockAtlas();
void registerBlock(LocalBlockDef def);
LocalBlockDef& fromIndex(int id);
LocalBlockDef& fromIdentifier(std::string identifier);
int definitionsSize() override;
LocalBlockDef& fromIndex(int id) override;
LocalBlockDef& fromIdentifier(std::string identifier) override;
private:
const static int AIR = 0;

View File

@ -4,29 +4,10 @@
#include "LocalBlockDef.h"
LocalBlockDef::LocalBlockDef(std::string identifier, int index, LocalBlockModel model, bool solid, SelectionBox selectionBox) :
BlockDef(std::move(identifier), index, model.culls, solid, selectionBox),
model(std::move(model)) {}
LocalBlockModel& LocalBlockDef::getModel() {
return model;
}
LocalBlockDef::LocalBlockDef(std::string identifier, LocalBlockModel model, bool solid, SelectionBox selectionBox) :
identifier(std::move(identifier)),
culls(model.culls),
model(std::move(model)),
solid(solid),
selectionBox(selectionBox) {}
bool LocalBlockDef::isSolid() {
return solid;
}
std::string LocalBlockDef::getIdentifier() {
return identifier;
}
bool LocalBlockDef::isCulling() {
return culls;
}
SelectionBox LocalBlockDef::getSelectionBox() {
return selectionBox;
}

View File

@ -8,23 +8,16 @@
#include <string>
#include "LocalBlockModel.h"
#include "../SelectionBox.h"
#include "../BlockDef.h"
class LocalBlockDef {
class LocalBlockDef : public BlockDef {
public:
LocalBlockDef() = default;
LocalBlockDef(std::string identifier, LocalBlockModel model, bool solid, SelectionBox selectionBox);
LocalBlockDef(std::string identifier, int index, LocalBlockModel model, bool solid, SelectionBox selectionBox);
bool isCulling();
bool isSolid();
LocalBlockModel& getModel();
std::string getIdentifier();
SelectionBox getSelectionBox();
private:
bool culls = false;
bool solid = false;
SelectionBox selectionBox;
LocalBlockModel model;
std::string identifier;
LocalBlockModel model;
};

View File

@ -7,12 +7,17 @@
ServerBlockAtlas::ServerBlockAtlas() {
//Register Air Node
ServerBlockModel nullModel; nullModel.visible = false, nullModel.culls = false;
ServerBlockDef air("builtin:air", nullModel, false, {{0, 0, 0}, {1, 1, 1}});
ServerBlockDef air("builtin:air", static_cast<int>(definitions.size()), nullModel, false, {{0, 0, 0}, {1, 1, 1}});
registerBlock(std::move(air));
}
int ServerBlockAtlas::definitionsSize() {
return static_cast<int>(definitions.size());
}
void ServerBlockAtlas::registerBlock(ServerBlockDef def) {
definitions.push_back(def);
identifierIndexTable.insert({def.getIdentifier(), def.getIndex()});
}
ServerBlockDef& ServerBlockAtlas::fromIndex(int id) {

View File

@ -10,15 +10,18 @@
#include <iostream>
#include <unordered_map>
#include "ServerBlockDef.h"
#include "../BlockAtlas.h"
class ServerBlockAtlas {
class ServerBlockAtlas : public BlockAtlas {
public:
ServerBlockAtlas();
void registerBlock(ServerBlockDef def);
ServerBlockDef& fromIndex(int id);
ServerBlockDef& fromIdentifier(std::string identifier);
int definitionsSize() override;
ServerBlockDef& fromIndex(int id) override;
ServerBlockDef& fromIdentifier(std::string identifier) override;
private:
const static int AIR = 0;

View File

@ -4,29 +4,10 @@
#include "ServerBlockDef.h"
ServerBlockDef::ServerBlockDef(std::string identifier, int index, ServerBlockModel model, bool solid, SelectionBox selectionBox) :
BlockDef(std::move(identifier), index, model.culls, solid, selectionBox),
model(std::move(model)) {}
ServerBlockModel& ServerBlockDef::getModel() {
return model;
}
ServerBlockDef::ServerBlockDef(std::string identifier, ServerBlockModel model, bool solid, SelectionBox selectionBox) :
identifier(std::move(identifier)),
solid(solid),
culls(model.culls),
model(std::move(model)),
selectionBox(selectionBox) {}
bool ServerBlockDef::isSolid() {
return solid;
}
std::string ServerBlockDef::getIdentifier() {
return identifier;
}
bool ServerBlockDef::isCulling() {
return culls;
}
SelectionBox ServerBlockDef::getSelectionBox() {
return selectionBox;
}

View File

@ -8,27 +8,16 @@
#include <string>
#include "../SelectionBox.h"
#include "ServerBlockModel.h"
#include "../BlockDef.h"
class ServerBlockDef {
class ServerBlockDef : public BlockDef {
public:
ServerBlockDef() = default;
ServerBlockDef(std::string identifier, ServerBlockModel model, bool solid, SelectionBox selectionBox);
std::string getIdentifier();
bool isCulling();
bool isSolid();
ServerBlockDef(std::string identifier, int index, ServerBlockModel model, bool solid, SelectionBox selectionBox);
ServerBlockModel& getModel();
SelectionBox getSelectionBox();
private:
std::string identifier;
bool culls = false;
bool solid = false;
ServerBlockModel model;
SelectionBox selectionBox;
};

View File

@ -9,11 +9,32 @@
#include "NoiseSample.h"
#include "../../util/Vec.h"
MapGen::MapGen(unsigned int seed) {
MapGen::MapGen(unsigned int seed, BlockAtlas& atlas) {
this->seed = seed;
// GRASS_BLOCK = defs.blocks().fromIndex(1);
//Get Block Indexes
GRASS_BLOCK = atlas.fromIdentifier("default:grass").getIndex();
DIRT_BLOCK = atlas.fromIdentifier("default:dirt").getIndex();
STONE_BLOCK = atlas.fromIdentifier("default:stone").getIndex();
PLANT_STEM_BLOCK = atlas.fromIdentifier("default:wood").getIndex();
LEAVES_BLOCK = atlas.fromIdentifier("default:leaves").getIndex();
for (int i = 1; i <= 5; i++) {
TALLGRASSES[i] = atlas.fromIdentifier("default:tallgrass_" + to_string(i)).getIndex();
}
FLOWERS[0] = atlas.fromIdentifier("default:flower_dandelion_yellow").getIndex();
FLOWERS[1] = atlas.fromIdentifier("default:flower_viola").getIndex();
FLOWERS[2] = atlas.fromIdentifier("default:flower_geranium").getIndex();
FLOWERS[3] = atlas.fromIdentifier("default:flower_tulip").getIndex();
FLOWERS[4] = atlas.fromIdentifier("default:flower_dandelion_white").getIndex();
FLOWERS[5] = atlas.fromIdentifier("default:flower_rose").getIndex();
FLOWERS[6] = atlas.fromIdentifier("default:flower_mushroom_red").getIndex();
FLOWERS[7] = atlas.fromIdentifier("default:flower_mushroom_brown").getIndex();
//Set up Noise Parameters
terrainGeneralElevation.SetFrequency(0.05);
terrainGeneralElevation.SetPersistence(0.4);
@ -150,32 +171,23 @@ void MapGen::fillChunk(MapGenJob &job) {
for (int m = 0; m < (int)pow(TransPos::CHUNK_SIZE, 3); m++) {
VecUtils::indAssignVec(m, lp);
int d = job.depth[m];
// float g = job.depthFloat[m];
int flora = AIR;
int grass = 1, dirt = 2, stone = 3;
int flora = 0;
bool flower = false;
if (flora_density_sample.get(lp) >= 1) flower = true;
if (flower) {
int flowerType = max(min((int)std::floor(flora_type_sample.get(lp)), 8), 0);
flora = flowerType + 10;
if (flora_density_sample.get(lp) >= 1) {
flora = FLOWERS[max(min((int) std::floor(flora_type_sample.get(lp)), 7), 0)];
}
else {
int grassType = min((int)std::floor(grass_sample.get(lp)), 5);
if (grassType > 0) flora = grassType + 5;
int grassType = min((int) std::floor(grass_sample.get(lp)), 5);
if (grassType > 0) flora = TALLGRASSES[grassType];
}
job.blocks[m] = d <= 0 ? 0
job.blocks[m] = d <= 0 ? AIR
: d <= 1 ? flora
// : d <= 1.5f+1 ? 21
: d <= 2 ? grass
: d <= 3 ? dirt
: stone;
: d <= 2 ? GRASS_BLOCK
: d <= 3 ? DIRT_BLOCK
: STONE_BLOCK;
}
}
@ -191,12 +203,12 @@ void MapGen::addTrees(MapGenJob &job) {
if (d == 1 && flora_density_sample.get(lp) <= -1) {
glm::vec3 p = lp;
addBlock(p, 5, job);
addBlock(p + glm::vec3( 1, 0, 0), 4, job);
addBlock(p + glm::vec3(-1, 0, 0), 4, job);
addBlock(p + glm::vec3( 0, 0, 1), 4, job);
addBlock(p + glm::vec3( 0, 0, -1), 4, job);
addBlock(p + glm::vec3( 0, 1, 0), 4, job);
addBlock(p, PLANT_STEM_BLOCK, job);
addBlock(p + glm::vec3( 1, 0, 0), LEAVES_BLOCK, job);
addBlock(p + glm::vec3(-1, 0, 0), LEAVES_BLOCK, job);
addBlock(p + glm::vec3( 0, 0, 1), LEAVES_BLOCK, job);
addBlock(p + glm::vec3( 0, 0, -1), LEAVES_BLOCK, job);
addBlock(p + glm::vec3( 0, 1, 0), LEAVES_BLOCK, job);
}
}
}

View File

@ -19,13 +19,9 @@ using namespace noise;
class MapGen {
public:
explicit MapGen(unsigned int seed);
MapGen(unsigned int seed, BlockAtlas& atlas);
BlockChunk* generate(glm::vec3 pos);
private:
int GRASS_BLOCK = 0, DIRT_BLOCK = 0, STONE_BLOCK = 0;
int PLANT_STEM_BLOCK = 0, LEAVES_BLOCK = 0;
int TALLGRASSES[5];
int FLOWERS[9];
void getDensityMap(MapGenJob &job);
void getElevation(MapGenJob &j);
@ -36,6 +32,12 @@ private:
unsigned int seed;
int AIR = 0;
int GRASS_BLOCK = 0, DIRT_BLOCK = 0, STONE_BLOCK = 0;
int PLANT_STEM_BLOCK = 0, LEAVES_BLOCK = 0;
int TALLGRASSES[6];
int FLOWERS[8];
module::Perlin terrainGeneralElevation;
module::RidgedMulti terrainMountains;
module::Billow terrainFlatBase;

View File

@ -2,17 +2,10 @@
// Created by aurailus on 16/04/19.
//
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#define CUTE_FILES_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#pragma clang diagnostic pop
#include "TextureAtlas.h"
#include <cute_files.h>
#include <stb_image.h>
#include <stb_image_write.h>
#include <cute_files.h>
//Height is optional and defaults to 0
TextureAtlas::TextureAtlas(unsigned int width, unsigned int height) :

View File

@ -4,7 +4,7 @@
#include "WorldInterpolationStream.h"
WorldInterpolationStream::WorldInterpolationStream(unsigned int seed, LocalDefs& defs) : gen(seed) {
WorldInterpolationStream::WorldInterpolationStream(unsigned int seed, LocalDefs& defs) : gen(seed, defs.blocks()) {
queuedTasks.reserve(1024);
threads.reserve(THREADS);

View File

@ -28,11 +28,11 @@ ServerWorld::ServerWorld(unsigned int seed, ServerDefs& defs) : genStream(seed,
}
}
std::cout << "Generated Chunk Queue is " << generateOrder.size() << " chunks long." << std::endl;
std::cout << "[INFO] Generated Chunk Queue is " << generateOrder.size() << " chunks long." << std::endl;
}
void ServerWorld::addPlayer(ServerPlayer *player) {
Timer t("New Chunk Allocation");
// Timer t("New Chunk Allocation");
this->players.push_back(player);
@ -49,11 +49,11 @@ void ServerWorld::addPlayer(ServerPlayer *player) {
}
}
t.printElapsedMs();
// t.printElapsedMs();
}
void ServerWorld::playerChangedChunks(ServerPlayer *player) {
Timer t("[INFO] Movement Allocation");
// Timer t("[INFO] Movement Allocation");
auto pos = player->getChunkPos();
@ -75,14 +75,14 @@ void ServerWorld::playerChangedChunks(ServerPlayer *player) {
}
}
printf("[INFO] %s moved to %d, %d, %d, generating %d chunks.\n",
player->getUsername().c_str(),
static_cast<int>(pos.x),
static_cast<int>(pos.y),
static_cast<int>(pos.z),
generated);
// printf("[INFO] %s moved to %d, %d, %d, generating %d chunks.\n",
// player->getUsername().c_str(),
// static_cast<int>(pos.x),
// static_cast<int>(pos.y),
// static_cast<int>(pos.z),
// generated);
t.printElapsedMs();
// t.printElapsedMs();
player->changedChunks = false;
}

View File

@ -7,8 +7,7 @@
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
//TODO: Give Gen Atlas
WorldGenStream::WorldGenStream(unsigned int seed, ServerBlockAtlas& atlas) : gen(seed) {
WorldGenStream::WorldGenStream(unsigned int seed, ServerBlockAtlas& atlas) : gen(seed, atlas) {
queuedTasks.reserve((unsigned long) TOTAL_QUEUE_SIZE);
threads.reserve(THREADS);

View File

@ -32,5 +32,5 @@ std::string Path::to_string() {
bool Path::contains(Path other) {
std::string sMe = to_string();
std::string sOther = other.to_string();
return (sMe.substr(0, sOther.length()) == sOther);
return (sOther.substr(0, sMe.length()) == sMe);
}