Merge branch 'dev' of https://github.com/Xertis/VoxelEngine-Cpp into dev
This commit is contained in:
@@ -38,9 +38,11 @@ extern const luaL_Reg mat4lib[];
|
||||
extern const luaL_Reg networklib[];
|
||||
extern const luaL_Reg packlib[];
|
||||
extern const luaL_Reg particleslib[]; // gfx.particles
|
||||
extern const luaL_Reg pathfindinglib[];
|
||||
extern const luaL_Reg playerlib[];
|
||||
extern const luaL_Reg posteffectslib[]; // gfx.posteffects
|
||||
extern const luaL_Reg quatlib[];
|
||||
extern const luaL_Reg randomlib[];
|
||||
extern const luaL_Reg text3dlib[]; // gfx.text3d
|
||||
extern const luaL_Reg timelib[];
|
||||
extern const luaL_Reg tomllib[];
|
||||
|
||||
@@ -62,6 +62,15 @@ static int l_set_gravity_scale(lua::State* L) {
|
||||
static int l_is_vdamping(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
return lua::pushboolean(
|
||||
L, entity->getRigidbody().hitbox.verticalDamping > 0.0
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_vdamping(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
return lua::pushnumber(
|
||||
L, entity->getRigidbody().hitbox.verticalDamping
|
||||
);
|
||||
}
|
||||
@@ -70,7 +79,11 @@ static int l_is_vdamping(lua::State* L) {
|
||||
|
||||
static int l_set_vdamping(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
entity->getRigidbody().hitbox.verticalDamping = lua::toboolean(L, 2);
|
||||
if (lua::isboolean(L, 2)) {
|
||||
entity->getRigidbody().hitbox.verticalDamping = lua::toboolean(L, 2);
|
||||
} else {
|
||||
entity->getRigidbody().hitbox.verticalDamping = lua::tonumber(L, 2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -144,6 +157,7 @@ const luaL_Reg rigidbodylib[] = {
|
||||
{"get_linear_damping", lua::wrap<l_get_linear_damping>},
|
||||
{"set_linear_damping", lua::wrap<l_set_linear_damping>},
|
||||
{"is_vdamping", lua::wrap<l_is_vdamping>},
|
||||
{"get_vdamping", lua::wrap<l_get_vdamping>},
|
||||
{"set_vdamping", lua::wrap<l_set_vdamping>},
|
||||
{"is_grounded", lua::wrap<l_is_grounded>},
|
||||
{"is_crouching", lua::wrap<l_is_crouching>},
|
||||
|
||||
@@ -91,7 +91,7 @@ static int l_set_texture(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_index(lua::State* L) {
|
||||
if (auto skeleton= get_skeleton(L)) {
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
if (auto bone = skeleton->config->find(lua::require_string(L, 2))) {
|
||||
return lua::pushinteger(L, bone->getIndex());
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "util/stringutil.hpp"
|
||||
|
||||
template<std::string(*encode_func)(const ubyte*, size_t)>
|
||||
static int l_encode(lua::State* L) {
|
||||
if (lua::istable(L, 1)) {
|
||||
lua::pushvalue(L, 1);
|
||||
@@ -13,12 +14,12 @@ static int l_encode(lua::State* L) {
|
||||
lua::pop(L);
|
||||
}
|
||||
lua::pop(L);
|
||||
return lua::pushstring(L, util::base64_encode(
|
||||
return lua::pushstring(L, encode_func(
|
||||
reinterpret_cast<const ubyte*>(buffer.data()), buffer.size()
|
||||
));
|
||||
} else {
|
||||
auto string = lua::bytearray_as_string(L, 1);
|
||||
auto out = util::base64_encode(
|
||||
auto out = encode_func(
|
||||
reinterpret_cast<const ubyte*>(string.data()),
|
||||
string.size()
|
||||
);
|
||||
@@ -28,8 +29,9 @@ static int l_encode(lua::State* L) {
|
||||
throw std::runtime_error("array or ByteArray expected");
|
||||
}
|
||||
|
||||
template<util::Buffer<ubyte>(*decode_func)(std::string_view)>
|
||||
static int l_decode(lua::State* L) {
|
||||
auto buffer = util::base64_decode(lua::require_lstring(L, 1));
|
||||
auto buffer = decode_func(lua::require_lstring(L, 1));
|
||||
if (lua::toboolean(L, 2)) {
|
||||
lua::createtable(L, buffer.size(), 0);
|
||||
for (size_t i = 0; i < buffer.size(); i++) {
|
||||
@@ -43,7 +45,9 @@ static int l_decode(lua::State* L) {
|
||||
}
|
||||
|
||||
const luaL_Reg base64lib[] = {
|
||||
{"encode", lua::wrap<l_encode>},
|
||||
{"decode", lua::wrap<l_decode>},
|
||||
{"encode", lua::wrap<l_encode<util::base64_encode>>},
|
||||
{"decode", lua::wrap<l_decode<util::base64_decode>>},
|
||||
{"encode_urlsafe", lua::wrap<l_encode<util::base64_urlsafe_encode>>},
|
||||
{"decode_urlsafe", lua::wrap<l_decode<util::base64_urlsafe_decode>>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -20,21 +20,21 @@
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static inline const Block* require_block(lua::State* L) {
|
||||
static inline const Block* get_block_def(lua::State* L) {
|
||||
auto indices = content->getIndices();
|
||||
auto id = lua::tointeger(L, 1);
|
||||
return indices->blocks.get(id);
|
||||
}
|
||||
|
||||
static inline int l_get_def(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
return lua::pushstring(L, def->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_material(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
return lua::pushstring(L, def->material);
|
||||
}
|
||||
return 0;
|
||||
@@ -59,14 +59,14 @@ static int l_index(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_is_extended(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
return lua::pushboolean(L, def->rt.extended);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_size(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
return lua::pushivec_stack(L, glm::ivec3(def->size));
|
||||
}
|
||||
return 0;
|
||||
@@ -343,14 +343,14 @@ static int l_is_replaceable_at(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_caption(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
return lua::pushstring(L, def->caption);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_textures(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
lua::createtable(L, 6, 0);
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
lua::pushstring(L, def->defaults.textureFaces[i]); // TODO: variant argument
|
||||
@@ -363,7 +363,7 @@ static int l_get_textures(lua::State* L) {
|
||||
|
||||
|
||||
static int l_model_name(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
// TODO: variant argument
|
||||
const auto& modelName = def->defaults.model.name;
|
||||
if (modelName.empty()) {
|
||||
@@ -375,7 +375,7 @@ static int l_model_name(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_get_model(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
// TODO: variant argument
|
||||
return lua::pushlstring(L, BlockModelTypeMeta.getName(def->defaults.model.type));
|
||||
}
|
||||
@@ -383,7 +383,7 @@ static int l_get_model(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_get_hitbox(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
size_t rotation = lua::tointeger(L, 2);
|
||||
if (def->rotatable) {
|
||||
rotation %= def->rotations.MAX_COUNT;
|
||||
@@ -404,14 +404,14 @@ static int l_get_hitbox(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_get_rotation_profile(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
return lua::pushstring(L, def->rotations.name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_picking_item(lua::State* L) {
|
||||
if (auto def = require_block(L)) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
return lua::pushinteger(L, def->rt.pickingItem);
|
||||
}
|
||||
return 0;
|
||||
@@ -698,6 +698,49 @@ static int l_reload_script(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_has_tag(lua::State* L) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
auto tag = lua::require_string(L, 2);
|
||||
const auto& tags = def->rt.tags;
|
||||
return lua::pushboolean(L, tags.find(content->getTagIndex(tag)) != tags.end());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_tags(lua::State* L) {
|
||||
if (auto def = get_block_def(L)) {
|
||||
if (def->tags.empty()) {
|
||||
return 0;
|
||||
}
|
||||
lua::createtable(L, 0, def->tags.size());
|
||||
for (const auto& tag : def->tags) {
|
||||
lua::pushboolean(L, true);
|
||||
lua::setfield(L, tag);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_pull_register_events(lua::State* L) {
|
||||
auto events = blocks_agent::pull_register_events();
|
||||
if (events.empty())
|
||||
return 0;
|
||||
|
||||
lua::createtable(L, events.size() * 4, 0);
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
const auto& event = events[i];
|
||||
lua::pushinteger(L, static_cast<int>(event.type) | event.id << 16);
|
||||
lua::rawseti(L, i * 4 + 1);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
lua::pushinteger(L, event.coord[j]);
|
||||
lua::rawseti(L, i * 4 + j + 2);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg blocklib[] = {
|
||||
{"index", lua::wrap<l_index>},
|
||||
{"name", lua::wrap<l_get_def>},
|
||||
@@ -737,5 +780,8 @@ const luaL_Reg blocklib[] = {
|
||||
{"get_field", lua::wrap<l_get_field>},
|
||||
{"set_field", lua::wrap<l_set_field>},
|
||||
{"reload_script", lua::wrap<l_reload_script>},
|
||||
{"has_tag", lua::wrap<l_has_tag>},
|
||||
{"__get_tags", lua::wrap<l_get_tags>},
|
||||
{"__pull_register_events", lua::wrap<l_pull_register_events>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#include "util/platform.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "world/generator/WorldGenerator.hpp"
|
||||
#include "util/platform.hpp"
|
||||
#include "frontend/locale.hpp"
|
||||
#include "graphics/ui/gui_util.hpp"
|
||||
#include "graphics/ui/GUI.hpp"
|
||||
#include "graphics/ui/elements/Menu.hpp"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
@@ -229,6 +234,24 @@ static int l_open_folder(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_open_url(lua::State* L) {
|
||||
auto url = lua::require_string(L, 1);
|
||||
|
||||
std::wstring msg = langs::get(L"Are you sure you want to open the link:") +
|
||||
L"\n" + util::str2wstr_utf8(url) +
|
||||
std::wstring(L"?");
|
||||
|
||||
auto menu = engine->getGUI().getMenu();
|
||||
|
||||
guiutil::confirm(*engine, msg, [url, menu]() {
|
||||
platform::open_url(url);
|
||||
if (!menu->back()) {
|
||||
menu->reset();
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Quit the game
|
||||
static int l_quit(lua::State*) {
|
||||
engine->quit();
|
||||
@@ -284,6 +307,7 @@ const luaL_Reg corelib[] = {
|
||||
{"str_setting", lua::wrap<l_str_setting>},
|
||||
{"get_setting_info", lua::wrap<l_get_setting_info>},
|
||||
{"open_folder", lua::wrap<l_open_folder>},
|
||||
{"open_url", lua::wrap<l_open_url>},
|
||||
{"quit", lua::wrap<l_quit>},
|
||||
{"capture_output", lua::wrap<l_capture_output>},
|
||||
{NULL, NULL}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "engine/Engine.hpp"
|
||||
#include "objects/Entities.hpp"
|
||||
#include "objects/EntityDef.hpp"
|
||||
#include "objects/Entity.hpp"
|
||||
#include "objects/Rigidbody.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "objects/rigging.hpp"
|
||||
#include "physics/Hitbox.hpp"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "frontend/hud.hpp"
|
||||
#include "objects/Entities.hpp"
|
||||
#include "objects/Entity.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "logic/LevelController.hpp"
|
||||
#include "api_lua.hpp"
|
||||
|
||||
@@ -31,6 +31,8 @@ static int l_mousecode(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_add_callback(lua::State* L) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
std::string bindname = lua::require_string(L, 1);
|
||||
size_t pos = bindname.find(':');
|
||||
|
||||
@@ -75,10 +77,14 @@ static int l_add_callback(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_get_mouse_pos(lua::State* L) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
return lua::pushvec2(L, engine->getInput().getCursor().pos);
|
||||
}
|
||||
|
||||
static int l_get_bindings(lua::State* L) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
const auto& bindings = engine->getInput().getBindings().getAll();
|
||||
lua::createtable(L, bindings.size(), 0);
|
||||
|
||||
@@ -92,18 +98,24 @@ static int l_get_bindings(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_get_binding_text(lua::State* L) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
auto bindname = lua::require_string(L, 1);
|
||||
const auto& bind = engine->getInput().getBindings().require(bindname);
|
||||
return lua::pushstring(L, bind.text());
|
||||
}
|
||||
|
||||
static int l_is_active(lua::State* L) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
auto bindname = lua::require_string(L, 1);
|
||||
auto& bind = engine->getInput().getBindings().require(bindname);
|
||||
return lua::pushboolean(L, bind.active());
|
||||
}
|
||||
|
||||
static int l_is_pressed(lua::State* L) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
std::string code = lua::require_string(L, 1);
|
||||
size_t sep = code.find(':');
|
||||
if (sep == std::string::npos) {
|
||||
@@ -136,6 +148,8 @@ static void reset_pack_bindings(const io::path& packFolder) {
|
||||
}
|
||||
|
||||
static int l_reset_bindings(lua::State*) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
reset_pack_bindings("res:");
|
||||
for (const auto& pack : content_control->getContentPacks()) {
|
||||
reset_pack_bindings(pack.folder);
|
||||
@@ -144,6 +158,8 @@ static int l_reset_bindings(lua::State*) {
|
||||
}
|
||||
|
||||
static int l_set_enabled(lua::State* L) {
|
||||
if (engine->isHeadless())
|
||||
return 0;
|
||||
std::string bindname = lua::require_string(L, 1);
|
||||
bool enabled = lua::toboolean(L, 2);
|
||||
engine->getInput().getBindings().require(bindname).enabled = enabled;
|
||||
@@ -161,4 +177,5 @@ const luaL_Reg inputlib[] = {
|
||||
{"is_pressed", lua::wrap<l_is_pressed>},
|
||||
{"reset_bindings", lua::wrap<l_reset_bindings>},
|
||||
{"set_enabled", lua::wrap<l_set_enabled>},
|
||||
{NULL, NULL}};
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -108,6 +108,30 @@ static int l_reload_script(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_has_tag(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
auto tag = lua::require_string(L, 2);
|
||||
const auto& tags = def->rt.tags;
|
||||
return lua::pushboolean(L, tags.find(content->getTagIndex(tag)) != tags.end());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_tags(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
if (def->tags.empty()) {
|
||||
return 0;
|
||||
}
|
||||
lua::createtable(L, 0, def->tags.size());
|
||||
for (const auto& tag : def->tags) {
|
||||
lua::pushboolean(L, true);
|
||||
lua::setfield(L, tag);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg itemlib[] = {
|
||||
{"index", lua::wrap<l_index>},
|
||||
{"name", lua::wrap<l_name>},
|
||||
@@ -121,5 +145,7 @@ const luaL_Reg itemlib[] = {
|
||||
{"emission", lua::wrap<l_emission>},
|
||||
{"uses", lua::wrap<l_uses>},
|
||||
{"reload_script", lua::wrap<l_reload_script>},
|
||||
{"has_tag", lua::wrap<l_has_tag>},
|
||||
{"__get_tags", lua::wrap<l_get_tags>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -3,73 +3,124 @@
|
||||
#include "engine/Engine.hpp"
|
||||
#include "network/Network.hpp"
|
||||
|
||||
#include <variant>
|
||||
#include <utility>
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static int l_get(lua::State* L, network::Network& network) {
|
||||
std::string url(lua::require_lstring(L, 1));
|
||||
enum NetworkEventType {
|
||||
CLIENT_CONNECTED = 1,
|
||||
CONNECTED_TO_SERVER,
|
||||
DATAGRAM,
|
||||
RESPONSE,
|
||||
};
|
||||
|
||||
lua::pushvalue(L, 2);
|
||||
auto onResponse = lua::create_lambda_nothrow(L);
|
||||
struct ConnectionEventDto {
|
||||
u64id_t server;
|
||||
u64id_t client;
|
||||
};
|
||||
|
||||
network::OnReject onReject = nullptr;
|
||||
if (lua::gettop(L) >= 3) {
|
||||
lua::pushvalue(L, 3);
|
||||
auto callback = lua::create_lambda_nothrow(L);
|
||||
onReject = [callback](int code) {
|
||||
callback({code});
|
||||
};
|
||||
struct ResponseEventDto {
|
||||
int status;
|
||||
bool binary;
|
||||
int requestId;
|
||||
std::vector<char> bytes;
|
||||
};
|
||||
|
||||
enum NetworkDatagramSide {
|
||||
ON_SERVER = 1,
|
||||
ON_CLIENT
|
||||
};
|
||||
|
||||
struct NetworkDatagramEventDto {
|
||||
NetworkDatagramSide side;
|
||||
u64id_t server;
|
||||
u64id_t client;
|
||||
std::string addr;
|
||||
int port;
|
||||
std::vector<char> buffer;
|
||||
};
|
||||
|
||||
struct NetworkEvent {
|
||||
using Payload = std::variant<
|
||||
ConnectionEventDto,
|
||||
ResponseEventDto,
|
||||
NetworkDatagramEventDto
|
||||
>;
|
||||
NetworkEventType type;
|
||||
|
||||
Payload payload;
|
||||
|
||||
NetworkEvent(
|
||||
NetworkEventType type,
|
||||
Payload payload
|
||||
) : type(type), payload(std::move(payload)) {}
|
||||
|
||||
virtual ~NetworkEvent() = default;
|
||||
};
|
||||
|
||||
static std::vector<NetworkEvent> events_queue {};
|
||||
static std::mutex events_queue_mutex;
|
||||
|
||||
static void push_event(NetworkEvent&& event) {
|
||||
std::lock_guard lock(events_queue_mutex);
|
||||
events_queue.push_back(std::move(event));
|
||||
}
|
||||
|
||||
static std::vector<std::string> read_headers(lua::State* L, int index) {
|
||||
std::vector<std::string> headers;
|
||||
if (lua::istable(L, index)) {
|
||||
int len = lua::objlen(L, index);
|
||||
for (int i = 1; i <= len; i++) {
|
||||
lua::rawgeti(L, i, index);
|
||||
headers.push_back(lua::tostring(L, -1));
|
||||
lua::pop(L);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
network.get(url, [onResponse](std::vector<char> bytes) {
|
||||
engine->postRunnable([=]() {
|
||||
onResponse({std::string(bytes.data(), bytes.size())});
|
||||
});
|
||||
}, std::move(onReject));
|
||||
return 0;
|
||||
static int request_id = 1;
|
||||
|
||||
static int perform_get(lua::State* L, network::Network& network, bool binary) {
|
||||
std::string url(lua::require_lstring(L, 1));
|
||||
auto headers = read_headers(L, 2);
|
||||
|
||||
int currentRequestId = request_id++;
|
||||
|
||||
network.get(
|
||||
url,
|
||||
[currentRequestId, binary](std::vector<char> bytes) {
|
||||
push_event(NetworkEvent(
|
||||
RESPONSE,
|
||||
ResponseEventDto {
|
||||
200, binary, currentRequestId, std::move(bytes)}
|
||||
));
|
||||
},
|
||||
[currentRequestId, binary](int code, std::vector<char> bytes) {
|
||||
push_event(NetworkEvent(
|
||||
RESPONSE,
|
||||
ResponseEventDto {
|
||||
code, binary, currentRequestId, std::move(bytes)}
|
||||
));
|
||||
},
|
||||
std::move(headers)
|
||||
);
|
||||
return lua::pushinteger(L, currentRequestId);
|
||||
}
|
||||
|
||||
static int l_get(lua::State* L, network::Network& network) {
|
||||
return perform_get(L, network, false);
|
||||
}
|
||||
|
||||
static int l_get_binary(lua::State* L, network::Network& network) {
|
||||
std::string url(lua::require_lstring(L, 1));
|
||||
|
||||
lua::pushvalue(L, 2);
|
||||
auto onResponse = lua::create_lambda_nothrow(L);
|
||||
|
||||
network::OnReject onReject = nullptr;
|
||||
if (lua::gettop(L) >= 3) {
|
||||
lua::pushvalue(L, 3);
|
||||
auto callback = lua::create_lambda_nothrow(L);
|
||||
onReject = [callback](int code) {
|
||||
callback({code});
|
||||
};
|
||||
}
|
||||
|
||||
network.get(url, [onResponse](std::vector<char> bytes) {
|
||||
auto buffer = std::make_shared<util::Buffer<ubyte>>(
|
||||
reinterpret_cast<const ubyte*>(bytes.data()), bytes.size()
|
||||
);
|
||||
engine->postRunnable([=]() {
|
||||
onResponse({buffer});
|
||||
});
|
||||
}, std::move(onReject));
|
||||
return 0;
|
||||
return perform_get(L, network, true);
|
||||
}
|
||||
|
||||
static int l_post(lua::State* L, network::Network& network) {
|
||||
std::string url(lua::require_lstring(L, 1));
|
||||
auto data = lua::tovalue(L, 2);
|
||||
|
||||
lua::pushvalue(L, 3);
|
||||
auto onResponse = lua::create_lambda_nothrow(L);
|
||||
|
||||
network::OnReject onReject = nullptr;
|
||||
if (lua::gettop(L) >= 4) {
|
||||
lua::pushvalue(L, 4);
|
||||
auto callback = lua::create_lambda_nothrow(L);
|
||||
onReject = [callback](int code) {
|
||||
callback({code});
|
||||
};
|
||||
}
|
||||
|
||||
std::string string;
|
||||
if (data.isString()) {
|
||||
string = data.asString();
|
||||
@@ -77,15 +128,29 @@ static int l_post(lua::State* L, network::Network& network) {
|
||||
string = json::stringify(data, false);
|
||||
}
|
||||
|
||||
engine->getNetwork().post(url, string, [onResponse](std::vector<char> bytes) {
|
||||
auto buffer = std::make_shared<util::Buffer<ubyte>>(
|
||||
reinterpret_cast<const ubyte*>(bytes.data()), bytes.size()
|
||||
);
|
||||
engine->postRunnable([=]() {
|
||||
onResponse({std::string(bytes.data(), bytes.size())});
|
||||
});
|
||||
}, std::move(onReject));
|
||||
return 0;
|
||||
auto headers = read_headers(L, 3);
|
||||
int currentRequestId = request_id++;
|
||||
|
||||
engine->getNetwork().post(
|
||||
url,
|
||||
string,
|
||||
[currentRequestId](std::vector<char> bytes) {
|
||||
push_event(NetworkEvent(
|
||||
RESPONSE,
|
||||
ResponseEventDto {
|
||||
200, false, currentRequestId, std::move(bytes)}
|
||||
));
|
||||
},
|
||||
[currentRequestId](int code, std::vector<char> bytes) {
|
||||
push_event(NetworkEvent(
|
||||
RESPONSE,
|
||||
ResponseEventDto {
|
||||
code, false, currentRequestId, std::move(bytes)}
|
||||
));
|
||||
},
|
||||
std::move(headers)
|
||||
);
|
||||
return lua::pushinteger(L, currentRequestId);
|
||||
}
|
||||
|
||||
static int l_close(lua::State* L, network::Network& network) {
|
||||
@@ -210,69 +275,14 @@ static int l_available(lua::State* L, network::Network& network) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum NetworkEventType {
|
||||
CLIENT_CONNECTED = 1,
|
||||
CONNECTED_TO_SERVER,
|
||||
DATAGRAM
|
||||
};
|
||||
|
||||
struct NetworkEvent {
|
||||
NetworkEventType type;
|
||||
u64id_t server;
|
||||
u64id_t client;
|
||||
|
||||
NetworkEvent(
|
||||
NetworkEventType type,
|
||||
u64id_t server,
|
||||
u64id_t client
|
||||
) {
|
||||
this->type = type;
|
||||
this->server = server;
|
||||
this->client = client;
|
||||
}
|
||||
|
||||
virtual ~NetworkEvent() = default;
|
||||
};
|
||||
|
||||
enum NetworkDatagramSide {
|
||||
ON_SERVER = 1,
|
||||
ON_CLIENT
|
||||
};
|
||||
|
||||
struct NetworkDatagramEvent : NetworkEvent {
|
||||
NetworkDatagramSide side;
|
||||
std::string addr;
|
||||
int port;
|
||||
const char* buffer;
|
||||
size_t length;
|
||||
|
||||
NetworkDatagramEvent(
|
||||
NetworkEventType datagram,
|
||||
u64id_t sid,
|
||||
u64id_t cid,
|
||||
NetworkDatagramSide side,
|
||||
const std::string& addr,
|
||||
int port,
|
||||
const char* data,
|
||||
size_t length
|
||||
) : NetworkEvent(DATAGRAM, sid, cid) {
|
||||
this->side = side;
|
||||
this->addr = addr;
|
||||
this->port = port;
|
||||
|
||||
buffer = data;
|
||||
|
||||
this->length = length;
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<std::unique_ptr<NetworkEvent>> events_queue {};
|
||||
|
||||
static int l_connect_tcp(lua::State* L, network::Network& network) {
|
||||
std::string address = lua::require_string(L, 1);
|
||||
int port = lua::tointeger(L, 2);
|
||||
u64id_t id = network.connectTcp(address, port, [](u64id_t cid) {
|
||||
events_queue.push_back(std::make_unique<NetworkEvent>(CONNECTED_TO_SERVER, 0, cid));
|
||||
push_event(NetworkEvent(
|
||||
CONNECTED_TO_SERVER,
|
||||
ConnectionEventDto {0, cid}
|
||||
));
|
||||
});
|
||||
return lua::pushinteger(L, id);
|
||||
}
|
||||
@@ -280,7 +290,10 @@ static int l_connect_tcp(lua::State* L, network::Network& network) {
|
||||
static int l_open_tcp(lua::State* L, network::Network& network) {
|
||||
int port = lua::tointeger(L, 1);
|
||||
u64id_t id = network.openTcpServer(port, [](u64id_t sid, u64id_t id) {
|
||||
events_queue.push_back(std::make_unique<NetworkEvent>(CLIENT_CONNECTED, sid, id));
|
||||
push_event(NetworkEvent(
|
||||
CLIENT_CONNECTED,
|
||||
ConnectionEventDto {sid, id}
|
||||
));
|
||||
});
|
||||
return lua::pushinteger(L, id);
|
||||
}
|
||||
@@ -289,18 +302,22 @@ static int l_connect_udp(lua::State* L, network::Network& network) {
|
||||
std::string address = lua::require_string(L, 1);
|
||||
int port = lua::tointeger(L, 2);
|
||||
u64id_t id = network.connectUdp(address, port, [](u64id_t cid) {
|
||||
events_queue.push_back(std::make_unique<NetworkEvent>(CONNECTED_TO_SERVER, 0, cid));
|
||||
push_event(NetworkEvent(
|
||||
CONNECTED_TO_SERVER,
|
||||
ConnectionEventDto {0, cid}
|
||||
));
|
||||
}, [address, port](
|
||||
u64id_t cid,
|
||||
const char* buffer,
|
||||
size_t length
|
||||
) {
|
||||
events_queue.push_back(
|
||||
std::make_unique<NetworkDatagramEvent>(
|
||||
DATAGRAM, 0, cid, ON_CLIENT,
|
||||
address, port, buffer, length
|
||||
)
|
||||
);
|
||||
push_event(NetworkEvent(
|
||||
DATAGRAM,
|
||||
NetworkDatagramEventDto {
|
||||
ON_CLIENT, 0, cid,
|
||||
address, port, std::vector<char>(buffer, buffer + length)
|
||||
}
|
||||
));
|
||||
});
|
||||
return lua::pushinteger(L, id);
|
||||
}
|
||||
@@ -313,10 +330,13 @@ static int l_open_udp(lua::State* L, network::Network& network) {
|
||||
int port,
|
||||
const char* buffer,
|
||||
size_t length) {
|
||||
events_queue.push_back(
|
||||
std::make_unique<NetworkDatagramEvent>(
|
||||
DATAGRAM, sid, 0, ON_SERVER,
|
||||
addr, port, buffer, length
|
||||
push_event(
|
||||
NetworkEvent(
|
||||
DATAGRAM,
|
||||
NetworkDatagramEventDto {
|
||||
ON_SERVER, sid, 0,
|
||||
addr, port, std::vector<char>(buffer, buffer + length)
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
@@ -405,39 +425,78 @@ static int l_get_nodelay(lua::State* L, network::Network& network) {
|
||||
}
|
||||
|
||||
static int l_pull_events(lua::State* L, network::Network& network) {
|
||||
lua::createtable(L, events_queue.size(), 0);
|
||||
std::vector<NetworkEvent> local_queue;
|
||||
{
|
||||
std::lock_guard lock(events_queue_mutex);
|
||||
local_queue.swap(events_queue);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < events_queue.size(); i++) {
|
||||
const auto* datagramEvent = dynamic_cast<NetworkDatagramEvent*>(events_queue[i].get());
|
||||
lua::createtable(L, local_queue.size(), 0);
|
||||
|
||||
lua::createtable(L, datagramEvent ? 7 : 3, 0);
|
||||
for (size_t i = 0; i < local_queue.size(); i++) {
|
||||
lua::createtable(L, 7, 0);
|
||||
|
||||
lua::pushinteger(L, events_queue[i]->type);
|
||||
lua::rawseti(L, 1);
|
||||
const auto& event = local_queue[i];
|
||||
switch (event.type) {
|
||||
case CLIENT_CONNECTED:
|
||||
case CONNECTED_TO_SERVER: {
|
||||
const auto& dto = std::get<ConnectionEventDto>(event.payload);
|
||||
lua::pushinteger(L, event.type);
|
||||
lua::rawseti(L, 1);
|
||||
|
||||
lua::pushinteger(L, events_queue[i]->server);
|
||||
lua::rawseti(L, 2);
|
||||
lua::pushinteger(L, dto.server);
|
||||
lua::rawseti(L, 2);
|
||||
|
||||
lua::pushinteger(L, events_queue[i]->client);
|
||||
lua::rawseti(L, 3);
|
||||
lua::pushinteger(L, dto.client);
|
||||
lua::rawseti(L, 3);
|
||||
break;
|
||||
}
|
||||
case DATAGRAM: {
|
||||
const auto& dto = std::get<NetworkDatagramEventDto>(event.payload);
|
||||
lua::pushinteger(L, event.type);
|
||||
lua::rawseti(L, 1);
|
||||
|
||||
if (datagramEvent) {
|
||||
lua::pushstring(L, datagramEvent->addr);
|
||||
lua::rawseti(L, 4);
|
||||
lua::pushinteger(L, dto.server);
|
||||
lua::rawseti(L, 2);
|
||||
|
||||
lua::pushinteger(L, datagramEvent->port);
|
||||
lua::rawseti(L, 5);
|
||||
lua::pushinteger(L, dto.client);
|
||||
lua::rawseti(L, 3);
|
||||
|
||||
lua::pushinteger(L, datagramEvent->side);
|
||||
lua::rawseti(L, 6);
|
||||
lua::pushstring(L, dto.addr);
|
||||
lua::rawseti(L, 4);
|
||||
|
||||
lua::create_bytearray(L, datagramEvent->buffer, datagramEvent->length);
|
||||
lua::rawseti(L, 7);
|
||||
lua::pushinteger(L, dto.port);
|
||||
lua::rawseti(L, 5);
|
||||
|
||||
lua::pushinteger(L, dto.side);
|
||||
lua::rawseti(L, 6);
|
||||
|
||||
lua::create_bytearray(L, dto.buffer.data(), dto.buffer.size());
|
||||
lua::rawseti(L, 7);
|
||||
break;
|
||||
}
|
||||
case RESPONSE: {
|
||||
const auto& dto = std::get<ResponseEventDto>(event.payload);
|
||||
lua::pushinteger(L, event.type);
|
||||
lua::rawseti(L, 1);
|
||||
|
||||
lua::pushinteger(L, dto.status);
|
||||
lua::rawseti(L, 2);
|
||||
|
||||
lua::pushinteger(L, dto.requestId);
|
||||
lua::rawseti(L, 3);
|
||||
|
||||
if (dto.binary) {
|
||||
lua::create_bytearray(L, dto.bytes.data(), dto.bytes.size());
|
||||
} else {
|
||||
lua::pushlstring(L, std::string_view(dto.bytes.data(), dto.bytes.size()));
|
||||
}
|
||||
lua::rawseti(L, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lua::rawseti(L, i + 1);
|
||||
}
|
||||
events_queue.clear();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -459,9 +518,9 @@ int wrap(lua_State* L) {
|
||||
}
|
||||
|
||||
const luaL_Reg networklib[] = {
|
||||
{"get", wrap<l_get>},
|
||||
{"get_binary", wrap<l_get_binary>},
|
||||
{"post", wrap<l_post>},
|
||||
{"__get", wrap<l_get>},
|
||||
{"__get_binary", wrap<l_get_binary>},
|
||||
{"__post", wrap<l_post>},
|
||||
{"get_total_upload", wrap<l_get_total_upload>},
|
||||
{"get_total_download", wrap<l_get_total_download>},
|
||||
{"__pull_events", wrap<l_pull_events>},
|
||||
|
||||
@@ -102,19 +102,20 @@ static int l_pack_get_info(
|
||||
auto& dpack = pack.dependencies[i];
|
||||
std::string prefix;
|
||||
switch (dpack.level) {
|
||||
case DependencyLevel::required:
|
||||
case DependencyLevel::REQUIRED:
|
||||
prefix = "!";
|
||||
break;
|
||||
case DependencyLevel::optional:
|
||||
case DependencyLevel::OPTIONAL:
|
||||
prefix = "?";
|
||||
break;
|
||||
case DependencyLevel::weak:
|
||||
case DependencyLevel::WEAK:
|
||||
prefix = "~";
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("");
|
||||
}
|
||||
lua::pushfstring(L, "%s%s", prefix.c_str(), dpack.id.c_str());
|
||||
|
||||
lua::pushfstring(L, "%s%s@%s%s", prefix.c_str(), dpack.id.c_str(), dpack.op.c_str(), dpack.version.c_str());
|
||||
lua::rawseti(L, i + 1);
|
||||
}
|
||||
lua::setfield(L, "dependencies");
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "api_lua.hpp"
|
||||
|
||||
#include "content/Content.hpp"
|
||||
#include "voxels/Pathfinding.hpp"
|
||||
#include "world/Level.hpp"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static voxels::Agent* get_agent(lua::State* L) {
|
||||
return level->pathfinding->getAgent(lua::tointeger(L, 1));
|
||||
}
|
||||
|
||||
static int l_create_agent(lua::State* L) {
|
||||
return lua::pushinteger(L, level->pathfinding->createAgent());
|
||||
}
|
||||
|
||||
static int l_remove_agent(lua::State* L) {
|
||||
int id = lua::tointeger(L, 1);
|
||||
return lua::pushboolean(L, level->pathfinding->removeAgent(id));
|
||||
}
|
||||
|
||||
static int l_set_enabled(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
agent->enabled = lua::toboolean(L, 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_is_enabled(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
return lua::pushboolean(L, agent->enabled);
|
||||
}
|
||||
return lua::pushboolean(L, false);
|
||||
}
|
||||
|
||||
static int push_route(lua::State* L, const voxels::Route& route) {
|
||||
lua::createtable(L, route.nodes.size(), 1);
|
||||
for (int i = 0; i < route.nodes.size(); i++) {
|
||||
lua::pushvec3(L, route.nodes[i].pos);
|
||||
lua::rawseti(L, i + 1);
|
||||
}
|
||||
lua::pushinteger(L, route.totalVisited);
|
||||
lua::setfield(L, "total_visited");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_make_route(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
auto start = lua::tovec3(L, 2);
|
||||
auto target = lua::tovec3(L, 3);
|
||||
agent->state = {};
|
||||
agent->start = glm::floor(start);
|
||||
agent->target = target;
|
||||
auto route = level->pathfinding->perform(*agent);
|
||||
if (!route.found) {
|
||||
return 0;
|
||||
}
|
||||
return push_route(L, route);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_make_route_async(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
auto start = lua::tovec3(L, 2);
|
||||
auto target = lua::tovec3(L, 3);
|
||||
agent->state = {};
|
||||
agent->start = glm::floor(start);
|
||||
agent->target = target;
|
||||
level->pathfinding->perform(*agent, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_pull_route(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
auto& route = agent->route;
|
||||
if (!agent->state.finished) {
|
||||
return 0;
|
||||
}
|
||||
if (!route.found && !agent->mayBeIncomplete) {
|
||||
return lua::createtable(L, 0, 0);
|
||||
}
|
||||
return push_route(L, route);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_max_visited_blocks(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
agent->maxVisitedBlocks = lua::tointeger(L, 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_jump_height(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
agent->jumpHeight = lua::tointeger(L, 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_avoid_tag(lua::State* L) {
|
||||
if (auto agent = get_agent(L)) {
|
||||
int index =
|
||||
content->getTagIndex(std::string(lua::require_lstring(L, 2)));
|
||||
if (index != -1) {
|
||||
int cost = lua::tonumber(L, 3);
|
||||
if (cost == 0) {
|
||||
cost = 10;
|
||||
}
|
||||
agent->avoidTags.insert({index, cost});
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg pathfindinglib[] = {
|
||||
{"create_agent", lua::wrap<l_create_agent>},
|
||||
{"remove_agent", lua::wrap<l_remove_agent>},
|
||||
{"set_enabled", lua::wrap<l_set_enabled>},
|
||||
{"is_enabled", lua::wrap<l_is_enabled>},
|
||||
{"make_route", lua::wrap<l_make_route>},
|
||||
{"make_route_async", lua::wrap<l_make_route_async>},
|
||||
{"pull_route", lua::wrap<l_pull_route>},
|
||||
{"set_max_visited", lua::wrap<l_set_max_visited_blocks>},
|
||||
{"set_jump_height", lua::wrap<l_set_jump_height>},
|
||||
{"avoid_tag", lua::wrap<l_avoid_tag>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -2,13 +2,14 @@
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "items/Inventory.hpp"
|
||||
#include "libentity.hpp"
|
||||
#include "objects/Entities.hpp"
|
||||
#include "objects/Entity.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "objects/Players.hpp"
|
||||
#include "physics/Hitbox.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "libentity.hpp"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
@@ -52,7 +53,7 @@ static int l_set_vel(lua::State* L) {
|
||||
auto x = lua::tonumber(L, 2);
|
||||
auto y = lua::tonumber(L, 3);
|
||||
auto z = lua::tonumber(L, 4);
|
||||
|
||||
|
||||
if (auto hitbox = player->getHitbox()) {
|
||||
hitbox->velocity = glm::vec3(x, y, z);
|
||||
}
|
||||
@@ -180,6 +181,21 @@ static int l_set_loading_chunks(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_interaction_distance(lua::State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
return lua::pushnumber(L, player->getMaxInteractionDistance());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_interaction_distance(lua::State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
player->setMaxInteractionDistance(
|
||||
static_cast<float>(lua::tonumber(L, 2)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_selected_block(lua::State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
if (player->selection.vox.id == BLOCK_VOID) {
|
||||
@@ -327,6 +343,8 @@ const luaL_Reg playerlib[] = {
|
||||
{"set_instant_destruction", lua::wrap<l_set_instant_destruction>},
|
||||
{"is_loading_chunks", lua::wrap<l_is_loading_chunks>},
|
||||
{"set_loading_chunks", lua::wrap<l_set_loading_chunks>},
|
||||
{"get_interaction_distance", lua::wrap<l_get_interaction_distance>},
|
||||
{"set_interaction_distance", lua::wrap<l_set_interaction_distance>},
|
||||
{"set_selected_slot", lua::wrap<l_set_selected_slot>},
|
||||
{"get_selected_block", lua::wrap<l_get_selected_block>},
|
||||
{"get_selected_entity", lua::wrap<l_get_selected_entity>},
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "api_lua.hpp"
|
||||
|
||||
#include "util/random.hpp"
|
||||
|
||||
static std::random_device random_device;
|
||||
|
||||
static int l_random(lua::State* L) {
|
||||
int argc = lua::gettop(L);
|
||||
|
||||
auto randomEngine = util::seeded_random_engine(random_device);
|
||||
if (argc == 0) {
|
||||
std::uniform_real_distribution<> dist(0.0, 1.0);
|
||||
return lua::pushnumber(L, dist(randomEngine));
|
||||
} else if (argc == 1) {
|
||||
std::uniform_int_distribution<integer_t> dist(1, lua::tointeger(L, 1));
|
||||
return lua::pushinteger(L, dist(randomEngine));
|
||||
} else {
|
||||
std::uniform_int_distribution<integer_t> dist(
|
||||
lua::tointeger(L, 1), lua::tointeger(L, 2)
|
||||
);
|
||||
return lua::pushinteger(L, dist(randomEngine));
|
||||
}
|
||||
}
|
||||
|
||||
static int l_bytes(lua::State* L) {
|
||||
size_t size = lua::tointeger(L, 1);
|
||||
|
||||
auto randomEngine = util::seeded_random_engine(random_device);
|
||||
static std::uniform_int_distribution<integer_t> dist(0, 0xFF);
|
||||
std::vector<ubyte> bytes (size);
|
||||
for (size_t i = 0; i < bytes.size(); i++) {
|
||||
bytes[i] = dist(randomEngine);
|
||||
}
|
||||
return lua::create_bytearray(L, bytes);
|
||||
}
|
||||
|
||||
static int l_uuid(lua::State* L) {
|
||||
return lua::pushlstring(L, util::generate_uuid());
|
||||
}
|
||||
|
||||
const luaL_Reg randomlib[] = {
|
||||
{"random", lua::wrap<l_random>},
|
||||
{"bytes", lua::wrap<l_bytes>},
|
||||
{"uuid", lua::wrap<l_uuid>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -15,10 +15,24 @@ inline T angle(glm::vec<2, T> vec) {
|
||||
return val;
|
||||
}
|
||||
|
||||
template <int n>
|
||||
static int l_mix(lua::State* L) {
|
||||
uint argc = lua::check_argc(L, 3, 4);
|
||||
auto a = lua::tovec<n, number_t>(L, 1);
|
||||
auto b = lua::tovec<n, number_t>(L, 2);
|
||||
auto t = lua::tonumber(L, 3);
|
||||
|
||||
if (argc == 3) {
|
||||
return lua::pushvec(L, a * (1.0 - t) + b * t);
|
||||
} else {
|
||||
return lua::setvec(L, 4, a * (1.0 - t) + b * t);
|
||||
}
|
||||
}
|
||||
|
||||
template <int n, template <class> class Op>
|
||||
static int l_binop(lua::State* L) {
|
||||
uint argc = lua::check_argc(L, 2, 3);
|
||||
auto a = lua::tovec<n>(L, 1);
|
||||
auto a = lua::tovec<n, number_t>(L, 1);
|
||||
|
||||
if (lua::isnumber(L, 2)) { // scalar second operand overload
|
||||
auto b = lua::tonumber(L, 2);
|
||||
@@ -31,10 +45,10 @@ static int l_binop(lua::State* L) {
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return lua::setvec(L, 3, op(a, glm::vec<n, float>(b)));
|
||||
return lua::setvec(L, 3, op(a, glm::vec<n, number_t>(b)));
|
||||
}
|
||||
} else {
|
||||
auto b = lua::tovec<n>(L, 2);
|
||||
auto b = lua::tovec<n, number_t>(L, 2);
|
||||
Op op;
|
||||
if (argc == 2) {
|
||||
lua::createtable(L, n, 0);
|
||||
@@ -49,10 +63,10 @@ static int l_binop(lua::State* L) {
|
||||
}
|
||||
}
|
||||
|
||||
template <int n, glm::vec<n, float> (*func)(const glm::vec<n, float>&)>
|
||||
template <int n, glm::vec<n, number_t> (*func)(const glm::vec<n, number_t>&)>
|
||||
static int l_unaryop(lua::State* L) {
|
||||
uint argc = lua::check_argc(L, 1, 2);
|
||||
auto vec = func(lua::tovec<n>(L, 1));
|
||||
auto vec = func(lua::tovec<n, number_t>(L, 1));
|
||||
switch (argc) {
|
||||
case 1:
|
||||
lua::createtable(L, n, 0);
|
||||
@@ -67,17 +81,25 @@ static int l_unaryop(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <int n, float (*func)(const glm::vec<n, float>&)>
|
||||
template <int n, number_t (*func)(const glm::vec<n, number_t>&)>
|
||||
static int l_scalar_op(lua::State* L) {
|
||||
lua::check_argc(L, 1);
|
||||
auto vec = lua::tovec<n>(L, 1);
|
||||
auto vec = lua::tovec<n, number_t>(L, 1);
|
||||
return lua::pushnumber(L, func(vec));
|
||||
}
|
||||
|
||||
template <int n>
|
||||
static int l_distance(lua::State* L) {
|
||||
lua::check_argc(L, 2);
|
||||
auto a = lua::tovec<n, number_t>(L, 1);
|
||||
auto b = lua::tovec<n, number_t>(L, 2);
|
||||
return lua::pushnumber(L,glm::distance(a, b));
|
||||
}
|
||||
|
||||
template <int n>
|
||||
static int l_pow(lua::State* L) {
|
||||
uint argc = lua::check_argc(L, 2, 3);
|
||||
auto a = lua::tovec<n>(L, 1);
|
||||
auto a = lua::tovec<n, number_t>(L, 1);
|
||||
|
||||
if (lua::isnumber(L, 2)) {
|
||||
auto b = lua::tonumber(L, 2);
|
||||
@@ -89,10 +111,10 @@ static int l_pow(lua::State* L) {
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return lua::setvec(L, 3, pow(a, glm::vec<n, float>(b)));
|
||||
return lua::setvec(L, 3, pow(a, glm::vec<n, number_t>(b)));
|
||||
}
|
||||
} else {
|
||||
auto b = lua::tovec<n>(L, 2);
|
||||
auto b = lua::tovec<n, number_t>(L, 2);
|
||||
if (argc == 2) {
|
||||
lua::createtable(L, n, 0);
|
||||
for (uint i = 0; i < n; i++) {
|
||||
@@ -109,15 +131,15 @@ static int l_pow(lua::State* L) {
|
||||
template <int n>
|
||||
static int l_dot(lua::State* L) {
|
||||
lua::check_argc(L, 2);
|
||||
const auto& a = lua::tovec<n>(L, 1);
|
||||
const auto& b = lua::tovec<n>(L, 2);
|
||||
auto a = lua::tovec<n, number_t>(L, 1);
|
||||
auto b = lua::tovec<n, number_t>(L, 2);
|
||||
return lua::pushnumber(L, glm::dot(a, b));
|
||||
}
|
||||
|
||||
template <int n>
|
||||
static int l_inverse(lua::State* L) {
|
||||
uint argc = lua::check_argc(L, 1, 2);
|
||||
auto vec = lua::tovec<n>(L, 1);
|
||||
auto vec = lua::tovec<n, number_t>(L, 1);
|
||||
switch (argc) {
|
||||
case 1:
|
||||
lua::createtable(L, n, 0);
|
||||
@@ -141,7 +163,7 @@ static int l_spherical_rand(lua::State* L) {
|
||||
return lua::setvec(
|
||||
L,
|
||||
2,
|
||||
glm::sphericalRand(static_cast<float>(lua::tonumber(L, 1)))
|
||||
glm::sphericalRand(lua::tonumber(L, 1))
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
@@ -161,10 +183,22 @@ static int l_vec2_angle(lua::State* L) {
|
||||
}
|
||||
}
|
||||
|
||||
static int l_vec2_rotate(lua::State* L) {
|
||||
uint argc = lua::check_argc(L, 2, 3);
|
||||
auto vec = lua::tovec<2, number_t>(L, 1);
|
||||
auto angle = glm::radians(lua::tonumber(L, 2));
|
||||
|
||||
if (argc == 2) {
|
||||
return lua::pushvec(L, glm::rotate(vec, angle));
|
||||
} else {
|
||||
return lua::setvec(L, 3, glm::rotate(vec, angle));
|
||||
}
|
||||
}
|
||||
|
||||
template <int n>
|
||||
static int l_tostring(lua::State* L) {
|
||||
lua::check_argc(L, 1);
|
||||
auto vec = lua::tovec<n>(L, 1);
|
||||
auto vec = lua::tovec<n, number_t>(L, 1);
|
||||
std::stringstream ss;
|
||||
ss << "vec" << std::to_string(n) << "{";
|
||||
for (int i = 0; i < n; i++) {
|
||||
@@ -182,6 +216,7 @@ const luaL_Reg vec2lib[] = {
|
||||
{"sub", lua::wrap<l_binop<2, std::minus>>},
|
||||
{"mul", lua::wrap<l_binop<2, std::multiplies>>},
|
||||
{"div", lua::wrap<l_binop<2, std::divides>>},
|
||||
{"distance", lua::wrap<l_distance<2>>},
|
||||
{"normalize", lua::wrap<l_unaryop<2, glm::normalize>>},
|
||||
{"length", lua::wrap<l_scalar_op<2, glm::length>>},
|
||||
{"tostring", lua::wrap<l_tostring<2>>},
|
||||
@@ -191,6 +226,8 @@ const luaL_Reg vec2lib[] = {
|
||||
{"pow", lua::wrap<l_pow<2>>},
|
||||
{"dot", lua::wrap<l_dot<2>>},
|
||||
{"angle", lua::wrap<l_vec2_angle>},
|
||||
{"mix", lua::wrap<l_mix<2>>},
|
||||
{"rotate", lua::wrap<l_vec2_rotate>},
|
||||
{NULL, NULL}};
|
||||
|
||||
const luaL_Reg vec3lib[] = {
|
||||
@@ -198,6 +235,7 @@ const luaL_Reg vec3lib[] = {
|
||||
{"sub", lua::wrap<l_binop<3, std::minus>>},
|
||||
{"mul", lua::wrap<l_binop<3, std::multiplies>>},
|
||||
{"div", lua::wrap<l_binop<3, std::divides>>},
|
||||
{"distance", lua::wrap<l_distance<3>>},
|
||||
{"normalize", lua::wrap<l_unaryop<3, glm::normalize>>},
|
||||
{"length", lua::wrap<l_scalar_op<3, glm::length>>},
|
||||
{"tostring", lua::wrap<l_tostring<3>>},
|
||||
@@ -207,6 +245,7 @@ const luaL_Reg vec3lib[] = {
|
||||
{"pow", lua::wrap<l_pow<3>>},
|
||||
{"dot", lua::wrap<l_dot<3>>},
|
||||
{"spherical_rand", lua::wrap<l_spherical_rand>},
|
||||
{"mix", lua::wrap<l_mix<3>>},
|
||||
{NULL, NULL}};
|
||||
|
||||
const luaL_Reg vec4lib[] = {
|
||||
@@ -214,6 +253,7 @@ const luaL_Reg vec4lib[] = {
|
||||
{"sub", lua::wrap<l_binop<4, std::minus>>},
|
||||
{"mul", lua::wrap<l_binop<4, std::multiplies>>},
|
||||
{"div", lua::wrap<l_binop<4, std::divides>>},
|
||||
{"distance", lua::wrap<l_distance<4>>},
|
||||
{"normalize", lua::wrap<l_unaryop<4, glm::normalize>>},
|
||||
{"length", lua::wrap<l_scalar_op<4, glm::length>>},
|
||||
{"tostring", lua::wrap<l_tostring<4>>},
|
||||
@@ -222,4 +262,5 @@ const luaL_Reg vec4lib[] = {
|
||||
{"inverse", lua::wrap<l_inverse<4>>},
|
||||
{"pow", lua::wrap<l_pow<4>>},
|
||||
{"dot", lua::wrap<l_dot<4>>},
|
||||
{"mix", lua::wrap<l_mix<4>>},
|
||||
{NULL, NULL}};
|
||||
|
||||
@@ -51,6 +51,7 @@ static void create_libs(State* L, StateType stateType) {
|
||||
openlib(L, "mat4", mat4lib);
|
||||
openlib(L, "pack", packlib);
|
||||
openlib(L, "quat", quatlib);
|
||||
openlib(L, "random", randomlib);
|
||||
openlib(L, "toml", tomllib);
|
||||
openlib(L, "utf8", utf8lib);
|
||||
openlib(L, "vec2", vec2lib);
|
||||
@@ -72,6 +73,7 @@ static void create_libs(State* L, StateType stateType) {
|
||||
openlib(L, "input", inputlib);
|
||||
openlib(L, "inventory", inventorylib);
|
||||
openlib(L, "network", networklib);
|
||||
openlib(L, "pathfinding", pathfindinglib);
|
||||
openlib(L, "player", playerlib);
|
||||
openlib(L, "time", timelib);
|
||||
openlib(L, "world", worldlib);
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace lua {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int n>
|
||||
inline int pushvec(lua::State* L, const glm::vec<n, float>& vec) {
|
||||
template <int n, typename T = float>
|
||||
inline int pushvec(lua::State* L, const glm::vec<n, T>& vec) {
|
||||
createtable(L, n, 0);
|
||||
for (int i = 0; i < n; i++) {
|
||||
pushnumber(L, vec[i]);
|
||||
@@ -161,8 +161,8 @@ namespace lua {
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
template <int n>
|
||||
inline int setvec(lua::State* L, int idx, glm::vec<n, float> vec) {
|
||||
template <int n, typename T = float>
|
||||
inline int setvec(lua::State* L, int idx, glm::vec<n, T> vec) {
|
||||
pushvalue(L, idx);
|
||||
for (int i = 0; i < n; i++) {
|
||||
pushnumber(L, vec[i]);
|
||||
@@ -305,15 +305,15 @@ namespace lua {
|
||||
setglobal(L, name);
|
||||
}
|
||||
|
||||
template <int n>
|
||||
inline glm::vec<n, float> tovec(lua::State* L, int idx) {
|
||||
template <int n, typename T = float>
|
||||
inline glm::vec<n, T> tovec(lua::State* L, int idx) {
|
||||
pushvalue(L, idx);
|
||||
if (!istable(L, idx) || objlen(L, idx) < n) {
|
||||
throw std::runtime_error(
|
||||
"value must be an array of " + std::to_string(n) + " numbers"
|
||||
);
|
||||
}
|
||||
glm::vec<n, float> vec;
|
||||
glm::vec<n, T> vec;
|
||||
for (int i = 0; i < n; i++) {
|
||||
rawgeti(L, i + 1);
|
||||
vec[i] = tonumber(L, -1);
|
||||
@@ -455,7 +455,7 @@ namespace lua {
|
||||
|
||||
inline bool getfield(lua::State* L, const std::string& name, int idx = -1) {
|
||||
lua_getfield(L, idx, name.c_str());
|
||||
if (isnil(L, idx)) {
|
||||
if (isnoneornil(L, -1)) {
|
||||
pop(L);
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user