Merge branch 'main' of https://github.com/MihailRis/VoxelEngine-Cpp
This commit is contained in:
+12
-12
@@ -18,8 +18,8 @@ Texture* Assets::getTexture(std::string name) const {
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
void Assets::store(Texture* texture, std::string name){
|
||||
textures.emplace(name, texture);
|
||||
void Assets::store(std::unique_ptr<Texture> texture, std::string name){
|
||||
textures.emplace(name, std::move(texture));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ Shader* Assets::getShader(std::string name) const{
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
void Assets::store(Shader* shader, std::string name){
|
||||
shaders.emplace(name, shader);
|
||||
void Assets::store(std::unique_ptr<Shader> shader, std::string name){
|
||||
shaders.emplace(name, std::move(shader));
|
||||
}
|
||||
|
||||
Font* Assets::getFont(std::string name) const {
|
||||
@@ -41,8 +41,8 @@ Font* Assets::getFont(std::string name) const {
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
void Assets::store(Font* font, std::string name){
|
||||
fonts.emplace(name, font);
|
||||
void Assets::store(std::unique_ptr<Font> font, std::string name){
|
||||
fonts.emplace(name, std::move(font));
|
||||
}
|
||||
|
||||
Atlas* Assets::getAtlas(std::string name) const {
|
||||
@@ -52,8 +52,8 @@ Atlas* Assets::getAtlas(std::string name) const {
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
void Assets::store(Atlas* atlas, std::string name){
|
||||
atlases.emplace(name, atlas);
|
||||
void Assets::store(std::unique_ptr<Atlas> atlas, std::string name){
|
||||
atlases.emplace(name, std::move(atlas));
|
||||
}
|
||||
|
||||
audio::Sound* Assets::getSound(std::string name) const {
|
||||
@@ -63,8 +63,8 @@ audio::Sound* Assets::getSound(std::string name) const {
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
void Assets::store(audio::Sound* sound, std::string name) {
|
||||
sounds.emplace(name, sound);
|
||||
void Assets::store(std::unique_ptr<audio::Sound> sound, std::string name) {
|
||||
sounds.emplace(name, std::move(sound));
|
||||
}
|
||||
|
||||
const std::vector<TextureAnimation>& Assets::getAnimations() {
|
||||
@@ -82,6 +82,6 @@ UiDocument* Assets::getLayout(std::string name) const {
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
void Assets::store(UiDocument* layout, std::string name) {
|
||||
layouts[name] = std::shared_ptr<UiDocument>(layout);
|
||||
void Assets::store(std::unique_ptr<UiDocument> layout, std::string name) {
|
||||
layouts[name] = std::shared_ptr<UiDocument>(std::move(layout));
|
||||
}
|
||||
|
||||
@@ -39,25 +39,25 @@ public:
|
||||
~Assets();
|
||||
|
||||
Texture* getTexture(std::string name) const;
|
||||
void store(Texture* texture, std::string name);
|
||||
void store(std::unique_ptr<Texture> texture, std::string name);
|
||||
|
||||
Shader* getShader(std::string name) const;
|
||||
void store(Shader* shader, std::string name);
|
||||
void store(std::unique_ptr<Shader> shader, std::string name);
|
||||
|
||||
Font* getFont(std::string name) const;
|
||||
void store(Font* font, std::string name);
|
||||
void store(std::unique_ptr<Font> font, std::string name);
|
||||
|
||||
Atlas* getAtlas(std::string name) const;
|
||||
void store(Atlas* atlas, std::string name);
|
||||
void store(std::unique_ptr<Atlas> atlas, std::string name);
|
||||
|
||||
audio::Sound* getSound(std::string name) const;
|
||||
void store(audio::Sound* sound, std::string name);
|
||||
void store(std::unique_ptr<audio::Sound> sound, std::string name);
|
||||
|
||||
const std::vector<TextureAnimation>& getAnimations();
|
||||
void store(const TextureAnimation& animation);
|
||||
|
||||
UiDocument* getLayout(std::string name) const;
|
||||
void store(UiDocument* layout, std::string name);
|
||||
void store(std::unique_ptr<UiDocument> layout, std::string name);
|
||||
};
|
||||
|
||||
#endif // ASSETS_ASSETS_HPP_
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "../files/engine_paths.hpp"
|
||||
#include "../content/Content.hpp"
|
||||
#include "../content/ContentPack.hpp"
|
||||
#include "../voxels/Block.hpp"
|
||||
#include "../graphics/core/Texture.hpp"
|
||||
#include "../logic/scripting/scripting.hpp"
|
||||
|
||||
@@ -187,7 +188,7 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
||||
loader.processPreloadConfigs(content);
|
||||
|
||||
for (auto& entry : content->getBlockMaterials()) {
|
||||
auto& material = entry.second;
|
||||
auto& material = *entry.second;
|
||||
loader.tryAddSound(material.stepsSound);
|
||||
loader.tryAddSound(material.placeSound);
|
||||
loader.tryAddSound(material.breakSound);
|
||||
@@ -217,7 +218,7 @@ bool AssetsLoader::loadExternalTexture(
|
||||
if (fs::exists(path)) {
|
||||
try {
|
||||
auto image = imageio::read(path.string());
|
||||
assets->store(Texture::from(image.get()).release(), name);
|
||||
assets->store(Texture::from(image.get()), name);
|
||||
return true;
|
||||
} catch (const std::exception& err) {
|
||||
logger.error() << "error while loading external "
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "../audio/audio.hpp"
|
||||
#include "../files/files.hpp"
|
||||
#include "../files/engine_paths.hpp"
|
||||
#include "../coders/commons.hpp"
|
||||
#include "../coders/imageio.hpp"
|
||||
#include "../coders/json.hpp"
|
||||
#include "../coders/GLSLExtension.hpp"
|
||||
@@ -43,7 +44,7 @@ assetload::postfunc assetload::texture(
|
||||
imageio::read(paths->find(filename+".png").u8string()).release()
|
||||
);
|
||||
return [name, image](auto assets) {
|
||||
assets->store(Texture::from(image.get()).release(), name);
|
||||
assets->store(Texture::from(image.get()), name);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ assetload::postfunc assetload::atlas(
|
||||
Atlas* atlas = builder.build(2, false).release();
|
||||
return [=](auto assets) {
|
||||
atlas->prepare();
|
||||
assets->store(atlas, name);
|
||||
assets->store(std::unique_ptr<Atlas>(atlas), name);
|
||||
for (const auto& file : names) {
|
||||
animation(assets, paths, name, directory, file, atlas);
|
||||
}
|
||||
@@ -128,7 +129,7 @@ assetload::postfunc assetload::font(
|
||||
for (auto& page : *pages) {
|
||||
textures.emplace_back(Texture::from(page.get()));
|
||||
}
|
||||
assets->store(new Font(std::move(textures), res, 4), name);
|
||||
assets->store(std::make_unique<Font>(std::move(textures), res, 4), name);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -142,8 +143,7 @@ assetload::postfunc assetload::layout(
|
||||
return [=](auto assets) {
|
||||
try {
|
||||
auto cfg = std::dynamic_pointer_cast<LayoutCfg>(config);
|
||||
auto document = UiDocument::read(cfg->env, name, file);
|
||||
assets->store(document.release(), name);
|
||||
assets->store(UiDocument::read(cfg->env, name, file), name);
|
||||
} catch (const parsing_error& err) {
|
||||
throw std::runtime_error(
|
||||
"failed to parse layout XML '"+file+"':\n"+err.errorLog()
|
||||
@@ -189,7 +189,7 @@ assetload::postfunc assetload::sound(
|
||||
}
|
||||
auto sound = baseSound.release();
|
||||
return [=](auto assets) {
|
||||
assets->store(sound, name);
|
||||
assets->store(std::unique_ptr<audio::Sound>(sound), name);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ static bool animation(
|
||||
auto animation = create_animation(
|
||||
srcAtlas.get(), dstAtlas, name, builder.getNames(), frameList
|
||||
);
|
||||
assets->store(srcAtlas.release(), atlasName + "/" + name + "_animation");
|
||||
assets->store(std::move(srcAtlas), atlasName + "/" + name + "_animation");
|
||||
assets->store(animation);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ std::unique_ptr<Stream> ALAudio::openStream(std::shared_ptr<PCMStream> stream, b
|
||||
return std::make_unique<ALStream>(this, stream, keepSource);
|
||||
}
|
||||
|
||||
ALAudio* ALAudio::create() {
|
||||
std::unique_ptr<ALAudio> ALAudio::create() {
|
||||
ALCdevice* device = alcOpenDevice(nullptr);
|
||||
if (device == nullptr)
|
||||
return nullptr;
|
||||
@@ -400,7 +400,7 @@ ALAudio* ALAudio::create() {
|
||||
}
|
||||
AL_CHECK();
|
||||
logger.info() << "initialized";
|
||||
return new ALAudio(device, context);
|
||||
return std::make_unique<ALAudio>(device, context);
|
||||
}
|
||||
|
||||
uint ALAudio::getFreeSource(){
|
||||
|
||||
@@ -136,9 +136,8 @@ namespace audio {
|
||||
std::vector<uint> freebuffers;
|
||||
|
||||
uint maxSources = 256;
|
||||
|
||||
ALAudio(ALCdevice* device, ALCcontext* context);
|
||||
public:
|
||||
ALAudio(ALCdevice* device, ALCcontext* context);
|
||||
~ALAudio();
|
||||
|
||||
uint getFreeSource();
|
||||
@@ -164,7 +163,7 @@ namespace audio {
|
||||
return false;
|
||||
}
|
||||
|
||||
static ALAudio* create();
|
||||
static std::unique_ptr<ALAudio> create();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,6 @@ std::unique_ptr<Stream> NoAudio::openStream(std::shared_ptr<PCMStream> stream, b
|
||||
return std::make_unique<NoStream>(stream, keepSource);
|
||||
}
|
||||
|
||||
NoAudio* NoAudio::create() {
|
||||
return new NoAudio();
|
||||
std::unique_ptr<NoAudio> NoAudio::create() {
|
||||
return std::make_unique<NoAudio>();
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace audio {
|
||||
return true;
|
||||
}
|
||||
|
||||
static NoAudio* create();
|
||||
static std::unique_ptr<NoAudio> create();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -147,11 +147,11 @@ public:
|
||||
|
||||
void audio::initialize(bool enabled) {
|
||||
if (enabled) {
|
||||
backend = ALAudio::create();
|
||||
backend = ALAudio::create().release();
|
||||
}
|
||||
if (backend == nullptr) {
|
||||
std::cerr << "could not to initialize audio" << std::endl;
|
||||
backend = NoAudio::create();
|
||||
backend = NoAudio::create().release();
|
||||
}
|
||||
create_channel("master");
|
||||
}
|
||||
@@ -333,7 +333,7 @@ int audio::create_channel(const std::string& name) {
|
||||
if (index != -1) {
|
||||
return index;
|
||||
}
|
||||
channels.emplace_back(new Channel(name));
|
||||
channels.emplace_back(std::make_unique<Channel>(name));
|
||||
return channels.size()-1;
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -11,20 +11,20 @@ namespace dynamic {
|
||||
}
|
||||
|
||||
namespace json {
|
||||
const int BJSON_END = 0x0;
|
||||
const int BJSON_TYPE_DOCUMENT = 0x1;
|
||||
const int BJSON_TYPE_LIST = 0x2;
|
||||
const int BJSON_TYPE_BYTE = 0x3;
|
||||
const int BJSON_TYPE_INT16 = 0x4;
|
||||
const int BJSON_TYPE_INT32 = 0x5;
|
||||
const int BJSON_TYPE_INT64 = 0x6;
|
||||
const int BJSON_TYPE_NUMBER = 0x7;
|
||||
const int BJSON_TYPE_STRING = 0x8;
|
||||
const int BJSON_TYPE_BYTES = 0x9;
|
||||
const int BJSON_TYPE_FALSE = 0xA;
|
||||
const int BJSON_TYPE_TRUE = 0xB;
|
||||
const int BJSON_TYPE_NULL = 0xC;
|
||||
const int BJSON_TYPE_CDOCUMENT = 0x1F;
|
||||
inline constexpr int BJSON_END = 0x0;
|
||||
inline constexpr int BJSON_TYPE_DOCUMENT = 0x1;
|
||||
inline constexpr int BJSON_TYPE_LIST = 0x2;
|
||||
inline constexpr int BJSON_TYPE_BYTE = 0x3;
|
||||
inline constexpr int BJSON_TYPE_INT16 = 0x4;
|
||||
inline constexpr int BJSON_TYPE_INT32 = 0x5;
|
||||
inline constexpr int BJSON_TYPE_INT64 = 0x6;
|
||||
inline constexpr int BJSON_TYPE_NUMBER = 0x7;
|
||||
inline constexpr int BJSON_TYPE_STRING = 0x8;
|
||||
inline constexpr int BJSON_TYPE_BYTES = 0x9;
|
||||
inline constexpr int BJSON_TYPE_FALSE = 0xA;
|
||||
inline constexpr int BJSON_TYPE_TRUE = 0xB;
|
||||
inline constexpr int BJSON_TYPE_NULL = 0xC;
|
||||
inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F;
|
||||
|
||||
extern std::vector<ubyte> to_binary(const dynamic::Map* obj, bool compress=false);
|
||||
extern std::shared_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
|
||||
|
||||
+4
-2
@@ -1,5 +1,7 @@
|
||||
#include "json.hpp"
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
#include "../data/dynamic.hpp"
|
||||
#include "../util/stringutil.hpp"
|
||||
|
||||
@@ -240,11 +242,11 @@ Value Parser::parseValue() {
|
||||
throw error("unexpected character '"+std::string({next})+"'");
|
||||
}
|
||||
|
||||
std::unique_ptr<Map> json::parse(const std::string& filename, const std::string& source) {
|
||||
dynamic::Map_sptr json::parse(const std::string& filename, const std::string& source) {
|
||||
Parser parser(filename, source);
|
||||
return parser.parse();
|
||||
}
|
||||
|
||||
std::unique_ptr<Map> json::parse(const std::string& source) {
|
||||
dynamic::Map_sptr json::parse(const std::string& source) {
|
||||
return parse("<string>", source);
|
||||
}
|
||||
|
||||
+4
-9
@@ -1,25 +1,20 @@
|
||||
#ifndef CODERS_JSON_HPP_
|
||||
#define CODERS_JSON_HPP_
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "binary_json.hpp"
|
||||
|
||||
#include "../data/dynamic.hpp"
|
||||
#include "../typedefs.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace json {
|
||||
std::unique_ptr<dynamic::Map> parse(const std::string& filename, const std::string& source);
|
||||
std::unique_ptr<dynamic::Map> parse(const std::string& source);
|
||||
dynamic::Map_sptr parse(const std::string& filename, const std::string& source);
|
||||
dynamic::Map_sptr parse(const std::string& source);
|
||||
|
||||
std::string stringify(
|
||||
const dynamic::Map* obj,
|
||||
bool nice,
|
||||
const dynamic::Map* obj,
|
||||
bool nice,
|
||||
const std::string& indent
|
||||
);
|
||||
|
||||
|
||||
+90
-38
@@ -7,15 +7,14 @@
|
||||
#include "../files/settings_io.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace toml;
|
||||
|
||||
class Reader : BasicParser {
|
||||
SettingsHandler& handler;
|
||||
class TomlReader : BasicParser {
|
||||
dynamic::Map_sptr root;
|
||||
|
||||
void skipWhitespace() override {
|
||||
BasicParser::skipWhitespace();
|
||||
@@ -26,7 +25,34 @@ class Reader : BasicParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
void readSection(const std::string& section) {
|
||||
|
||||
dynamic::Map& getSection(const std::string& section) {
|
||||
if (section.empty()) {
|
||||
return *root;
|
||||
}
|
||||
size_t offset = 0;
|
||||
auto& rootMap = *root;
|
||||
do {
|
||||
size_t index = section.find('.', offset);
|
||||
if (index == std::string::npos) {
|
||||
auto map = rootMap.map(section);
|
||||
if (map == nullptr) {
|
||||
return rootMap.putMap(section);
|
||||
}
|
||||
return *map;
|
||||
}
|
||||
auto subsection = section.substr(offset, index);
|
||||
auto map = rootMap.map(subsection);
|
||||
if (map == nullptr) {
|
||||
rootMap = rootMap.putMap(subsection);
|
||||
} else {
|
||||
rootMap = *map;
|
||||
}
|
||||
offset = index+1;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void readSection(const std::string& section, dynamic::Map& map) {
|
||||
while (hasNext()) {
|
||||
skipWhitespace();
|
||||
if (!hasNext()) {
|
||||
@@ -36,43 +62,31 @@ class Reader : BasicParser {
|
||||
if (c == '[') {
|
||||
std::string name = parseName();
|
||||
pos++;
|
||||
readSection(name);
|
||||
readSection(name, getSection(name));
|
||||
return;
|
||||
}
|
||||
pos--;
|
||||
std::string name = section+"."+parseName();
|
||||
std::string name = parseName();
|
||||
expect('=');
|
||||
c = peek();
|
||||
if (is_digit(c)) {
|
||||
auto num = parseNumber(1);
|
||||
if (handler.has(name)) {
|
||||
handler.setValue(name, num);
|
||||
}
|
||||
map.put(name, parseNumber(1));
|
||||
} else if (c == '-' || c == '+') {
|
||||
int sign = c == '-' ? -1 : 1;
|
||||
pos++;
|
||||
auto num = parseNumber(sign);
|
||||
if (handler.has(name)) {
|
||||
handler.setValue(name, num);
|
||||
}
|
||||
map.put(name, parseNumber(sign));
|
||||
} else if (is_identifier_start(c)) {
|
||||
std::string identifier = parseName();
|
||||
if (handler.has(name)) {
|
||||
if (identifier == "true" || identifier == "false") {
|
||||
bool flag = identifier == "true";
|
||||
handler.setValue(name, flag);
|
||||
} else if (identifier == "inf") {
|
||||
handler.setValue(name, INFINITY);
|
||||
} else if (identifier == "nan") {
|
||||
handler.setValue(name, NAN);
|
||||
}
|
||||
if (identifier == "true" || identifier == "false") {
|
||||
map.put(name, identifier == "true");
|
||||
} else if (identifier == "inf") {
|
||||
map.put(name, INFINITY);
|
||||
} else if (identifier == "nan") {
|
||||
map.put(name, NAN);
|
||||
}
|
||||
} else if (c == '"' || c == '\'') {
|
||||
pos++;
|
||||
std::string str = parseString(c);
|
||||
if (handler.has(name)) {
|
||||
handler.setValue(name, str);
|
||||
}
|
||||
map.put(name, parseString(c));
|
||||
} else {
|
||||
throw error("feature is not supported");
|
||||
}
|
||||
@@ -81,29 +95,67 @@ class Reader : BasicParser {
|
||||
}
|
||||
|
||||
public:
|
||||
Reader(
|
||||
SettingsHandler& handler,
|
||||
TomlReader(
|
||||
std::string_view file,
|
||||
std::string_view source)
|
||||
: BasicParser(file, source), handler(handler) {
|
||||
: BasicParser(file, source) {
|
||||
root = dynamic::create_map();
|
||||
}
|
||||
|
||||
void read() {
|
||||
dynamic::Map_sptr read() {
|
||||
skipWhitespace();
|
||||
if (!hasNext()) {
|
||||
return;
|
||||
return root;
|
||||
}
|
||||
readSection("");
|
||||
readSection("", *root);
|
||||
return root;
|
||||
}
|
||||
};
|
||||
|
||||
dynamic::Map_sptr toml::parse(std::string_view file, std::string_view source) {
|
||||
return TomlReader(file, source).read();
|
||||
}
|
||||
|
||||
void toml::parse(
|
||||
SettingsHandler& handler,
|
||||
const std::string& file,
|
||||
const std::string& source
|
||||
SettingsHandler& handler, std::string_view file, std::string_view source
|
||||
) {
|
||||
Reader reader(handler, file, source);
|
||||
reader.read();
|
||||
auto map = parse(file, source);
|
||||
for (auto& entry : map->values) {
|
||||
const auto& sectionName = entry.first;
|
||||
auto sectionMap = std::get_if<dynamic::Map_sptr>(&entry.second);
|
||||
if (sectionMap == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (auto& sectionEntry : (*sectionMap)->values) {
|
||||
const auto& name = sectionEntry.first;
|
||||
auto& value = sectionEntry.second;
|
||||
auto fullname = sectionName+"."+name;
|
||||
if (handler.has(fullname)) {
|
||||
handler.setValue(fullname, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string toml::stringify(dynamic::Map& root, const std::string& name) {
|
||||
std::stringstream ss;
|
||||
if (!name.empty()) {
|
||||
ss << "[" << name << "]\n";
|
||||
}
|
||||
for (auto& entry : root.values) {
|
||||
if (!std::holds_alternative<dynamic::Map_sptr>(entry.second)) {
|
||||
ss << entry.first << " = ";
|
||||
ss << entry.second << "\n";
|
||||
}
|
||||
}
|
||||
for (auto& entry : root.values) {
|
||||
if (auto submap = std::get_if<dynamic::Map_sptr>(&entry.second)) {
|
||||
ss << "\n" << toml::stringify(
|
||||
**submap, name.empty() ? entry.first : name+"."+entry.first
|
||||
);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string toml::stringify(SettingsHandler& handler) {
|
||||
|
||||
+5
-4
@@ -1,19 +1,20 @@
|
||||
#ifndef CODERS_TOML_HPP_
|
||||
#define CODERS_TOML_HPP_
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
#include "../data/dynamic.hpp"
|
||||
#include <string>
|
||||
|
||||
class SettingsHandler;
|
||||
|
||||
namespace toml {
|
||||
std::string stringify(SettingsHandler& handler);
|
||||
std::string stringify(dynamic::Map& root, const std::string& name="");
|
||||
dynamic::Map_sptr parse(std::string_view file, std::string_view source);
|
||||
|
||||
void parse(
|
||||
SettingsHandler& handler,
|
||||
const std::string& file,
|
||||
const std::string& source
|
||||
std::string_view file,
|
||||
std::string_view source
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+11
-138
@@ -10,127 +10,6 @@
|
||||
#include "ContentPack.hpp"
|
||||
#include "../logic/scripting/scripting.hpp"
|
||||
|
||||
ContentBuilder::~ContentBuilder() {}
|
||||
|
||||
void ContentBuilder::add(Block* def) {
|
||||
checkIdentifier(def->name);
|
||||
blockDefs[def->name] = def;
|
||||
blockIds.push_back(def->name);
|
||||
}
|
||||
|
||||
void ContentBuilder::add(ItemDef* def) {
|
||||
checkIdentifier(def->name);
|
||||
itemDefs[def->name] = def;
|
||||
itemIds.push_back(def->name);
|
||||
}
|
||||
|
||||
void ContentBuilder::add(ContentPackRuntime* pack) {
|
||||
packs.emplace(pack->getId(), pack);
|
||||
}
|
||||
|
||||
void ContentBuilder::add(BlockMaterial material) {
|
||||
blockMaterials.emplace(material.name, material);
|
||||
}
|
||||
|
||||
Block& ContentBuilder::createBlock(std::string id) {
|
||||
auto found = blockDefs.find(id);
|
||||
if (found != blockDefs.end()) {
|
||||
return *found->second;
|
||||
// throw namereuse_error("name "+id+" is already used", contenttype::item);
|
||||
}
|
||||
Block* block = new Block(id);
|
||||
add(block);
|
||||
return *block;
|
||||
}
|
||||
|
||||
ItemDef& ContentBuilder::createItem(std::string id) {
|
||||
auto found = itemDefs.find(id);
|
||||
if (found != itemDefs.end()) {
|
||||
// if (found->second->generated) {
|
||||
return *found->second;
|
||||
// }
|
||||
// throw namereuse_error("name "+id+" is already used", contenttype::item);
|
||||
}
|
||||
ItemDef* item = new ItemDef(id);
|
||||
add(item);
|
||||
return *item;
|
||||
}
|
||||
|
||||
void ContentBuilder::checkIdentifier(std::string id) {
|
||||
contenttype result;
|
||||
if (((result = checkContentType(id)) != contenttype::none)) {
|
||||
throw namereuse_error("name "+id+" is already used", result);
|
||||
}
|
||||
}
|
||||
|
||||
contenttype ContentBuilder::checkContentType(std::string id) {
|
||||
if (blockDefs.find(id) != blockDefs.end()) {
|
||||
return contenttype::block;
|
||||
}
|
||||
if (itemDefs.find(id) != itemDefs.end()) {
|
||||
return contenttype::item;
|
||||
}
|
||||
return contenttype::none;
|
||||
}
|
||||
|
||||
Content* ContentBuilder::build() {
|
||||
std::vector<Block*> blockDefsIndices;
|
||||
auto groups = std::make_unique<DrawGroups>();
|
||||
for (const std::string& name : blockIds) {
|
||||
Block* def = blockDefs[name];
|
||||
|
||||
// Generating runtime info
|
||||
def->rt.id = blockDefsIndices.size();
|
||||
def->rt.emissive = *reinterpret_cast<uint32_t*>(def->emission);
|
||||
def->rt.solid = def->model == BlockModel::block;
|
||||
|
||||
if (def->rotatable) {
|
||||
for (uint i = 0; i < BlockRotProfile::MAX_COUNT; i++) {
|
||||
def->rt.hitboxes[i].reserve(def->hitboxes.size());
|
||||
for (AABB aabb : def->hitboxes) {
|
||||
def->rotations.variants[i].transform(aabb);
|
||||
def->rt.hitboxes[i].push_back(aabb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockDefsIndices.push_back(def);
|
||||
groups->insert(def->drawGroup);
|
||||
}
|
||||
|
||||
std::vector<ItemDef*> itemDefsIndices;
|
||||
for (const std::string& name : itemIds) {
|
||||
ItemDef* def = itemDefs[name];
|
||||
|
||||
// Generating runtime info
|
||||
def->rt.id = itemDefsIndices.size();
|
||||
def->rt.emissive = *reinterpret_cast<uint32_t*>(def->emission);
|
||||
itemDefsIndices.push_back(def);
|
||||
}
|
||||
|
||||
auto indices = new ContentIndices(blockDefsIndices, itemDefsIndices);
|
||||
|
||||
auto content = std::make_unique<Content>(
|
||||
indices,
|
||||
std::move(groups),
|
||||
blockDefs,
|
||||
itemDefs,
|
||||
std::move(packs),
|
||||
std::move(blockMaterials)
|
||||
);
|
||||
|
||||
// Now, it's time to resolve foreign keys
|
||||
for (Block* def : blockDefsIndices) {
|
||||
def->rt.pickingItem = content->requireItem(def->pickingItem).rt.id;
|
||||
}
|
||||
|
||||
for (ItemDef* def : itemDefsIndices) {
|
||||
def->rt.placingBlock = content->requireBlock(def->placingBlock).rt.id;
|
||||
}
|
||||
|
||||
return content.release();
|
||||
}
|
||||
|
||||
ContentIndices::ContentIndices(
|
||||
std::vector<Block*> blockDefs,
|
||||
std::vector<ItemDef*> itemDefs
|
||||
@@ -139,27 +18,21 @@ ContentIndices::ContentIndices(
|
||||
{}
|
||||
|
||||
Content::Content(
|
||||
ContentIndices* indices,
|
||||
std::unique_ptr<ContentIndices> indices,
|
||||
std::unique_ptr<DrawGroups> drawGroups,
|
||||
std::unordered_map<std::string, Block*> blockDefs,
|
||||
std::unordered_map<std::string, ItemDef*> itemDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
|
||||
std::unordered_map<std::string, BlockMaterial> blockMaterials
|
||||
) : blockDefs(blockDefs),
|
||||
itemDefs(itemDefs),
|
||||
indices(indices),
|
||||
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials
|
||||
) : blockDefs(std::move(blockDefs)),
|
||||
itemDefs(std::move(itemDefs)),
|
||||
indices(std::move(indices)),
|
||||
packs(std::move(packs)),
|
||||
blockMaterials(std::move(blockMaterials)),
|
||||
drawGroups(std::move(drawGroups))
|
||||
{}
|
||||
|
||||
Content::~Content() {
|
||||
for (auto& entry : blockDefs) {
|
||||
delete entry.second;
|
||||
}
|
||||
for (auto& entry : itemDefs) {
|
||||
delete entry.second;
|
||||
}
|
||||
}
|
||||
|
||||
Block* Content::findBlock(std::string id) const {
|
||||
@@ -167,7 +40,7 @@ Block* Content::findBlock(std::string id) const {
|
||||
if (found == blockDefs.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second;
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
Block& Content::requireBlock(std::string id) const {
|
||||
@@ -183,7 +56,7 @@ ItemDef* Content::findItem(std::string id) const {
|
||||
if (found == itemDefs.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second;
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
ItemDef& Content::requireItem(std::string id) const {
|
||||
@@ -199,7 +72,7 @@ const BlockMaterial* Content::findBlockMaterial(std::string id) const {
|
||||
if (found == blockMaterials.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &found->second;
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
const ContentPackRuntime* Content::getPackRuntime(std::string id) const {
|
||||
@@ -210,7 +83,7 @@ const ContentPackRuntime* Content::getPackRuntime(std::string id) const {
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, BlockMaterial>& Content::getBlockMaterials() const {
|
||||
const std::unordered_map<std::string, std::unique_ptr<BlockMaterial>>& Content::getBlockMaterials() const {
|
||||
return blockMaterials;
|
||||
}
|
||||
|
||||
|
||||
+12
-37
@@ -1,17 +1,19 @@
|
||||
#ifndef CONTENT_CONTENT_HPP_
|
||||
#define CONTENT_CONTENT_HPP_
|
||||
|
||||
#include "../typedefs.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include "../typedefs.hpp"
|
||||
#include "../voxels/Block.hpp"
|
||||
|
||||
using DrawGroups = std::set<ubyte>;
|
||||
|
||||
class Block;
|
||||
struct BlockMaterial;
|
||||
class ItemDef;
|
||||
class Content;
|
||||
class ContentPackRuntime;
|
||||
@@ -41,33 +43,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ContentBuilder {
|
||||
std::unordered_map<std::string, Block*> blockDefs;
|
||||
std::vector<std::string> blockIds;
|
||||
|
||||
std::unordered_map<std::string, ItemDef*> itemDefs;
|
||||
std::vector<std::string> itemIds;
|
||||
|
||||
std::unordered_map<std::string, BlockMaterial> blockMaterials;
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
||||
public:
|
||||
~ContentBuilder();
|
||||
|
||||
void add(Block* def);
|
||||
void add(ItemDef* def);
|
||||
void add(ContentPackRuntime* pack);
|
||||
void add(BlockMaterial material);
|
||||
|
||||
Block& createBlock(std::string id);
|
||||
ItemDef& createItem(std::string id);
|
||||
|
||||
void checkIdentifier(std::string id);
|
||||
contenttype checkContentType(std::string id);
|
||||
|
||||
Content* build();
|
||||
};
|
||||
|
||||
/// @brief Runtime defs cache: indices
|
||||
class ContentIndices {
|
||||
std::vector<Block*> blockDefs;
|
||||
@@ -110,21 +85,21 @@ public:
|
||||
|
||||
/* Content is a definitions repository */
|
||||
class Content {
|
||||
std::unordered_map<std::string, Block*> blockDefs;
|
||||
std::unordered_map<std::string, ItemDef*> itemDefs;
|
||||
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs;
|
||||
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs;
|
||||
std::unique_ptr<ContentIndices> indices;
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
||||
std::unordered_map<std::string, BlockMaterial> blockMaterials;
|
||||
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials;
|
||||
public:
|
||||
std::unique_ptr<DrawGroups> const drawGroups;
|
||||
|
||||
Content(
|
||||
ContentIndices* indices,
|
||||
std::unique_ptr<ContentIndices> indices,
|
||||
std::unique_ptr<DrawGroups> drawGroups,
|
||||
std::unordered_map<std::string, Block*> blockDefs,
|
||||
std::unordered_map<std::string, ItemDef*> itemDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
|
||||
std::unordered_map<std::string, BlockMaterial> blockMaterials
|
||||
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials
|
||||
);
|
||||
~Content();
|
||||
|
||||
@@ -142,7 +117,7 @@ public:
|
||||
|
||||
const ContentPackRuntime* getPackRuntime(std::string id) const;
|
||||
|
||||
const std::unordered_map<std::string, BlockMaterial>& getBlockMaterials() const;
|
||||
const std::unordered_map<std::string, std::unique_ptr<BlockMaterial>>& getBlockMaterials() const;
|
||||
const std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>>& getPacks() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#include "ContentBuilder.hpp"
|
||||
|
||||
ContentBuilder::~ContentBuilder() {}
|
||||
|
||||
void ContentBuilder::add(std::unique_ptr<ContentPackRuntime> pack) {
|
||||
packs[pack->getId()] = std::move(pack);
|
||||
}
|
||||
|
||||
Block& ContentBuilder::createBlock(std::string id) {
|
||||
auto found = blockDefs.find(id);
|
||||
if (found != blockDefs.end()) {
|
||||
return *found->second;
|
||||
}
|
||||
checkIdentifier(id);
|
||||
blockIds.push_back(id);
|
||||
blockDefs[id] = std::make_unique<Block>(id);
|
||||
return *blockDefs[id];
|
||||
}
|
||||
|
||||
ItemDef& ContentBuilder::createItem(std::string id) {
|
||||
auto found = itemDefs.find(id);
|
||||
if (found != itemDefs.end()) {
|
||||
return *found->second;
|
||||
}
|
||||
checkIdentifier(id);
|
||||
itemIds.push_back(id);
|
||||
itemDefs[id] = std::make_unique<ItemDef>(id);
|
||||
return *itemDefs[id];
|
||||
}
|
||||
|
||||
BlockMaterial& ContentBuilder::createBlockMaterial(std::string id) {
|
||||
blockMaterials[id] = std::make_unique<BlockMaterial>();
|
||||
auto& material = *blockMaterials[id];
|
||||
material.name = id;
|
||||
return material;
|
||||
}
|
||||
|
||||
void ContentBuilder::checkIdentifier(std::string id) {
|
||||
contenttype result;
|
||||
if (((result = checkContentType(id)) != contenttype::none)) {
|
||||
throw namereuse_error("name "+id+" is already used", result);
|
||||
}
|
||||
}
|
||||
|
||||
contenttype ContentBuilder::checkContentType(std::string id) {
|
||||
if (blockDefs.find(id) != blockDefs.end()) {
|
||||
return contenttype::block;
|
||||
}
|
||||
if (itemDefs.find(id) != itemDefs.end()) {
|
||||
return contenttype::item;
|
||||
}
|
||||
return contenttype::none;
|
||||
}
|
||||
|
||||
std::unique_ptr<Content> ContentBuilder::build() {
|
||||
std::vector<Block*> blockDefsIndices;
|
||||
auto groups = std::make_unique<DrawGroups>();
|
||||
for (const std::string& name : blockIds) {
|
||||
Block& def = *blockDefs[name];
|
||||
|
||||
// Generating runtime info
|
||||
def.rt.id = blockDefsIndices.size();
|
||||
def.rt.emissive = *reinterpret_cast<uint32_t*>(def.emission);
|
||||
def.rt.solid = def.model == BlockModel::block;
|
||||
|
||||
if (def.rotatable) {
|
||||
for (uint i = 0; i < BlockRotProfile::MAX_COUNT; i++) {
|
||||
def.rt.hitboxes[i].reserve(def.hitboxes.size());
|
||||
for (AABB aabb : def.hitboxes) {
|
||||
def.rotations.variants[i].transform(aabb);
|
||||
def.rt.hitboxes[i].push_back(aabb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockDefsIndices.push_back(&def);
|
||||
groups->insert(def.drawGroup);
|
||||
}
|
||||
|
||||
std::vector<ItemDef*> itemDefsIndices;
|
||||
for (const std::string& name : itemIds) {
|
||||
ItemDef& def = *itemDefs[name];
|
||||
|
||||
// Generating runtime info
|
||||
def.rt.id = itemDefsIndices.size();
|
||||
def.rt.emissive = *reinterpret_cast<uint32_t*>(def.emission);
|
||||
itemDefsIndices.push_back(&def);
|
||||
}
|
||||
|
||||
auto content = std::make_unique<Content>(
|
||||
std::make_unique<ContentIndices>(blockDefsIndices, itemDefsIndices),
|
||||
std::move(groups),
|
||||
std::move(blockDefs),
|
||||
std::move(itemDefs),
|
||||
std::move(packs),
|
||||
std::move(blockMaterials)
|
||||
);
|
||||
|
||||
// Now, it's time to resolve foreign keys
|
||||
for (Block* def : blockDefsIndices) {
|
||||
def->rt.pickingItem = content->requireItem(def->pickingItem).rt.id;
|
||||
}
|
||||
|
||||
for (ItemDef* def : itemDefsIndices) {
|
||||
def->rt.placingBlock = content->requireBlock(def->placingBlock).rt.id;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef CONTENT_CONTENT_BUILDER_HPP_
|
||||
#define CONTENT_CONTENT_BUILDER_HPP_
|
||||
|
||||
#include "../items/ItemDef.hpp"
|
||||
#include "../voxels/Block.hpp"
|
||||
#include "../content/Content.hpp"
|
||||
#include "../content/ContentPack.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
class ContentBuilder {
|
||||
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs;
|
||||
std::vector<std::string> blockIds;
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs;
|
||||
std::vector<std::string> itemIds;
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials;
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
||||
public:
|
||||
~ContentBuilder();
|
||||
|
||||
void add(std::unique_ptr<ContentPackRuntime> pack);
|
||||
|
||||
Block& createBlock(std::string id);
|
||||
ItemDef& createItem(std::string id);
|
||||
BlockMaterial& createBlockMaterial(std::string id);
|
||||
|
||||
void checkIdentifier(std::string id);
|
||||
contenttype checkContentType(std::string id);
|
||||
|
||||
std::unique_ptr<Content> build();
|
||||
};
|
||||
|
||||
#endif // CONTENT_CONTENT_BUILDER_HPP_
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Content.hpp"
|
||||
#include "ContentPack.hpp"
|
||||
#include "ContentBuilder.hpp"
|
||||
#include "../coders/json.hpp"
|
||||
#include "../core_defs.hpp"
|
||||
#include "../data/dynamic.hpp"
|
||||
@@ -26,9 +27,11 @@ static debug::Logger logger("content-loader");
|
||||
ContentLoader::ContentLoader(ContentPack* pack) : pack(pack) {
|
||||
}
|
||||
|
||||
bool ContentLoader::fixPackIndices(fs::path folder,
|
||||
dynamic::Map* indicesRoot,
|
||||
std::string contentSection) {
|
||||
bool ContentLoader::fixPackIndices(
|
||||
fs::path folder,
|
||||
dynamic::Map* indicesRoot,
|
||||
std::string contentSection
|
||||
) {
|
||||
std::vector<std::string> detected;
|
||||
std::vector<std::string> indexed;
|
||||
if (fs::is_directory(folder)) {
|
||||
@@ -209,6 +212,10 @@ void ContentLoader::loadBlock(Block& def, std::string name, fs::path file) {
|
||||
root->str("script-name", def.scriptName);
|
||||
root->str("ui-layout", def.uiLayout);
|
||||
root->num("inventory-size", def.inventorySize);
|
||||
root->num("tick-interval", def.tickInterval);
|
||||
if (def.tickInterval == 0) {
|
||||
def.tickInterval = 1;
|
||||
}
|
||||
|
||||
if (def.hidden && def.pickingItem == def.name+BLOCK_ITEM_SUFFIX) {
|
||||
def.pickingItem = CORE_EMPTY;
|
||||
@@ -312,22 +319,22 @@ void ContentLoader::loadItem(ItemDef& def, std::string full, std::string name) {
|
||||
}
|
||||
}
|
||||
|
||||
BlockMaterial ContentLoader::loadBlockMaterial(fs::path file, std::string full) {
|
||||
void ContentLoader::loadBlockMaterial(BlockMaterial& def, fs::path file) {
|
||||
auto root = files::read_json(file);
|
||||
BlockMaterial material {full};
|
||||
root->str("steps-sound", material.stepsSound);
|
||||
root->str("place-sound", material.placeSound);
|
||||
root->str("break-sound", material.breakSound);
|
||||
return material;
|
||||
root->str("steps-sound", def.stepsSound);
|
||||
root->str("place-sound", def.placeSound);
|
||||
root->str("break-sound", def.breakSound);
|
||||
}
|
||||
|
||||
void ContentLoader::load(ContentBuilder& builder) {
|
||||
logger.info() << "loading pack [" << pack->id << "]";
|
||||
|
||||
auto runtime = new ContentPackRuntime(*pack, scripting::create_pack_environment(*pack));
|
||||
builder.add(runtime);
|
||||
auto runtime = std::make_unique<ContentPackRuntime>(
|
||||
*pack, scripting::create_pack_environment(*pack)
|
||||
);
|
||||
env = runtime->getEnvironment();
|
||||
ContentPackStats& stats = runtime->getStatsWriteable();
|
||||
builder.add(std::move(runtime));
|
||||
|
||||
fixPackIndices();
|
||||
|
||||
@@ -350,7 +357,9 @@ void ContentLoader::load(ContentBuilder& builder) {
|
||||
std::string full = colon == std::string::npos ? pack->id + ":" + name : name;
|
||||
if (colon != std::string::npos) name[colon] = '/';
|
||||
auto& def = builder.createBlock(full);
|
||||
if (colon != std::string::npos) def.scriptName = name.substr(0, colon) + '/' + def.scriptName;
|
||||
if (colon != std::string::npos) {
|
||||
def.scriptName = name.substr(0, colon) + '/' + def.scriptName;
|
||||
}
|
||||
loadBlock(def, full, name);
|
||||
stats.totalBlocks++;
|
||||
if (!def.hidden) {
|
||||
@@ -388,7 +397,7 @@ void ContentLoader::load(ContentBuilder& builder) {
|
||||
for (auto entry : fs::directory_iterator(materialsDir)) {
|
||||
fs::path file = entry.path();
|
||||
std::string name = pack->id+":"+file.stem().u8string();
|
||||
builder.add(loadBlockMaterial(file, name));
|
||||
loadBlockMaterial(builder.createBlockMaterial(name), file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#ifndef CONTENT_CONTENT_LOADER_HPP_
|
||||
#define CONTENT_CONTENT_LOADER_HPP_
|
||||
|
||||
#include "../voxels/Block.hpp"
|
||||
#include "../typedefs.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class Block;
|
||||
struct BlockMaterial;
|
||||
class ItemDef;
|
||||
struct ContentPack;
|
||||
class ContentBuilder;
|
||||
@@ -23,7 +25,7 @@ class ContentLoader {
|
||||
void loadBlock(Block& def, std::string full, std::string name);
|
||||
void loadCustomBlockModel(Block& def, dynamic::Map* primitives);
|
||||
void loadItem(ItemDef& def, std::string full, std::string name);
|
||||
BlockMaterial loadBlockMaterial(fs::path file, std::string full);
|
||||
void loadBlockMaterial(BlockMaterial& def, fs::path file);
|
||||
public:
|
||||
ContentLoader(ContentPack* pack);
|
||||
|
||||
|
||||
@@ -12,17 +12,11 @@ class EnginePaths;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace scripting {
|
||||
class Environment;
|
||||
}
|
||||
|
||||
class contentpack_error : public std::runtime_error {
|
||||
std::string packId;
|
||||
fs::path folder;
|
||||
public:
|
||||
contentpack_error(std::string packId,
|
||||
fs::path folder,
|
||||
std::string message);
|
||||
contentpack_error(std::string packId, fs::path folder, std::string message);
|
||||
|
||||
std::string getPackId() const;
|
||||
fs::path getFolder() const;
|
||||
@@ -31,11 +25,11 @@ public:
|
||||
enum class DependencyLevel {
|
||||
required, // dependency must be installed
|
||||
optional, // dependency will be installed if found
|
||||
weak, // dependency will not be installed automatically
|
||||
weak, // only affects packs order
|
||||
};
|
||||
|
||||
|
||||
/// @brief Content-pack that should be installed before the dependent
|
||||
/// @brief Content-pack that should be installed earlier the dependent
|
||||
struct DependencyPack {
|
||||
DependencyLevel level;
|
||||
std::string id;
|
||||
|
||||
+10
-20
@@ -2,13 +2,16 @@
|
||||
|
||||
#include "items/ItemDef.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "content/ContentBuilder.hpp"
|
||||
#include "files/files.hpp"
|
||||
#include "files/engine_paths.hpp"
|
||||
#include "window/Window.hpp"
|
||||
#include "window/Events.hpp"
|
||||
#include "window/input.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
|
||||
// All in-game definitions (blocks, items, etc..)
|
||||
void corecontent::setup(ContentBuilder* builder) {
|
||||
void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
|
||||
Block& block = builder->createBlock("core:air");
|
||||
block.replaceable = true;
|
||||
block.drawGroup = 1;
|
||||
@@ -21,24 +24,11 @@ void corecontent::setup(ContentBuilder* builder) {
|
||||
|
||||
ItemDef& item = builder->createItem("core:empty");
|
||||
item.iconType = item_icon_type::none;
|
||||
}
|
||||
|
||||
void corecontent::setup_bindings() {
|
||||
Events::bind(BIND_DEVTOOLS_CONSOLE, inputtype::keyboard, keycode::GRAVE_ACCENT);
|
||||
Events::bind(BIND_MOVE_FORWARD, inputtype::keyboard, keycode::W);
|
||||
Events::bind(BIND_MOVE_BACK, inputtype::keyboard, keycode::S);
|
||||
Events::bind(BIND_MOVE_RIGHT, inputtype::keyboard, keycode::D);
|
||||
Events::bind(BIND_MOVE_LEFT, inputtype::keyboard, keycode::A);
|
||||
Events::bind(BIND_MOVE_JUMP, inputtype::keyboard, keycode::SPACE);
|
||||
Events::bind(BIND_MOVE_SPRINT, inputtype::keyboard, keycode::LEFT_CONTROL);
|
||||
Events::bind(BIND_MOVE_CROUCH, inputtype::keyboard, keycode::LEFT_SHIFT);
|
||||
Events::bind(BIND_MOVE_CHEAT, inputtype::keyboard, keycode::R);
|
||||
Events::bind(BIND_CAM_ZOOM, inputtype::keyboard, keycode::C);
|
||||
Events::bind(BIND_CAM_MODE, inputtype::keyboard, keycode::F4);
|
||||
Events::bind(BIND_PLAYER_NOCLIP, inputtype::keyboard, keycode::N);
|
||||
Events::bind(BIND_PLAYER_FLIGHT, inputtype::keyboard, keycode::F);
|
||||
Events::bind(BIND_PLAYER_ATTACK, inputtype::mouse, mousecode::BUTTON_1);
|
||||
Events::bind(BIND_PLAYER_BUILD, inputtype::mouse, mousecode::BUTTON_2);
|
||||
Events::bind(BIND_PLAYER_PICK, inputtype::mouse, mousecode::BUTTON_3);
|
||||
Events::bind(BIND_HUD_INVENTORY, inputtype::keyboard, keycode::TAB);
|
||||
auto bindsFile = paths->getResources()/fs::path("bindings.toml");
|
||||
if (fs::is_regular_file(bindsFile)) {
|
||||
Events::loadBindings(
|
||||
bindsFile.u8string(), files::read_string(bindsFile)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -10,6 +10,7 @@ inline const std::string TEXTURE_NOTFOUND = "notfound";
|
||||
|
||||
// built-in bindings
|
||||
inline const std::string BIND_DEVTOOLS_CONSOLE = "devtools.console";
|
||||
inline const std::string BIND_CHUNKS_RELOAD = "chunks.reload";
|
||||
inline const std::string BIND_MOVE_FORWARD = "movement.forward";
|
||||
inline const std::string BIND_MOVE_BACK = "movement.back";
|
||||
inline const std::string BIND_MOVE_LEFT = "movement.left";
|
||||
@@ -27,11 +28,11 @@ inline const std::string BIND_PLAYER_BUILD = "player.build";
|
||||
inline const std::string BIND_PLAYER_PICK = "player.pick";
|
||||
inline const std::string BIND_HUD_INVENTORY = "hud.inventory";
|
||||
|
||||
class EnginePaths;
|
||||
class ContentBuilder;
|
||||
|
||||
namespace corecontent {
|
||||
void setup_bindings();
|
||||
void setup(ContentBuilder* builder);
|
||||
void setup(EnginePaths* paths, ContentBuilder* builder);
|
||||
}
|
||||
|
||||
#endif // CORE_DEFS_HPP_
|
||||
|
||||
@@ -214,7 +214,7 @@ void Map::flag(const std::string& key, bool& dst) const {
|
||||
}
|
||||
|
||||
Map& Map::put(std::string key, const Value& value) {
|
||||
values.emplace(key, value);
|
||||
values[key] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <variant>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
@@ -151,6 +152,9 @@ namespace dynamic {
|
||||
Map& put(std::string key, bool value) {
|
||||
return put(key, Value(static_cast<bool>(value)));
|
||||
}
|
||||
Map& put(std::string key, const char* value) {
|
||||
return put(key, Value(value));
|
||||
}
|
||||
Map& put(std::string key, const Value& value);
|
||||
|
||||
void remove(const std::string& key);
|
||||
|
||||
@@ -44,13 +44,14 @@ void Logger::log(LogLevel level, const std::string& name, std::string message) {
|
||||
auto ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch()) % 1000;
|
||||
ss << " " << std::put_time(std::localtime(&tm), "%Y/%m/%d %T");
|
||||
ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
|
||||
ss << utcOffset << " (" << std::setfill(' ') << std::setw(moduleLen) << name << ") ";
|
||||
ss << utcOffset << " [" << std::setfill(' ') << std::setw(moduleLen) << name << "] ";
|
||||
ss << message;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
auto string = ss.str();
|
||||
if (file.good()) {
|
||||
file << string << '\n';
|
||||
file.flush();
|
||||
}
|
||||
std::cout << string << std::endl;
|
||||
}
|
||||
|
||||
+35
-5
@@ -9,6 +9,7 @@
|
||||
#include "coders/imageio.hpp"
|
||||
#include "coders/json.hpp"
|
||||
#include "coders/toml.hpp"
|
||||
#include "content/ContentBuilder.hpp"
|
||||
#include "content/ContentLoader.hpp"
|
||||
#include "core_defs.hpp"
|
||||
#include "files/files.hpp"
|
||||
@@ -34,6 +35,7 @@
|
||||
#include "window/input.hpp"
|
||||
#include "window/Window.hpp"
|
||||
#include "world/WorldGenerators.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
@@ -56,20 +58,20 @@ inline void create_channel(Engine* engine, std::string name, NumberSetting& sett
|
||||
}
|
||||
engine->keepAlive(setting.observe([=](auto value) {
|
||||
audio::get_channel(name)->setVolume(value*value);
|
||||
}));
|
||||
}, true));
|
||||
}
|
||||
|
||||
Engine::Engine(EngineSettings& settings, SettingsHandler& settingsHandler, EnginePaths* paths)
|
||||
: settings(settings), settingsHandler(settingsHandler), paths(paths),
|
||||
interpreter(std::make_unique<cmd::CommandsInterpreter>())
|
||||
{
|
||||
corecontent::setup_bindings();
|
||||
loadSettings();
|
||||
|
||||
controller = std::make_unique<EngineController>(this);
|
||||
if (Window::initialize(&this->settings.display)){
|
||||
throw initialize_error("could not initialize window");
|
||||
}
|
||||
loadControls();
|
||||
audio::initialize(settings.audio.enabled.get());
|
||||
create_channel(this, "master", settings.audio.volumeMaster);
|
||||
create_channel(this, "regular", settings.audio.volumeRegular);
|
||||
@@ -93,6 +95,9 @@ Engine::Engine(EngineSettings& settings, SettingsHandler& settingsHandler, Engin
|
||||
addWorldGenerators();
|
||||
|
||||
scripting::initialize(this);
|
||||
|
||||
auto resdir = paths->getResources();
|
||||
basePacks = files::read_list(resdir/fs::path("config/builtins.list"));
|
||||
}
|
||||
|
||||
void Engine::loadSettings() {
|
||||
@@ -102,11 +107,22 @@ void Engine::loadSettings() {
|
||||
std::string text = files::read_string(settings_file);
|
||||
toml::parse(settingsHandler, settings_file.string(), text);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::loadControls() {
|
||||
fs::path controls_file = paths->getControlsFile();
|
||||
if (fs::is_regular_file(controls_file)) {
|
||||
logger.info() << "loading controls";
|
||||
std::string text = files::read_string(controls_file);
|
||||
Events::loadBindings(controls_file.u8string(), text);
|
||||
} else {
|
||||
controls_file = paths->getControlsFileOld();
|
||||
if (fs::is_regular_file(controls_file)) {
|
||||
logger.info() << "loading controls (old)";
|
||||
std::string text = files::read_string(controls_file);
|
||||
Events::loadBindingsOld(controls_file.u8string(), text);
|
||||
fs::remove(controls_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,10 +267,20 @@ void Engine::loadAssets() {
|
||||
assets.reset(new_assets.release());
|
||||
}
|
||||
|
||||
static void load_configs(const fs::path& root) {
|
||||
auto configFolder = root/fs::path("config");
|
||||
auto bindsFile = configFolder/fs::path("bindings.toml");
|
||||
if (fs::is_regular_file(bindsFile)) {
|
||||
Events::loadBindings(
|
||||
bindsFile.u8string(), files::read_string(bindsFile)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::loadContent() {
|
||||
auto resdir = paths->getResources();
|
||||
ContentBuilder contentBuilder;
|
||||
corecontent::setup(&contentBuilder);
|
||||
corecontent::setup(paths, &contentBuilder);
|
||||
paths->setContentPacks(&contentPacks);
|
||||
|
||||
std::vector<std::string> names;
|
||||
@@ -272,8 +298,12 @@ void Engine::loadContent() {
|
||||
|
||||
ContentLoader loader(&pack);
|
||||
loader.load(contentBuilder);
|
||||
}
|
||||
content.reset(contentBuilder.build());
|
||||
|
||||
load_configs(pack.folder);
|
||||
}
|
||||
load_configs(paths->getResources());
|
||||
|
||||
content = contentBuilder.build();
|
||||
resPaths = std::make_unique<ResPaths>(resdir, resRoots);
|
||||
|
||||
langs::setup(resdir, langs::current->getId(), contentPacks);
|
||||
|
||||
+3
-2
@@ -2,7 +2,6 @@
|
||||
#define ENGINE_HPP_
|
||||
|
||||
#include "delegates.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "typedefs.hpp"
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
@@ -27,6 +26,7 @@ class ResPaths;
|
||||
class Batch2D;
|
||||
class EngineController;
|
||||
class SettingsHandler;
|
||||
struct EngineSettings;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -57,7 +57,7 @@ class Engine : public util::ObjectsKeeper {
|
||||
std::recursive_mutex postRunnablesMutex;
|
||||
std::unique_ptr<EngineController> controller;
|
||||
std::unique_ptr<cmd::CommandsInterpreter> interpreter;
|
||||
std::vector<std::string> basePacks {"base"};
|
||||
std::vector<std::string> basePacks;
|
||||
|
||||
uint64_t frame = 0;
|
||||
double lastTime = 0.0;
|
||||
@@ -65,6 +65,7 @@ class Engine : public util::ObjectsKeeper {
|
||||
|
||||
std::unique_ptr<gui::GUI> gui;
|
||||
|
||||
void loadControls();
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
void updateTimers();
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "../objects/Player.hpp"
|
||||
#include "../physics/Hitbox.hpp"
|
||||
#include "../typedefs.hpp"
|
||||
#include "../settings.hpp"
|
||||
#include "../util/data_io.hpp"
|
||||
#include "../voxels/Block.hpp"
|
||||
#include "../voxels/Chunk.hpp"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "files.hpp"
|
||||
#include "../typedefs.hpp"
|
||||
#include "../settings.hpp"
|
||||
#include "../content/ContentPack.hpp"
|
||||
#include "../voxels/Chunk.hpp"
|
||||
|
||||
@@ -24,6 +23,7 @@ class Player;
|
||||
class Content;
|
||||
class ContentIndices;
|
||||
class World;
|
||||
struct DebugSettings;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
@@ -374,7 +374,7 @@ void WorldRegions::put(Chunk* chunk){
|
||||
chunk->encode(), CHUNK_DATA_LEN, true);
|
||||
|
||||
// Writing lights cache
|
||||
if (doWriteLights && chunk->isLighted()) {
|
||||
if (doWriteLights && chunk->flags.lighted) {
|
||||
put(chunk->x, chunk->z, REGION_LAYER_LIGHTS,
|
||||
chunk->lightmap.encode(), LIGHTMAP_DATA_LEN, true);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "WorldFiles.hpp"
|
||||
|
||||
const fs::path SCREENSHOTS_FOLDER {"screenshots"};
|
||||
const fs::path CONTROLS_FILE {"controls.json"};
|
||||
const fs::path CONTROLS_FILE {"controls.toml"};
|
||||
const fs::path SETTINGS_FILE {"settings.toml"};
|
||||
|
||||
fs::path EnginePaths::getUserfiles() const {
|
||||
@@ -60,6 +60,10 @@ fs::path EnginePaths::getControlsFile() {
|
||||
return userfiles/fs::path(CONTROLS_FILE);
|
||||
}
|
||||
|
||||
fs::path EnginePaths::getControlsFileOld() {
|
||||
return userfiles/fs::path("controls.json");
|
||||
}
|
||||
|
||||
fs::path EnginePaths::getSettingsFile() {
|
||||
return userfiles/fs::path(SETTINGS_FILE);
|
||||
}
|
||||
@@ -135,7 +139,7 @@ static fs::path toCanonic(fs::path path) {
|
||||
return path;
|
||||
}
|
||||
|
||||
fs::path EnginePaths::resolve(std::string path) {
|
||||
fs::path EnginePaths::resolve(std::string path, bool throwErr) {
|
||||
size_t separator = path.find(':');
|
||||
if (separator == std::string::npos) {
|
||||
throw files_access_error("no entry point specified");
|
||||
@@ -161,7 +165,10 @@ fs::path EnginePaths::resolve(std::string path) {
|
||||
}
|
||||
}
|
||||
}
|
||||
throw files_access_error("unknown entry point '"+prefix+"'");
|
||||
if (throwErr) {
|
||||
throw files_access_error("unknown entry point '"+prefix+"'");
|
||||
}
|
||||
return fs::path(filename);
|
||||
}
|
||||
|
||||
ResPaths::ResPaths(fs::path mainRoot, std::vector<PathsRoot> roots)
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
fs::path getWorldFolder();
|
||||
fs::path getWorldFolder(const std::string& name);
|
||||
fs::path getControlsFile();
|
||||
fs::path getControlsFileOld(); // TODO: remove in 0.22
|
||||
fs::path getSettingsFile();
|
||||
bool isWorldNameUsed(std::string name);
|
||||
|
||||
@@ -39,7 +40,7 @@ public:
|
||||
|
||||
std::vector<fs::path> scanForWorlds();
|
||||
|
||||
fs::path resolve(std::string path);
|
||||
fs::path resolve(std::string path, bool throwErr=true);
|
||||
};
|
||||
|
||||
struct PathsRoot {
|
||||
|
||||
+7
-2
@@ -1,6 +1,8 @@
|
||||
#include "files.hpp"
|
||||
|
||||
#include "../coders/commons.hpp"
|
||||
#include "../coders/json.hpp"
|
||||
#include "../coders/toml.hpp"
|
||||
#include "../coders/gzip.hpp"
|
||||
#include "../util/stringutil.hpp"
|
||||
#include "../data/dynamic.hpp"
|
||||
@@ -107,8 +109,7 @@ bool files::write_binary_json(fs::path filename, const dynamic::Map* obj, bool c
|
||||
std::shared_ptr<dynamic::Map> files::read_json(fs::path filename) {
|
||||
std::string text = files::read_string(filename);
|
||||
try {
|
||||
auto obj = json::parse(filename.string(), text);
|
||||
return obj;
|
||||
return json::parse(filename.string(), text);;
|
||||
} catch (const parsing_error& error) {
|
||||
std::cerr << error.errorLog() << std::endl;
|
||||
throw std::runtime_error("could not to parse "+filename.string());
|
||||
@@ -121,6 +122,10 @@ std::shared_ptr<dynamic::Map> files::read_binary_json(fs::path file) {
|
||||
return json::from_binary(bytes.get(), size);
|
||||
}
|
||||
|
||||
std::shared_ptr<dynamic::Map> files::read_toml(fs::path file) {
|
||||
return toml::parse(file.u8string(), files::read_string(file));
|
||||
}
|
||||
|
||||
std::vector<std::string> files::read_list(fs::path filename) {
|
||||
std::ifstream file(filename);
|
||||
if (!file) {
|
||||
|
||||
+3
-5
@@ -20,7 +20,7 @@ namespace files {
|
||||
std::ifstream file;
|
||||
size_t filelength;
|
||||
public:
|
||||
rafile(std::filesystem::path filename);
|
||||
rafile(fs::path filename);
|
||||
|
||||
void seekg(std::streampos pos);
|
||||
void read(char* buffer, std::streamsize size);
|
||||
@@ -44,10 +44,7 @@ namespace files {
|
||||
|
||||
/// @brief Write dynamic data to the JSON file
|
||||
/// @param nice if true, human readable format will be used, otherwise minimal
|
||||
bool write_json(
|
||||
fs::path filename,
|
||||
const dynamic::Map* obj,
|
||||
bool nice=true);
|
||||
bool write_json(fs::path filename, const dynamic::Map* obj, bool nice=true);
|
||||
|
||||
/// @brief Write dynamic data to the binary JSON file
|
||||
/// (see src/coders/binary_json_spec.md)
|
||||
@@ -66,6 +63,7 @@ namespace files {
|
||||
/// @param file *.json or *.bjson file
|
||||
std::shared_ptr<dynamic::Map> read_json(fs::path file);
|
||||
std::shared_ptr<dynamic::Map> read_binary_json(fs::path file);
|
||||
std::shared_ptr<dynamic::Map> read_toml(fs::path file);
|
||||
std::vector<std::string> read_list(fs::path file);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ LevelFrontend::LevelFrontend(LevelController* controller, Assets* assets)
|
||||
contentCache(std::make_unique<ContentGfxCache>(level->content, assets))
|
||||
{
|
||||
assets->store(
|
||||
BlocksPreview::build(contentCache.get(), assets, level->content).release(),
|
||||
BlocksPreview::build(contentCache.get(), assets, level->content),
|
||||
"block-previews"
|
||||
);
|
||||
controller->getPlayerController()->listenBlockInteraction(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../audio/audio.hpp"
|
||||
#include "../delegates.hpp"
|
||||
#include "../engine.hpp"
|
||||
#include "../settings.hpp"
|
||||
#include "../graphics/core/Mesh.hpp"
|
||||
#include "../graphics/ui/elements/CheckBox.hpp"
|
||||
#include "../graphics/ui/elements/TextBox.hpp"
|
||||
@@ -19,6 +20,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
|
||||
using namespace gui;
|
||||
|
||||
@@ -71,15 +73,24 @@ std::shared_ptr<UINode> create_debug_panel(
|
||||
L" visible: "+std::to_wstring(level->chunks->visible);
|
||||
}));
|
||||
panel->add(create_label([=](){
|
||||
auto* indices = level->content->getIndices();
|
||||
auto def = indices->getBlockDef(player->selectedVoxel.id);
|
||||
std::wstringstream stream;
|
||||
stream << std::hex << player->selectedVoxel.states;
|
||||
if (def) {
|
||||
stream << L" (" << util::str2wstr_utf8(def->name) << L")";
|
||||
stream << "r:" << player->selectedVoxel.state.rotation << " s:"
|
||||
<< player->selectedVoxel.state.segment << " u:"
|
||||
<< std::bitset<8>(player->selectedVoxel.state.userbits);
|
||||
if (player->selectedVoxel.id == BLOCK_VOID) {
|
||||
return std::wstring {L"block: -"};
|
||||
} else {
|
||||
return L"block: "+std::to_wstring(player->selectedVoxel.id)+
|
||||
L" "+stream.str();
|
||||
}
|
||||
}));
|
||||
panel->add(create_label([=](){
|
||||
auto* indices = level->content->getIndices();
|
||||
if (auto def = indices->getBlockDef(player->selectedVoxel.id)) {
|
||||
return L"name: " + util::str2wstr_utf8(def->name);
|
||||
} else {
|
||||
return std::wstring {L"name: void"};
|
||||
}
|
||||
return L"block: "+std::to_wstring(player->selectedVoxel.id)+
|
||||
L" "+stream.str();
|
||||
}));
|
||||
panel->add(create_label([=](){
|
||||
return L"seed: "+std::to_wstring(level->getWorld()->getSeed());
|
||||
@@ -137,8 +148,8 @@ std::shared_ptr<UINode> create_debug_panel(
|
||||
}
|
||||
{
|
||||
auto bar = std::make_shared<TrackBar>(0.0f, 1.0f, 0.0f, 0.005f, 8);
|
||||
bar->setSupplier([=]() {return WorldRenderer::fog;});
|
||||
bar->setConsumer([=](double val) {WorldRenderer::fog = val;});
|
||||
bar->setSupplier([=]() {return level->getWorld()->fog;});
|
||||
bar->setConsumer([=](double val) {level->getWorld()->fog = val;});
|
||||
panel->add(bar);
|
||||
}
|
||||
{
|
||||
|
||||
@@ -333,7 +333,7 @@ void Hud::openInventory(
|
||||
if (blockinv == nullptr) {
|
||||
blockinv = level->inventories->createVirtual(blockUI->getSlotsCount());
|
||||
}
|
||||
level->chunks->getChunkByVoxel(block.x, block.y, block.z)->setUnsaved(true);
|
||||
level->chunks->getChunkByVoxel(block.x, block.y, block.z)->flags.unsaved = true;
|
||||
blockUI->bind(blockinv, content);
|
||||
blockPos = block;
|
||||
currentblockid = level->chunks->get(block.x, block.y, block.z)->id;
|
||||
|
||||
+10
-5
@@ -62,9 +62,11 @@ gui::page_loader_func menus::create_page_loader(Engine* engine) {
|
||||
auto file = engine->getResPaths()->find("layouts/pages/"+name+".xml");
|
||||
auto fullname = "core:pages/"+name;
|
||||
|
||||
auto document = UiDocument::read(scripting::get_root_environment(), fullname, file).release();
|
||||
engine->getAssets()->store(document, fullname);
|
||||
|
||||
auto document_ptr = UiDocument::read(
|
||||
scripting::get_root_environment(), fullname, file
|
||||
);
|
||||
auto document = document_ptr.get();
|
||||
engine->getAssets()->store(std::move(document_ptr), fullname);
|
||||
scripting::on_ui_open(document, std::move(args));
|
||||
return document->getRoot();
|
||||
};
|
||||
@@ -75,8 +77,11 @@ UiDocument* menus::show(Engine* engine, const std::string& name, std::vector<dyn
|
||||
auto file = engine->getResPaths()->find("layouts/"+name+".xml");
|
||||
auto fullname = "core:layouts/"+name;
|
||||
|
||||
auto document = UiDocument::read(scripting::get_root_environment(), fullname, file).release();
|
||||
engine->getAssets()->store(document, fullname);
|
||||
auto document_ptr = UiDocument::read(
|
||||
scripting::get_root_environment(), fullname, file
|
||||
);
|
||||
auto document = document_ptr.get();
|
||||
engine->getAssets()->store(std::move(document_ptr), fullname);
|
||||
scripting::on_ui_open(document, std::move(args));
|
||||
menu->addPage(name, document->getRoot());
|
||||
menu->setPage(name);
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
#include "LevelScreen.hpp"
|
||||
|
||||
#include "../../core_defs.hpp"
|
||||
#include "../hud.hpp"
|
||||
#include "../LevelFrontend.hpp"
|
||||
#include "../../debug/Logger.hpp"
|
||||
#include "../../audio/audio.hpp"
|
||||
#include "../../coders/imageio.hpp"
|
||||
#include "../../graphics/core/PostProcessing.hpp"
|
||||
#include "../../debug/Logger.hpp"
|
||||
#include "../../engine.hpp"
|
||||
#include "../../files/files.hpp"
|
||||
#include "../../graphics/core/DrawContext.hpp"
|
||||
#include "../../graphics/core/Viewport.hpp"
|
||||
#include "../../graphics/core/ImageData.hpp"
|
||||
#include "../../graphics/ui/GUI.hpp"
|
||||
#include "../../graphics/ui/elements/Menu.hpp"
|
||||
#include "../../graphics/core/PostProcessing.hpp"
|
||||
#include "../../graphics/core/Viewport.hpp"
|
||||
#include "../../graphics/render/WorldRenderer.hpp"
|
||||
#include "../../graphics/ui/elements/Menu.hpp"
|
||||
#include "../../graphics/ui/GUI.hpp"
|
||||
#include "../../logic/LevelController.hpp"
|
||||
#include "../../logic/scripting/scripting_hud.hpp"
|
||||
#include "../../util/stringutil.hpp"
|
||||
#include "../../physics/Hitbox.hpp"
|
||||
#include "../../voxels/Chunks.hpp"
|
||||
#include "../../world/Level.hpp"
|
||||
#include "../../world/World.hpp"
|
||||
#include "../../window/Camera.hpp"
|
||||
#include "../../window/Events.hpp"
|
||||
#include "../../window/Window.hpp"
|
||||
#include "../../engine.hpp"
|
||||
#include "../../world/Level.hpp"
|
||||
#include "../../world/World.hpp"
|
||||
|
||||
static debug::Logger logger("level-screen");
|
||||
|
||||
@@ -45,6 +48,9 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> level)
|
||||
keepAlive(settings.camera.fov.observe([=](double value) {
|
||||
controller->getPlayer()->camera->setFov(glm::radians(value));
|
||||
}));
|
||||
keepAlive(Events::getBinding(BIND_CHUNKS_RELOAD).onactived.add([=](){
|
||||
controller->getLevel()->chunks->saveAndClear();
|
||||
}));
|
||||
|
||||
animator = std::make_unique<TextureAnimator>();
|
||||
animator->addAnimations(assets->getAnimations());
|
||||
@@ -55,16 +61,19 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> level)
|
||||
void LevelScreen::initializeContent() {
|
||||
auto content = controller->getLevel()->content;
|
||||
for (auto& entry : content->getPacks()) {
|
||||
auto pack = entry.second.get();
|
||||
const ContentPack& info = pack->getInfo();
|
||||
fs::path scriptFile = info.folder/fs::path("scripts/hud.lua");
|
||||
if (fs::is_regular_file(scriptFile)) {
|
||||
scripting::load_hud_script(pack->getEnvironment(), info.id, scriptFile);
|
||||
}
|
||||
initializePack(entry.second.get());
|
||||
}
|
||||
scripting::on_frontend_init(hud.get());
|
||||
}
|
||||
|
||||
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
||||
const ContentPack& info = pack->getInfo();
|
||||
fs::path scriptFile = info.folder/fs::path("scripts/hud.lua");
|
||||
if (fs::is_regular_file(scriptFile)) {
|
||||
scripting::load_hud_script(pack->getEnvironment(), info.id, scriptFile);
|
||||
}
|
||||
}
|
||||
|
||||
LevelScreen::~LevelScreen() {
|
||||
saveWorldPreview();
|
||||
scripting::on_frontend_close();
|
||||
@@ -83,8 +92,11 @@ void LevelScreen::saveWorldPreview() {
|
||||
// camera special copy for world preview
|
||||
Camera camera = *player->camera;
|
||||
camera.setFov(glm::radians(70.0f));
|
||||
|
||||
DrawContext pctx(nullptr, {Window::width, Window::height}, batch.get());
|
||||
|
||||
Viewport viewport(previewSize * 1.5, previewSize);
|
||||
DrawContext ctx(nullptr, viewport, batch.get());
|
||||
DrawContext ctx(&pctx, viewport, batch.get());
|
||||
|
||||
worldRenderer->draw(ctx, &camera, false, postProcessing.get());
|
||||
auto image = postProcessing->toImage();
|
||||
@@ -106,9 +118,6 @@ void LevelScreen::updateHotkeys() {
|
||||
if (Events::jpressed(keycode::F3)) {
|
||||
controller->getPlayer()->debug = !controller->getPlayer()->debug;
|
||||
}
|
||||
if (Events::jpressed(keycode::F5)) {
|
||||
controller->getLevel()->chunks->saveAndClear();
|
||||
}
|
||||
}
|
||||
|
||||
void LevelScreen::update(float delta) {
|
||||
@@ -138,7 +147,7 @@ void LevelScreen::update(float delta) {
|
||||
controller->getLevel()->getWorld()->updateTimers(delta);
|
||||
animator->update(delta);
|
||||
}
|
||||
controller->update(delta, !inputLocked, hud->isPause());
|
||||
controller->update(glm::min(delta, 0.2f), !inputLocked, hud->isPause());
|
||||
hud->update(hudVisible);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,21 +12,23 @@ class LevelController;
|
||||
class WorldRenderer;
|
||||
class TextureAnimator;
|
||||
class PostProcessing;
|
||||
class ContentPackRuntime;
|
||||
class Level;
|
||||
|
||||
class LevelScreen : public Screen {
|
||||
std::unique_ptr<LevelFrontend> frontend;
|
||||
std::unique_ptr<Hud> hud;
|
||||
std::unique_ptr<LevelController> controller;
|
||||
std::unique_ptr<WorldRenderer> worldRenderer;
|
||||
std::unique_ptr<TextureAnimator> animator;
|
||||
std::unique_ptr<PostProcessing> postProcessing;
|
||||
std::unique_ptr<Hud> hud;
|
||||
|
||||
void saveWorldPreview();
|
||||
|
||||
bool hudVisible = true;
|
||||
void updateHotkeys();
|
||||
void initializeContent();
|
||||
void initializePack(ContentPackRuntime* pack);
|
||||
public:
|
||||
LevelScreen(Engine* engine, std::unique_ptr<Level> level);
|
||||
~LevelScreen();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../../graphics/core/Batch2D.hpp"
|
||||
#include "../../graphics/core/Shader.hpp"
|
||||
#include "../../graphics/core/Texture.hpp"
|
||||
#include "../../maths/UVRegion.hpp"
|
||||
#include "../../window/Window.hpp"
|
||||
#include "../../window/Camera.hpp"
|
||||
#include "../../engine.hpp"
|
||||
|
||||
@@ -13,19 +13,18 @@ Batch2D::Batch2D(size_t capacity) : capacity(capacity), color(1.0f){
|
||||
{2}, {2}, {4}, {0}
|
||||
};
|
||||
|
||||
buffer = new float[capacity * B2D_VERTEX_SIZE];
|
||||
mesh = std::make_unique<Mesh>(buffer, 0, attrs);
|
||||
buffer = std::make_unique<float[]>(capacity * B2D_VERTEX_SIZE);
|
||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
||||
index = 0;
|
||||
|
||||
ubyte pixels[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
blank = std::make_unique<Texture>(pixels, 1, 1, ImageFormat::rgba8888);
|
||||
_texture = nullptr;
|
||||
currentTexture = nullptr;
|
||||
}
|
||||
|
||||
Batch2D::~Batch2D(){
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void Batch2D::setPrimitive(DrawPrimitive primitive) {
|
||||
@@ -37,7 +36,7 @@ void Batch2D::setPrimitive(DrawPrimitive primitive) {
|
||||
}
|
||||
|
||||
void Batch2D::begin(){
|
||||
_texture = nullptr;
|
||||
currentTexture = nullptr;
|
||||
blank->bind();
|
||||
color = glm::vec4(1.0f);
|
||||
primitive = DrawPrimitive::triangle;
|
||||
@@ -73,14 +72,16 @@ void Batch2D::vertex(
|
||||
}
|
||||
|
||||
void Batch2D::texture(Texture* new_texture){
|
||||
if (_texture == new_texture)
|
||||
if (currentTexture == new_texture) {
|
||||
return;
|
||||
}
|
||||
flush();
|
||||
_texture = new_texture;
|
||||
if (new_texture == nullptr)
|
||||
currentTexture = new_texture;
|
||||
if (new_texture == nullptr) {
|
||||
blank->bind();
|
||||
else
|
||||
} else {
|
||||
new_texture->bind();
|
||||
}
|
||||
}
|
||||
|
||||
void Batch2D::untexture() {
|
||||
@@ -327,7 +328,7 @@ void Batch2D::sprite(float x, float y, float w, float h, int atlasRes, int index
|
||||
void Batch2D::flush() {
|
||||
if (index == 0)
|
||||
return;
|
||||
mesh->reload(buffer, index / B2D_VERTEX_SIZE);
|
||||
mesh->reload(buffer.get(), index / B2D_VERTEX_SIZE);
|
||||
mesh->draw(gl::to_glenum(primitive));
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@ class Texture;
|
||||
struct UVRegion;
|
||||
|
||||
class Batch2D {
|
||||
float* buffer;
|
||||
std::unique_ptr<float[]> buffer;
|
||||
size_t capacity;
|
||||
std::unique_ptr<Mesh> mesh;
|
||||
std::unique_ptr<Texture> blank;
|
||||
size_t index;
|
||||
glm::vec4 color;
|
||||
Texture* _texture;
|
||||
Texture* currentTexture;
|
||||
DrawPrimitive primitive = DrawPrimitive::triangle;
|
||||
|
||||
void setPrimitive(DrawPrimitive primitive);
|
||||
|
||||
@@ -14,28 +14,29 @@ Batch3D::Batch3D(size_t capacity)
|
||||
{3}, {2}, {4}, {0}
|
||||
};
|
||||
|
||||
buffer = new float[capacity * B3D_VERTEX_SIZE];
|
||||
mesh = std::make_unique<Mesh>(buffer, 0, attrs);
|
||||
buffer = std::make_unique<float[]>(capacity * B3D_VERTEX_SIZE);
|
||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
||||
index = 0;
|
||||
|
||||
ubyte pixels[] = {
|
||||
255, 255, 255, 255,
|
||||
};
|
||||
blank = std::make_unique<Texture>(pixels, 1, 1, ImageFormat::rgba8888);
|
||||
_texture = nullptr;
|
||||
currentTexture = nullptr;
|
||||
}
|
||||
|
||||
Batch3D::~Batch3D(){
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void Batch3D::begin(){
|
||||
_texture = nullptr;
|
||||
currentTexture = nullptr;
|
||||
blank->bind();
|
||||
}
|
||||
|
||||
void Batch3D::vertex(float x, float y, float z, float u, float v,
|
||||
float r, float g, float b, float a) {
|
||||
void Batch3D::vertex(
|
||||
float x, float y, float z, float u, float v,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = x;
|
||||
buffer[index++] = y;
|
||||
buffer[index++] = z;
|
||||
@@ -46,8 +47,10 @@ void Batch3D::vertex(float x, float y, float z, float u, float v,
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
}
|
||||
void Batch3D::vertex(glm::vec3 coord, float u, float v,
|
||||
float r, float g, float b, float a) {
|
||||
void Batch3D::vertex(
|
||||
glm::vec3 coord, float u, float v,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = coord.x;
|
||||
buffer[index++] = coord.y;
|
||||
buffer[index++] = coord.z;
|
||||
@@ -58,9 +61,11 @@ void Batch3D::vertex(glm::vec3 coord, float u, float v,
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
}
|
||||
void Batch3D::vertex(glm::vec3 point,
|
||||
glm::vec2 uvpoint,
|
||||
float r, float g, float b, float a) {
|
||||
void Batch3D::vertex(
|
||||
glm::vec3 point,
|
||||
glm::vec2 uvpoint,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = point.x;
|
||||
buffer[index++] = point.y;
|
||||
buffer[index++] = point.z;
|
||||
@@ -99,10 +104,10 @@ void Batch3D::face(
|
||||
}
|
||||
|
||||
void Batch3D::texture(Texture* new_texture){
|
||||
if (_texture == new_texture)
|
||||
if (currentTexture == new_texture)
|
||||
return;
|
||||
flush();
|
||||
_texture = new_texture;
|
||||
currentTexture = new_texture;
|
||||
if (new_texture == nullptr)
|
||||
blank->bind();
|
||||
else
|
||||
@@ -166,7 +171,9 @@ inline glm::vec4 do_tint(float value) {
|
||||
return glm::vec4(value, value, value, 1.0f);
|
||||
}
|
||||
|
||||
void Batch3D::xSprite(float w, float h, const UVRegion& uv, const glm::vec4 tint, bool shading) {
|
||||
void Batch3D::xSprite(
|
||||
float w, float h, const UVRegion& uv, const glm::vec4 tint, bool shading
|
||||
) {
|
||||
face(
|
||||
glm::vec3(-w * 0.25f, 0.0f, -w * 0.25f),
|
||||
w, h,
|
||||
@@ -244,13 +251,13 @@ void Batch3D::point(glm::vec3 coord, glm::vec4 tint) {
|
||||
}
|
||||
|
||||
void Batch3D::flush() {
|
||||
mesh->reload(buffer, index / B3D_VERTEX_SIZE);
|
||||
mesh->reload(buffer.get(), index / B3D_VERTEX_SIZE);
|
||||
mesh->draw();
|
||||
index = 0;
|
||||
}
|
||||
|
||||
void Batch3D::flushPoints() {
|
||||
mesh->reload(buffer, index / B3D_VERTEX_SIZE);
|
||||
mesh->reload(buffer.get(), index / B3D_VERTEX_SIZE);
|
||||
mesh->draw(GL_POINTS);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@@ -12,28 +12,35 @@ class Mesh;
|
||||
class Texture;
|
||||
|
||||
class Batch3D {
|
||||
float* buffer;
|
||||
std::unique_ptr<float[]> buffer;
|
||||
size_t capacity;
|
||||
std::unique_ptr<Mesh> mesh;
|
||||
std::unique_ptr<Texture> blank;
|
||||
size_t index;
|
||||
|
||||
Texture* _texture;
|
||||
Texture* currentTexture;
|
||||
|
||||
void vertex(float x, float y, float z,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a);
|
||||
void vertex(glm::vec3 coord,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a);
|
||||
void vertex(glm::vec3 point, glm::vec2 uvpoint,
|
||||
float r, float g, float b, float a);
|
||||
|
||||
void face(const glm::vec3& coord, float w, float h,
|
||||
void vertex(
|
||||
float x, float y, float z,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a
|
||||
);
|
||||
void vertex(
|
||||
glm::vec3 coord,
|
||||
float u, float v,
|
||||
float r, float g, float b, float a
|
||||
);
|
||||
void vertex(
|
||||
glm::vec3 point, glm::vec2 uvpoint,
|
||||
float r, float g, float b, float a
|
||||
);
|
||||
void face(
|
||||
const glm::vec3& coord, float w, float h,
|
||||
const glm::vec3& axisX,
|
||||
const glm::vec3& axisY,
|
||||
const UVRegion& region,
|
||||
const glm::vec4& tint);
|
||||
const glm::vec4& tint
|
||||
);
|
||||
|
||||
public:
|
||||
Batch3D(size_t capacity);
|
||||
|
||||
@@ -98,7 +98,7 @@ glshader compile_shader(GLenum type, const GLchar* source, const std::string& fi
|
||||
return glshader(new GLuint(shader), shader_deleter);
|
||||
}
|
||||
|
||||
Shader* Shader::create(
|
||||
std::unique_ptr<Shader> Shader::create(
|
||||
const std::string& vertexFile,
|
||||
const std::string& fragmentFile,
|
||||
const std::string& vertexCode,
|
||||
@@ -125,5 +125,5 @@ Shader* Shader::create(
|
||||
"shader program linking failed:\n"+std::string(infoLog)
|
||||
);
|
||||
}
|
||||
return new Shader(id);
|
||||
return std::make_unique<Shader>(id);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../../typedefs.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
@@ -36,7 +37,7 @@ public:
|
||||
/// @param vertexSource vertex shader source code
|
||||
/// @param fragmentSource fragment shader source code
|
||||
/// @return linked shader program containing vertex and fragment shaders
|
||||
static Shader* create(
|
||||
static std::unique_ptr<Shader> create(
|
||||
const std::string& vertexFile,
|
||||
const std::string& fragmentFile,
|
||||
const std::string& vertexSource,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "../../typedefs.hpp"
|
||||
#include "ImageData.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
class Texture {
|
||||
|
||||
@@ -44,13 +44,18 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
||||
break;
|
||||
case BlockModel::aabb:
|
||||
{
|
||||
glm::vec3 hitbox = glm::vec3();
|
||||
for (const auto& box : def->hitboxes)
|
||||
glm::vec3 hitbox {};
|
||||
for (const auto& box : def->hitboxes) {
|
||||
hitbox = glm::max(hitbox, box.size());
|
||||
offset.y += (1.0f - hitbox).y * 0.5f;
|
||||
}
|
||||
offset = glm::vec3(1, 1, 0.0f);
|
||||
shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||
batch->blockCube(hitbox * glm::vec3(size * 0.63f),
|
||||
texfaces, glm::vec4(1.0f), !def->rt.emissive);
|
||||
batch->cube(
|
||||
-hitbox * glm::vec3(size * 0.63f)*0.5f * glm::vec3(1,1,-1),
|
||||
hitbox * glm::vec3(size * 0.63f),
|
||||
texfaces, glm::vec4(1.0f),
|
||||
!def->rt.emissive
|
||||
);
|
||||
}
|
||||
batch->flush();
|
||||
break;
|
||||
@@ -138,7 +143,7 @@ std::unique_ptr<Atlas> BlocksPreview::build(
|
||||
shader->uniformMatrix("u_projview",
|
||||
glm::ortho(0.0f, float(iconSize), 0.0f, float(iconSize),
|
||||
-100.0f, 100.0f) *
|
||||
glm::lookAt(glm::vec3(2, 2, 2),
|
||||
glm::lookAt(glm::vec3(0.57735f),
|
||||
glm::vec3(0.0f),
|
||||
glm::vec3(0, 1, 0)));
|
||||
|
||||
|
||||
@@ -219,10 +219,13 @@ void BlocksRenderer::blockXSprite(int x, int y, int z,
|
||||
// HINT: texture faces order: {east, west, bottom, top, south, north}
|
||||
|
||||
/* AABB blocks render method */
|
||||
void BlocksRenderer::blockAABB(const ivec3& icoord,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block, ubyte rotation,
|
||||
bool lights) {
|
||||
void BlocksRenderer::blockAABB(
|
||||
const ivec3& icoord,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights
|
||||
) {
|
||||
if (block->hitboxes.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -301,11 +304,13 @@ void BlocksRenderer::blockCustomModel(const ivec3& icoord,
|
||||
}
|
||||
|
||||
/* Fastest solid shaded blocks render method */
|
||||
void BlocksRenderer::blockCube(int x, int y, int z,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block,
|
||||
ubyte states,
|
||||
bool lights) {
|
||||
void BlocksRenderer::blockCube(
|
||||
int x, int y, int z,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const Block* block,
|
||||
blockstate states,
|
||||
bool lights
|
||||
) {
|
||||
ubyte group = block->drawGroup;
|
||||
|
||||
vec3 X(1, 0, 0);
|
||||
@@ -314,7 +319,7 @@ void BlocksRenderer::blockCube(int x, int y, int z,
|
||||
vec3 coord(x, y, z);
|
||||
if (block->rotatable) {
|
||||
auto& rotations = block->rotations;
|
||||
auto& orient = rotations.variants[states & BLOCK_ROT_MASK];
|
||||
auto& orient = rotations.variants[states.rotation];
|
||||
X = orient.axisX;
|
||||
Y = orient.axisY;
|
||||
Z = orient.axisZ;
|
||||
@@ -423,7 +428,7 @@ void BlocksRenderer::render(const voxel* voxels) {
|
||||
int z = (i / CHUNK_D) % CHUNK_W;
|
||||
switch (def.model) {
|
||||
case BlockModel::block:
|
||||
blockCube(x, y, z, texfaces, &def, vox.states, !def.rt.emissive);
|
||||
blockCube(x, y, z, texfaces, &def, vox.state, !def.rt.emissive);
|
||||
break;
|
||||
case BlockModel::xsprite: {
|
||||
blockXSprite(x, y, z, vec3(1.0f),
|
||||
@@ -431,11 +436,11 @@ void BlocksRenderer::render(const voxel* voxels) {
|
||||
break;
|
||||
}
|
||||
case BlockModel::aabb: {
|
||||
blockAABB(ivec3(x,y,z), texfaces, &def, vox.rotation(), !def.rt.emissive);
|
||||
blockAABB(ivec3(x,y,z), texfaces, &def, vox.state.rotation, !def.rt.emissive);
|
||||
break;
|
||||
}
|
||||
case BlockModel::custom: {
|
||||
blockCustomModel(ivec3(x, y, z), &def, vox.rotation(), !def.rt.emissive);
|
||||
blockCustomModel(ivec3(x, y, z), &def, vox.state.rotation, !def.rt.emissive);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -70,16 +70,33 @@ class BlocksRenderer {
|
||||
const UVRegion& texreg,
|
||||
bool lights);
|
||||
|
||||
void blockCube(int x, int y, int z, const UVRegion(&faces)[6], const Block* block, ubyte states, bool lights);
|
||||
void blockAABB(const glm::ivec3& coord,
|
||||
const UVRegion(&faces)[6],
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights);
|
||||
void blockXSprite(int x, int y, int z, const glm::vec3& size, const UVRegion& face1, const UVRegion& face2, float spread);
|
||||
void blockCustomModel(const glm::ivec3& icoord,
|
||||
const Block* block, ubyte rotation,
|
||||
bool lights);
|
||||
void blockCube(
|
||||
int x, int y, int z,
|
||||
const UVRegion(&faces)[6],
|
||||
const Block* block,
|
||||
blockstate states,
|
||||
bool lights
|
||||
);
|
||||
void blockAABB(
|
||||
const glm::ivec3& coord,
|
||||
const UVRegion(&faces)[6],
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights
|
||||
);
|
||||
void blockXSprite(
|
||||
int x, int y, int z,
|
||||
const glm::vec3& size,
|
||||
const UVRegion& face1,
|
||||
const UVRegion& face2,
|
||||
float spread
|
||||
);
|
||||
void blockCustomModel(
|
||||
const glm::ivec3& icoord,
|
||||
const Block* block,
|
||||
ubyte rotation,
|
||||
bool lights
|
||||
);
|
||||
|
||||
bool isOpenForLight(int x, int y, int z) const;
|
||||
bool isOpen(int x, int y, int z, ubyte group) const;
|
||||
|
||||
@@ -56,19 +56,16 @@ ChunksRenderer::~ChunksRenderer() {
|
||||
}
|
||||
|
||||
std::shared_ptr<Mesh> ChunksRenderer::render(std::shared_ptr<Chunk> chunk, bool important) {
|
||||
chunk->setModified(false);
|
||||
|
||||
chunk->flags.modified = false;
|
||||
if (important) {
|
||||
auto mesh = renderer->render(chunk.get(), level->chunksStorage.get());
|
||||
meshes[glm::ivec2(chunk->x, chunk->z)] = mesh;
|
||||
return mesh;
|
||||
}
|
||||
|
||||
glm::ivec2 key(chunk->x, chunk->z);
|
||||
if (inwork.find(key) != inwork.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inwork[key] = true;
|
||||
threadPool.enqueueJob(chunk);
|
||||
return nullptr;
|
||||
@@ -86,7 +83,7 @@ std::shared_ptr<Mesh> ChunksRenderer::getOrRender(std::shared_ptr<Chunk> chunk,
|
||||
if (found == meshes.end()) {
|
||||
return render(chunk, important);
|
||||
}
|
||||
if (chunk->isModified()) {
|
||||
if (chunk->flags.modified) {
|
||||
render(chunk, important);
|
||||
}
|
||||
return found->second;
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <glm/ext.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
bool WorldRenderer::showChunkBorders = false;
|
||||
|
||||
WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player)
|
||||
@@ -76,7 +79,7 @@ bool WorldRenderer::drawChunk(
|
||||
bool culling
|
||||
){
|
||||
auto chunk = level->chunks->chunks[index];
|
||||
if (!chunk->isLighted()) {
|
||||
if (!chunk->flags.lighted) {
|
||||
return false;
|
||||
}
|
||||
float distance = glm::distance(
|
||||
@@ -160,6 +163,7 @@ void WorldRenderer::renderLevel(
|
||||
shader->use();
|
||||
shader->uniformMatrix("u_proj", camera->getProjection());
|
||||
shader->uniformMatrix("u_view", camera->getView());
|
||||
shader->uniform1f("u_timer", Window::time());
|
||||
shader->uniform1f("u_gamma", settings.graphics.gamma.get());
|
||||
shader->uniform1f("u_fogFactor", fogFactor);
|
||||
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve.get());
|
||||
@@ -194,19 +198,19 @@ void WorldRenderer::renderBlockSelection(Camera* camera, Shader* linesShader) {
|
||||
auto indices = level->content->getIndices();
|
||||
blockid_t id = PlayerController::selectedBlockId;
|
||||
auto block = indices->getBlockDef(id);
|
||||
const glm::vec3 pos = PlayerController::selectedBlockPosition;
|
||||
const glm::ivec3 pos = player->selectedBlockPosition;
|
||||
const glm::vec3 point = PlayerController::selectedPointPosition;
|
||||
const glm::vec3 norm = PlayerController::selectedBlockNormal;
|
||||
|
||||
const std::vector<AABB>& hitboxes = block->rotatable
|
||||
? block->rt.hitboxes[PlayerController::selectedBlockStates]
|
||||
? block->rt.hitboxes[PlayerController::selectedBlockRotation]
|
||||
: block->hitboxes;
|
||||
|
||||
linesShader->use();
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||
lineBatch->lineWidth(2.0f);
|
||||
for (auto& hitbox: hitboxes) {
|
||||
const glm::vec3 center = pos + hitbox.center();
|
||||
const glm::vec3 center = glm::vec3(pos) + hitbox.center();
|
||||
const glm::vec3 size = hitbox.size();
|
||||
lineBatch->box(center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f));
|
||||
if (player->debug) {
|
||||
@@ -274,11 +278,12 @@ void WorldRenderer::draw(
|
||||
bool hudVisible,
|
||||
PostProcessing* postProcessing
|
||||
){
|
||||
auto world = level->getWorld();
|
||||
const Viewport& vp = pctx.getViewport();
|
||||
camera->aspect = vp.getWidth() / static_cast<float>(vp.getHeight());
|
||||
|
||||
const EngineSettings& settings = engine->getSettings();
|
||||
skybox->refresh(pctx, level->getWorld()->daytime, 1.0f+fog*2.0f, 4);
|
||||
skybox->refresh(pctx, world->daytime, 1.0f+world->fog*2.0f, 4);
|
||||
|
||||
Assets* assets = engine->getAssets();
|
||||
Shader* linesShader = assets->getShader("lines");
|
||||
@@ -291,7 +296,7 @@ void WorldRenderer::draw(
|
||||
Window::clearDepth();
|
||||
|
||||
// Drawing background sky plane
|
||||
skybox->draw(pctx, camera, assets, level->getWorld()->daytime, fog);
|
||||
skybox->draw(pctx, camera, assets, world->daytime, world->fog);
|
||||
|
||||
// Actually world render with depth buffer on
|
||||
{
|
||||
@@ -355,5 +360,3 @@ void WorldRenderer::drawBorders(int sx, int sy, int sz, int ex, int ey, int ez)
|
||||
}
|
||||
lineBatch->render();
|
||||
}
|
||||
|
||||
float WorldRenderer::fog = 0.0f;
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include <string>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
class Level;
|
||||
class Player;
|
||||
@@ -76,8 +74,6 @@ public:
|
||||
Camera* camera,
|
||||
const EngineSettings& settings
|
||||
);
|
||||
|
||||
static float fog;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+53
-2
@@ -1,9 +1,14 @@
|
||||
#include "GUI.hpp"
|
||||
|
||||
#include "gui_util.hpp"
|
||||
|
||||
#include "elements/UINode.hpp"
|
||||
#include "elements/Label.hpp"
|
||||
#include "elements/Menu.hpp"
|
||||
|
||||
#include "../../assets/Assets.hpp"
|
||||
#include "../../frontend/UiDocument.hpp"
|
||||
#include "../../frontend/locale.hpp"
|
||||
#include "../../graphics/core/Batch2D.hpp"
|
||||
#include "../../graphics/core/Shader.hpp"
|
||||
#include "../../graphics/core/DrawContext.hpp"
|
||||
@@ -27,6 +32,15 @@ GUI::GUI() {
|
||||
menu->setId("menu");
|
||||
container->add(menu);
|
||||
container->setScrollable(false);
|
||||
|
||||
tooltip = guiutil::create(
|
||||
"<container color='#000000A0' interactive='false' z-index='999'>"
|
||||
"<label id='tooltip.label' pos='2' autoresize='true'></label>"
|
||||
"</container>"
|
||||
);
|
||||
store("tooltip", tooltip);
|
||||
store("tooltip.label", UINode::find(tooltip, "tooltip.label"));
|
||||
container->add(tooltip);
|
||||
}
|
||||
|
||||
GUI::~GUI() {
|
||||
@@ -37,7 +51,7 @@ std::shared_ptr<Menu> GUI::getMenu() {
|
||||
}
|
||||
|
||||
void GUI::onAssetsLoad(Assets* assets) {
|
||||
assets->store(new UiDocument(
|
||||
assets->store(std::make_unique<UiDocument>(
|
||||
"core:root",
|
||||
uidocscript {},
|
||||
std::dynamic_pointer_cast<gui::UINode>(container),
|
||||
@@ -45,10 +59,41 @@ void GUI::onAssetsLoad(Assets* assets) {
|
||||
), "core:root");
|
||||
}
|
||||
|
||||
void GUI::resetTooltip() {
|
||||
tooltipTimer = 0.0f;
|
||||
tooltip->setVisible(false);
|
||||
}
|
||||
|
||||
void GUI::updateTooltip(float delta) {
|
||||
if (hover == nullptr || !hover->isInside(Events::cursor)) {
|
||||
return resetTooltip();
|
||||
}
|
||||
if (tooltipTimer + delta >= hover->getTooltipDelay()) {
|
||||
auto label = std::dynamic_pointer_cast<gui::Label>(get("tooltip.label"));
|
||||
const auto& text = hover->getTooltip();
|
||||
if (text.empty() && tooltip->isVisible()) {
|
||||
return resetTooltip();
|
||||
}
|
||||
if (label && !text.empty()) {
|
||||
tooltip->setVisible(true);
|
||||
label->setText(langs::get(text));
|
||||
auto size = label->getSize()+glm::vec2(4.0f);
|
||||
auto pos = Events::cursor+glm::vec2(10.0f);
|
||||
auto rootSize = container->getSize();
|
||||
pos.x = glm::min(pos.x, rootSize.x-size.x);
|
||||
pos.y = glm::min(pos.y, rootSize.y-size.y);
|
||||
tooltip->setSize(size);
|
||||
tooltip->setPos(pos);
|
||||
}
|
||||
}
|
||||
tooltipTimer += delta;
|
||||
}
|
||||
|
||||
/// @brief Mouse related input and logic handling
|
||||
void GUI::actMouse(float delta) {
|
||||
float mouseDelta = glm::length(Events::delta);
|
||||
doubleClicked = false;
|
||||
doubleClickTimer += delta + glm::length(Events::delta) * 0.1f;
|
||||
doubleClickTimer += delta + mouseDelta * 0.1f;
|
||||
|
||||
auto hover = container->getAt(Events::cursor, nullptr);
|
||||
if (this->hover && this->hover != hover) {
|
||||
@@ -134,8 +179,14 @@ void GUI::act(float delta, const Viewport& vp) {
|
||||
container->act(delta);
|
||||
auto prevfocus = focus;
|
||||
|
||||
updateTooltip(delta);
|
||||
if (!Events::_cursor_locked) {
|
||||
actMouse(delta);
|
||||
} else {
|
||||
if (hover) {
|
||||
hover->setHover(false);
|
||||
hover = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (focus) {
|
||||
|
||||
@@ -54,21 +54,25 @@ namespace gui {
|
||||
/// @brief The main UI controller
|
||||
class GUI {
|
||||
std::shared_ptr<Container> container;
|
||||
std::shared_ptr<UINode> hover = nullptr;
|
||||
std::shared_ptr<UINode> pressed = nullptr;
|
||||
std::shared_ptr<UINode> focus = nullptr;
|
||||
std::shared_ptr<UINode> hover;
|
||||
std::shared_ptr<UINode> pressed;
|
||||
std::shared_ptr<UINode> focus;
|
||||
std::shared_ptr<UINode> tooltip;
|
||||
std::unordered_map<std::string, std::shared_ptr<UINode>> storage;
|
||||
|
||||
std::unique_ptr<Camera> uicamera;
|
||||
std::shared_ptr<Menu> menu;
|
||||
std::queue<runnable> postRunnables;
|
||||
|
||||
float tooltipTimer = 0.0f;
|
||||
float doubleClickTimer = 0.0f;
|
||||
float doubleClickDelay = 0.5f;
|
||||
bool doubleClicked = false;
|
||||
|
||||
void actMouse(float delta);
|
||||
void actFocused();
|
||||
void updateTooltip(float delta);
|
||||
void resetTooltip();
|
||||
public:
|
||||
GUI();
|
||||
~GUI();
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
using namespace gui;
|
||||
|
||||
CheckBox::CheckBox(bool checked) : UINode(glm::vec2(32.0f)), checked(checked) {
|
||||
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
setColor({0.0f, 0.0f, 0.0f, 0.5f});
|
||||
setHoverColor({0.05f, 0.1f, 0.2f, 0.75f});
|
||||
}
|
||||
|
||||
void CheckBox::draw(const DrawContext* pctx, Assets*) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
namespace gui {
|
||||
class CheckBox : public UINode {
|
||||
protected:
|
||||
glm::vec4 hoverColor {0.05f, 0.1f, 0.2f, 0.75f};
|
||||
glm::vec4 checkColor {1.0f, 1.0f, 1.0f, 0.4f};
|
||||
boolsupplier supplier = nullptr;
|
||||
boolconsumer consumer = nullptr;
|
||||
@@ -51,6 +50,11 @@ namespace gui {
|
||||
virtual bool isChecked() const {
|
||||
return checkbox->isChecked();
|
||||
}
|
||||
|
||||
virtual void setTooltip(const std::wstring& text) override {
|
||||
Panel::setTooltip(text);
|
||||
checkbox->setTooltip(text);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ Container::Container(glm::vec2 size) : UINode(size) {
|
||||
}
|
||||
|
||||
std::shared_ptr<UINode> Container::getAt(glm::vec2 pos, std::shared_ptr<UINode> self) {
|
||||
if (!interactive || !isEnabled()) {
|
||||
if (!isInteractive() || !isEnabled()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!isInside(pos)) return nullptr;
|
||||
@@ -127,6 +127,14 @@ void Container::remove(std::shared_ptr<UINode> selected) {
|
||||
refresh();
|
||||
}
|
||||
|
||||
void Container::remove(const std::string& id) {
|
||||
for (auto& node : nodes) {
|
||||
if (node->getId() == id) {
|
||||
return remove(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Container::clear() {
|
||||
for (auto node : nodes) {
|
||||
node->setParent(nullptr);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace gui {
|
||||
virtual void add(std::shared_ptr<UINode> node, glm::vec2 pos);
|
||||
virtual void clear();
|
||||
virtual void remove(std::shared_ptr<UINode> node);
|
||||
virtual void remove(const std::string& id);
|
||||
virtual void scrolled(int value) override;
|
||||
virtual void setScrollable(bool flag);
|
||||
void listenInterval(float interval, ontimeout callback, int repeat=-1);
|
||||
|
||||
@@ -33,3 +33,11 @@ void Image::setAutoResize(bool flag) {
|
||||
bool Image::isAutoResize() const {
|
||||
return autoresize;
|
||||
}
|
||||
|
||||
const std::string& Image::getTexture() const {
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Image::setTexture(const std::string& name) {
|
||||
texture = name;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace gui {
|
||||
|
||||
virtual void setAutoResize(bool flag);
|
||||
virtual bool isAutoResize() const;
|
||||
virtual const std::string& getTexture() const;
|
||||
virtual void setTexture(const std::string& name);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "InventoryView.hpp"
|
||||
|
||||
#include "../../../assets/Assets.hpp"
|
||||
#include "../../../content/Content.hpp"
|
||||
#include "../../../frontend/LevelFrontend.hpp"
|
||||
#include "../../../frontend/locale.hpp"
|
||||
#include "../../../items/Inventories.hpp"
|
||||
#include "../../../items/Inventory.hpp"
|
||||
#include "../../../items/ItemDef.hpp"
|
||||
@@ -22,7 +24,6 @@
|
||||
#include "../../render/BlocksPreview.hpp"
|
||||
#include "../GUI.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
using namespace gui;
|
||||
@@ -108,6 +109,7 @@ SlotView::SlotView(
|
||||
layout(layout)
|
||||
{
|
||||
setColor(glm::vec4(0, 0, 0, 0.2f));
|
||||
setTooltipDelay(0.05f);
|
||||
}
|
||||
|
||||
void SlotView::draw(const DrawContext* pctx, Assets* assets) {
|
||||
@@ -251,11 +253,12 @@ void SlotView::clicked(gui::GUI* gui, mousecode button) {
|
||||
stack.setCount(halfremain);
|
||||
}
|
||||
} else {
|
||||
auto stackDef = content->getIndices()->getItemDef(stack.getItemId());
|
||||
if (stack.isEmpty()) {
|
||||
stack.set(grabbed);
|
||||
stack.setCount(1);
|
||||
grabbed.setCount(grabbed.getCount()-1);
|
||||
} else if (stack.accepts(grabbed)){
|
||||
} else if (stack.accepts(grabbed) && stack.getCount() < stackDef->stackSize){
|
||||
stack.setCount(stack.getCount()+1);
|
||||
grabbed.setCount(grabbed.getCount()-1);
|
||||
}
|
||||
@@ -270,6 +273,17 @@ void SlotView::onFocus(gui::GUI* gui) {
|
||||
clicked(gui, mousecode::BUTTON_1);
|
||||
}
|
||||
|
||||
const std::wstring SlotView::getTooltip() const {
|
||||
const auto str = UINode::getTooltip();
|
||||
if (!str.empty() || bound->isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
auto def = content->getIndices()->getItemDef(bound->getItemId());
|
||||
return util::pascal_case(
|
||||
langs::get(util::str2wstr_utf8(def->caption))
|
||||
); // TODO: cache
|
||||
}
|
||||
|
||||
void SlotView::bind(
|
||||
int64_t inventoryid,
|
||||
ItemStack& stack,
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace gui {
|
||||
|
||||
virtual void clicked(gui::GUI*, mousecode) override;
|
||||
virtual void onFocus(gui::GUI*) override;
|
||||
virtual const std::wstring getTooltip() const override;
|
||||
|
||||
void bind(
|
||||
int64_t inventoryid,
|
||||
|
||||
@@ -64,12 +64,28 @@ Label::Label(std::wstring text, std::string fontName)
|
||||
cache.update(this->text, multiline, textWrap);
|
||||
}
|
||||
|
||||
glm::vec2 Label::calcSize() {
|
||||
auto font = cache.font;
|
||||
uint lineHeight = font->getLineHeight();
|
||||
if (cache.lines.size() > 1) {
|
||||
lineHeight *= lineInterval;
|
||||
}
|
||||
return glm::vec2 (
|
||||
cache.font->calcWidth(text),
|
||||
lineHeight * cache.lines.size() + font->getYOffset()
|
||||
);
|
||||
}
|
||||
|
||||
void Label::setText(std::wstring text) {
|
||||
if (text == this->text && !cache.resetFlag) {
|
||||
return;
|
||||
}
|
||||
this->text = text;
|
||||
cache.update(this->text, multiline, textWrap);
|
||||
|
||||
if (cache.font && autoresize) {
|
||||
setSize(calcSize());
|
||||
}
|
||||
}
|
||||
|
||||
const std::wstring& Label::getText() const {
|
||||
@@ -156,10 +172,10 @@ void Label::draw(const DrawContext* pctx, Assets* assets) {
|
||||
lineHeight *= lineInterval;
|
||||
}
|
||||
glm::vec2 size = getSize();
|
||||
glm::vec2 newsize (
|
||||
font->calcWidth(text),
|
||||
lineHeight * cache.lines.size() + font->getYOffset()
|
||||
);
|
||||
glm::vec2 newsize = calcSize();
|
||||
if (autoresize) {
|
||||
setSize(newsize);
|
||||
}
|
||||
|
||||
glm::vec2 pos = calcPos();
|
||||
switch (align) {
|
||||
@@ -194,6 +210,13 @@ void Label::textSupplier(wstringsupplier supplier) {
|
||||
this->supplier = supplier;
|
||||
}
|
||||
|
||||
void Label::setAutoResize(bool flag) {
|
||||
this->autoresize = flag;
|
||||
}
|
||||
|
||||
bool Label::isAutoResize() const {
|
||||
return autoresize;
|
||||
}
|
||||
|
||||
void Label::setMultiline(bool multiline) {
|
||||
if (multiline != this->multiline) {
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace gui {
|
||||
|
||||
class Label : public UINode {
|
||||
LabelCache cache;
|
||||
|
||||
glm::vec2 calcSize();
|
||||
protected:
|
||||
std::wstring text;
|
||||
std::string fontName;
|
||||
@@ -47,6 +49,9 @@ namespace gui {
|
||||
|
||||
/// @brief Text line height multiplied by line interval
|
||||
int totalLineHeight = 1;
|
||||
|
||||
/// @brief Auto resize label to fit text
|
||||
bool autoresize = false;
|
||||
public:
|
||||
Label(std::string text, std::string fontName="normal");
|
||||
Label(std::wstring text, std::string fontName="normal");
|
||||
@@ -95,6 +100,9 @@ namespace gui {
|
||||
|
||||
virtual void textSupplier(wstringsupplier supplier);
|
||||
|
||||
virtual void setAutoResize(bool flag);
|
||||
virtual bool isAutoResize() const;
|
||||
|
||||
virtual void setMultiline(bool multiline);
|
||||
virtual bool isMultiline() const;
|
||||
|
||||
|
||||
@@ -337,6 +337,9 @@ inline std::wstring get_alphabet(wchar_t c) {
|
||||
}
|
||||
|
||||
void TextBox::tokenSelectAt(int index) {
|
||||
if (input.empty()) {
|
||||
return;
|
||||
}
|
||||
int left = index;
|
||||
int right = index;
|
||||
|
||||
@@ -369,7 +372,7 @@ void TextBox::click(GUI*, int x, int y) {
|
||||
}
|
||||
|
||||
void TextBox::mouseMove(GUI*, int x, int y) {
|
||||
ssize_t index = calcIndexAt(x, y);
|
||||
ptrdiff_t index = calcIndexAt(x, y);
|
||||
setCaret(index);
|
||||
extendSelection(index);
|
||||
resetMaxLocalCaret();
|
||||
@@ -452,7 +455,7 @@ void TextBox::stepDefaultUp(bool shiftPressed, bool breakSelection) {
|
||||
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine-1)-1);
|
||||
setCaret(label->getTextLineOffset(caretLine-1) + offset);
|
||||
} else {
|
||||
setCaret(0UL);
|
||||
setCaret(static_cast<size_t>(0));
|
||||
}
|
||||
if (shiftPressed) {
|
||||
if (selectionStart == selectionEnd) {
|
||||
@@ -652,11 +655,11 @@ void TextBox::setCaret(size_t position) {
|
||||
if (realoffset-width > 0) {
|
||||
setTextOffset(textOffset + realoffset-width);
|
||||
} else if (realoffset < 0) {
|
||||
setTextOffset(std::max(textOffset + realoffset, 0LU));
|
||||
setTextOffset(std::max(textOffset + realoffset, static_cast<size_t>(0)));
|
||||
}
|
||||
}
|
||||
|
||||
void TextBox::setCaret(ssize_t position) {
|
||||
void TextBox::setCaret(ptrdiff_t position) {
|
||||
if (position < 0) {
|
||||
setCaret(static_cast<size_t>(input.length() + position + 1));
|
||||
} else {
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace gui {
|
||||
|
||||
/// @brief Set caret position in the text
|
||||
/// @param position integer in range [-text.length(), text.length()]
|
||||
virtual void setCaret(ssize_t position);
|
||||
virtual void setCaret(ptrdiff_t position);
|
||||
|
||||
/// @brief Select part of the text
|
||||
/// @param start index of the first selected character
|
||||
|
||||
@@ -13,6 +13,9 @@ UINode::~UINode() {
|
||||
}
|
||||
|
||||
bool UINode::isVisible() const {
|
||||
if (visible && parent) {
|
||||
return parent->isVisible();
|
||||
}
|
||||
return visible;
|
||||
}
|
||||
|
||||
@@ -107,7 +110,7 @@ bool UINode::isInside(glm::vec2 point) {
|
||||
}
|
||||
|
||||
std::shared_ptr<UINode> UINode::getAt(glm::vec2 point, std::shared_ptr<UINode> self) {
|
||||
if (!interactive || !enabled) {
|
||||
if (!isInteractive() || !enabled) {
|
||||
return nullptr;
|
||||
}
|
||||
return isInside(point) ? self : nullptr;
|
||||
@@ -129,6 +132,22 @@ bool UINode::isResizing() const {
|
||||
return resizing;
|
||||
}
|
||||
|
||||
void UINode::setTooltip(const std::wstring& text) {
|
||||
this->tooltip = text;
|
||||
}
|
||||
|
||||
const std::wstring UINode::getTooltip() const {
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
void UINode::setTooltipDelay(float delay) {
|
||||
tooltipDelay = delay;
|
||||
}
|
||||
|
||||
float UINode::getTooltipDelay() const {
|
||||
return tooltipDelay;
|
||||
}
|
||||
|
||||
glm::vec2 UINode::calcPos() const {
|
||||
if (parent) {
|
||||
return pos + parent->calcPos() + parent->contentOffset();
|
||||
@@ -315,8 +334,18 @@ void UINode::setGravity(Gravity gravity) {
|
||||
}
|
||||
}
|
||||
|
||||
bool UINode::isSubnodeOf(const UINode* node) {
|
||||
if (parent == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (parent == node) {
|
||||
return true;
|
||||
}
|
||||
return parent->isSubnodeOf(node);
|
||||
}
|
||||
|
||||
void UINode::getIndices(
|
||||
std::shared_ptr<UINode> node,
|
||||
const std::shared_ptr<UINode> node,
|
||||
std::unordered_map<std::string, std::shared_ptr<UINode>>& map
|
||||
) {
|
||||
const std::string& id = node->getId();
|
||||
@@ -330,3 +359,19 @@ void UINode::getIndices(
|
||||
}
|
||||
}
|
||||
}
|
||||
std::shared_ptr<UINode> UINode::find(
|
||||
const std::shared_ptr<UINode> node,
|
||||
const std::string& id
|
||||
) {
|
||||
if (node->getId() == id) {
|
||||
return node;
|
||||
}
|
||||
if (auto container = std::dynamic_pointer_cast<Container>(node)) {
|
||||
for (auto subnode : container->getNodes()) {
|
||||
if (auto found = UINode::find(subnode, id)) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -109,6 +109,10 @@ namespace gui {
|
||||
ActionsSet actions;
|
||||
/// @brief 'ondoubleclick' callbacks
|
||||
ActionsSet doubleClickCallbacks;
|
||||
/// @brief element tooltip text
|
||||
std::wstring tooltip;
|
||||
/// @brief element tooltip delay
|
||||
float tooltipDelay = 0.5f;
|
||||
|
||||
UINode(glm::vec2 size);
|
||||
public:
|
||||
@@ -197,6 +201,12 @@ namespace gui {
|
||||
virtual void setResizing(bool flag);
|
||||
virtual bool isResizing() const;
|
||||
|
||||
virtual void setTooltip(const std::wstring& text);
|
||||
virtual const std::wstring getTooltip() const;
|
||||
|
||||
virtual void setTooltipDelay(float delay);
|
||||
virtual float getTooltipDelay() const;
|
||||
|
||||
virtual glm::vec4 calcColor() const;
|
||||
|
||||
/// @brief Get inner content offset. Used for scroll
|
||||
@@ -235,11 +245,18 @@ namespace gui {
|
||||
|
||||
virtual void setGravity(Gravity gravity);
|
||||
|
||||
bool isSubnodeOf(const UINode* node);
|
||||
|
||||
/// @brief collect all nodes having id
|
||||
static void getIndices(
|
||||
std::shared_ptr<UINode> node,
|
||||
const std::shared_ptr<UINode> node,
|
||||
std::unordered_map<std::string, std::shared_ptr<UINode>>& map
|
||||
);
|
||||
|
||||
static std::shared_ptr<UINode> find(
|
||||
const std::shared_ptr<UINode> node,
|
||||
const std::string& id
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,13 @@ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& no
|
||||
));
|
||||
}
|
||||
|
||||
if (element->has("tooltip")) {
|
||||
node.setTooltip(util::str2wstr_utf8(element->attr("tooltip").getText()));
|
||||
}
|
||||
if (element->has("tooltip-delay")) {
|
||||
node.setTooltipDelay(element->attr("tooltip-delay").asFloat());
|
||||
}
|
||||
|
||||
if (auto onclick = create_action(reader, element, "onclick")) {
|
||||
node.listenAction(onclick);
|
||||
}
|
||||
@@ -245,6 +252,9 @@ static std::shared_ptr<UINode> readLabel(UiXmlReader& reader, xml::xmlelement el
|
||||
reader.getFilename()
|
||||
));
|
||||
}
|
||||
if (element->has("autoresize")) {
|
||||
label->setAutoResize(element->attr("autoresize").asBool());
|
||||
}
|
||||
if (element->has("multiline")) {
|
||||
label->setMultiline(element->attr("multiline").asBool());
|
||||
if (!element->has("valign")) {
|
||||
|
||||
@@ -21,7 +21,7 @@ void LightSolver::add(int x, int y, int z, int emission) {
|
||||
addqueue.push(lightentry {x, y, z, ubyte(emission)});
|
||||
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
chunk->lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, emission);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ void LightSolver::solve(){
|
||||
if (chunk) {
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
|
||||
ubyte light = chunk->lightmap.get(lx,y,lz, channel);
|
||||
if (light != 0 && light == entry.light-1){
|
||||
@@ -96,7 +96,7 @@ void LightSolver::solve(){
|
||||
if (chunk) {
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
chunk->setModified(true);
|
||||
chunk->flags.modified = true;
|
||||
|
||||
ubyte light = chunk->lightmap.get(lx, y, lz, channel);
|
||||
voxel& v = chunk->voxels[vox_index(lx, y, lz)];
|
||||
|
||||
@@ -53,8 +53,8 @@ int Clock::getTickId() const {
|
||||
|
||||
BlocksController::BlocksController(Level* level, uint padding)
|
||||
: level(level),
|
||||
chunks(level->chunks.get()),
|
||||
lighting(level->lighting.get()),
|
||||
chunks(level->chunks.get()),
|
||||
lighting(level->lighting.get()),
|
||||
randTickClock(20, 3),
|
||||
blocksTickClock(20, 1),
|
||||
worldTickClock(20, 1),
|
||||
@@ -71,7 +71,7 @@ void BlocksController::updateSides(int x, int y, int z) {
|
||||
}
|
||||
|
||||
void BlocksController::breakBlock(Player* player, const Block* def, int x, int y, int z) {
|
||||
chunks->set(x,y,z, 0, 0);
|
||||
chunks->set(x,y,z, 0, {});
|
||||
lighting->onBlockSet(x,y,z, 0);
|
||||
if (def->rt.funcsset.onbroken) {
|
||||
scripting::on_block_broken(player, def, x, y, z);
|
||||
@@ -113,8 +113,9 @@ void BlocksController::onBlocksTick(int tickid, int parts) {
|
||||
if ((id + tickid) % parts != 0)
|
||||
continue;
|
||||
auto def = indices->getBlockDef(id);
|
||||
if (def->rt.funcsset.onblockstick) {
|
||||
scripting::on_blocks_tick(def, tickRate);
|
||||
auto interval = def->tickInterval;
|
||||
if (def->rt.funcsset.onblockstick && tickid / parts % interval == 0) {
|
||||
scripting::on_blocks_tick(def, tickRate / interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +133,7 @@ void BlocksController::randomTick(int tickid, int parts) {
|
||||
if ((index + tickid) % parts != 0)
|
||||
continue;
|
||||
auto& chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr || !chunk->isLighted())
|
||||
if (chunk == nullptr || !chunk->flags.lighted)
|
||||
continue;
|
||||
for (int s = 0; s < segments; s++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -150,49 +151,49 @@ void BlocksController::randomTick(int tickid, int parts) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t BlocksController::createBlockInventory(int x, int y, int z) {
|
||||
auto chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
auto inv = chunk->getBlockInventory(lx, y, lz);
|
||||
if (inv == nullptr) {
|
||||
auto chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
auto inv = chunk->getBlockInventory(lx, y, lz);
|
||||
if (inv == nullptr) {
|
||||
auto indices = level->content->getIndices();
|
||||
auto def = indices->getBlockDef(chunk->voxels[vox_index(lx, y, lz)].id);
|
||||
int invsize = def->inventorySize;
|
||||
if (invsize == 0) {
|
||||
return 0;
|
||||
}
|
||||
inv = level->inventories->create(invsize);
|
||||
inv = level->inventories->create(invsize);
|
||||
chunk->addBlockInventory(inv, lx, y, lz);
|
||||
}
|
||||
}
|
||||
return inv->getId();
|
||||
}
|
||||
|
||||
void BlocksController::bindInventory(int64_t invid, int x, int y, int z) {
|
||||
auto chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr) {
|
||||
throw std::runtime_error("block does not exists");
|
||||
}
|
||||
if (chunk == nullptr) {
|
||||
throw std::runtime_error("block does not exists");
|
||||
}
|
||||
if (invid <= 0) {
|
||||
throw std::runtime_error("unable to bind virtual inventory");
|
||||
}
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
chunk->addBlockInventory(level->inventories->get(invid), lx, y, lz);
|
||||
}
|
||||
|
||||
void BlocksController::unbindInventory(int x, int y, int z) {
|
||||
auto chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr) {
|
||||
throw std::runtime_error("block does not exists");
|
||||
}
|
||||
if (chunk == nullptr) {
|
||||
throw std::runtime_error("block does not exists");
|
||||
}
|
||||
int lx = x - chunk->x * CHUNK_W;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
int lz = z - chunk->z * CHUNK_D;
|
||||
chunk->removeBlockInventory(lx, y, lz);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ bool ChunksController::loadVisible(){
|
||||
int index = z * w + x;
|
||||
auto& chunk = chunks->chunks[index];
|
||||
if (chunk != nullptr){
|
||||
if (chunk->isLoaded() && !chunk->isLighted()) {
|
||||
if (chunk->flags.loaded && !chunk->flags.lighted) {
|
||||
if (buildLights(chunk)) {
|
||||
return true;
|
||||
}
|
||||
@@ -99,12 +99,12 @@ bool ChunksController::buildLights(std::shared_ptr<Chunk> chunk) {
|
||||
}
|
||||
}
|
||||
if (surrounding == MIN_SURROUNDING) {
|
||||
bool lightsCache = chunk->isLoadedLights();
|
||||
bool lightsCache = chunk->flags.loadedLights;
|
||||
if (!lightsCache) {
|
||||
lighting->buildSkyLight(chunk->x, chunk->z);
|
||||
}
|
||||
lighting->onChunkLoaded(chunk->x, chunk->z, !lightsCache);
|
||||
chunk->setLighted(true);
|
||||
chunk->flags.lighted = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -114,20 +114,20 @@ void ChunksController::createChunk(int x, int z) {
|
||||
auto chunk = level->chunksStorage->create(x, z);
|
||||
chunks->putChunk(chunk);
|
||||
|
||||
if (!chunk->isLoaded()) {
|
||||
if (!chunk->flags.loaded) {
|
||||
generator->generate(
|
||||
chunk->voxels, x, z,
|
||||
level->getWorld()->getSeed()
|
||||
);
|
||||
chunk->setUnsaved(true);
|
||||
chunk->flags.unsaved = true;
|
||||
}
|
||||
chunk->updateHeights();
|
||||
|
||||
if (!chunk->isLoadedLights()) {
|
||||
if (!chunk->flags.loadedLights) {
|
||||
Lighting::prebuildSkyLight(
|
||||
chunk.get(), level->content->getIndices()
|
||||
);
|
||||
}
|
||||
chunk->setLoaded(true);
|
||||
chunk->setReady(true);
|
||||
chunk->flags.loaded = true;
|
||||
chunk->flags.ready = true;
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ public:
|
||||
dynamic::Value value = dynamic::NONE;
|
||||
if (peek() == '~') {
|
||||
relative = true;
|
||||
value = 0L;
|
||||
value = static_cast<integer_t>(0);
|
||||
nextChar();
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,8 @@ void EngineController::reconfigPacks(
|
||||
|
||||
std::stringstream ss;
|
||||
for (const auto& id : packsToRemove) {
|
||||
if (content->getPackRuntime(id)->getStats().hasSavingContent()) {
|
||||
auto runtime = content->getPackRuntime(id);
|
||||
if (runtime && runtime->getStats().hasSavingContent()) {
|
||||
if (hasIndices) {
|
||||
ss << ", ";
|
||||
}
|
||||
@@ -234,13 +235,22 @@ void EngineController::reconfigPacks(
|
||||
|
||||
runnable removeFunc = [=]() {
|
||||
if (controller == nullptr) {
|
||||
auto manager = engine->createPacksManager(fs::path(""));
|
||||
manager.scan();
|
||||
std::vector<std::string> names = engine->getBasePacks();
|
||||
for (auto& name : packsToAdd) {
|
||||
names.push_back(name);
|
||||
try {
|
||||
auto manager = engine->createPacksManager(fs::path(""));
|
||||
manager.scan();
|
||||
std::vector<std::string> names = PacksManager::getNames(engine->getContentPacks());
|
||||
for (const auto& id : packsToAdd) {
|
||||
names.push_back(id);
|
||||
}
|
||||
for (const auto& id : packsToRemove) {
|
||||
manager.exclude(id);
|
||||
names.erase(std::find(names.begin(), names.end(), id));
|
||||
}
|
||||
names = manager.assembly(names);
|
||||
engine->getContentPacks() = manager.getAll(names);
|
||||
} catch (const contentpack_error& err) {
|
||||
throw std::runtime_error(std::string(err.what())+" ["+err.getPackId()+"]");
|
||||
}
|
||||
engine->getContentPacks() = manager.getAll(names);
|
||||
} else {
|
||||
auto world = controller->getLevel()->getWorld();
|
||||
auto wfile = world->wfile.get();
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "LevelController.hpp"
|
||||
|
||||
#include "../settings.hpp"
|
||||
#include "../files/WorldFiles.hpp"
|
||||
#include "../debug/Logger.hpp"
|
||||
#include "../world/Level.hpp"
|
||||
@@ -20,12 +22,12 @@ LevelController::LevelController(EngineSettings& settings, std::unique_ptr<Level
|
||||
}
|
||||
|
||||
void LevelController::update(float delta, bool input, bool pause) {
|
||||
player->update(delta, input, pause);
|
||||
glm::vec3 position = player->getPlayer()->hitbox->position;
|
||||
level->loadMatrix(position.x, position.z,
|
||||
settings.chunks.loadDistance.get() +
|
||||
settings.chunks.padding.get() * 2);
|
||||
chunks->update(settings.chunks.loadSpeed.get());
|
||||
player->update(delta, input, pause);
|
||||
|
||||
// erease null pointers
|
||||
level->objects.erase(
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define LOGIC_LEVEL_CONTROLLER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include "../settings.hpp"
|
||||
|
||||
#include "PlayerController.hpp"
|
||||
#include "BlocksController.hpp"
|
||||
@@ -10,6 +9,7 @@
|
||||
|
||||
class Level;
|
||||
class Player;
|
||||
struct EngineSettings;
|
||||
|
||||
/// @brief LevelController manages other controllers
|
||||
class LevelController {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "../items/ItemStack.hpp"
|
||||
#include "../items/Inventory.hpp"
|
||||
#include "../core_defs.hpp"
|
||||
#include "../settings.hpp"
|
||||
|
||||
const float CAM_SHAKE_OFFSET = 0.025f;
|
||||
const float CAM_SHAKE_OFFSET_Y = 0.031f;
|
||||
@@ -46,14 +47,16 @@ void CameraControl::refresh() {
|
||||
}
|
||||
|
||||
void CameraControl::updateMouse(PlayerInput& input) {
|
||||
glm::vec2& cam = player->cam;
|
||||
glm::vec3& cam = player->cam;
|
||||
|
||||
float sensitivity = (input.zoom
|
||||
? settings.sensitivity.get() / 4.f
|
||||
: settings.sensitivity.get());
|
||||
|
||||
cam -= glm::degrees(Events::delta / (float)Window::height * sensitivity);
|
||||
|
||||
auto d = glm::degrees(Events::delta / (float)Window::height * sensitivity);
|
||||
cam.x -= d.x;
|
||||
cam.y -= d.y;
|
||||
|
||||
if (cam.y < -89.9f) {
|
||||
cam.y = -89.9f;
|
||||
}
|
||||
@@ -68,7 +71,7 @@ void CameraControl::updateMouse(PlayerInput& input) {
|
||||
}
|
||||
|
||||
camera->rotation = glm::mat4(1.0f);
|
||||
camera->rotate(glm::radians(cam.y), glm::radians(cam.x), 0);
|
||||
camera->rotate(glm::radians(cam.y), glm::radians(cam.x), glm::radians(cam.z));
|
||||
}
|
||||
|
||||
glm::vec3 CameraControl::updateCameraShaking(float delta) {
|
||||
@@ -163,11 +166,10 @@ void CameraControl::update(const PlayerInput& input, float delta, Chunks* chunks
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 PlayerController::selectedBlockPosition;
|
||||
glm::vec3 PlayerController::selectedPointPosition;
|
||||
glm::ivec3 PlayerController::selectedBlockNormal;
|
||||
int PlayerController::selectedBlockId = -1;
|
||||
int PlayerController::selectedBlockStates = 0;
|
||||
int PlayerController::selectedBlockRotation = 0;
|
||||
|
||||
PlayerController::PlayerController(
|
||||
Level* level,
|
||||
@@ -247,7 +249,7 @@ void PlayerController::update(float delta, bool input, bool pause) {
|
||||
updateInteraction();
|
||||
} else {
|
||||
selectedBlockId = -1;
|
||||
selectedBlockStates = 0;
|
||||
selectedBlockRotation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,11 +361,11 @@ void PlayerController::updateInteraction(){
|
||||
maxDistance,
|
||||
end, norm, iend
|
||||
);
|
||||
if (vox != nullptr){
|
||||
if (vox != nullptr) {
|
||||
player->selectedVoxel = *vox;
|
||||
selectedBlockId = vox->id;
|
||||
selectedBlockStates = vox->states;
|
||||
selectedBlockPosition = iend;
|
||||
selectedBlockRotation = vox->state.rotation;
|
||||
player->selectedBlockPosition = iend;
|
||||
selectedPointPosition = end;
|
||||
selectedBlockNormal = norm;
|
||||
int x = iend.x;
|
||||
@@ -371,7 +373,8 @@ void PlayerController::updateInteraction(){
|
||||
int z = iend.z;
|
||||
|
||||
Block* def = indices->getBlockDef(item->rt.placingBlock);
|
||||
uint8_t states = determine_rotation(def, norm, camera->dir);
|
||||
blockstate state {};
|
||||
state.rotation = determine_rotation(def, norm, camera->dir);
|
||||
|
||||
if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) {
|
||||
if (scripting::on_item_break_block(player.get(), item, x, y, z))
|
||||
@@ -408,13 +411,13 @@ void PlayerController::updateInteraction(){
|
||||
z = (iend.z)+(norm.z);
|
||||
} else {
|
||||
if (def->rotations.name == "pipe") {
|
||||
states = BLOCK_DIR_UP;
|
||||
state.rotation = BLOCK_DIR_UP;
|
||||
}
|
||||
}
|
||||
vox = chunks->get(x, y, z);
|
||||
blockid_t chosenBlock = def->rt.id;
|
||||
if (vox && (target = indices->getBlockDef(vox->id))->replaceable) {
|
||||
if (!level->physics->isBlockInside(x,y,z,def,states, player->hitbox.get())
|
||||
if (!level->physics->isBlockInside(x,y,z,def,state, player->hitbox.get())
|
||||
|| !def->obstacle){
|
||||
if (def->grounded && !chunks->isSolidBlock(x, y-1, z)) {
|
||||
chosenBlock = 0;
|
||||
@@ -424,7 +427,7 @@ void PlayerController::updateInteraction(){
|
||||
glm::ivec3(x, y, z), def,
|
||||
BlockInteraction::placing
|
||||
);
|
||||
chunks->set(x, y, z, chosenBlock, states);
|
||||
chunks->set(x, y, z, chosenBlock, state);
|
||||
lighting->onBlockSet(x,y,z, chosenBlock);
|
||||
if (def->rt.funcsset.onplaced) {
|
||||
scripting::on_block_placed(player.get(), def, x, y, z);
|
||||
@@ -439,12 +442,13 @@ void PlayerController::updateInteraction(){
|
||||
}
|
||||
} else {
|
||||
selectedBlockId = -1;
|
||||
selectedBlockStates = 0;
|
||||
}
|
||||
if (rclick) {
|
||||
if (item->rt.funcsset.on_use) {
|
||||
scripting::on_item_use(player.get(), item);
|
||||
}
|
||||
selectedBlockRotation = 0;
|
||||
player->selectedVoxel.id = BLOCK_VOID;
|
||||
if (rclick) {
|
||||
if (item->rt.funcsset.on_use) {
|
||||
scripting::on_item_use(player.get(), item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef PLAYER_CONTROL_HPP_
|
||||
#define PLAYER_CONTROL_HPP_
|
||||
|
||||
#include "../settings.hpp"
|
||||
#include "../objects/Player.hpp"
|
||||
|
||||
#include <memory>
|
||||
@@ -12,7 +11,9 @@
|
||||
class Camera;
|
||||
class Level;
|
||||
class Block;
|
||||
class Chunks;
|
||||
class BlocksController;
|
||||
struct CameraSettings;
|
||||
|
||||
class CameraControl {
|
||||
std::shared_ptr<Player> player;
|
||||
@@ -76,11 +77,10 @@ class PlayerController {
|
||||
void onFootstep();
|
||||
void updateFootsteps(float delta);
|
||||
public:
|
||||
static glm::vec3 selectedBlockPosition;
|
||||
static glm::ivec3 selectedBlockNormal;
|
||||
static glm::vec3 selectedPointPosition;
|
||||
static int selectedBlockId;
|
||||
static int selectedBlockStates;
|
||||
static int selectedBlockRotation;
|
||||
|
||||
PlayerController(
|
||||
Level* level,
|
||||
|
||||
@@ -12,14 +12,16 @@ inline std::string LAMBDAS_TABLE = "$L";
|
||||
|
||||
static debug::Logger logger("lua-state");
|
||||
|
||||
using namespace lua;
|
||||
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
extern LuaState* state;
|
||||
}
|
||||
|
||||
lua::luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
|
||||
luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
|
||||
}
|
||||
|
||||
void lua::LuaState::removeLibFuncs(const char* libname, const char* funcs[]) {
|
||||
void LuaState::removeLibFuncs(const char* libname, const char* funcs[]) {
|
||||
if (getglobal(libname)) {
|
||||
for (uint i = 0; funcs[i]; i++) {
|
||||
pushnil();
|
||||
@@ -28,13 +30,13 @@ void lua::LuaState::removeLibFuncs(const char* libname, const char* funcs[]) {
|
||||
}
|
||||
}
|
||||
|
||||
lua::LuaState::LuaState() {
|
||||
LuaState::LuaState() {
|
||||
logger.info() << LUA_VERSION;
|
||||
logger.info() << LUAJIT_VERSION;
|
||||
|
||||
L = luaL_newstate();
|
||||
if (L == nullptr) {
|
||||
throw lua::luaerror("could not to initialize Lua");
|
||||
throw luaerror("could not to initialize Lua");
|
||||
}
|
||||
// Allowed standard libraries
|
||||
luaopen_base(L);
|
||||
@@ -66,24 +68,24 @@ lua::LuaState::LuaState() {
|
||||
setglobal(LAMBDAS_TABLE);
|
||||
}
|
||||
|
||||
const std::string lua::LuaState::envName(int env) {
|
||||
const std::string LuaState::envName(int env) {
|
||||
return "_ENV"+util::mangleid(env);
|
||||
}
|
||||
|
||||
lua::LuaState::~LuaState() {
|
||||
LuaState::~LuaState() {
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
void lua::LuaState::logError(const std::string& text) {
|
||||
void LuaState::logError(const std::string& text) {
|
||||
logger.error() << text;
|
||||
}
|
||||
|
||||
void lua::LuaState::addfunc(const std::string& name, lua_CFunction func) {
|
||||
void LuaState::addfunc(const std::string& name, lua_CFunction func) {
|
||||
lua_pushcfunction(L, func);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
bool lua::LuaState::getglobal(const std::string& name) {
|
||||
bool LuaState::getglobal(const std::string& name) {
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
@@ -92,7 +94,7 @@ bool lua::LuaState::getglobal(const std::string& name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lua::LuaState::hasglobal(const std::string& name) {
|
||||
bool LuaState::hasglobal(const std::string& name) {
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
@@ -102,11 +104,11 @@ bool lua::LuaState::hasglobal(const std::string& name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void lua::LuaState::setglobal(const std::string& name) {
|
||||
void LuaState::setglobal(const std::string& name) {
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
bool lua::LuaState::rename(const std::string& from, const std::string& to) {
|
||||
bool LuaState::rename(const std::string& from, const std::string& to) {
|
||||
const char* src = from.c_str();
|
||||
lua_getglobal(L, src);
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
@@ -121,12 +123,12 @@ bool lua::LuaState::rename(const std::string& from, const std::string& to) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void lua::LuaState::remove(const std::string& name) {
|
||||
void LuaState::remove(const std::string& name) {
|
||||
lua_pushnil(L);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
void lua::LuaState::createLibs() {
|
||||
void LuaState::createLibs() {
|
||||
openlib("audio", audiolib);
|
||||
openlib("block", blocklib);
|
||||
openlib("console", consolelib);
|
||||
@@ -140,28 +142,29 @@ void lua::LuaState::createLibs() {
|
||||
openlib("pack", packlib);
|
||||
openlib("player", playerlib);
|
||||
openlib("time", timelib);
|
||||
openlib("toml", tomllib);
|
||||
openlib("world", worldlib);
|
||||
|
||||
addfunc("print", lua_wrap_errors<l_print>);
|
||||
}
|
||||
|
||||
void lua::LuaState::loadbuffer(int env, const std::string& src, const std::string& file) {
|
||||
void LuaState::loadbuffer(int env, const std::string& src, const std::string& file) {
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
|
||||
throw lua::luaerror(lua_tostring(L, -1));
|
||||
throw luaerror(lua_tostring(L, -1));
|
||||
}
|
||||
if (env && getglobal(envName(env))) {
|
||||
lua_setfenv(L, -2);
|
||||
}
|
||||
}
|
||||
|
||||
int lua::LuaState::call(int argc, int nresults) {
|
||||
int LuaState::call(int argc, int nresults) {
|
||||
if (lua_pcall(L, argc, nresults, 0)) {
|
||||
throw lua::luaerror(lua_tostring(L, -1));
|
||||
throw luaerror(lua_tostring(L, -1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::callNoThrow(int argc) {
|
||||
int LuaState::callNoThrow(int argc) {
|
||||
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
|
||||
logError(lua_tostring(L, -1));
|
||||
return 0;
|
||||
@@ -169,59 +172,59 @@ int lua::LuaState::callNoThrow(int argc) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::eval(int env, const std::string& src, const std::string& file) {
|
||||
int LuaState::eval(int env, const std::string& src, const std::string& file) {
|
||||
auto srcText = "return "+src;
|
||||
loadbuffer(env, srcText, file);
|
||||
return call(0);
|
||||
}
|
||||
|
||||
int lua::LuaState::execute(int env, const std::string& src, const std::string& file) {
|
||||
int LuaState::execute(int env, const std::string& src, const std::string& file) {
|
||||
loadbuffer(env, src, file);
|
||||
return callNoThrow(0);
|
||||
}
|
||||
|
||||
int lua::LuaState::gettop() const {
|
||||
int LuaState::gettop() const {
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
int lua::LuaState::pushinteger(luaint x) {
|
||||
int LuaState::pushinteger(lua_Integer x) {
|
||||
lua_pushinteger(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushnumber(luanumber x) {
|
||||
int LuaState::pushnumber(lua_Number x) {
|
||||
lua_pushnumber(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushboolean(bool x) {
|
||||
int LuaState::pushboolean(bool x) {
|
||||
lua_pushboolean(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushivec3(luaint x, luaint y, luaint z) {
|
||||
int LuaState::pushivec3(lua_Integer x, lua_Integer y, lua_Integer z) {
|
||||
lua::pushivec3(L, x, y, z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushstring(const std::string& str) {
|
||||
int LuaState::pushstring(const std::string& str) {
|
||||
lua_pushstring(L, str.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushenv(int env) {
|
||||
int LuaState::pushenv(int env) {
|
||||
if (getglobal(envName(env))) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushvalue(int idx) {
|
||||
int LuaState::pushvalue(int idx) {
|
||||
lua_pushvalue(L, idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushvalue(const dynamic::Value& value) {
|
||||
int LuaState::pushvalue(const dynamic::Value& value) {
|
||||
using namespace dynamic;
|
||||
|
||||
if (auto* flag = std::get_if<bool>(&value)) {
|
||||
@@ -252,26 +255,26 @@ int lua::LuaState::pushvalue(const dynamic::Value& value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushglobals() {
|
||||
int LuaState::pushglobals() {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushcfunction(lua_CFunction function) {
|
||||
int LuaState::pushcfunction(lua_CFunction function) {
|
||||
lua_pushcfunction(L, function);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lua::LuaState::pop(int n) {
|
||||
void LuaState::pop(int n) {
|
||||
lua_pop(L, n);
|
||||
}
|
||||
|
||||
int lua::LuaState::pushnil() {
|
||||
int LuaState::pushnil() {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool lua::LuaState::getfield(const std::string& name, int idx) {
|
||||
bool LuaState::getfield(const std::string& name, int idx) {
|
||||
lua_getfield(L, idx, name.c_str());
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, -1);
|
||||
@@ -280,35 +283,35 @@ bool lua::LuaState::getfield(const std::string& name, int idx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void lua::LuaState::setfield(const std::string& name, int idx) {
|
||||
void LuaState::setfield(const std::string& name, int idx) {
|
||||
lua_setfield(L, idx, name.c_str());
|
||||
}
|
||||
|
||||
bool lua::LuaState::toboolean(int idx) {
|
||||
bool LuaState::toboolean(int idx) {
|
||||
return lua_toboolean(L, idx);
|
||||
}
|
||||
|
||||
lua::luaint lua::LuaState::tointeger(int idx) {
|
||||
lua_Integer LuaState::tointeger(int idx) {
|
||||
return lua_tointeger(L, idx);
|
||||
}
|
||||
|
||||
lua::luanumber lua::LuaState::tonumber(int idx) {
|
||||
lua_Number LuaState::tonumber(int idx) {
|
||||
return lua_tonumber(L, idx);
|
||||
}
|
||||
|
||||
glm::vec2 lua::LuaState::tovec2(int idx) {
|
||||
glm::vec2 LuaState::tovec2(int idx) {
|
||||
return lua::tovec2(L, idx);
|
||||
}
|
||||
|
||||
glm::vec4 lua::LuaState::tocolor(int idx) {
|
||||
glm::vec4 LuaState::tocolor(int idx) {
|
||||
return lua::tocolor(L, idx);
|
||||
}
|
||||
|
||||
const char* lua::LuaState::tostring(int idx) {
|
||||
const char* LuaState::tostring(int idx) {
|
||||
return lua_tostring(L, idx);
|
||||
}
|
||||
|
||||
dynamic::Value lua::LuaState::tovalue(int idx) {
|
||||
dynamic::Value LuaState::tovalue(int idx) {
|
||||
using namespace dynamic;
|
||||
auto type = lua_type(L, idx);
|
||||
switch (type) {
|
||||
@@ -361,21 +364,21 @@ dynamic::Value lua::LuaState::tovalue(int idx) {
|
||||
}
|
||||
}
|
||||
|
||||
bool lua::LuaState::isstring(int idx) {
|
||||
bool LuaState::isstring(int idx) {
|
||||
return lua_isstring(L, idx);
|
||||
}
|
||||
|
||||
bool lua::LuaState::isfunction(int idx) {
|
||||
bool LuaState::isfunction(int idx) {
|
||||
return lua_isfunction(L, idx);
|
||||
}
|
||||
|
||||
void lua::LuaState::openlib(const std::string& name, const luaL_Reg* libfuncs) {
|
||||
void LuaState::openlib(const std::string& name, const luaL_Reg* libfuncs) {
|
||||
lua_newtable(L);
|
||||
luaL_setfuncs(L, libfuncs, 0);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
std::shared_ptr<std::string> lua::LuaState::createLambdaHandler() {
|
||||
std::shared_ptr<std::string> LuaState::createLambdaHandler() {
|
||||
auto ptr = reinterpret_cast<ptrdiff_t>(lua_topointer(L, -1));
|
||||
auto name = util::mangleid(ptr);
|
||||
lua_getglobal(L, LAMBDAS_TABLE.c_str());
|
||||
@@ -392,7 +395,7 @@ std::shared_ptr<std::string> lua::LuaState::createLambdaHandler() {
|
||||
});
|
||||
}
|
||||
|
||||
runnable lua::LuaState::createRunnable() {
|
||||
runnable LuaState::createRunnable() {
|
||||
auto funcptr = createLambdaHandler();
|
||||
return [=]() {
|
||||
lua_getglobal(L, LAMBDAS_TABLE.c_str());
|
||||
@@ -401,7 +404,7 @@ runnable lua::LuaState::createRunnable() {
|
||||
};
|
||||
}
|
||||
|
||||
scripting::common_func lua::LuaState::createLambda() {
|
||||
scripting::common_func LuaState::createLambda() {
|
||||
auto funcptr = createLambdaHandler();
|
||||
return [=](const std::vector<dynamic::Value>& args) {
|
||||
lua_getglobal(L, LAMBDAS_TABLE.c_str());
|
||||
@@ -418,7 +421,14 @@ scripting::common_func lua::LuaState::createLambda() {
|
||||
};
|
||||
}
|
||||
|
||||
int lua::LuaState::createEnvironment(int parent) {
|
||||
const char* LuaState::requireString(int idx) {
|
||||
if (!lua_isstring(L, idx)) {
|
||||
throw luaerror("string expected at "+std::to_string(idx));
|
||||
}
|
||||
return lua_tostring(L, idx);
|
||||
}
|
||||
|
||||
int LuaState::createEnvironment(int parent) {
|
||||
int id = nextEnvironment++;
|
||||
|
||||
// local env = {}
|
||||
@@ -442,7 +452,7 @@ int lua::LuaState::createEnvironment(int parent) {
|
||||
}
|
||||
|
||||
|
||||
void lua::LuaState::removeEnvironment(int id) {
|
||||
void LuaState::removeEnvironment(int id) {
|
||||
if (id == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -450,7 +460,7 @@ void lua::LuaState::removeEnvironment(int id) {
|
||||
setglobal(envName(id));
|
||||
}
|
||||
|
||||
bool lua::LuaState::emit_event(const std::string &name, std::function<int(lua::LuaState *)> args) {
|
||||
bool LuaState::emit_event(const std::string &name, std::function<int(LuaState *)> args) {
|
||||
getglobal("events");
|
||||
getfield("emit");
|
||||
pushstring(name);
|
||||
@@ -461,7 +471,7 @@ bool lua::LuaState::emit_event(const std::string &name, std::function<int(lua::L
|
||||
}
|
||||
|
||||
|
||||
void lua::LuaState::dumpStack() {
|
||||
void LuaState::dumpStack() {
|
||||
int top = gettop();
|
||||
for (int i = 1; i <= top; i++) {
|
||||
std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30);
|
||||
@@ -486,6 +496,6 @@ void lua::LuaState::dumpStack() {
|
||||
}
|
||||
}
|
||||
|
||||
lua_State* lua::LuaState::getLua() const {
|
||||
lua_State* LuaState::getLua() const {
|
||||
return L;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
#include "../../../data/dynamic.hpp"
|
||||
#include "../../../delegates.hpp"
|
||||
|
||||
#ifndef LUAJIT_VERSION
|
||||
#error LuaJIT required
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -36,9 +32,9 @@ namespace lua {
|
||||
static const std::string envName(int env);
|
||||
void loadbuffer(int env, const std::string& src, const std::string& file);
|
||||
int gettop() const;
|
||||
int pushivec3(luaint x, luaint y, luaint z);
|
||||
int pushinteger(luaint x);
|
||||
int pushnumber(luanumber x);
|
||||
int pushivec3(lua_Integer x, lua_Integer y, lua_Integer z);
|
||||
int pushinteger(lua_Integer x);
|
||||
int pushnumber(lua_Number x);
|
||||
int pushboolean(bool x);
|
||||
int pushstring(const std::string& str);
|
||||
int pushenv(int env);
|
||||
@@ -51,8 +47,8 @@ namespace lua {
|
||||
bool getfield(const std::string& name, int idx = -1);
|
||||
void setfield(const std::string& name, int idx = -2);
|
||||
bool toboolean(int idx);
|
||||
luaint tointeger(int idx);
|
||||
luanumber tonumber(int idx);
|
||||
lua_Integer tointeger(int idx);
|
||||
lua_Number tonumber(int idx);
|
||||
glm::vec2 tovec2(int idx);
|
||||
glm::vec4 tocolor(int idx);
|
||||
dynamic::Value tovalue(int idx);
|
||||
@@ -73,6 +69,8 @@ namespace lua {
|
||||
runnable createRunnable();
|
||||
scripting::common_func createLambda();
|
||||
|
||||
const char* requireString(int idx);
|
||||
|
||||
int createEnvironment(int parent);
|
||||
void removeEnvironment(int id);
|
||||
bool emit_event(const std::string& name, std::function<int(lua::LuaState*)> args=[](auto*){return 0;});
|
||||
|
||||
@@ -8,19 +8,20 @@
|
||||
// Libraries
|
||||
extern const luaL_Reg audiolib [];
|
||||
extern const luaL_Reg blocklib [];
|
||||
extern const luaL_Reg consolelib [];
|
||||
extern const luaL_Reg corelib [];
|
||||
extern const luaL_Reg filelib [];
|
||||
extern const luaL_Reg guilib [];
|
||||
extern const luaL_Reg hudlib [];
|
||||
extern const luaL_Reg inputlib [];
|
||||
extern const luaL_Reg inventorylib [];
|
||||
extern const luaL_Reg itemlib [];
|
||||
extern const luaL_Reg jsonlib [];
|
||||
extern const luaL_Reg packlib [];
|
||||
extern const luaL_Reg playerlib [];
|
||||
extern const luaL_Reg timelib [];
|
||||
extern const luaL_Reg tomllib [];
|
||||
extern const luaL_Reg worldlib [];
|
||||
extern const luaL_Reg jsonlib [];
|
||||
extern const luaL_Reg inputlib [];
|
||||
extern const luaL_Reg consolelib [];
|
||||
|
||||
// Lua Overrides
|
||||
extern int l_print(lua_State* L);
|
||||
|
||||
@@ -23,22 +23,22 @@ inline int extract_channel_index(lua_State* L, int idx) {
|
||||
inline audio::speakerid_t play_sound(
|
||||
const char* name,
|
||||
bool relative,
|
||||
lua::luanumber x,
|
||||
lua::luanumber y,
|
||||
lua::luanumber z,
|
||||
lua::luanumber volume,
|
||||
lua::luanumber pitch,
|
||||
lua_Number x,
|
||||
lua_Number y,
|
||||
lua_Number z,
|
||||
lua_Number volume,
|
||||
lua_Number pitch,
|
||||
bool loop,
|
||||
int channel
|
||||
) {
|
||||
if (channel == -1)
|
||||
if (channel == -1) {
|
||||
return 0;
|
||||
}
|
||||
auto assets = scripting::engine->getAssets();
|
||||
auto sound = assets->getSound(name);
|
||||
if (sound == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return audio::play(
|
||||
sound,
|
||||
glm::vec3(
|
||||
@@ -58,20 +58,20 @@ inline audio::speakerid_t play_sound(
|
||||
inline audio::speakerid_t play_stream(
|
||||
const char* filename,
|
||||
bool relative,
|
||||
lua::luanumber x,
|
||||
lua::luanumber y,
|
||||
lua::luanumber z,
|
||||
lua::luanumber volume,
|
||||
lua::luanumber pitch,
|
||||
lua_Number x,
|
||||
lua_Number y,
|
||||
lua_Number z,
|
||||
lua_Number volume,
|
||||
lua_Number pitch,
|
||||
bool loop,
|
||||
int channel
|
||||
) {
|
||||
if (channel == -1)
|
||||
if (channel == -1) {
|
||||
return 0;
|
||||
}
|
||||
auto paths = scripting::engine->getResPaths();
|
||||
fs::path file = paths->find(filename);
|
||||
return audio::play_stream(
|
||||
file,
|
||||
paths->find(filename),
|
||||
glm::vec3(
|
||||
static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
@@ -95,7 +95,7 @@ inline audio::speakerid_t play_stream(
|
||||
/// channel: string = "regular",
|
||||
/// loop: bool = false)
|
||||
static int l_audio_play_stream(lua_State* L) {
|
||||
lua_pushinteger(L, static_cast<lua::luaint>(
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(
|
||||
play_stream(
|
||||
lua_tostring(L, 1),
|
||||
false,
|
||||
@@ -118,7 +118,7 @@ static int l_audio_play_stream(lua_State* L) {
|
||||
/// channel: string = "regular",
|
||||
/// loop: bool = false)
|
||||
static int l_audio_play_stream_2d(lua_State* L) {
|
||||
lua_pushinteger(L, static_cast<lua::luaint>(
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(
|
||||
play_stream(
|
||||
lua_tostring(L, 1),
|
||||
true,
|
||||
@@ -142,7 +142,7 @@ static int l_audio_play_stream_2d(lua_State* L) {
|
||||
/// channel: string = "regular",
|
||||
/// loop: bool = false)
|
||||
static int l_audio_play_sound(lua_State* L) {
|
||||
lua_pushinteger(L, static_cast<lua::luaint>(
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(
|
||||
play_sound(
|
||||
lua_tostring(L, 1),
|
||||
false,
|
||||
@@ -165,7 +165,7 @@ static int l_audio_play_sound(lua_State* L) {
|
||||
/// channel: string = "regular",
|
||||
/// loop: bool = false)
|
||||
static int l_audio_play_sound_2d(lua_State* L) {
|
||||
lua_pushinteger(L, static_cast<lua::luaint>(
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(
|
||||
play_sound(
|
||||
lua_tostring(L, 1),
|
||||
true,
|
||||
@@ -181,8 +181,7 @@ static int l_audio_play_sound_2d(lua_State* L) {
|
||||
|
||||
/// @brief audio.stop(speakerid: integer) -> nil
|
||||
static int l_audio_stop(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
speaker->stop();
|
||||
}
|
||||
@@ -191,8 +190,7 @@ static int l_audio_stop(lua_State* L) {
|
||||
|
||||
/// @brief audio.pause(speakerid: integer) -> nil
|
||||
static int l_audio_pause(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
speaker->pause();
|
||||
}
|
||||
@@ -201,8 +199,7 @@ static int l_audio_pause(lua_State* L) {
|
||||
|
||||
/// @brief audio.resume(speakerid: integer) -> nil
|
||||
static int l_audio_resume(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr && speaker->isPaused()) {
|
||||
speaker->play();
|
||||
}
|
||||
@@ -211,8 +208,7 @@ static int l_audio_resume(lua_State* L) {
|
||||
|
||||
/// @brief audio.set_loop(speakerid: integer, value: bool) -> nil
|
||||
static int l_audio_set_loop(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
bool value = lua_toboolean(L, 2);
|
||||
speaker->setLoop(value);
|
||||
@@ -222,45 +218,38 @@ static int l_audio_set_loop(lua_State* L) {
|
||||
|
||||
/// @brief audio.set_volume(speakerid: integer, value: number) -> nil
|
||||
static int l_audio_set_volume(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua::luanumber value = lua_tonumber(L, 2);
|
||||
speaker->setVolume(static_cast<float>(value));
|
||||
speaker->setVolume(static_cast<float>(lua_tonumber(L, 2)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief audio.set_pitch(speakerid: integer, value: number) -> nil
|
||||
static int l_audio_set_pitch(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua::luanumber value = lua_tonumber(L, 2);
|
||||
speaker->setPitch(static_cast<float>(value));
|
||||
speaker->setPitch(static_cast<float>(lua_tonumber(L, 2)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief audio.set_time(speakerid: integer, value: number) -> nil
|
||||
static int l_audio_set_time(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua::luanumber value = lua_tonumber(L, 2);
|
||||
speaker->setTime(static_cast<audio::duration_t>(value));
|
||||
speaker->setTime(static_cast<audio::duration_t>(lua_tonumber(L, 2)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief audio.set_position(speakerid: integer, x: number, y: number, z: number) -> nil
|
||||
static int l_audio_set_position(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua::luanumber x = lua_tonumber(L, 2);
|
||||
lua::luanumber y = lua_tonumber(L, 3);
|
||||
lua::luanumber z = lua_tonumber(L, 4);
|
||||
auto x = lua_tonumber(L, 2);
|
||||
auto y = lua_tonumber(L, 3);
|
||||
auto z = lua_tonumber(L, 4);
|
||||
speaker->setPosition(glm::vec3(
|
||||
static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
@@ -272,12 +261,11 @@ static int l_audio_set_position(lua_State* L) {
|
||||
|
||||
/// @brief audio.set_velocity(speakerid: integer, x: number, y: number, z: number) -> nil
|
||||
static int l_audio_set_velocity(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua::luanumber x = lua_tonumber(L, 2);
|
||||
lua::luanumber y = lua_tonumber(L, 3);
|
||||
lua::luanumber z = lua_tonumber(L, 4);
|
||||
auto x = lua_tonumber(L, 2);
|
||||
auto y = lua_tonumber(L, 3);
|
||||
auto z = lua_tonumber(L, 4);
|
||||
speaker->setVelocity(glm::vec3(
|
||||
static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
@@ -289,8 +277,7 @@ static int l_audio_set_velocity(lua_State* L) {
|
||||
|
||||
/// @brief audio.is_playing(speakerid: integer) -> bool
|
||||
static int l_audio_is_playing(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua_pushboolean(L, speaker->isPlaying());
|
||||
return 1;
|
||||
@@ -301,8 +288,7 @@ static int l_audio_is_playing(lua_State* L) {
|
||||
|
||||
/// @brief audio.is_paused(speakerid: integer) -> bool
|
||||
static int l_audio_is_paused(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua_pushboolean(L, speaker->isPaused());
|
||||
return 1;
|
||||
@@ -313,8 +299,7 @@ static int l_audio_is_paused(lua_State* L) {
|
||||
|
||||
/// @brief audio.is_loop(speakerid: integer) -> bool
|
||||
static int l_audio_is_loop(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua_pushboolean(L, speaker->isLoop());
|
||||
return 1;
|
||||
@@ -325,8 +310,7 @@ static int l_audio_is_loop(lua_State* L) {
|
||||
|
||||
/// @brief audio.get_volume(speakerid: integer) -> number
|
||||
static int l_audio_get_volume(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua_pushnumber(L, speaker->getVolume());
|
||||
return 1;
|
||||
@@ -337,8 +321,7 @@ static int l_audio_get_volume(lua_State* L) {
|
||||
|
||||
/// @brief audio.get_pitch(speakerid: integer) -> number
|
||||
static int l_audio_get_pitch(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua_pushnumber(L, speaker->getPitch());
|
||||
return 1;
|
||||
@@ -349,8 +332,7 @@ static int l_audio_get_pitch(lua_State* L) {
|
||||
|
||||
/// @brief audio.get_time(speakerid: integer) -> number
|
||||
static int l_audio_get_time(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua_pushnumber(L, speaker->getTime());
|
||||
return 1;
|
||||
@@ -361,8 +343,7 @@ static int l_audio_get_time(lua_State* L) {
|
||||
|
||||
/// @brief audio.get_duration(speakerid: integer) -> number
|
||||
static int l_audio_get_duration(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
lua_pushnumber(L, speaker->getDuration());
|
||||
return 1;
|
||||
@@ -373,11 +354,9 @@ static int l_audio_get_duration(lua_State* L) {
|
||||
|
||||
/// @brief audio.get_position(speakerid: integer) -> number, number, number
|
||||
static int l_audio_get_position(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
auto vec = speaker->getPosition();
|
||||
lua::pushvec3(L, vec);
|
||||
lua::pushvec3(L, speaker->getPosition());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -385,8 +364,7 @@ static int l_audio_get_position(lua_State* L) {
|
||||
|
||||
/// @brief audio.get_velocity(speakerid: integer) -> number, number, number
|
||||
static int l_audio_get_velocity(lua_State* L) {
|
||||
lua::luaint id = lua_tonumber(L, 1);
|
||||
auto speaker = audio::get_speaker(id);
|
||||
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
|
||||
if (speaker != nullptr) {
|
||||
auto vec = speaker->getVelocity();
|
||||
lua::pushvec3(L, vec);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "lua_commons.hpp"
|
||||
|
||||
#include "api_lua.hpp"
|
||||
#include "lua_util.hpp"
|
||||
#include "../scripting.hpp"
|
||||
|
||||
#include "../../../world/Level.hpp"
|
||||
#include "../../../voxels/Chunks.hpp"
|
||||
#include "../../../voxels/Chunk.hpp"
|
||||
@@ -13,8 +15,8 @@
|
||||
|
||||
int l_block_name(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua::luaint id = lua_tointeger(L, 1);
|
||||
if (id < 0 || size_t(id) >= indices->countBlockDefs()) {
|
||||
lua_Integer id = lua_tointeger(L, 1);
|
||||
if (static_cast<size_t>(id) >= indices->countBlockDefs()) {
|
||||
return 0;
|
||||
}
|
||||
auto def = indices->getBlockDef(id);
|
||||
@@ -22,11 +24,10 @@ int l_block_name(lua_State* L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int l_block_material(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua::luaint id = lua_tointeger(L, 1);
|
||||
if (id < 0 || size_t(id) >= indices->countBlockDefs()) {
|
||||
lua_Integer id = lua_tointeger(L, 1);
|
||||
if (static_cast<size_t>(id) >= indices->countBlockDefs()) {
|
||||
return 0;
|
||||
}
|
||||
auto def = indices->getBlockDef(id);
|
||||
@@ -35,9 +36,9 @@ int l_block_material(lua_State* L) {
|
||||
}
|
||||
|
||||
int l_is_solid_at(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isSolidBlock(x, y, z));
|
||||
return 1;
|
||||
@@ -49,35 +50,36 @@ int l_blocks_count(lua_State* L) {
|
||||
}
|
||||
|
||||
int l_block_index(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
std::string name = lua_tostring(L, 1);
|
||||
lua_pushinteger(L, scripting::content->requireBlock(name).rt.id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_set_block(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua::luaint id = lua_tointeger(L, 4);
|
||||
lua::luaint states = lua_tointeger(L, 5);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
lua_Integer id = lua_tointeger(L, 4);
|
||||
lua_Integer state = lua_tointeger(L, 5);
|
||||
bool noupdate = lua_toboolean(L, 6);
|
||||
if (id < 0 || size_t(id) >= scripting::indices->countBlockDefs()) {
|
||||
if (static_cast<size_t>(id) >= scripting::indices->countBlockDefs()) {
|
||||
return 0;
|
||||
}
|
||||
if (!scripting::level->chunks->get(x, y, z)) {
|
||||
return 0;
|
||||
}
|
||||
scripting::level->chunks->set(x, y, z, id, states);
|
||||
scripting::level->chunks->set(x, y, z, id, int2blockstate(state));
|
||||
scripting::level->lighting->onBlockSet(x,y,z, id);
|
||||
if (!noupdate)
|
||||
if (!noupdate) {
|
||||
scripting::blocks->updateSides(x, y, z);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_get_block(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int id = vox == nullptr ? -1 : vox->id;
|
||||
lua_pushinteger(L, id);
|
||||
@@ -85,9 +87,9 @@ int l_get_block(lua_State* L) {
|
||||
}
|
||||
|
||||
int l_get_block_x(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return lua::pushivec3(L, 1, 0, 0);
|
||||
@@ -96,15 +98,15 @@ int l_get_block_x(lua_State* L) {
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 1, 0, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
const CoordSystem& rot = def->rotations.variants[vox->state.rotation];
|
||||
return lua::pushivec3(L, rot.axisX.x, rot.axisX.y, rot.axisX.z);
|
||||
}
|
||||
}
|
||||
|
||||
int l_get_block_y(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return lua::pushivec3(L, 0, 1, 0);
|
||||
@@ -113,15 +115,15 @@ int l_get_block_y(lua_State* L) {
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 0, 1, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
const CoordSystem& rot = def->rotations.variants[vox->state.rotation];
|
||||
return lua::pushivec3(L, rot.axisY.x, rot.axisY.y, rot.axisY.z);
|
||||
}
|
||||
}
|
||||
|
||||
int l_get_block_z(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return lua::pushivec3(L, 0, 0, 1);
|
||||
@@ -130,67 +132,67 @@ int l_get_block_z(lua_State* L) {
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 0, 0, 1);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
const CoordSystem& rot = def->rotations.variants[vox->state.rotation];
|
||||
return lua::pushivec3(L, rot.axisZ.x, rot.axisZ.y, rot.axisZ.z);
|
||||
}
|
||||
}
|
||||
|
||||
int l_get_block_rotation(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int rotation = vox == nullptr ? 0 : vox->rotation();
|
||||
int rotation = vox == nullptr ? 0 : vox->state.rotation;
|
||||
lua_pushinteger(L, rotation);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_set_block_rotation(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua::luaint value = lua_tointeger(L, 4);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
lua_Integer value = lua_tointeger(L, 4);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
vox->setRotation(value);
|
||||
scripting::level->chunks->getChunkByVoxel(x, y, z)->setModified(true);
|
||||
vox->state.rotation = value;
|
||||
scripting::level->chunks->getChunkByVoxel(x, y, z)->setModifiedAndUnsaved();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_get_block_states(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int states = vox == nullptr ? 0 : vox->states;
|
||||
int states = vox == nullptr ? 0 : blockstate2int(vox->state);
|
||||
lua_pushinteger(L, states);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_set_block_states(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua::luaint states = lua_tointeger(L, 4);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
lua_Integer states = lua_tointeger(L, 4);
|
||||
|
||||
Chunk* chunk = scripting::level->chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
vox->states = states;
|
||||
chunk->setModified(true);
|
||||
vox->state = int2blockstate(states);
|
||||
chunk->setModifiedAndUnsaved();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_get_block_user_bits(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua::luaint offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
lua::luaint bits = lua_tointeger(L, 5);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
lua_Integer offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
lua_Integer bits = lua_tointeger(L, 5);
|
||||
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
@@ -198,42 +200,59 @@ int l_get_block_user_bits(lua_State* L) {
|
||||
return 1;
|
||||
}
|
||||
uint mask = ((1 << bits) - 1) << offset;
|
||||
uint data = (vox->states & mask) >> offset;
|
||||
uint data = (blockstate2int(vox->state) & mask) >> offset;
|
||||
lua_pushinteger(L, data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_set_block_user_bits(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua::luaint offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
lua::luaint bits = lua_tointeger(L, 5);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
lua_Integer offset = lua_tointeger(L, 4);
|
||||
lua_Integer bits = lua_tointeger(L, 5);
|
||||
|
||||
uint mask = ((1 << bits) - 1) << offset;
|
||||
lua::luaint value = (lua_tointeger(L, 6) << offset) & mask;
|
||||
size_t mask = ((1 << bits) - 1) << offset;
|
||||
lua_Integer value = (lua_tointeger(L, 6) << offset) & mask;
|
||||
|
||||
Chunk* chunk = scripting::level->chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
vox->states = (vox->states & (~mask)) | value;
|
||||
return 0;
|
||||
vox->state.userbits = (vox->state.userbits & (~mask)) | value;
|
||||
chunk->setModifiedAndUnsaved();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_is_replaceable_at(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isReplaceableBlock(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_block_caption(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua_Integer id = lua_tointeger(L, 1);
|
||||
if (static_cast<size_t>(id) >= indices->countBlockDefs()) {
|
||||
return 0;
|
||||
}
|
||||
auto def = indices->getBlockDef(id);
|
||||
lua_pushstring(L, def->caption.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg blocklib [] = {
|
||||
{"index", lua_wrap_errors<l_block_index>},
|
||||
{"name", lua_wrap_errors<l_block_name>},
|
||||
{"material", lua_wrap_errors<l_block_material>},
|
||||
{"caption", lua_wrap_errors<l_block_caption>},
|
||||
{"defs_count", lua_wrap_errors<l_blocks_count>},
|
||||
{"is_solid_at", lua_wrap_errors<l_is_solid_at>},
|
||||
{"is_replaceable_at", lua_wrap_errors<l_is_replaceable_at>},
|
||||
|
||||
@@ -14,11 +14,11 @@ namespace scripting {
|
||||
using namespace scripting;
|
||||
|
||||
static int l_add_command(lua_State* L) {
|
||||
if (!lua_isstring(L, 1) || !lua_isstring(L, 2) || !lua_isfunction(L, 3)) {
|
||||
throw std::runtime_error("invalid argument type");
|
||||
if (!lua_isfunction(L, 3)) {
|
||||
throw std::runtime_error("invalid callback");
|
||||
}
|
||||
auto scheme = lua_tostring(L, 1);
|
||||
auto description = lua_tostring(L, 2);
|
||||
auto scheme = state->requireString(1);
|
||||
auto description = state->requireString(2);
|
||||
lua_pushvalue(L, 3);
|
||||
auto func = state->createLambda();
|
||||
try {
|
||||
@@ -33,15 +33,15 @@ static int l_add_command(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_execute(lua_State* L) {
|
||||
auto prompt = lua_tostring(L, 1);
|
||||
static int l_execute(lua_State*) {
|
||||
auto prompt = state->requireString(1);
|
||||
auto result = engine->getCommandsInterpreter()->execute(prompt);
|
||||
state->pushvalue(result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
static int l_set(lua_State*) {
|
||||
auto name = state->requireString(1);
|
||||
auto value = state->tovalue(2);
|
||||
(*engine->getCommandsInterpreter())[name] = value;
|
||||
return 0;
|
||||
@@ -62,7 +62,7 @@ static int l_get_commands_list(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_get_command_info(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto name = state->requireString(1);
|
||||
auto interpreter = engine->getCommandsInterpreter();
|
||||
auto repo = interpreter->getRepository();
|
||||
auto command = repo->get(name);
|
||||
|
||||
@@ -100,19 +100,6 @@ static int l_reconfig_packs(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_bindings(lua_State* L) {
|
||||
auto& bindings = Events::bindings;
|
||||
lua_createtable(L, bindings.size(), 0);
|
||||
|
||||
int i = 0;
|
||||
for (auto& entry : bindings) {
|
||||
lua_pushstring(L, entry.first.c_str());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto value = scripting::engine->getSettingsHandler().getValue(name);
|
||||
@@ -186,7 +173,6 @@ const luaL_Reg corelib [] = {
|
||||
{"close_world", lua_wrap_errors<l_close_world>},
|
||||
{"delete_world", lua_wrap_errors<l_delete_world>},
|
||||
{"reconfig_packs", lua_wrap_errors<l_reconfig_packs>},
|
||||
{"get_bindings", lua_wrap_errors<l_get_bindings>},
|
||||
{"get_setting", lua_wrap_errors<l_get_setting>},
|
||||
{"set_setting", lua_wrap_errors<l_set_setting>},
|
||||
{"str_setting", lua_wrap_errors<l_str_setting>},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lua_commons.hpp"
|
||||
#include "api_lua.hpp"
|
||||
#include "LuaState.hpp"
|
||||
#include "../scripting.hpp"
|
||||
#include "../../../engine.hpp"
|
||||
#include "../../../files/files.hpp"
|
||||
@@ -11,24 +12,41 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static fs::path resolve_path(lua_State*, const std::string& path) {
|
||||
return scripting::engine->getPaths()->resolve(path);
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static fs::path resolve_path(const std::string& path) {
|
||||
return engine->getPaths()->resolve(path);
|
||||
}
|
||||
|
||||
static fs::path resolve_path_soft(const std::string& path) {
|
||||
if (path.find(':') == std::string::npos) {
|
||||
return path;
|
||||
}
|
||||
return engine->getPaths()->resolve(path, false);
|
||||
}
|
||||
|
||||
static int l_file_find(lua_State* L) {
|
||||
std::string path = lua_tostring(L, 1);
|
||||
lua_pushstring(L, scripting::engine->getResPaths()->findRaw(path).c_str());
|
||||
return 1;
|
||||
std::string path = state->requireString(1);
|
||||
try {
|
||||
lua_pushstring(L, engine->getResPaths()->findRaw(path).c_str());
|
||||
return 1;
|
||||
} catch (const std::runtime_error& err) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int l_file_resolve(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
lua_pushstring(L, path.u8string().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_read(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
lua_pushstring(L, files::read_string(path).c_str());
|
||||
return 1;
|
||||
@@ -36,55 +54,50 @@ static int l_file_read(lua_State* L) {
|
||||
throw std::runtime_error("file does not exists "+util::quote(path.u8string()));
|
||||
}
|
||||
|
||||
static int l_file_write(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
const char* text = lua_tostring(L, 2);
|
||||
static int l_file_write(lua_State*) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
auto text = state->requireString(2);
|
||||
files::write_string(path, text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_remove(lua_State* L) {
|
||||
std::string rawpath = lua_tostring(L, 1);
|
||||
fs::path path = resolve_path(L, rawpath);
|
||||
static int l_file_remove(lua_State*) {
|
||||
std::string rawpath = state->requireString(1);
|
||||
fs::path path = resolve_path(rawpath);
|
||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||
if (entryPoint != "world") {
|
||||
throw std::runtime_error("access denied");
|
||||
}
|
||||
lua_pushboolean(L, fs::remove(path));
|
||||
return 1;
|
||||
return state->pushboolean(fs::remove(path));
|
||||
}
|
||||
|
||||
static int l_file_remove_tree(lua_State* L) {
|
||||
std::string rawpath = lua_tostring(L, 1);
|
||||
fs::path path = resolve_path(L, rawpath);
|
||||
static int l_file_remove_tree(lua_State*) {
|
||||
std::string rawpath = state->requireString(1);
|
||||
fs::path path = resolve_path(rawpath);
|
||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||
if (entryPoint != "world") {
|
||||
throw std::runtime_error("access denied");
|
||||
}
|
||||
lua_pushinteger(L, fs::remove_all(path));
|
||||
return 1;
|
||||
return state->pushinteger(fs::remove_all(path));
|
||||
}
|
||||
|
||||
static int l_file_exists(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::exists(path));
|
||||
return 1;
|
||||
static int l_file_exists(lua_State*) {
|
||||
fs::path path = resolve_path_soft(state->requireString(1));
|
||||
return state->pushboolean(fs::exists(path));
|
||||
}
|
||||
|
||||
static int l_file_isfile(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::is_regular_file(path));
|
||||
return 1;
|
||||
static int l_file_isfile(lua_State*) {
|
||||
fs::path path = resolve_path_soft(state->requireString(1));
|
||||
return state->pushboolean(fs::is_regular_file(path));
|
||||
}
|
||||
|
||||
static int l_file_isdir(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::is_directory(path));
|
||||
return 1;
|
||||
static int l_file_isdir(lua_State*) {
|
||||
fs::path path = resolve_path_soft(state->requireString(1));
|
||||
return state->pushboolean(fs::is_directory(path));
|
||||
}
|
||||
|
||||
static int l_file_length(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
if (fs::exists(path)){
|
||||
lua_pushinteger(L, fs::file_size(path));
|
||||
} else {
|
||||
@@ -94,19 +107,19 @@ static int l_file_length(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_file_mkdir(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
lua_pushboolean(L, fs::create_directory(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_mkdirs(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
lua_pushboolean(L, fs::create_directories(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_read_bytes(lua_State* L) {
|
||||
fs::path path = resolve_path(L, lua_tostring(L, 1));
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
size_t length = static_cast<size_t>(fs::file_size(path));
|
||||
|
||||
@@ -148,7 +161,7 @@ static int l_file_write_bytes(lua_State* L) {
|
||||
throw std::runtime_error("string expected");
|
||||
}
|
||||
|
||||
fs::path path = resolve_path(L, lua_tostring(L, pathIndex));
|
||||
fs::path path = resolve_path(state->requireString(pathIndex));
|
||||
|
||||
std::vector<ubyte> bytes;
|
||||
|
||||
@@ -163,7 +176,7 @@ static int l_file_write_bytes(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_file_list_all_res(lua_State* L, const std::string& path) {
|
||||
auto files = scripting::engine->getResPaths()->listdirRaw(path);
|
||||
auto files = engine->getResPaths()->listdirRaw(path);
|
||||
lua_createtable(L, files.size(), 0);
|
||||
for (size_t i = 0; i < files.size(); i++) {
|
||||
lua_pushstring(L, files[i].c_str());
|
||||
@@ -173,11 +186,11 @@ static int l_file_list_all_res(lua_State* L, const std::string& path) {
|
||||
}
|
||||
|
||||
static int l_file_list(lua_State* L) {
|
||||
std::string dirname = lua_tostring(L, 1);
|
||||
std::string dirname = state->requireString(1);
|
||||
if (dirname.find(':') == std::string::npos) {
|
||||
return l_file_list_all_res(L, dirname);
|
||||
}
|
||||
fs::path path = resolve_path(L, dirname);
|
||||
fs::path path = resolve_path(dirname);
|
||||
if (!fs::is_directory(path)) {
|
||||
throw std::runtime_error(util::quote(path.u8string())+" is not a directory");
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "../../../graphics/ui/gui_util.hpp"
|
||||
#include "../../../graphics/ui/elements/UINode.hpp"
|
||||
#include "../../../graphics/ui/elements/Button.hpp"
|
||||
#include "../../../graphics/ui/elements/Image.hpp"
|
||||
#include "../../../graphics/ui/elements/CheckBox.hpp"
|
||||
#include "../../../graphics/ui/elements/TextBox.hpp"
|
||||
#include "../../../graphics/ui/elements/TrackBar.hpp"
|
||||
@@ -49,8 +50,8 @@ static DocumentNode getDocumentNode(lua_State*, const std::string& name, const s
|
||||
static DocumentNode getDocumentNode(lua_State* L, int idx=1) {
|
||||
lua_getfield(L, idx, "docname");
|
||||
lua_getfield(L, idx, "name");
|
||||
auto docname = lua_tostring(L, -2);
|
||||
auto name = lua_tostring(L, -1);
|
||||
auto docname = state->requireString(-2);
|
||||
auto name = state->requireString(-1);
|
||||
auto node = getDocumentNode(L, docname, name);
|
||||
lua_pop(L, 2);
|
||||
return node;
|
||||
@@ -73,7 +74,7 @@ static int l_menu_reset(lua_State* L) {
|
||||
static int l_textbox_paste(lua_State* L) {
|
||||
auto node = getDocumentNode(L);
|
||||
auto box = dynamic_cast<TextBox*>(node.node.get());
|
||||
auto text = lua_tostring(L, 2);
|
||||
auto text = state->requireString(2);
|
||||
box->paste(util::str2wstr_utf8(text));
|
||||
return 0;
|
||||
}
|
||||
@@ -81,7 +82,7 @@ static int l_textbox_paste(lua_State* L) {
|
||||
static int l_container_add(lua_State* L) {
|
||||
auto docnode = getDocumentNode(L);
|
||||
auto node = dynamic_cast<Container*>(docnode.node.get());
|
||||
auto xmlsrc = lua_tostring(L, 2);
|
||||
auto xmlsrc = state->requireString(2);
|
||||
try {
|
||||
auto subnode = guiutil::create(xmlsrc, docnode.document->getEnvironment());
|
||||
node->add(subnode);
|
||||
@@ -92,6 +93,18 @@ static int l_container_add(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_node_destruct(lua_State* L) {
|
||||
auto docnode = getDocumentNode(L);
|
||||
auto node = std::dynamic_pointer_cast<Container>(docnode.node);
|
||||
engine->getGUI()->postRunnable([node]() {
|
||||
auto parent = node->getParent();
|
||||
if (auto container = dynamic_cast<Container*>(parent)) {
|
||||
container->remove(node);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_container_clear(lua_State* L) {
|
||||
auto node = getDocumentNode(L, 1);
|
||||
if (auto container = std::dynamic_pointer_cast<Container>(node.node)) {
|
||||
@@ -100,7 +113,18 @@ static int l_container_clear(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_uinode_move_into(lua_State* L) {
|
||||
static int l_container_set_interval(lua_State* L) {
|
||||
auto node = getDocumentNode(L, 1);
|
||||
auto interval = state->tointeger(2) / 1000.0f;
|
||||
if (auto container = std::dynamic_pointer_cast<Container>(node.node)) {
|
||||
state->pushvalue(3);
|
||||
auto runnable = state->createRunnable();
|
||||
container->listenInterval(interval, runnable);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_move_into(lua_State* L) {
|
||||
auto node = getDocumentNode(L, 1);
|
||||
auto dest = getDocumentNode(L, 2);
|
||||
UINode::moveInto(node.node, std::dynamic_pointer_cast<Container>(dest.node));
|
||||
@@ -233,16 +257,34 @@ static int p_get_editable(UINode* node) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_add(UINode* node) {
|
||||
if (dynamic_cast<Container*>(node)) {
|
||||
return state->pushcfunction(l_container_add);
|
||||
static int p_get_src(UINode* node) {
|
||||
if (auto image = dynamic_cast<Image*>(node)) {
|
||||
return state->pushstring(image->getTexture());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_add(UINode* node) {
|
||||
if (dynamic_cast<Container*>(node)) {
|
||||
return state->pushcfunction(lua_wrap_errors<l_container_add>);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_destruct(UINode*) {
|
||||
return state->pushcfunction(lua_wrap_errors<l_node_destruct>);
|
||||
}
|
||||
|
||||
static int p_get_clear(UINode* node) {
|
||||
if (dynamic_cast<Container*>(node)) {
|
||||
return state->pushcfunction(l_container_clear);
|
||||
return state->pushcfunction(lua_wrap_errors<l_container_clear>);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_set_interval(UINode* node) {
|
||||
if (dynamic_cast<Container*>(node)) {
|
||||
return state->pushcfunction(lua_wrap_errors<l_container_set_interval>);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -256,9 +298,18 @@ static int p_get_hover_color(UINode* node) {
|
||||
static int p_get_pressed_color(UINode* node) {
|
||||
return lua::pushcolor_arr(state->getLua(), node->getPressedColor());
|
||||
}
|
||||
static int p_get_tooltip(UINode* node) {
|
||||
return state->pushstring(util::wstr2str_utf8(node->getTooltip()));
|
||||
}
|
||||
static int p_get_tooltip_delay(UINode* node) {
|
||||
return state->pushnumber(node->getTooltipDelay());
|
||||
}
|
||||
static int p_get_pos(UINode* node) {
|
||||
return lua::pushvec2_arr(state->getLua(), node->getPos());
|
||||
}
|
||||
static int p_get_wpos(UINode* node) {
|
||||
return lua::pushvec2_arr(state->getLua(), node->calcPos());
|
||||
}
|
||||
static int p_get_size(UINode* node) {
|
||||
return lua::pushvec2_arr(state->getLua(), node->getSize());
|
||||
}
|
||||
@@ -272,16 +323,16 @@ static int p_is_enabled(UINode* node) {
|
||||
return state->pushboolean(node->isEnabled());
|
||||
}
|
||||
static int p_move_into(UINode*) {
|
||||
return state->pushcfunction(l_uinode_move_into);
|
||||
return state->pushcfunction(l_move_into);
|
||||
}
|
||||
static int p_get_focused(UINode* node) {
|
||||
return state->pushboolean(node->isFocused());
|
||||
}
|
||||
|
||||
static int l_gui_getattr(lua_State* L) {
|
||||
auto docname = lua_tostring(L, 1);
|
||||
auto element = lua_tostring(L, 2);
|
||||
auto attr = lua_tostring(L, 3);
|
||||
auto docname = state->requireString(1);
|
||||
auto element = state->requireString(2);
|
||||
auto attr = state->requireString(3);
|
||||
auto docnode = getDocumentNode(L, docname, element);
|
||||
auto node = docnode.node;
|
||||
|
||||
@@ -289,19 +340,25 @@ static int l_gui_getattr(lua_State* L) {
|
||||
{"color", p_get_color},
|
||||
{"hoverColor", p_get_hover_color},
|
||||
{"pressedColor", p_get_pressed_color},
|
||||
{"tooltip", p_get_tooltip},
|
||||
{"tooltipDelay", p_get_tooltip_delay},
|
||||
{"pos", p_get_pos},
|
||||
{"wpos", p_get_wpos},
|
||||
{"size", p_get_size},
|
||||
{"interactive", p_is_interactive},
|
||||
{"visible", p_is_visible},
|
||||
{"enabled", p_is_enabled},
|
||||
{"enabled", p_is_enabled},
|
||||
{"move_into", p_move_into},
|
||||
{"add", p_get_add},
|
||||
{"destruct", p_get_destruct},
|
||||
{"clear", p_get_clear},
|
||||
{"setInterval", p_set_interval},
|
||||
{"placeholder", p_get_placeholder},
|
||||
{"valid", p_is_valid},
|
||||
{"caret", p_get_caret},
|
||||
{"text", p_get_text},
|
||||
{"editable", p_get_editable},
|
||||
{"src", p_get_src},
|
||||
{"value", p_get_value},
|
||||
{"min", p_get_min},
|
||||
{"max", p_get_max},
|
||||
@@ -332,9 +389,18 @@ static void p_set_hover_color(UINode* node, int idx) {
|
||||
static void p_set_pressed_color(UINode* node, int idx) {
|
||||
node->setPressedColor(state->tocolor(idx));
|
||||
}
|
||||
static void p_set_tooltip(UINode* node, int idx) {
|
||||
node->setTooltip(util::str2wstr_utf8(state->requireString(idx)));
|
||||
}
|
||||
static void p_set_tooltip_delay(UINode* node, int idx) {
|
||||
node->setTooltipDelay(state->tonumber(idx));
|
||||
}
|
||||
static void p_set_pos(UINode* node, int idx) {
|
||||
node->setPos(state->tovec2(idx));
|
||||
}
|
||||
static void p_set_wpos(UINode* node, int idx) {
|
||||
node->setPos(state->tovec2(idx)-node->calcPos());
|
||||
}
|
||||
static void p_set_size(UINode* node, int idx) {
|
||||
node->setSize(state->tovec2(idx));
|
||||
}
|
||||
@@ -349,21 +415,21 @@ static void p_set_enabled(UINode* node, int idx) {
|
||||
}
|
||||
static void p_set_placeholder(UINode* node, int idx) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
box->setPlaceholder(util::str2wstr_utf8(state->tostring(idx)));
|
||||
box->setPlaceholder(util::str2wstr_utf8(state->requireString(idx)));
|
||||
}
|
||||
}
|
||||
static void p_set_text(UINode* node, int idx) {
|
||||
if (auto label = dynamic_cast<Label*>(node)) {
|
||||
label->setText(util::str2wstr_utf8(state->tostring(idx)));
|
||||
label->setText(util::str2wstr_utf8(state->requireString(idx)));
|
||||
} else if (auto button = dynamic_cast<Button*>(node)) {
|
||||
button->setText(util::str2wstr_utf8(state->tostring(idx)));
|
||||
button->setText(util::str2wstr_utf8(state->requireString(idx)));
|
||||
} else if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
box->setText(util::str2wstr_utf8(state->tostring(idx)));
|
||||
box->setText(util::str2wstr_utf8(state->requireString(idx)));
|
||||
}
|
||||
}
|
||||
static void p_set_caret(UINode* node, int idx) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
box->setCaret(static_cast<ssize_t>(state->tointeger(idx)));
|
||||
box->setCaret(static_cast<ptrdiff_t>(state->tointeger(idx)));
|
||||
}
|
||||
}
|
||||
static void p_set_editable(UINode* node, int idx) {
|
||||
@@ -371,6 +437,11 @@ static void p_set_editable(UINode* node, int idx) {
|
||||
box->setEditable(state->toboolean(idx));
|
||||
}
|
||||
}
|
||||
static void p_set_src(UINode* node, int idx) {
|
||||
if (auto image = dynamic_cast<Image*>(node)) {
|
||||
image->setTexture(state->requireString(idx));
|
||||
}
|
||||
}
|
||||
static void p_set_value(UINode* node, int idx) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
bar->setValue(state->tonumber(idx));
|
||||
@@ -410,7 +481,7 @@ static void p_set_checked(UINode* node, int idx) {
|
||||
}
|
||||
static void p_set_page(UINode* node, int idx) {
|
||||
if (auto menu = dynamic_cast<Menu*>(node)) {
|
||||
menu->setPage(state->tostring(idx));
|
||||
menu->setPage(state->requireString(idx));
|
||||
}
|
||||
}
|
||||
static void p_set_inventory(UINode* node, int idx) {
|
||||
@@ -432,9 +503,9 @@ static void p_set_focused(std::shared_ptr<UINode> node, int idx) {
|
||||
}
|
||||
|
||||
static int l_gui_setattr(lua_State* L) {
|
||||
auto docname = lua_tostring(L, 1);
|
||||
auto element = lua_tostring(L, 2);
|
||||
auto attr = lua_tostring(L, 3);
|
||||
auto docname = state->requireString(1);
|
||||
auto element = state->requireString(2);
|
||||
auto attr = state->requireString(3);
|
||||
|
||||
auto docnode = getDocumentNode(L, docname, element);
|
||||
auto node = docnode.node;
|
||||
@@ -443,7 +514,10 @@ static int l_gui_setattr(lua_State* L) {
|
||||
{"color", p_set_color},
|
||||
{"hoverColor", p_set_hover_color},
|
||||
{"pressedColor", p_set_pressed_color},
|
||||
{"tooltip", p_set_tooltip},
|
||||
{"tooltipDelay", p_set_tooltip_delay},
|
||||
{"pos", p_set_pos},
|
||||
{"wpos", p_set_wpos},
|
||||
{"size", p_set_size},
|
||||
{"interactive", p_set_interactive},
|
||||
{"visible", p_set_visible},
|
||||
@@ -451,6 +525,7 @@ static int l_gui_setattr(lua_State* L) {
|
||||
{"placeholder", p_set_placeholder},
|
||||
{"text", p_set_text},
|
||||
{"editable", p_set_editable},
|
||||
{"src", p_set_src},
|
||||
{"caret", p_set_caret},
|
||||
{"value", p_set_value},
|
||||
{"min", p_set_min},
|
||||
@@ -477,7 +552,7 @@ static int l_gui_setattr(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_gui_get_env(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto name = state->requireString(1);
|
||||
auto doc = scripting::engine->getAssets()->getLayout(name);
|
||||
if (doc == nullptr) {
|
||||
throw std::runtime_error("document '"+std::string(name)+"' not found");
|
||||
@@ -487,9 +562,9 @@ static int l_gui_get_env(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_gui_str(lua_State* L) {
|
||||
auto text = util::str2wstr_utf8(lua_tostring(L, 1));
|
||||
auto text = util::str2wstr_utf8(state->requireString(1));
|
||||
if (!lua_isnoneornil(L, 2)) {
|
||||
auto context = util::str2wstr_utf8(lua_tostring(L, 2));
|
||||
auto context = util::str2wstr_utf8(state->requireString(2));
|
||||
lua_pushstring(L, util::wstr2str_utf8(langs::get(text, context)).c_str());
|
||||
} else {
|
||||
lua_pushstring(L, util::wstr2str_utf8(langs::get(text)).c_str());
|
||||
@@ -498,7 +573,7 @@ static int l_gui_str(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_gui_reindex(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto name = state->requireString(1);
|
||||
auto doc = scripting::engine->getAssets()->getLayout(name);
|
||||
if (doc == nullptr) {
|
||||
throw std::runtime_error("document '"+std::string(name)+"' not found");
|
||||
@@ -530,7 +605,7 @@ const luaL_Reg guilib [] = {
|
||||
{"setattr", lua_wrap_errors<l_gui_setattr>},
|
||||
{"get_env", lua_wrap_errors<l_gui_get_env>},
|
||||
{"str", lua_wrap_errors<l_gui_str>},
|
||||
{"reindex", lua_wrap_errors<l_gui_reindex>},
|
||||
{"get_locales_info", lua_wrap_errors<l_gui_get_locales_info>},
|
||||
{"__reindex", lua_wrap_errors<l_gui_reindex>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -40,14 +40,14 @@ static int l_hud_close_inventory(lua_State*) {
|
||||
}
|
||||
|
||||
static int l_hud_open_block(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
auto x = lua_tointeger(L, 1);
|
||||
auto y = lua_tointeger(L, 2);
|
||||
auto z = lua_tointeger(L, 3);
|
||||
bool playerInventory = !lua_toboolean(L, 4);
|
||||
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
throw std::runtime_error("block does not exists at "+
|
||||
throw std::runtime_error("block does not exists at " +
|
||||
std::to_string(x) + " " + std::to_string(y) + " " + std::to_string(z)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,21 +20,28 @@ namespace scripting {
|
||||
using namespace scripting;
|
||||
|
||||
static int l_keycode(lua_State* L) {
|
||||
const char* name = lua_tostring(L, 1);
|
||||
const char* name = state->requireString(1);
|
||||
lua_pushinteger(L, static_cast<int>(input_util::keycode_from(name)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_add_callback(lua_State* L) {
|
||||
auto bindname = lua_tostring(L, 1);
|
||||
static int l_mousecode(lua_State* L) {
|
||||
const char* name = state->requireString(1);
|
||||
lua_pushinteger(L, static_cast<int>(input_util::mousecode_from(name)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_add_callback(lua_State*) {
|
||||
auto bindname = state->requireString(1);
|
||||
const auto& bind = Events::bindings.find(bindname);
|
||||
if (bind == Events::bindings.end()) {
|
||||
throw std::runtime_error("unknown binding "+util::quote(bindname));
|
||||
}
|
||||
state->pushvalue(2);
|
||||
runnable actual_callback = state->createRunnable();
|
||||
runnable callback = [=]() {
|
||||
if (!scripting::engine->getGUI()->isFocusCaught()) {
|
||||
state->createRunnable();
|
||||
actual_callback();
|
||||
}
|
||||
};
|
||||
if (hud) {
|
||||
@@ -49,10 +56,25 @@ static int l_get_mouse_pos(lua_State* L) {
|
||||
return lua::pushvec2_arr(L, Events::cursor);
|
||||
}
|
||||
|
||||
static int l_get_bindings(lua_State* L) {
|
||||
auto& bindings = Events::bindings;
|
||||
lua_createtable(L, bindings.size(), 0);
|
||||
|
||||
int i = 0;
|
||||
for (auto& entry : bindings) {
|
||||
lua_pushstring(L, entry.first.c_str());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg inputlib [] = {
|
||||
{"keycode", lua_wrap_errors<l_keycode>},
|
||||
{"mousecode", lua_wrap_errors<l_mousecode>},
|
||||
{"add_callback", lua_wrap_errors<l_add_callback>},
|
||||
{"get_mouse_pos", lua_wrap_errors<l_get_mouse_pos>},
|
||||
{"get_bindings", lua_wrap_errors<l_get_bindings>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "lua_commons.hpp"
|
||||
|
||||
#include "api_lua.hpp"
|
||||
#include "lua_util.hpp"
|
||||
|
||||
#include "../scripting.hpp"
|
||||
#include "../../../content/Content.hpp"
|
||||
#include "../../../world/Level.hpp"
|
||||
@@ -38,8 +40,8 @@ static void validate_slotid(int slotid, Inventory* inv) {
|
||||
}
|
||||
|
||||
static int l_inventory_get(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
lua::luaint slotid = lua_tointeger(L, 2);
|
||||
lua_Integer invid = lua_tointeger(L, 1);
|
||||
lua_Integer slotid = lua_tointeger(L, 2);
|
||||
auto inv = get_inventory(invid);
|
||||
validate_slotid(slotid, inv.get());
|
||||
const ItemStack& item = inv->getSlot(slotid);
|
||||
@@ -49,10 +51,10 @@ static int l_inventory_get(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_inventory_set(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
lua::luaint slotid = lua_tointeger(L, 2);
|
||||
lua::luaint itemid = lua_tointeger(L, 3);
|
||||
lua::luaint count = lua_tointeger(L, 4);
|
||||
lua_Integer invid = lua_tointeger(L, 1);
|
||||
lua_Integer slotid = lua_tointeger(L, 2);
|
||||
lua_Integer itemid = lua_tointeger(L, 3);
|
||||
lua_Integer count = lua_tointeger(L, 4);
|
||||
validate_itemid(itemid);
|
||||
|
||||
auto inv = get_inventory(invid);
|
||||
@@ -64,16 +66,16 @@ static int l_inventory_set(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_inventory_size(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
lua_Integer invid = lua_tointeger(L, 1);
|
||||
auto inv = get_inventory(invid);
|
||||
lua_pushinteger(L, inv->size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_inventory_add(lua_State* L) {
|
||||
lua::luaint invid = lua_tointeger(L, 1);
|
||||
lua::luaint itemid = lua_tointeger(L, 2);
|
||||
lua::luaint count = lua_tointeger(L, 3);
|
||||
lua_Integer invid = lua_tointeger(L, 1);
|
||||
lua_Integer itemid = lua_tointeger(L, 2);
|
||||
lua_Integer count = lua_tointeger(L, 3);
|
||||
validate_itemid(itemid);
|
||||
|
||||
auto inv = get_inventory(invid);
|
||||
@@ -84,33 +86,33 @@ static int l_inventory_add(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_inventory_get_block(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
int64_t id = scripting::blocks->createBlockInventory(x, y, z);
|
||||
lua_pushinteger(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_inventory_bind_block(lua_State* L) {
|
||||
lua::luaint id = lua_tointeger(L, 1);
|
||||
lua::luaint x = lua_tointeger(L, 2);
|
||||
lua::luaint y = lua_tointeger(L, 3);
|
||||
lua::luaint z = lua_tointeger(L, 4);
|
||||
lua_Integer id = lua_tointeger(L, 1);
|
||||
lua_Integer x = lua_tointeger(L, 2);
|
||||
lua_Integer y = lua_tointeger(L, 3);
|
||||
lua_Integer z = lua_tointeger(L, 4);
|
||||
scripting::blocks->bindInventory(id, x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_inventory_unbind_block(lua_State* L) {
|
||||
lua::luaint x = lua_tointeger(L, 1);
|
||||
lua::luaint y = lua_tointeger(L, 2);
|
||||
lua::luaint z = lua_tointeger(L, 3);
|
||||
lua_Integer x = lua_tointeger(L, 1);
|
||||
lua_Integer y = lua_tointeger(L, 2);
|
||||
lua_Integer z = lua_tointeger(L, 3);
|
||||
scripting::blocks->unbindInventory(x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_inventory_clone(lua_State* L) {
|
||||
lua::luaint id = lua_tointeger(L, 1);
|
||||
lua_Integer id = lua_tointeger(L, 1);
|
||||
auto clone = scripting::level->inventories->clone(id);
|
||||
if (clone == nullptr) {
|
||||
lua_pushinteger(L, 0);
|
||||
@@ -121,13 +123,13 @@ static int l_inventory_clone(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_inventory_move(lua_State* L) {
|
||||
lua::luaint invAid = lua_tointeger(L, 1);
|
||||
lua::luaint slotAid = lua_tointeger(L, 2);
|
||||
lua_Integer invAid = lua_tointeger(L, 1);
|
||||
lua_Integer slotAid = lua_tointeger(L, 2);
|
||||
auto invA = get_inventory(invAid, 1);
|
||||
validate_slotid(slotAid, invA.get());
|
||||
|
||||
lua::luaint invBid = lua_tointeger(L, 3);
|
||||
lua::luaint slotBid = lua_isnil(L, 4) ? -1 : lua_tointeger(L, 4);
|
||||
lua_Integer invBid = lua_tointeger(L, 3);
|
||||
lua_Integer slotBid = lua_isnil(L, 4) ? -1 : lua_tointeger(L, 4);
|
||||
auto invB = get_inventory(invBid, 3);
|
||||
auto& slot = invA->getSlot(slotAid);
|
||||
if (slotBid == -1) {
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
#include "lua_commons.hpp"
|
||||
#include "api_lua.hpp"
|
||||
#include "LuaState.hpp"
|
||||
#include "../scripting.hpp"
|
||||
#include "../../../content/Content.hpp"
|
||||
#include "../../../items/ItemDef.hpp"
|
||||
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static int l_item_name(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua::luaint id = lua_tointeger(L, 1);
|
||||
if (id < 0 || size_t(id) >= indices->countItemDefs()) {
|
||||
lua_Number id = lua_tointeger(L, 1);
|
||||
if (static_cast<size_t>(id) >= indices->countItemDefs()) {
|
||||
return 0;
|
||||
}
|
||||
auto def = indices->getItemDef(id);
|
||||
@@ -16,14 +23,14 @@ static int l_item_name(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_item_index(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto name = scripting::state->requireString(1);
|
||||
lua_pushinteger(L, scripting::content->requireItem(name).rt.id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_item_stack_size(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua::luaint id = lua_tointeger(L, 1);
|
||||
lua_Integer id = lua_tointeger(L, 1);
|
||||
if (id < 0 || size_t(id) >= indices->countItemDefs()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,17 +23,14 @@ static int l_json_stringify(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_json_parse(lua_State* L) {
|
||||
auto string = lua_tostring(L, 1);
|
||||
auto string = scripting::state->requireString(1);
|
||||
auto element = json::parse("<string>", string);
|
||||
auto value = std::make_unique<dynamic::Value>(
|
||||
dynamic::Map_sptr(element.release())
|
||||
);
|
||||
scripting::state->pushvalue(*value);
|
||||
scripting::state->pushvalue(element);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg jsonlib [] = {
|
||||
{"stringify", lua_wrap_errors<l_json_stringify>},
|
||||
{"tostring", lua_wrap_errors<l_json_stringify>},
|
||||
{"parse", lua_wrap_errors<l_json_parse>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -9,10 +9,15 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
inline std::shared_ptr<Player> get_player(lua_State* L, int idx) {
|
||||
return scripting::level->getObject<Player>(lua_tointeger(L, idx));
|
||||
}
|
||||
|
||||
static int l_player_get_pos(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
auto player = scripting::level->getObject<Player>(playerid);
|
||||
if (!player) return 0;
|
||||
auto player = get_player(L, 1);
|
||||
if (!player) {
|
||||
return 0;
|
||||
}
|
||||
glm::vec3 pos = player->hitbox->position;
|
||||
lua_pushnumber(L, pos.x);
|
||||
lua_pushnumber(L, pos.y);
|
||||
@@ -21,19 +26,22 @@ static int l_player_get_pos(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_player_set_pos(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
lua::luanumber x = lua_tonumber(L, 2);
|
||||
lua::luanumber y = lua_tonumber(L, 3);
|
||||
lua::luanumber z = lua_tonumber(L, 4);
|
||||
auto player = scripting::level->getObject<Player>(playerid);
|
||||
if (player) player->hitbox->position = glm::vec3(x, y, z);
|
||||
auto player = get_player(L, 1);
|
||||
if (!player) {
|
||||
return 0;
|
||||
}
|
||||
auto x = lua_tonumber(L, 2);
|
||||
auto y = lua_tonumber(L, 3);
|
||||
auto z = lua_tonumber(L, 4);
|
||||
player->hitbox->position = glm::vec3(x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_get_vel(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
auto player = scripting::level->getObject<Player>(playerid);
|
||||
if (!player) return 0;
|
||||
auto player = get_player(L, 1);
|
||||
if (!player) {
|
||||
return 0;
|
||||
}
|
||||
glm::vec3 vel = player->hitbox->velocity;
|
||||
lua_pushnumber(L, vel.x);
|
||||
lua_pushnumber(L, vel.y);
|
||||
@@ -42,46 +50,102 @@ static int l_player_get_vel(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_player_set_vel(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
lua::luanumber x = lua_tonumber(L, 2);
|
||||
lua::luanumber y = lua_tonumber(L, 3);
|
||||
lua::luanumber z = lua_tonumber(L, 4);
|
||||
auto player = scripting::level->getObject<Player>(playerid);
|
||||
if (player) player->hitbox->velocity = glm::vec3(x, y, z);
|
||||
auto player = get_player(L, 1);
|
||||
if (!player) {
|
||||
return 0;
|
||||
}
|
||||
auto x = lua_tonumber(L, 2);
|
||||
auto y = lua_tonumber(L, 3);
|
||||
auto z = lua_tonumber(L, 4);
|
||||
player->hitbox->velocity = glm::vec3(x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_get_rot(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
auto player = scripting::level->getObject<Player>(playerid);
|
||||
if (!player) return 0;
|
||||
glm::vec2 rot = player->cam;
|
||||
auto player = get_player(L, 1);
|
||||
if (!player) {
|
||||
return 0;
|
||||
}
|
||||
const glm::vec3& rot = player->cam;
|
||||
lua_pushnumber(L, rot.x);
|
||||
lua_pushnumber(L, rot.y);
|
||||
return 2;
|
||||
lua_pushnumber(L, rot.z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int l_player_set_rot(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
auto player = scripting::level->getObject<Player>(playerid);
|
||||
if (!player) return 0;
|
||||
lua::luanumber x = lua_tonumber(L, 2);
|
||||
lua::luanumber y = lua_tonumber(L, 3);
|
||||
glm::vec2& cam = player->cam;
|
||||
auto player = get_player(L, 1);
|
||||
if (!player) {
|
||||
return 0;
|
||||
}
|
||||
glm::vec3& cam = player->cam;
|
||||
|
||||
lua_Number x = lua_tonumber(L, 2);
|
||||
lua_Number y = lua_tonumber(L, 3);
|
||||
lua_Number z = cam.z;
|
||||
if (lua_isnumber(L, 4)) {
|
||||
z = lua_tonumber(L, 4);
|
||||
}
|
||||
cam.x = x;
|
||||
cam.y = y;
|
||||
cam.z = z;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_get_inv(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
auto player = scripting::level->getObject<Player>(playerid);
|
||||
if (!player) return 0;
|
||||
auto player = get_player(L, 1);
|
||||
if (!player) {
|
||||
return 0;
|
||||
}
|
||||
lua_pushinteger(L, player->getInventory()->getId());
|
||||
lua_pushinteger(L, player->getChosenSlot());
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_player_is_flight(lua_State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
lua_pushboolean(L, player->isFlight());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_set_flight(lua_State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
player->setFlight(lua_toboolean(L, 2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_is_noclip(lua_State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
lua_pushboolean(L, player->isNoclip());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_set_noclip(lua_State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
player->setNoclip(lua_toboolean(L, 2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_get_selected_block(lua_State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
if (player->selectedVoxel.id == BLOCK_VOID) {
|
||||
return 0;
|
||||
}
|
||||
const glm::ivec3 pos = player->selectedBlockPosition;
|
||||
lua_pushinteger(L, pos.x);
|
||||
lua_pushinteger(L, pos.y);
|
||||
lua_pushinteger(L, pos.z);
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg playerlib [] = {
|
||||
{"get_pos", lua_wrap_errors<l_player_get_pos>},
|
||||
{"set_pos", lua_wrap_errors<l_player_set_pos>},
|
||||
@@ -90,5 +154,10 @@ const luaL_Reg playerlib [] = {
|
||||
{"get_rot", lua_wrap_errors<l_player_get_rot>},
|
||||
{"set_rot", lua_wrap_errors<l_player_set_rot>},
|
||||
{"get_inventory", lua_wrap_errors<l_player_get_inv>},
|
||||
{"is_flight", lua_wrap_errors<l_player_is_flight>},
|
||||
{"set_flight", lua_wrap_errors<l_player_set_flight>},
|
||||
{"is_noclip", lua_wrap_errors<l_player_is_noclip>},
|
||||
{"set_noclip", lua_wrap_errors<l_player_set_noclip>},
|
||||
{"get_selected_block", lua_wrap_errors<l_player_get_selected_block>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "api_lua.hpp"
|
||||
#include "lua_commons.hpp"
|
||||
#include "LuaState.hpp"
|
||||
|
||||
#include "../../../coders/toml.hpp"
|
||||
#include "../../../data/dynamic.hpp"
|
||||
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
using namespace scripting;
|
||||
|
||||
static int l_toml_stringify(lua_State* L) {
|
||||
auto value = state->tovalue(1);
|
||||
|
||||
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
|
||||
auto string = toml::stringify(**mapptr);
|
||||
lua_pushstring(L, string.c_str());
|
||||
return 1;
|
||||
} else {
|
||||
throw std::runtime_error("table expected");
|
||||
}
|
||||
}
|
||||
|
||||
static int l_toml_parse(lua_State*) {
|
||||
auto string = state->requireString(1);
|
||||
auto element = toml::parse("<string>", string);
|
||||
auto value = std::make_unique<dynamic::Value>(element);
|
||||
state->pushvalue(*value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg tomllib [] = {
|
||||
{"tostring", lua_wrap_errors<l_toml_stringify>},
|
||||
{"parse", lua_wrap_errors<l_toml_parse>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -7,14 +7,14 @@
|
||||
#else
|
||||
#include <lua.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef LUAJIT_VERSION
|
||||
#error LuaJIT required
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
namespace lua {
|
||||
using luaint = lua_Integer;
|
||||
using luanumber = lua_Number;
|
||||
}
|
||||
|
||||
template <lua_CFunction func> int lua_wrap_errors(lua_State *L) {
|
||||
int result = 0;
|
||||
try {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace lua {
|
||||
inline int pushivec3(lua_State* L, luaint x, luaint y, luaint z) {
|
||||
inline int pushivec3(lua_State* L, lua_Integer x, lua_Integer y, lua_Integer z) {
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
@@ -100,9 +100,9 @@ namespace lua {
|
||||
throw std::runtime_error("value must be an array of two numbers");
|
||||
}
|
||||
lua_rawgeti(L, -1, 1);
|
||||
lua::luanumber x = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_Number x = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 2);
|
||||
lua::luanumber y = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_Number y = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_pop(L, 1);
|
||||
return glm::vec2(x, y);
|
||||
}
|
||||
@@ -113,13 +113,13 @@ namespace lua {
|
||||
throw std::runtime_error("RGBA array required");
|
||||
}
|
||||
lua_rawgeti(L, -1, 1);
|
||||
lua::luanumber r = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_Number r = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 2);
|
||||
lua::luanumber g = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_Number g = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 3);
|
||||
lua::luanumber b = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_Number b = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 4);
|
||||
lua::luanumber a = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_Number a = lua_tonumber(L, -1); lua_pop(L, 1);
|
||||
lua_pop(L, 1);
|
||||
return glm::vec4(r/255, g/255, b/255, a/255);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,8 @@ doublesupplier scripting::create_number_supplier(
|
||||
if (state->isfunction(-1)) {
|
||||
state->callNoThrow(0);
|
||||
}
|
||||
lua::luanumber x = state->tonumber(-1); state->pop();
|
||||
auto x = state->tonumber(-1);
|
||||
state->pop();
|
||||
return x;
|
||||
}
|
||||
return 0.0;
|
||||
@@ -169,8 +170,8 @@ vec2supplier scripting::create_vec2_supplier(
|
||||
if (state->isfunction(-1)) {
|
||||
state->callNoThrow(0);
|
||||
}
|
||||
lua::luanumber y = state->tonumber(-1); state->pop();
|
||||
lua::luanumber x = state->tonumber(-1); state->pop();
|
||||
auto y = state->tonumber(-1); state->pop();
|
||||
auto x = state->tonumber(-1); state->pop();
|
||||
return glm::vec2(x, y);
|
||||
}
|
||||
return glm::vec2(0, 0);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user