Lua Defined structures - WIP, New UI Library, move Base from mods~

Refactor GUIBuilder and MenuSandbox
Added outlined textures
master
Nicole Collings 2020-03-25 18:27:05 -07:00
parent 6579255b70
commit 4febca7ef8
77 changed files with 848 additions and 640 deletions

View File

@ -1,6 +1,6 @@
{
"name": "base",
"description": "Base definitions for Zepha.",
"description": "Base definitions for the Zepha Engine.",
"version": "1.0.0",
"depends": []
}

View File

@ -0,0 +1,43 @@
local env = {}
setmetatable(env, {__index = _G})
env.Gui = {}
local function create_gui_table(elem_type, data)
local element = {}
element.type = elem_type
element.children = {}
element.callbacks = {}
element.traits = {}
element.key = ""
for k, v in pairs(data) do
if type(k) == "number" then
table.insert(element.children, v)
elseif k == "key" then
element.key = v
elseif k == "callbacks" then
element.callbacks = v
else
element.traits[k] = v
end
end
return element
end
env.Gui.Body = function(data) return create_gui_table("body", data) end
env.Gui.Rect = function(data) return create_gui_table("rect", data) end
env.Gui.Text = function(data) return create_gui_table("text", data) end
env.Gui.Model = function(data) return create_gui_table("model", data) end
env.Gui.Button = function(data) return create_gui_table("button", data) end
env.Gui.InventoryList = function(data) return create_gui_table("inventory_list", data) end
env.pc = function(num)
return tostring(num) .. "%"
end
zepha.create_menu = function(fn)
setfenv(fn, env)
return fn()
end

View File

@ -0,0 +1,8 @@
-- Register base models (if not on main menu)
if zepha.register_blockmodel then runfile(_PATH .. "models/_index") end
-- Load Libraries
runfile(_PATH .. "dump")
runfile(_PATH .. "math")
runfile(_PATH .. "vector")
runfile(_PATH .. "gui")

View File

@ -320,6 +320,6 @@ set(ZEPHA_SRC
game/inventory/InventoryList.h
lua/api/modules/time.h
util/net/PacketView.cpp
util/net/PacketView.h)
util/net/PacketView.h lua/api/modules/create_structure.h util/Any.h)
add_library (Zepha_Core ${ZEPHA_SRC})

View File

@ -17,4 +17,5 @@
int main(int argc, char* argv[]) {
return StartGame(argc, argv);
}
}

View File

@ -5,23 +5,26 @@
#include "BiomeDef.h"
BiomeDef::BiomeDef(
const std::string& identifier, unsigned int index, float temperature, float humidity, float roughness,
unsigned int topBlock, unsigned int soilBlock, unsigned int rockBlock,
const std::vector<noise::module::Module*>& heightmap, const std::vector<noise::module::Module*>& volume,
glm::vec3 biomeTint) :
const std::string& identifier, unsigned int index, float temperature, float humidity, float roughness,
unsigned int topBlock, unsigned int soilBlock, unsigned int rockBlock,
const std::vector<noise::module::Module*>& heightmap, const std::vector<noise::module::Module*>& volume,
const std::vector<std::shared_ptr<Schematic>> schematics,
glm::vec3 biomeTint) :
identifier(identifier),
index(index),
identifier(identifier),
index(index),
temperature(temperature),
humidity(humidity),
roughness(roughness),
temperature(temperature),
humidity(humidity),
roughness(roughness),
topBlock(topBlock),
soilBlock(soilBlock),
rockBlock(rockBlock),
topBlock(topBlock),
soilBlock(soilBlock),
rockBlock(rockBlock),
heightmap(heightmap),
volume(volume),
heightmap(heightmap),
volume(volume),
biomeTint(biomeTint) {}
schematics(schematics),
biomeTint(biomeTint) {}

View File

@ -6,14 +6,18 @@
#include <string>
#include <vector>
#include <memory>
#include <glm/glm.hpp>
#include <noise/module/modulebase.h>
#include "../../game/scene/world/Schematic.h"
struct BiomeDef {
BiomeDef() = default;
BiomeDef(const std::string& identifier, unsigned int index, float temperature, float humidity, float roughness,
unsigned int topBlock, unsigned int soilBlock, unsigned int rockBlock,
const std::vector<noise::module::Module*>& heightmap, const std::vector<noise::module::Module*>& volume,
const std::vector<std::shared_ptr<Schematic>> schematics,
glm::vec3 biomeTint);
std::string identifier = "";
@ -30,5 +34,7 @@ struct BiomeDef {
std::vector<noise::module::Module*> heightmap;
std::vector<noise::module::Module*> volume;
std::vector<std::shared_ptr<Schematic>> schematics;
glm::vec3 biomeTint {};
};

View File

@ -6,7 +6,7 @@
LocalBiomeAtlas::LocalBiomeAtlas() {
//Invalid Biome
BiomeDef* invalid = new BiomeDef("invalid", 0, -1, -1, -1, 0, 0, 0, {}, {}, {});
BiomeDef* invalid = new BiomeDef("invalid", 0, -1, -1, -1, 0, 0, 0, {}, {}, {}, {});
defs.push_back(invalid);
defTable.insert({"invalid", 0});
}

View File

@ -206,16 +206,16 @@ void MapGen::generateStructures(chunk_partials_map& chunks, chunk_partial& chunk
std::default_random_engine generator(chunk.second->pos.x + chunk.second->pos.y * 30 + chunk.second->pos.z * 3.5);
std::uniform_real_distribution<float> distribution(0, 1);
unsigned int cWood = defs.blockFromStr("zeus:default:wood").index;
unsigned int cLeaves = defs.blockFromStr("zeus:default:leaves").index;
unsigned int cAir = DefinitionAtlas::INVALID;
// unsigned int cWood = defs.blockFromStr("zeus:default:wood").index;
// unsigned int cLeaves = defs.blockFromStr("zeus:default:leaves").index;
// unsigned int cAir = DefinitionAtlas::INVALID;
Schematic c {};
c.dimensions = {3, 3, 3};
c.origin = {1, 0, 1};
c.blocks = { cAir, cAir, cAir, cAir, cLeaves, cAir, cAir, cAir, cAir,
cAir, cWood, cAir, cLeaves, cWood, cLeaves, cAir, cLeaves, cAir,
cAir, cAir, cAir, cAir, cLeaves, cAir, cAir, cAir, cAir };
// Schematic c {};
// c.dimensions = {3, 3, 3};
// c.origin = {1, 0, 1};
// c.blocks = { cAir, cAir, cAir, cAir, cLeaves, cAir, cAir, cAir, cAir,
// cAir, cWood, cAir, cLeaves, cWood, cLeaves, cAir, cLeaves, cAir,
// cAir, cAir, cAir, cAir, cLeaves, cAir, cAir, cAir, cAir };
glm::ivec3 wp = chunk.second->pos;
glm::ivec3 lp;
@ -234,9 +234,15 @@ void MapGen::generateStructures(chunk_partials_map& chunks, chunk_partial& chunk
glm::ivec3 off = {};
glm::ivec3 p = wp * 16 + lp;
for (unsigned int j = 0; j < c.length(); j++) {
c.assignOffset(j, off);
setBlock(p + off - c.origin, c.blocks[j], chunks);
auto biome = biomes.biomeFromId(chunk.second->getBiome(ind));
auto schematic = biome.schematics.size() > 0 ? biome.schematics[0] : nullptr;
if (schematic != nullptr) {
if (!schematic->processed) schematic->process(defs);
for (unsigned int j = 0; j < schematic->length(); j++) {
schematic->assignOffset(j, off);
setBlock(p + off - schematic->origin, schematic->blocks[j], chunks);
}
}
}
}

View File

@ -6,7 +6,7 @@
ServerBiomeAtlas::ServerBiomeAtlas() {
//Invalid Biome
BiomeDef* invalid = new BiomeDef("invalid", INVALID, -1, -1, -1, 0, 0, 0, {}, {}, {});
BiomeDef* invalid = new BiomeDef("invalid", INVALID, -1, -1, -1, 0, 0, 0, {}, {}, {}, {});
registerBiome(invalid);
}

View File

@ -44,19 +44,19 @@ void GameGui::winResized(glm::ivec2 win) {
menuBuilder.build(win);
}
void GameGui::setMenu(const std::string& menu, const std::map<std::string, GuiBuilder::ComponentCallbacks>& callbacks) {
menuState = "menu"; //TODO: Implement the menu state properly
menuBuilder.setGui(menu, callbacks);
void GameGui::buildMenu(sol::state_view state, sol::table menu) {
menuBuilder.setGuiTable(state, menu);
menuBuilder.build(win);
inMenu = true;
}
void GameGui::closeMenu() {
menuBuilder.clear();
menuState = "";
inMenu = false;
}
const std::string &GameGui::getMenuState() {
return menuState;
const bool GameGui::isInMenu() const {
return inMenu;
}
void GameGui::setVisible(bool visible) {

View File

@ -25,9 +25,9 @@ public:
void setVisible(bool visible);
bool isVisible();
void setMenu(const std::string& menu, const std::map<std::string, GuiBuilder::ComponentCallbacks>& callbacks);
void buildMenu(sol::state_view state, sol::table menu);
const bool isInMenu() const;
void closeMenu();
const std::string& getMenuState();
void drawHud(Renderer& renderer);
void drawMenu(Renderer& renderer);
@ -36,7 +36,7 @@ private:
Renderer& renderer;
glm::ivec2 win {};
std::string menuState = "";
bool inMenu = false;
std::shared_ptr<GuiContainer> menuRoot = std::make_shared<GuiInventoryList>("menuRoot");
std::shared_ptr<GuiContainer> menuLuaRoot = std::make_shared<GuiInventoryList>("menuLuaRoot");

View File

@ -2,36 +2,34 @@
// Created by aurailus on 2019-12-12.
//
#include <array>
#include "GameGuiBuilder.h"
#include "components/compound/GuiInventoryList.h"
std::shared_ptr<GuiComponent> GameGuiBuilder::createComponent(SerialGui::Elem &data, glm::ivec2 bounds) {
auto c = GuiBuilder::createComponent(data, bounds);
std::shared_ptr<GuiComponent> GameGuiBuilder::createComponent(const SerialGui::Element& elem, glm::ivec2 bounds) {
auto c = GuiBuilder::createComponent(elem, bounds);
if (c != nullptr) return c;
GuiComponent::callback cbLeftClick = nullptr;
GuiComponent::callback cbRightClick = nullptr;
GuiComponent::callback cbHover = nullptr;
if (callbacks.count(data.key)) {
cbLeftClick = callbacks[data.key].left;
cbRightClick = callbacks[data.key].right;
cbHover = callbacks[data.key].hover;
}
switch (Util::hash(data.type.c_str())) {
switch (Util::hash(elem.type.c_str())) {
default: break;
case Util::hash("inventory"): {
c = GuiInventoryList::fromSerialized(data, game, bounds, refs);
case Util::hash("inventory_list"): {
c = GuiInventoryList::fromSerialized(elem, defs, bounds, refs);
break;
}
}
if (c != nullptr) {
c->setCallback(GuiComponent::CallbackType::PRIMARY, cbLeftClick);
c->setCallback(GuiComponent::CallbackType::SECONDARY, cbRightClick);
c->setCallback(GuiComponent::CallbackType::HOVER, cbHover);
}
if (!c) return nullptr;
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)])
c->setCallback(GuiComponent::CallbackType::PRIMARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)]);
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)])
c->setCallback(GuiComponent::CallbackType::SECONDARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)]);
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)])
c->setCallback(GuiComponent::CallbackType::HOVER, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)]);
return c;
}

View File

@ -12,9 +12,10 @@
class GameGuiBuilder : public GuiBuilder {
public:
GameGuiBuilder(LocalInventoryRefs& refs, ClientGame& defs, std::shared_ptr<GuiContainer> root) :
refs(refs), GuiBuilder(defs, root) {};
defs(defs), refs(refs), GuiBuilder(defs.textures, defs.models, root) {};
std::shared_ptr<GuiComponent> createComponent(SerialGui::Elem& data, glm::ivec2 bounds) override;
std::shared_ptr<GuiComponent> createComponent(const SerialGui::Element& elem, glm::ivec2 bounds) override;
private:
LocalInventoryRefs& refs;
ClientGame& defs;
};

View File

@ -10,160 +10,150 @@
#include "components/basic/GuiContainer.h"
#include "components/compound/GuiImageButton.h"
GuiBuilder::GuiBuilder(ClientGame& defs, std::shared_ptr<GuiContainer> root) :
game(defs), root(root) {}
GuiBuilder::GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root) :
textures(textures), models(models), root(root) {}
void GuiBuilder::setGui(const std::string& menu, const std::map<std::string, ComponentCallbacks>& callbacks) {
this->callbacks = callbacks;
deserialize(menu);
void GuiBuilder::setGuiTable(sol::state_view state, sol::table menu) {
keyInd = 0;
serialized = rDeserialize(state, menu);
}
void GuiBuilder::deserialize(const std::string& menu) {
// Split the lines by the newline delimiter
std::vector<std::string> lines;
{
std::string::size_type pos = 0;
std::string::size_type prev = 0;
SerialGui::Element GuiBuilder::rDeserialize(sol::state_view state, sol::table menu) {
std::string type = menu.get<std::string>("type");
std::string key = (menu.get<sol::optional<std::string>>("key") ? menu.get<std::string>("key") : "__UNKEYED_COMPONENT_" + std::to_string(keyInd++));
while ((pos = menu.find('\n', prev)) != std::string::npos) {
std::string sub = menu.substr(prev, pos - prev);
std::string::size_type start = sub.find_first_not_of("\t\v\r ");
if (start == std::string::npos) start = 0;
std::string::size_type end = sub.find_last_not_of("\t\v\r ");
SerialGui::Element element(type, key);
sub = sub.substr(start, end - start + 1);
if (sub.substr(0, 2) != "--" && !sub.empty()) lines.push_back(sub);
prev = pos + 1;
for (auto trait : menu.get<sol::table>("traits")) {
auto key = trait.first.as<std::string>();
if (trait.second.is<std::string>()) {
element.addTrait(key, Any::from<std::string>(trait.second.as<std::string>()));
}
else if (trait.second.is<sol::table>()) {
if (trait.second.as<sol::table>().size() == 2) {
auto x = trait.second.as<sol::table>().get<sol::object>(1);
auto y = trait.second.as<sol::table>().get<sol::object>(2);
glm::vec2 values = {};
if (x.is<float>()) values.x = x.as<float>();
else if (x.is<std::string>()) values.x = SerialGui::toDouble(x.as<std::string>());
if (y.is<float>()) values.y = y.as<float>();
else if (y.is<std::string>()) values.y = SerialGui::toDouble(y.as<std::string>());
element.addTrait(key, Any::from<glm::vec2>(values));
}
else if (trait.second.as<sol::table>().size() == 4) {
auto x = trait.second.as<sol::table>().get<sol::object>(1);
auto y = trait.second.as<sol::table>().get<sol::object>(2);
auto z = trait.second.as<sol::table>().get<sol::object>(3);
auto w = trait.second.as<sol::table>().get<sol::object>(4);
glm::vec4 values = {};
if (x.is<float>()) values.x = x.as<float>();
else if (x.is<std::string>()) values.x = SerialGui::toDouble(x.as<std::string>());
if (y.is<float>()) values.y = y.as<float>();
else if (y.is<std::string>()) values.y = SerialGui::toDouble(y.as<std::string>());
if (z.is<float>()) values.z = z.as<float>();
else if (z.is<std::string>()) values.z = SerialGui::toDouble(z.as<std::string>());
if (w.is<float>()) values.w = w.as<float>();
else if (w.is<std::string>()) values.w = SerialGui::toDouble(w.as<std::string>());
element.addTrait(key, Any::from<glm::vec4>(values));
}
}
}
components.clear();
unsigned int keyInd = 0;
std::vector<SerialGui::Elem*> stack {};
SerialGui::Elem* component = nullptr;
auto callbacks = menu.get<sol::optional<sol::table>>("callbacks");
if (callbacks) {
if (callbacks->get<sol::optional<sol::function>>("primary"))
element.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)] = [=](bool down, glm::ivec2 pos) {
callbacks->get<sol::function>("primary")(down, LuaParser::luaVec(state, {pos.x, pos.y, 0})); };
// Parse through the serialized structure and create the Serialized tree
for (const std::string& line : lines) {
if (line.find(':') != std::string::npos) {
// A Property
if (component == nullptr) throw "expected a component name before a property";
if (callbacks->get<sol::optional<sol::function>>("secondary"))
element.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)] = [=](bool down, glm::ivec2 pos) {
callbacks->get<sol::function>("secondary")(down, LuaParser::luaVec(state, {pos.x, pos.y, 0})); };
std::string::size_type delimiter = line.find(':');
std::string name = line.substr(0, delimiter);
std::string::size_type start = name.find_first_not_of("\t\v\r ");
if (start == std::string::npos) start = 0;
std::string::size_type end = name.find_last_not_of("\t\v\r ");
name = name.substr(start, end - start + 1);
std::string value = line.substr(delimiter + 1, std::string::npos);
start = value.find_first_not_of("\t\v\r ");
if (start == std::string::npos) start = 0;
end = value.find_last_not_of("\t\v\r ");
value = value.substr(start, end - start + 1);
component->tokens.emplace(name, value);
}
else if (line != "end") {
// Beginning of a component definition
std::string key = "";
std::string::size_type keyStart;
std::string::size_type keyEnd;
if ((keyStart = line.find('[')) != std::string::npos &&
(keyEnd = line.find_last_of(']')) != std::string::npos && keyEnd > keyStart) {
key = line.substr(keyStart + 1, keyEnd - keyStart - 1);
}
else {
// Create an implicit key because one was not specified
key = "__" + std::to_string(keyInd++);
}
std::string type = line.substr(0, keyStart);
SerialGui::Elem g {type, key, {}, {}};
if (component == nullptr) {
components.push_back(std::move(g));
component = &components[components.size() - 1];
}
else {
component->children.push_back(std::move(g));
stack.push_back(component);
component = &component->children[component->children.size() - 1];
}
}
else {
// End of a component definition -- pop the stack up
if (stack.size() > 0) {
component = stack[stack.size() - 1];
stack.pop_back();
}
else component = nullptr;
}
if (callbacks->get<sol::optional<sol::function>>("hover"))
element.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)] = [=](bool down, glm::ivec2 pos) {
callbacks->get<sol::function>("hover")(down, LuaParser::luaVec(state, {pos.x, pos.y, 0})); };
}
auto children = menu.get<sol::optional<sol::table>>("children");
if (children) for (auto& pair : *children) element.children.push_back(rDeserialize(state, pair.second.as<sol::table>()));
return element;
}
void GuiBuilder::build(glm::ivec2 winBounds) {
clear(false);
recursivelyCreate(components, root, winBounds);
if (serialized.type != "")
rCreate(serialized, root, winBounds);
}
void GuiBuilder::clear(bool clrCallbacks) {
if (clrCallbacks) callbacks.clear();
void GuiBuilder::clear(bool deleteRoot) {
rClearCallbacks(root);
root->empty();
if (deleteRoot) serialized = {"", ""};
}
void GuiBuilder::recursivelyCreate(std::vector<SerialGui::Elem> components, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds) {
for (auto& data : components) {
std::shared_ptr<GuiComponent> component = createComponent(data, bounds);
if (component == nullptr) continue;
parent->add(component);
recursivelyCreate(data.children, component, component->getScale());
void GuiBuilder::rCreate(const SerialGui::Element& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds) {
auto component = createComponent(element, bounds);
if (!component) throw std::runtime_error("GuiBuilder failed to create component: " + element.key);
parent->add(component);
for (auto& child : element.children) rCreate(child, component, component->getScale());
}
void GuiBuilder::rClearCallbacks(std::shared_ptr<GuiComponent> component) {
component->setCallback(GuiComponent::CallbackType::PRIMARY, nullptr);
component->setCallback(GuiComponent::CallbackType::SECONDARY, nullptr);
component->setCallback(GuiComponent::CallbackType::HOVER, nullptr);
for (auto& child : component->getChildren()) {
rClearCallbacks(child);
}
}
std::shared_ptr<GuiComponent> GuiBuilder::createComponent(SerialGui::Elem& data, glm::ivec2 bounds) {
std::shared_ptr<GuiComponent> GuiBuilder::createComponent(const SerialGui::Element& elem, glm::ivec2 bounds) {
std::shared_ptr<GuiComponent> c = nullptr;
GuiComponent::callback cbLeftClick = nullptr;
GuiComponent::callback cbRightClick = nullptr;
GuiComponent::callback cbHover = nullptr;
if (callbacks.count(data.key)) {
cbLeftClick = callbacks[data.key].left;
cbRightClick = callbacks[data.key].right;
cbHover = callbacks[data.key].hover;
}
switch (Util::hash(data.type.c_str())) {
switch (Util::hash(elem.type.c_str())) {
default: break;
case Util::hash("body"): {
auto body = GuiRect::fromSerialized(data, game, bounds);
auto body = GuiRect::fromSerialized(elem, textures, bounds);
body->setScale(bounds);
c = body;
break;
}
case Util::hash("rect"):
c = GuiRect::fromSerialized(data, game, bounds);
c = GuiRect::fromSerialized(elem, textures, bounds);
break;
case Util::hash("button"):
c = GuiImageButton::fromSerialized(data, game, bounds);
c = GuiImageButton::fromSerialized(elem, textures, bounds);
break;
case Util::hash("text"):
c = GuiText::fromSerialized(data, game, bounds);
c = GuiText::fromSerialized(elem, textures, bounds);
break;
case Util::hash("model"):
c = GuiModel::fromSerialized(data, game, bounds);
c = GuiModel::fromSerialized(elem, textures, models, bounds);
break;
}
if (c != nullptr) {
c->setCallback(GuiComponent::CallbackType::PRIMARY, cbLeftClick);
c->setCallback(GuiComponent::CallbackType::SECONDARY, cbRightClick);
c->setCallback(GuiComponent::CallbackType::HOVER, cbHover);
}
if (!c) return nullptr;
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)])
c->setCallback(GuiComponent::CallbackType::PRIMARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::PRIMARY)]);
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)])
c->setCallback(GuiComponent::CallbackType::SECONDARY, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::SECONDARY)]);
if (elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)])
c->setCallback(GuiComponent::CallbackType::HOVER, elem.callbacks[static_cast<unsigned int>(GuiComponent::CallbackType::HOVER)]);
return c;
}
GuiBuilder::~GuiBuilder() {
clear(true);
clear();
}

View File

@ -14,21 +14,23 @@ class GuiBuilder {
public:
struct ComponentCallbacks { GuiComponent::callback left {}, right {}, hover {}; };
GuiBuilder(ClientGame& defs, std::shared_ptr<GuiContainer> root);
void setGui(const std::string& menu, const std::map<std::string, ComponentCallbacks>& callbacks = {});
void clear(bool clrCallbacks = true);
GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr<GuiContainer> root);
void setGuiTable(sol::state_view state, const sol::table menu);
void build(glm::ivec2 winBounds);
void clear(bool deleteRoot = true);
~GuiBuilder();
protected:
void deserialize(const std::string& menu);
void recursivelyCreate(std::vector<SerialGui::Elem> components, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds);
virtual std::shared_ptr<GuiComponent> createComponent(SerialGui::Elem& component, glm::ivec2 bounds);
SerialGui::Element rDeserialize(sol::state_view state, sol::table menu);
void rCreate(const SerialGui::Element& element, std::shared_ptr<GuiComponent> parent, glm::ivec2 bounds);
static void rClearCallbacks(std::shared_ptr<GuiComponent> component);
virtual std::shared_ptr<GuiComponent> createComponent(const SerialGui::Element& elem, glm::ivec2 bounds);
std::map<std::string, ComponentCallbacks> callbacks;
TextureAtlas& textures;
ModelStore& models;
ClientGame& game;
std::shared_ptr<GuiContainer> root;
std::vector<SerialGui::Elem> components {};
std::shared_ptr<GuiContainer> root = nullptr;
SerialGui::Element serialized = {"", ""};
unsigned int keyInd = 0;
};

View File

@ -15,13 +15,42 @@
#include <glm/vec2.hpp>
#include <glm/vec4.hpp>
#include <sol2/sol.hpp>
#include "../../util/Any.h"
#include <iostream>
namespace SerialGui {
struct Elem {
class Element {
public:
Element(const std::string& type, const std::string& key) : type(type), key(key) {};
std::string type;
std::string key;
std::map<std::string, std::string> tokens;
std::vector<SerialGui::Elem> children;
void addTrait(const std::string& key, const Any& any) {
traits.emplace(key, any);
}
template <typename T> const T& get(const std::string& key) const {
if (!traits.count(key)) throw std::logic_error("Key missing from table");
return traits.at(key).get<T>();
}
template <typename T> const T& get_or(const std::string& key, const T& other) const noexcept {
if (!traits.count(key)) return other;
return traits.at(key).get_or<T>(other);
}
template <typename T> const bool has(const std::string& key) const noexcept {
if (!traits.count(key)) return false;
return traits.at(key).is<T>();
}
std::array<std::function<void(bool, glm::ivec2)>, 3> callbacks = {{nullptr, nullptr, nullptr}};
std::vector<SerialGui::Element> children {};
private:
std::map<std::string, Any> traits {};
};
const float SCALE_MODIFIER = 3;
@ -51,46 +80,43 @@ namespace SerialGui {
return std::move(vec);
}
static double toDouble(const std::string& input, unsigned int multiple) {
static double toDouble(const std::string& input) {
char* e;
errno = 0;
if (input.find("px") == input.length() - 2) {
double v = round(std::strtod(input.substr(0, input.find("px")).c_str(), &e));
if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string");
return v * SCALE_MODIFIER;
}
if (input.find('%') == input.length() - 1) {
double v = std::strtod(input.substr(0, input.find("%")).c_str(), &e) / 100;
if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string");
if (!multiple) return v;
return round(v * multiple / SCALE_MODIFIER) * SCALE_MODIFIER;
return v - 10.f; // Percentages are going to be stored in negatives. Ew.
}
double v = std::strtod(input.c_str(), &e);
double v = round(std::strtod(input.c_str(), &e));
if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string");
return v;
}
static double convertNum(float input, unsigned int multiple) {
if (input >= -20 && input < 0) {
if (!multiple) return input + 10;
else return (((input + 10) * multiple / SCALE_MODIFIER) * SCALE_MODIFIER);
}
return input * SCALE_MODIFIER;
}
}
template <typename T> static T deserialize(const std::string& in, glm::ivec2 multiple = {}) {};
template <typename T> static T calcNumbers(const T in, glm::ivec2 multiple = {}) {};
template <typename T> static T deserializeToken(const std::map<std::string, std::string>& tokens,
const std::string& req, glm::ivec2 multiple = {}) {
if (!tokens.count(req)) return T{};
return deserialize<T>(tokens.at(req), multiple);
template <typename T> static T get(const SerialGui::Element& elem, const std::string& req, glm::ivec2 multiple = {}) {
if (!elem.has<T>(req)) return T{};
return calcNumbers<T>(elem.get<T>(req), multiple);
}
template <> glm::vec2 deserialize<glm::vec2>(const std::string& in, glm::ivec2 multiple) {
auto tokens = split(in, 2);
return {toDouble(tokens[0], multiple.x), toDouble(tokens[1], multiple.y)};
template <> glm::vec2 calcNumbers<glm::vec2>(const glm::vec2 in, glm::ivec2 multiple) {
return {convertNum(in.x, multiple.x), convertNum(in.y, multiple.y)};
}
template <> glm::vec4 deserialize<glm::vec4>(const std::string& in, glm::ivec2 multiple) {
auto tokens = split(in, 4);
return {toDouble(tokens[0], multiple.x), toDouble(tokens[1], multiple.y),
toDouble(tokens[2], multiple.x), toDouble(tokens[3], multiple.y)};
template <> glm::vec4 calcNumbers<glm::vec4>(const glm::vec4 in, glm::ivec2 multiple) {
return {convertNum(in.x, multiple.x), convertNum(in.y, multiple.y), convertNum(in.z, multiple.x), convertNum(in.w, multiple.y)};
}
};

View File

@ -170,4 +170,8 @@ void GuiComponent::updatePos() {
for (const auto& child : children) {
child->updatePos();
}
}
}
std::list<std::shared_ptr<GuiComponent>> GuiComponent::getChildren() {
return children;
}

View File

@ -45,6 +45,8 @@ public:
std::shared_ptr<GuiComponent> insert(unsigned int index, std::shared_ptr<GuiComponent> component);
std::shared_ptr<GuiComponent> add(std::shared_ptr<GuiComponent> component);
std::list<std::shared_ptr<GuiComponent>> getChildren();
void remove(const std::string& key);
void empty();

View File

@ -5,23 +5,24 @@
#include "GuiModel.h"
#include "../../../../def/ClientGame.h"
#include "../../../../def/model/ModelStore.h"
GuiModel::GuiModel(const std::string &key) : GuiComponent(key) {}
std::shared_ptr<GuiModel> GuiModel::fromSerialized(SerialGui::Elem s, ClientGame &game, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position", bounds);
glm::vec2 scale = SerialGui::deserializeToken<glm::vec2>(s.tokens, "scale");
glm::vec2 anim_range = SerialGui::deserializeToken<glm::vec2>(s.tokens, "anim_range");
std::shared_ptr<GuiModel> GuiModel::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 scale = SerialGui::get<glm::vec2>(elem, "scale");
glm::vec2 anim_range = SerialGui::get<glm::vec2>(elem, "anim_range");
if (scale == glm::vec2{0, 0}) scale = {1, 1};
std::string type = s.tokens.count("type") ? s.tokens["type"] : "model";
std::string source = s.tokens["source"];
std::string texture = s.tokens["texture"];
std::string type = elem.get_or<std::string>("type", "model");
std::string source = elem.get_or<std::string>("source", "");
std::string texture = elem.get_or<std::string>("texture", "");
auto m = std::make_shared<Model>();
if (type == "model") m->fromSerialized(game.models.models[source], {game.textures[texture]});
if (type == "model") m->fromSerialized(models.models[source], {textures[texture]});
auto model = std::make_shared<GuiModel>(s.key);
auto model = std::make_shared<GuiModel>(elem.key);
model->create(scale, m);
model->setPos(pos);

View File

@ -11,13 +11,14 @@
#include "../../SerialGui.h"
class ClientGame;
class ModelStore;
class GuiModel : public GuiComponent {
public:
GuiModel() = default;
GuiModel(const std::string& key);
static std::shared_ptr<GuiModel> fromSerialized(SerialGui::Elem s, ClientGame& game, glm::ivec2 bounds);
static std::shared_ptr<GuiModel> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds);
void create(glm::vec2 scale, std::shared_ptr<Model> model);
void update(double delta) override;

View File

@ -10,22 +10,21 @@
GuiRect::GuiRect(const std::string &key) : GuiComponent(key) {}
std::shared_ptr<GuiRect> GuiRect::fromSerialized(SerialGui::Elem s, ClientGame& game, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position", bounds);
glm::vec2 offset = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position_anchor");
glm::vec2 size = SerialGui::deserializeToken<glm::vec2>(s.tokens, "size", bounds);
glm::vec4 padding = SerialGui::deserializeToken<glm::vec4>(s.tokens, "padding", bounds);
std::shared_ptr<GuiRect> GuiRect::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
pos -= offset * size;
size -= glm::vec2 {padding.y + padding.w, padding.x + padding.z};
std::string background = s.tokens["background"];
std::string background = elem.get_or<std::string>("background", "");
bool hideOverflow = elem.get_or<std::string>("overflow", "visible") == "hidden";
bool hideOverflow = s.tokens["overflow"] == "hidden";
auto rect = std::make_shared<GuiRect>(s.key);
auto rect = std::make_shared<GuiRect>(elem.key);
if (background[0] == '#') rect->create(size, padding, Util::hexToColorVec(background));
else if (background.size() > 0) rect->create(size, padding, game.textures[background]);
else if (background.size() > 0) rect->create(size, padding, textures[background]);
else rect->create(size, padding, glm::vec4 {});
rect->setOverflows(!hideOverflow);
rect->setPos(pos);

View File

@ -18,7 +18,7 @@ public:
GuiRect() = default;
GuiRect(const std::string& key);
static std::shared_ptr<GuiRect> fromSerialized(SerialGui::Elem s, ClientGame& game, glm::ivec2 bounds);
static std::shared_ptr<GuiRect> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds);
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color);
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br);

View File

@ -23,32 +23,22 @@ void GuiText::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm:
setText("");
}
std::shared_ptr<GuiText> GuiText::fromSerialized(SerialGui::Elem s, ClientGame &game, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position", bounds);
glm::vec2 offset = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position_anchor");
glm::vec2 size = SerialGui::deserializeToken<glm::vec2>(s.tokens, "size", bounds);
glm::vec4 padding = SerialGui::deserializeToken<glm::vec4>(s.tokens, "padding", bounds);
glm::vec2 scale = SerialGui::deserializeToken<glm::vec2>(s.tokens, "scale");
std::shared_ptr<GuiText> GuiText::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
glm::vec2 scale = SerialGui::get<glm::vec2>(elem, "scale");
if (scale == glm::vec2{0, 0}) scale = {1, 1};
pos -= offset * size;
// size -= glm::vec2 {padding.y + padding.w, padding.x + padding.z};
glm::vec4 background_color = Util::hexToColorVec("#0000");
if (s.tokens.count("background")) background_color = Util::hexToColorVec(s.tokens["background"]);
glm::vec4 color = Util::hexToColorVec("#fff");
if (s.tokens.count("color")) color = Util::hexToColorVec(s.tokens["color"]);
glm::vec4 background_color = Util::hexToColorVec(elem.get_or<std::string>("background", "#0000"));
glm::vec4 color = Util::hexToColorVec(elem.get_or<std::string>("color", "#fff"));
std::string content = elem.get_or<std::string>("content", "");
std::string content = "";
if (s.tokens.count("content") && s.tokens["content"].length() >= 2) content = s.tokens["content"].substr(1, s.tokens["content"].size() - 2);
std::string::size_type off = 0;
while ((off = content.find("\\n", off)) != std::string::npos) {
content.replace(off, 2, "\n");
off += 1;
}
auto text = std::make_shared<GuiText>(s.key);
text->create(scale * SerialGui::SCALE_MODIFIER, padding, background_color, color, {game.textures, game.textures["font"]});
auto text = std::make_shared<GuiText>(elem.key);
text->create(scale * SerialGui::SCALE_MODIFIER, padding, background_color, color, {textures, textures["font"]});
text->setText(content);
text->setPos(pos);

View File

@ -17,7 +17,7 @@ public:
GuiText() = default;
explicit GuiText(const std::string& key);
static std::shared_ptr<GuiText> fromSerialized(SerialGui::Elem s, ClientGame& game, glm::ivec2 bounds);
static std::shared_ptr<GuiText> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds);
void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font);

View File

@ -9,37 +9,29 @@
GuiImageButton::GuiImageButton(const std::string &key) : GuiRect(key) {}
std::shared_ptr<GuiImageButton> GuiImageButton::fromSerialized(SerialGui::Elem s, ClientGame &game, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position", bounds);
glm::vec2 offset = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position_anchor");
glm::vec2 size = SerialGui::deserializeToken<glm::vec2>(s.tokens, "size", bounds);
glm::vec4 padding = SerialGui::deserializeToken<glm::vec4>(s.tokens, "padding", bounds);
std::shared_ptr<GuiImageButton> GuiImageButton::fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds) {
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
glm::vec2 size = SerialGui::get<glm::vec2>(elem, "size", bounds);
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
pos -= offset * size;
size -= glm::vec2 {padding.y + padding.w, padding.x + padding.z};
std::string background = s.tokens["background"];
std::string background_hover = s.tokens["background_hover"];
if (background_hover.length() == 0) background_hover = background;
std::string background = elem.get_or<std::string>("background", "");
std::string background_hover = elem.get_or<std::string>("background_hover", background);
bool hideOverflow = s.tokens["overflow"] == "hidden";
bool hideOverflow = elem.get_or<std::string>("overflow", "visible") == "hidden";
std::string content = elem.get_or<std::string>("content", "");
std::string content = "";
if (s.tokens.count("content") && s.tokens["content"].length() >= 2) content = s.tokens["content"].substr(1, s.tokens["content"].size() - 2);
std::string::size_type off = 0;
while ((off = content.find("\\n", off)) != std::string::npos) {
content.replace(off, 2, "\n");
off += 1;
}
auto button = std::make_shared<GuiImageButton>(s.key);
button->create(size, padding, game.textures[background], game.textures[background_hover]);
auto button = std::make_shared<GuiImageButton>(elem.key);
button->create(size, padding, textures[background], textures[background_hover]);
button->setOverflows(!hideOverflow);
button->setPos(pos);
if (content != "") {
auto text = std::make_shared<GuiText>(s.key + "__TEXT");
text->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding, {}, {1, 1, 1, 1}, {game.textures, game.textures["font"]});
auto text = std::make_shared<GuiText>(elem.key + "__TEXT");
text->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding, {}, {1, 1, 1, 1}, {textures, textures["font"]});
text->setPos({6 * SerialGui::SCALE_MODIFIER, size.y / 2 - 4.5 * SerialGui::SCALE_MODIFIER});
text->setText(content);
button->add(text);

View File

@ -11,7 +11,7 @@ public:
GuiImageButton() = default;
GuiImageButton(const std::string& key);
static std::shared_ptr<GuiImageButton> fromSerialized(SerialGui::Elem s, ClientGame& game, glm::ivec2 bounds);
static std::shared_ptr<GuiImageButton> fromSerialized(const SerialGui::Element& elem, TextureAtlas& textures, glm::ivec2 bounds);
void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr<AtlasRef> texture, std::shared_ptr<AtlasRef> hoverTexture);

View File

@ -9,20 +9,20 @@
#include "../../../../def/texture/Font.h"
GuiInventoryList::GuiInventoryList(const std::string &key) : GuiContainer(key) {}
std::shared_ptr<GuiInventoryList> GuiInventoryList::fromSerialized(SerialGui::Elem s, ClientGame &game,
std::shared_ptr<GuiInventoryList> GuiInventoryList::fromSerialized(SerialGui::Element elem, ClientGame &game,
glm::ivec2 bounds, LocalInventoryRefs& refs) {
glm::vec2 pos = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position", bounds);
glm::vec2 offset = SerialGui::deserializeToken<glm::vec2>(s.tokens, "position_anchor");
glm::vec2 pos = SerialGui::get<glm::vec2>(elem, "position", bounds);
glm::vec2 offset = SerialGui::get<glm::vec2>(elem, "position_anchor");
// glm::vec2 size = SerialGui::deserializeToken<glm::vec2>(s.tokens, "size", bounds);
glm::vec4 padding = SerialGui::deserializeToken<glm::vec4>(s.tokens, "padding", bounds);
glm::vec2 slotspc = SerialGui::deserializeToken<glm::vec2>(s.tokens, "slot_spacing", bounds);
glm::vec4 padding = SerialGui::get<glm::vec4>(elem, "padding", bounds);
glm::vec2 slotspc = SerialGui::get<glm::vec2>(elem, "slot_spacing", bounds);
std::string source = s.tokens["source"];
std::string list = s.tokens["list"];
std::string source = elem.get_or<std::string>("source", "");
std::string list = elem.get_or<std::string>("list", "");
auto invList = refs.getList(source, list);
auto inv = std::make_shared<GuiInventoryList>(s.key);
auto inv = std::make_shared<GuiInventoryList>(elem.key);
inv->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding * SerialGui::SCALE_MODIFIER,
slotspc * SerialGui::SCALE_MODIFIER, invList, refs.getHand(), game);

View File

@ -19,7 +19,7 @@ public:
GuiInventoryList(const std::string& key);
~GuiInventoryList() override;
static std::shared_ptr<GuiInventoryList> fromSerialized(SerialGui::Elem s, ClientGame &game,
static std::shared_ptr<GuiInventoryList> fromSerialized(SerialGui::Element elem, ClientGame &game,
glm::ivec2 bounds, LocalInventoryRefs& refs);
void create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding,

View File

@ -7,44 +7,49 @@
#include "../../../lua/api/menu/mDelay.h"
#include "../../../lua/api/menu/mSetGui.h"
#include "../../../lua/api/menu/mStartGame.h"
#include "../../../lua/ErrorFormatter.h"
MenuSandbox::MenuSandbox(glm::ivec2 &win, ClientState& state, std::shared_ptr<GuiContainer> container) :
win(win),
state(state),
container(container),
builder(state.defs, container) {}
win(win),
state(state),
container(container),
builder(state.defs.textures, state.defs.models, container) {}
void MenuSandbox::setup() {
void MenuSandbox::reset() {
builder.clear(true);
delayed_functions.clear();
core = {};
mod = {};
lua = sol::state {};
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table);
loadApi();
}
void MenuSandbox::loadApi() {
//Create Zepha Table
core = lua.create_table();
lua["zepha"] = core;
core["__builtin"] = lua.create_table();
//Sandbox the dofile function
MenuApi::delay (core, delayed_functions);
MenuApi::set_gui (builder, win, lua, core);
MenuApi::start_game (state, core);
// Create sandboxed runfile()
lua["dofile"] = lua["loadfile"] = sol::nil;
lua.set_function("runfile", &MenuSandbox::DoFileSandboxed, this);
MenuApi::delay(core, delayed_functions);
MenuApi::set_gui(builder, win, lua, core);
MenuApi::start_game(state, core);
lua.set_function("runfile", &MenuSandbox::runFileSandboxed, this);
}
void MenuSandbox::load(const Subgame& subgame) {
builder.clear();
setup();
reset();
try {
loadMod(subgame.subgamePath + "/menu");
DoFileSandboxed("init");
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
loadAndRunMod(subgame.subgamePath + "/menu");
}
catch (const std::string& e) {
std::cout << Log::err <<
"Encountered an error loading menu mod for subgame '" + subgame.config.name + "':\n\t"
<< e << Log::endl;
std::cout << Log::err << "Encountered an error loading menu mod for subgame '" + subgame.config.name + "':\n\t" << e << Log::endl;
}
}
@ -52,32 +57,24 @@ void MenuSandbox::windowResized() {
builder.build(win);
}
sol::protected_function_result MenuSandbox::DoFileSandboxed(const std::string& file) {
sol::protected_function_result MenuSandbox::runFileSandboxed(const std::string& file) {
for (LuaModFile& f : mod.files) {
if (f.path == file) {
sol::environment env(lua, sol::create, lua.globals());
env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1);
env["_FILE"] = f.path;
env["_MODNAME"] = mod.config.name;
auto pfr = lua.safe_script(f.file, env, [&](lua_State*, sol::protected_function_result errPfr) {
sol::error err = errPfr;
std::cout << Log::err << file << " returned an error: " << err.what() << Log::endl;
return errPfr;
}, "@" + f.path, sol::load_mode::text);
return pfr;
return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback, this,
std::placeholders::_2), "@" + f.path, sol::load_mode::text);
}
}
throw std::string("Error executing file '" + file + "', file not found.");
}
void MenuSandbox::loadMod(const std::string &modPath) {
void MenuSandbox::loadAndRunMod(const std::string &modPath) {
if (!cf_file_exists(modPath.data())) throw std::string("Directory not found.");
mod = LuaMod {};
LuaMod mod;
std::string root = modPath + "/script";
std::list<std::string> dirsToScan {root};
@ -133,4 +130,33 @@ void MenuSandbox::loadMod(const std::string &modPath) {
if (cf_file_exists(texPath.data())) {
this->modAssets = state.defs.textures.loadDirectory(texPath, false, true);
}
this->mod = mod;
runFileSandboxed("main");
}
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result errPfr) {
sol::error err = errPfr;
std::string errString = err.what();
try {
std::string::size_type lineNumStart = errString.find(':');
assert(lineNumStart != std::string::npos);
std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1);
assert(lineNumEnd != std::string::npos);
std::string fileName = errString.substr(0, lineNumStart);
int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1));
for (LuaModFile &f : mod.files) {
if (f.path == fileName) {
std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, f.file) << std::endl;
exit(1);
}
}
}
catch (...) {
std::cout << std::endl << Log::err << errString << Log::endl;
}
exit(1);
}

View File

@ -23,15 +23,19 @@ public:
using LuaParser::update;
private:
void setup();
void loadMod(const std::string& modPath);
void reset();
void loadApi();
void executeMods();
void loadAndRunMod(const std::string& modPath);
sol::protected_function_result DoFileSandboxed(const std::string& file);
sol::protected_function_result runFileSandboxed(const std::string& file);
sol::protected_function_result errorCallback(sol::protected_function_result errPfr);
LuaMod mod {};
std::vector<std::shared_ptr<AtlasRef>> modAssets {};
std::shared_ptr<GuiContainer> container = nullptr;
ClientState& state;
GuiBuilder builder;
glm::ivec2& win;

View File

@ -276,8 +276,8 @@ void Player::setActiveBlock(const std::string& block) {
handItemModel.setModel(defs.defs.fromId(activeBlock).entityModel);
}
void Player::setMenu(const std::string& menu, const std::map<std::string, GuiBuilder::ComponentCallbacks>& callbacks) {
gameGui.setMenu(menu, callbacks);
void Player::buildMenu(sol::state_view state, sol::table menu) {
gameGui.buildMenu(state, menu);
renderer.window.lockMouse(false);
}
@ -290,8 +290,8 @@ void Player::setGuiVisible(bool hudVisible) {
gameGui.setVisible(hudVisible);
}
std::string Player::getMenuState() {
return gameGui.getMenuState();
bool Player::isInMenu() {
return gameGui.isInMenu();
}
/*

View File

@ -43,9 +43,9 @@ public:
void setActiveBlock(const std::string& block);
void setMenu(const std::string& menu, const std::map<std::string, GuiBuilder::ComponentCallbacks>& callbacks);
std::string getMenuState();
void buildMenu(sol::state_view state, sol::table menu);
void closeMenu();
bool isInMenu();
void setGuiVisible(bool hudVisible);
void draw(Renderer& renderer) override;

View File

@ -3,3 +3,29 @@
//
#include "Schematic.h"
#include "../../../def/DefinitionAtlas.h"
void Schematic::process(DefinitionAtlas& atlas) {
blocks.reserve(stringData.size());
for (auto& string : stringData) {
blocks.push_back(atlas.blockFromStr(string).index);
}
stringData.clear();
stringData.shrink_to_fit();
processed = true;
}
void Schematic::assignOffset(int ind, glm::ivec3& vec) {
vec.z = ind / (dimensions.x * dimensions.y);
ind -= (vec.z * dimensions.x * dimensions.y);
vec.y = ind / dimensions.z;
vec.x = ind % dimensions.x;
}
unsigned int Schematic::index(const glm::ivec3& vec) {
return static_cast<unsigned int>(vec.x + dimensions.x * (vec.y + dimensions.y * vec.z));
}

View File

@ -5,25 +5,23 @@
#pragma once
#include <vector>
#include <string>
#include <glm/vec3.hpp>
class DefinitionAtlas;
struct Schematic {
std::vector<std::string> stringData {};
bool processed = false;
std::vector<unsigned int> blocks {};
glm::ivec3 dimensions {};
glm::ivec3 origin {};
// inline unsigned int index(const glm::ivec3& vec) {
// return static_cast<unsigned int>(vec.x + dimensions.x * (vec.y + dimensions.y * vec.z));
// }
void process(DefinitionAtlas& atlas);
inline unsigned int length() {
return blocks.size();
}
inline unsigned int length() { return blocks.size(); }
inline void assignOffset(int ind, glm::ivec3& vec) {
vec.z = ind / (dimensions.x * dimensions.y);
ind -= ((int)vec.z * dimensions.x * dimensions.y);
vec.y = ind / dimensions.y;
vec.x = ind % dimensions.z;
}
void assignOffset(int ind, glm::ivec3& vec);
unsigned int index(const glm::ivec3& vec);
};

View File

@ -18,10 +18,10 @@ class LuaParser {
public:
constexpr static double UPDATE_STEP {1 / 60.0};
static inline void override_panic(sol::optional<std::string> message) {
std::cout << Log::err << "Zepha has panicked! Error:" << Log::endl;
if (message) std::cout << Log::err << message.value() << Log::endl;
}
// static inline void override_panic(sol::optional<std::string> message) {
// std::cout << Log::err << "Zepha has panicked! Error:" << Log::endl;
// if (message) std::cout << Log::err << message.value() << Log::endl;
// }
struct DelayedFunction {
sol::function function;

View File

@ -43,39 +43,12 @@ float LocalLuaPlayer::get_look_pitch() {
return player.getPitch();
}
std::string LocalLuaPlayer::get_menu_state() {
return player.getMenuState();
bool LocalLuaPlayer::is_in_menu() {
return player.isInMenu();
}
void LocalLuaPlayer::open_menu(sol::this_state s, std::string menu, sol::optional<sol::table> callbacks) {
if (callbacks) {
std::map<std::string, GuiBuilder::ComponentCallbacks> callbackMap;
for (auto& pair : *callbacks) {
if (!pair.first.is<std::string>() || !pair.second.is<sol::table>()) continue;
std::string identifier = pair.first.as<std::string>();
sol::table callbacks = pair.second.as<sol::table>();
GuiBuilder::ComponentCallbacks componentCallbacks {};
auto left = callbacks.get<sol::optional<sol::function>>("left");
auto right = callbacks.get<sol::optional<sol::function>>("right");
auto hover = callbacks.get<sol::optional<sol::function>>("hover");
if (left) componentCallbacks.left = [=](bool down, glm::ivec2 pos) {
(*left)(down, sol::state_view(s).create_table_with("x", pos.x, "y", pos.y)); };
if (right) componentCallbacks.right = [=](bool down, glm::ivec2 pos) {
(*right)(down, sol::state_view(s).create_table_with("x", pos.x, "y", pos.y)); };
if (hover) componentCallbacks.hover = [=](bool down, glm::ivec2 pos) {
(*hover)(down, sol::state_view(s).create_table_with("x", pos.x, "y", pos.y)); };
callbackMap.emplace(identifier, componentCallbacks);
}
player.setMenu(menu, callbackMap);
}
else player.setMenu(menu, {});
void LocalLuaPlayer::show_menu(sol::this_state s, sol::table menu) {
player.buildMenu(s, menu);
}
void LocalLuaPlayer::close_menu() {

View File

@ -29,9 +29,9 @@ public:
void set_look_pitch(float rot);
float get_look_pitch();
std::string get_menu_state();
bool is_in_menu();
void close_menu();
void open_menu(sol::this_state s, std::string menu, sol::optional<sol::table> callbacks);
void show_menu(sol::this_state s, sol::table menu);
LocalLuaInventory get_inventory();

View File

@ -9,35 +9,8 @@
namespace MenuApi {
void set_gui(GuiBuilder& builder, glm::ivec2& win, sol::state& lua, sol::table& core) {
core.set_function("set_gui", [&](std::string gui, sol::optional<sol::table> callbacks) {
if (callbacks) {
std::map<std::string, GuiBuilder::ComponentCallbacks> callbackMap;
for (auto& pair : *callbacks) {
if (!pair.first.is<std::string>() || !pair.second.is<sol::table>()) continue;
std::string identifier = pair.first.as<std::string>();
sol::table callbacks = pair.second.as<sol::table>();
GuiBuilder::ComponentCallbacks componentCallbacks {};
auto left = callbacks.get<sol::optional<sol::function>>("left");
auto right = callbacks.get<sol::optional<sol::function>>("right");
auto hover = callbacks.get<sol::optional<sol::function>>("hover");
if (left) componentCallbacks.left = [=, &lua](bool down, glm::ivec2 pos) {
(*left)(down, lua.create_table_with("x", pos.x, "y", pos.y)); };
if (right) componentCallbacks.right = [=, &lua](bool down, glm::ivec2 pos) {
(*right)(down, lua.create_table_with("x", pos.x, "y", pos.y)); };
if (hover) componentCallbacks.hover = [=, &lua](bool down, glm::ivec2 pos) {
(*hover)(down, lua.create_table_with("x", pos.x, "y", pos.y)); };
callbackMap.emplace(identifier, componentCallbacks);
}
builder.setGui(gui, callbackMap);
}
else builder.setGui(gui);
core.set_function("set_gui", [&](sol::this_state s, sol::table gui) {
builder.setGuiTable(sol::state_view(s), gui);
builder.build(win);
});
}

View File

@ -0,0 +1,44 @@
//
// Created by aurailus on 2020-03-15.
//
#pragma once
#include <sol2/sol.hpp>
#include "../../../game/scene/world/Schematic.h"
namespace Api {
static void create_structure(sol::state& lua, sol::table& core) {
core.set_function("create_structure", [&](sol::optional<sol::table> data) {
if (!data) throw "expected a table as the first argument.";
auto origin = data->get<sol::optional<sol::table>>("origin");
auto schematic = data->get<sol::optional<sol::table>>("schematic");
if (!origin) throw "expected a table as the first argument.";
if (!schematic) throw "expected a table as the first argument.";
auto s = std::make_shared<Schematic>();
unsigned int yWid = schematic->size();
unsigned int zWid = (*schematic).get<sol::table>(1).size();
unsigned int xWid = (*schematic).get<sol::table>(1).get<sol::table>(1).size();
s->dimensions = {xWid, yWid, zWid};
s->stringData.resize(xWid * yWid * zWid);
s->origin = {origin->get<unsigned int>(1), origin->get<unsigned int>(2), origin->get<unsigned int>(3)};
for (unsigned int y = 1; y <= yWid; y++) {
for (unsigned int z = 1; z <= zWid; z++) {
for (unsigned int x = 1; x <= xWid; x++) {
s->stringData[s->index({x - 1, y - 1, z - 1})] =
schematic->get<sol::table>(y).get<sol::table>(z).get_or<std::string>(x, "");
}
}
}
return s;
});
}
}

View File

@ -23,7 +23,7 @@ namespace ClientApi {
"get_inventory", &LocalLuaPlayer::get_inventory,
"set_selected_block", &LocalLuaPlayer::set_selected_block,
"open_menu", &LocalLuaPlayer::open_menu,
"show_menu", &LocalLuaPlayer::show_menu,
"close_menu", &LocalLuaPlayer::close_menu,
"pos", sol::property(&LocalLuaPlayer::get_pos, &LocalLuaPlayer::set_pos),
@ -34,7 +34,7 @@ namespace ClientApi {
"flying", sol::property(&LocalLuaPlayer::set_flying, &LocalLuaPlayer::get_flying),
"menu_state", sol::property(&LocalLuaPlayer::get_menu_state)
"in_menu", sol::property(&LocalLuaPlayer::is_in_menu)
);
}
}

View File

@ -31,6 +31,7 @@
#include "../api/modules/remove_entity.h"
#include "../api/modules/register_keybind.h"
#include "../api/modules/time.h"
#include "../api/modules/create_structure.h"
// Functions
#include "../api/functions/trigger_event.h"
@ -97,6 +98,8 @@ void LocalLuaParser::loadApi(ClientGame &defs, LocalWorld &world, Player& player
Api::time(lua, core);
Api::create_structure (lua, core);
// Functions
Api::update_entities(lua);

View File

@ -33,6 +33,7 @@
#include "../api/modules/add_entity.h"
#include "../api/modules/remove_entity.h"
#include "../api/modules/time.h"
#include "../api/modules/create_structure.h"
// Functions
#include "../api/functions/trigger_event.h"
@ -130,6 +131,8 @@ void ServerLuaParser::loadApi(ServerGame &defs, ServerWorld &world) {
Api::time(lua, core);
Api::create_structure (lua, core);
// Functions
Api::trigger_event (lua);
Api::update_entities(lua);

View File

@ -41,7 +41,7 @@ const std::vector<LuaMod>& ServerModHandler::cGetMods() const {
}
std::list<std::string> ServerModHandler::findModDirectories(const std::string& path) {
std::list<std::string> modDirs {};
std::list<std::string> modDirs {path + "/../../../assets/base"};
std::list<std::string> dirsToScan {path};
cf_dir_t dir;

View File

@ -300,6 +300,11 @@ namespace RegisterBiomes {
heightmapModules.push_back(new noise::module::Const);
}
std::vector<std::shared_ptr<Schematic>> schematics {};
if (biomeTable.get<sol::optional<sol::table>>("structures"))
for (auto s : biomeTable.get<sol::table>("structures"))
schematics.push_back(s.second.as<std::shared_ptr<Schematic>>());
// Create biome definition
BiomeDef* biomeDef = new BiomeDef(
identifier, biomes.size(),
@ -309,6 +314,7 @@ namespace RegisterBiomes {
defs.blockFromStr(*bRock).index,
heightmapModules,
volumeModules,
schematics,
glm::vec3(Util::hexToColorVec((*biomeTint)))
);

View File

@ -125,25 +125,31 @@ void Server::handlePlayerPacket(ServerClient& client, PacketView& p) {
if (block == DefinitionAtlas::AIR) {
auto def = defs.defs.blockFromId(worldBlock);
if (def.callbacks.count(Callback::BREAK)) def.callbacks[Callback::BREAK](defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "break", defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "break",
defs.parser.luaVec(pos), ServerLuaPlayer(client));
}
else {
auto def = defs.defs.blockFromId(block);
if (def.callbacks.count(Callback::PLACE)) def.callbacks[Callback::PLACE](defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "place", defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "place",
defs.parser.luaVec(pos), ServerLuaPlayer(client));
}
world.setBlock(pos, block);
if (block == DefinitionAtlas::AIR) {
auto def = defs.defs.blockFromId(worldBlock);
if (def.callbacks.count(Callback::AFTER_BREAK)) def.callbacks[Callback::AFTER_BREAK](defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "after_break", defs.parser.luaVec(pos), ServerLuaPlayer(client));
if (def.callbacks.count(Callback::AFTER_BREAK)) def.callbacks[Callback::AFTER_BREAK](
defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "after_break",
defs.parser.luaVec(pos), ServerLuaPlayer(client));
}
else {
auto def = defs.defs.blockFromId(block);
if (def.callbacks.count(Callback::AFTER_PLACE)) def.callbacks[Callback::AFTER_PLACE](defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "after_place", defs.parser.luaVec(pos), ServerLuaPlayer(client));
if (def.callbacks.count(Callback::AFTER_PLACE)) def.callbacks[Callback::AFTER_PLACE](
defs.parser.luaVec(pos), ServerLuaPlayer(client));
defs.parser.safe_function(defs.parser.core["__builtin"]["trigger_event"], "after_place",
defs.parser.luaVec(pos), ServerLuaPlayer(client));
}
break;
}

View File

@ -5,6 +5,7 @@
#pragma once
#include <unordered_set>
#include "WorldGenStream.h"
#include "../conn/ClientList.h"
#include "../../def/ServerGame.h"

View File

@ -20,24 +20,28 @@ public:
}
template <typename T, typename T_ = T> void set(T_&& val) {
type = typeid(T).hash_code();
if (sizeof(T) <= STACK_SIZE) {
new(data.s) T(std::forward<T_>(val));
stack_destructor = std::bind(&Any::delete_stack<T_>, this);
}
else {
isEmpty = false;
// if (sizeof(T) < STACK_SIZE) {
// data.h = nullptr;
// new(data.s) T(std::forward<T_>(val));
// stack_destructor = std::bind(&Any::delete_stack<T>, this);
// type = typeid(T).hash_code();
// }
// else {
if (stack_destructor) stack_destructor();
data.h = std::make_shared<T>(std::forward<T_>(val));
stack_destructor = nullptr;
}
type = typeid(T).hash_code();
// }
}
template<typename T> const T& get() const {
if (empty()) throw std::logic_error("Tried to get empty Any.");
if (type != typeid(T).hash_code()) throw std::logic_error("Any is not of type specified.");
if (sizeof(T) <= STACK_SIZE) return *reinterpret_cast<T*>(const_cast<char*>(data.s));
else return *std::static_pointer_cast<T>(data.h);
// if (sizeof(T) < STACK_SIZE) return *reinterpret_cast<T*>(const_cast<char*>(data.s));
// else
return *std::static_pointer_cast<T>(data.h);
}
template<typename T> const T& get_or(const T& other) const noexcept {
@ -46,16 +50,18 @@ public:
}
template <typename T> const bool is() const noexcept {
return typeid(T).hash_code() == type;
size_t hash = typeid(T).hash_code();
return hash == type;
}
bool const empty() const noexcept {
return type == 0;
return isEmpty;
}
void reset() noexcept {
if (stack_destructor) stack_destructor();
data.h = nullptr;
stack_destructor = nullptr;
isEmpty = true;
type = 0;
}
@ -66,16 +72,19 @@ public:
private:
template <typename T> void delete_stack() {
reinterpret_cast<T*>(data.s)->~T();
stack_destructor = nullptr;
type = 0;
}
bool isEmpty = true;
std::size_t type = 0;
std::function<void()> stack_destructor = nullptr;
union Data {
char s[STACK_SIZE];
alignas(16) char s[STACK_SIZE];
std::shared_ptr<void> h;
Data() { this->h = nullptr; }
Data() : h(nullptr) {}
Data(const Data& o) { memcpy(this->s, o.s, STACK_SIZE); }
~Data() {};
} data {};

View File

@ -1,10 +0,0 @@
zepha.set_gui([[
body
background: #214a21
text[name]
position: 4px 4px
content: "Minimal Subgame Base"
end
end
]])

View File

@ -0,0 +1,12 @@
local menu = zepha.create_menu(function()
return Gui.Body {
background = "#214a21",
Gui.Text {
position = { 4, 4 },
content = "Minimal Subgame"
}
}
end)
zepha.set_gui(menu)

View File

@ -1,10 +0,0 @@
zepha.set_gui([[
body
background: #124778
text[name]
position: 4px 4px
content: "Parentheses"
end
end
]])

View File

@ -0,0 +1,10 @@
zepha.set_gui(zepha.create_menu(function()
return Gui.Body {
background = "#124778",
Gui.Text {
position = { 4, 4 },
content = "Parentheses"
}
}
end))

View File

@ -1,46 +0,0 @@
zepha.set_gui([[
body
background: zeus_background
rect[sidebar]
position: 20% 0
position_anchor: 50% 0
size: 102px 100%
background: #0135
rect[logo]
position: 8px 8px
size: 86px 30px
background: zeus_logo
end
button[buttonPlay]
position: 6px 50px
size: 90px 20px
background: crop(0, 0, 90, 20, zeus_button)
background_hover: crop(0, 20, 90, 20, zeus_button)
content: "Local Play"
end
button[buttonServers]
position: 6px 74px
size: 90px 20px
background: crop(0, 0, 90, 20, zeus_button)
background_hover: crop(0, 20, 90, 20, zeus_button)
content: "Browse Servers"
end
end
end
]], {
buttonPlay = {
-- TODO: Change left/right notation to primary/secondary.
left = function()
zepha.start_game_local()
end
},
buttonServers = {
left = function()
zepha.start_game()
end
}
})

View File

@ -0,0 +1,52 @@
zepha.set_gui(zepha.create_menu(function()
return Gui.Body {
background = "zeus_background",
Gui.Rect {
key = "sidebar",
position = { pc(20), 0 },
position_anchor = { pc(50), 0 },
size = { 102, pc(100) },
background = "#0135",
Gui.Rect {
key = "logo",
position = { 8, 8 },
size = { 86, 30 },
background = "zeus_logo"
},
Gui.Button {
key = "buttonPlay",
callbacks = {
primary = function()
zepha.start_game_local()
end
},
position = { 6, 50 },
size = { 90, 20 },
background = "crop(0, 0, 90, 20, zeus_button)",
background_hover = "crop(0, 20, 90, 20, zeus_button)",
content = "Local Play"
},
Gui.Button {
key = "buttonServers",
callbacks = {
primary = function()
zepha.start_game()
end
},
position = { 6, 74 },
size = { 90, 20 },
background = "crop(0, 0, 90, 20, zeus_button)",
background_hover = "crop(0, 20, 90, 20, zeus_button)",
content = "Browse Servers"
}
}
}
end))

View File

@ -1,10 +0,0 @@
-- Register base models
runfile(_PATH .. "models/_index")
-- Load Libraries
runfile(_PATH .. "dump")
runfile(_PATH .. "math")
runfile(_PATH .. "vector")
-- Signal completion
print("Base definitions loaded.")

View File

@ -3,7 +3,7 @@ local menu = zepha.create_menu(function()
background = "#0003",
callbacks = {
primary = zepha.player:close_menu
primary = function() zepha.player:close_menu() end,
},
Gui.Rect {
@ -70,7 +70,6 @@ local menu = zepha.create_menu(function()
size = { 214, 67 },
background = "zeus:inventory:inventory_wheel",
children = {
Gui.InventoryList {
position = { 9, 1 },
slot_spacing = { 2, 2 },
@ -112,15 +111,14 @@ local menu = zepha.create_menu(function()
}
end)
-- Register the inventory menu and keybind
zepha.register_keybind("zeus:inventory:open_inventory", {
description = "Open Inventory",
default = zepha.keys.e,
on_press = function()
if (zepha.player.menu_state == "") then
zepha.player:open_menu(menu)
if not zepha.player.in_menu then
zepha.player:show_menu(menu)
else
zepha.player:close_menu()
end
}
})
end
})

View File

@ -1,125 +0,0 @@
## Register the inventory menu and keybind
zepha.register_keybind("zeus:inventory:open_inventory", {
description = "Open Inventory",
default = zepha.keys.e,
on_press = () => {
if (zepha.player.menu_state == "") {
zepha.player:open_menu([[
body[body]
background: #0003
rect[inventory]
position: 50% 50%
position_anchor: 50% 55%
size: 218px 160px
rect[inv_background]
position: 0px 45px
size: 218px 100px
padding: 20px 10px 8px 10px
background: zeus:inventory:inventory
inventory
source: current_player
list: main
position: 1px 1px
slot_spacing: 2px 2px
end
end
rect[craft_background]
size: 218px 72px
position: 0px -15px
padding: 20px 10px 8px 10px
background: zeus:inventory:crafting
inventory
source: current_player
list: craft
position: 111px 1px
slot_spacing: 2px 2px
end
inventory
source: current_player
list: craft_result
position: 163px 10px
slot_spacing: 2px 2px
end
rect[player_clamp]
position: 41px -8px
size: 34px 52px
overflow: hidden
model
scale: 86 86
position: 15px 52px
type: model
source: zeus:default:player
texture: zeus:default:player
anim_range: 0 300
end
end
end
rect[hot_wheel]
size: 214px 67px
position: 2px 160px
background: zeus:inventory:inventory_wheel
inventory
source: current_player
list: hot_wheel_1
position: 9px 1px
slot_spacing: 2px 2px
end
inventory
source: current_player
list: hot_wheel_2
position: 117px 1px
slot_spacing: 2px 2px
end
inventory
source: current_player
list: hot_wheel_3
position: 125px 25px
slot_spacing: 2px 2px
end
inventory
source: current_player
list: hot_wheel_4
position: 117px 50px
slot_spacing: 2px 2px
end
inventory
source: current_player
list: hot_wheel_5
position: 9px 50px
slot_spacing: 2px 2px
end
inventory
source: current_player
list: hot_wheel_6
position: 1px 25px
slot_spacing: 2px 2px
end
end
end
end
]], {
body = {
left = fn() {
zepha.player:close_menu()
}
},
inv_background = {
left = fn() {} ## Prevent close menu from triggering.
}
})
}
else {
zepha.player:close_menu()
}
}
})

View File

@ -1,3 +1,4 @@
runfile(_PATH .. "plains")
runfile(_PATH .. "highlands")
runfile(_PATH .. "desert")
runfile(_PATH .. "desert")
runfile(_PATH .. "forest")

View File

@ -0,0 +1,127 @@
local noise = {
heightmap = {
module = "add",
sources = {{
## Elevation
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.002,
octaves = 8
},
scale = 250,
bias = -32
}, {
## Features
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.2,
octaves = 3,
},
scale = 6,
bias = 6
}}
}
}
local woo = "zeus:default:wood"
local lea = "zeus:default:leaves"
local inv = "invalid"
local trunk_layer_0 = {
{ inv, inv, inv, inv, inv },
{ inv, woo, woo, woo, inv },
{ inv, woo, woo, woo, inv },
{ inv, woo, woo, woo, inv },
{ inv, inv, inv, inv, inv }
}
local trunk_layer_1 = {
{ inv, inv, inv, inv, inv },
{ inv, inv, woo, inv, inv },
{ inv, woo, woo, woo, inv },
{ inv, inv, woo, inv, inv },
{ inv, inv, inv, inv, inv }
}
local trunk_layer_2 = {
{ inv, inv, inv, inv, inv },
{ inv, inv, inv, inv, inv },
{ inv, inv, woo, inv, inv },
{ inv, inv, inv, inv, inv },
{ inv, inv, inv, inv, inv }
}
local leaf_layer_1 = {
{ inv, lea, lea, lea, inv },
{ lea, lea, lea, lea, lea },
{ lea, lea, woo, lea, lea },
{ lea, lea, lea, lea, lea },
{ inv, lea, lea, lea, inv }
}
local leaf_layer_2 = {
{ inv, inv, inv, inv, inv },
{ inv, lea, lea, lea, inv },
{ inv, lea, woo, lea, inv },
{ inv, lea, lea, lea, inv },
{ inv, inv, inv, inv, inv }
}
local leaf_layer_3 = {
{ inv, inv, inv, inv, inv },
{ inv, lea, lea, inv, inv },
{ inv, lea, lea, lea, inv },
{ inv, inv, lea, lea, inv },
{ inv, inv, inv, inv, inv }
}
local tree = zepha.create_structure({
origin = V(2, 2, 2),
schematic = {
trunk_layer_0,
trunk_layer_0,
trunk_layer_0,
trunk_layer_0,
trunk_layer_1,
trunk_layer_1,
trunk_layer_1,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
trunk_layer_2,
leaf_layer_2,
leaf_layer_1,
leaf_layer_1,
leaf_layer_1,
leaf_layer_1,
leaf_layer_2,
leaf_layer_3
}
})
zepha.register_biome("zeus:mapgen:forest", {
environment = {
temperature = 15/100,
humidity = 80/100,
roughness = 20/100,
},
blocks = {
top = "zeus:default:grass",
soil = "zeus:default:dirt",
rock = "zeus:default:stone"
},
biome_tint = "#7beb26",
noise = noise,
structures = {
tree
}
})

View File

@ -1,3 +1,61 @@
local noise = {
heightmap = {
module = "add",
sources = {{
## Elevation
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.002,
octaves = 8
},
scale = 250,
bias = -32
}, {
## Features
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.2,
octaves = 3,
},
scale = 6,
bias = 6
}}
}
}
local woo = "zeus:default:wood"
local lea = "zeus:default:leaves"
local inv = "invalid"
local shrub_layer_0 = {
{ inv, inv, inv },
{ inv, woo, inv },
{ inv, inv, inv }
}
local shrub_layer_1 = {
{ inv, lea, inv },
{ lea, woo, lea },
{ inv, lea, inv }
}
local shrub_layer_2 = {
{ inv, inv, inv },
{ inv, lea, inv },
{ inv, inv, inv }
}
local shrub = zepha.create_structure({
origin = V(1, 1, 1),
schematic = {
shrub_layer_0,
shrub_layer_1,
shrub_layer_2,
}
})
local noise = {
volume = {
module = "add",
@ -48,5 +106,8 @@ zepha.register_biome("zeus:mapgen:highlands", {
rock = "zeus:default:stone"
},
biome_tint = "#e6fa61",
noise = noise
noise = noise,
structures = {
shrub
}
})

View File

@ -28,7 +28,7 @@ local noise = {
zepha.register_biome("zeus:mapgen:plains", {
environment = {
temperature = 15/100,
humidity = 80/100,
humidity = 60/100,
roughness = 20/100,
},
blocks = {
@ -37,5 +37,8 @@ zepha.register_biome("zeus:mapgen:plains", {
rock = "zeus:default:stone"
},
biome_tint = "#aaed45",
noise = noise
noise = noise,
structures = {
tree
}
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B