refactor: LuaState replaced with lua_engine

This commit is contained in:
MihailRis 2024-06-11 13:18:30 +03:00
parent 0647bc6f90
commit 90bc86408b
22 changed files with 643 additions and 675 deletions

View File

@ -1,31 +0,0 @@
#ifndef LOGIC_SCRIPTING_LUA_STATE_HPP_
#define LOGIC_SCRIPTING_LUA_STATE_HPP_
#include "lua_commons.hpp"
#include "../scripting_functional.hpp"
#include "../../../data/dynamic.hpp"
#include "../../../delegates.hpp"
#include <string>
#include <stdexcept>
namespace lua {
class LuaState {
lua_State* mainThread;
void removeLibFuncs(lua_State*, const char* libname, const char* funcs[]);
void createLibs(lua_State* L);
public:
LuaState();
~LuaState();
void openlib(lua_State*, const std::string& name, const luaL_Reg* libfuncs);
void addfunc(lua_State*, const std::string& name, lua_CFunction func);
bool emitEvent(lua_State*, const std::string& name, std::function<int(lua_State*)> args=[](auto*){return 0;});
lua_State* getMainThread() const;
};
}
#endif // LOGIC_SCRIPTING_LUA_STATE_HPP_

View File

@ -7,8 +7,8 @@ inline const char* DEFAULT_CHANNEL = "regular";
inline int extract_channel_index(lua_State* L, int idx) { inline int extract_channel_index(lua_State* L, int idx) {
const char* channel = DEFAULT_CHANNEL; const char* channel = DEFAULT_CHANNEL;
if (!lua_isnoneornil(L, idx)) { if (!lua::isnoneornil(L, idx)) {
channel = lua_tostring(L, idx); channel = lua::tostring(L, idx);
} }
int index = audio::get_channel_index(channel); int index = audio::get_channel_index(channel);
if (index == 0) { if (index == 0) {
@ -92,20 +92,19 @@ inline audio::speakerid_t play_stream(
/// channel: string = "regular", /// channel: string = "regular",
/// loop: bool = false) /// loop: bool = false)
static int l_audio_play_stream(lua_State* L) { static int l_audio_play_stream(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>( return lua::pushinteger(L, static_cast<lua_Integer>(
play_stream( play_stream(
lua_tostring(L, 1), lua::tostring(L, 1),
false, false,
lua_tonumber(L, 2), lua::tonumber(L, 2),
lua_tonumber(L, 3), lua::tonumber(L, 3),
lua_tonumber(L, 4), lua::tonumber(L, 4),
lua_tonumber(L, 5), lua::tonumber(L, 5),
lua_tonumber(L, 6), lua::tonumber(L, 6),
lua_toboolean(L, 8), lua::toboolean(L, 8),
extract_channel_index(L, 7) extract_channel_index(L, 7)
) )
)); ));
return 1;
} }
/// @brief audio.play_stream_2d( /// @brief audio.play_stream_2d(
@ -115,18 +114,17 @@ static int l_audio_play_stream(lua_State* L) {
/// channel: string = "regular", /// channel: string = "regular",
/// loop: bool = false) /// loop: bool = false)
static int l_audio_play_stream_2d(lua_State* L) { static int l_audio_play_stream_2d(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>( return lua::pushinteger(L, static_cast<lua_Integer>(
play_stream( play_stream(
lua_tostring(L, 1), lua::tostring(L, 1),
true, true,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
lua_tonumber(L, 2), lua::tonumber(L, 2),
lua_tonumber(L, 3), lua::tonumber(L, 3),
lua_toboolean(L, 5), lua::toboolean(L, 5),
extract_channel_index(L, 4) extract_channel_index(L, 4)
) )
)); ));
return 1;
} }
/// @brief audio.play_sound( /// @brief audio.play_sound(
@ -139,20 +137,19 @@ static int l_audio_play_stream_2d(lua_State* L) {
/// channel: string = "regular", /// channel: string = "regular",
/// loop: bool = false) /// loop: bool = false)
static int l_audio_play_sound(lua_State* L) { static int l_audio_play_sound(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>( return lua::pushinteger(L, static_cast<lua_Integer>(
play_sound( play_sound(
lua_tostring(L, 1), lua::tostring(L, 1),
false, false,
lua_tonumber(L, 2), lua::tonumber(L, 2),
lua_tonumber(L, 3), lua::tonumber(L, 3),
lua_tonumber(L, 4), lua::tonumber(L, 4),
lua_tonumber(L, 5), lua::tonumber(L, 5),
lua_tonumber(L, 6), lua::tonumber(L, 6),
lua_toboolean(L, 8), lua::toboolean(L, 8),
extract_channel_index(L, 7) extract_channel_index(L, 7)
) )
)); ));
return 1;
} }
/// @brief audio.play_sound_2d( /// @brief audio.play_sound_2d(
@ -162,23 +159,22 @@ static int l_audio_play_sound(lua_State* L) {
/// channel: string = "regular", /// channel: string = "regular",
/// loop: bool = false) /// loop: bool = false)
static int l_audio_play_sound_2d(lua_State* L) { static int l_audio_play_sound_2d(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>( return lua::pushinteger(L, static_cast<lua_Integer>(
play_sound( play_sound(
lua_tostring(L, 1), lua::tostring(L, 1),
true, true,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
lua_tonumber(L, 2), lua::tonumber(L, 2),
lua_tonumber(L, 3), lua::tonumber(L, 3),
lua_toboolean(L, 5), lua::toboolean(L, 5),
extract_channel_index(L, 4) extract_channel_index(L, 4)
) )
)); ));
return 1;
} }
/// @brief audio.stop(speakerid: integer) -> nil /// @brief audio.stop(speakerid: integer) -> nil
static int l_audio_stop(lua_State* L) { static int l_audio_stop(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
speaker->stop(); speaker->stop();
} }
@ -187,7 +183,7 @@ static int l_audio_stop(lua_State* L) {
/// @brief audio.pause(speakerid: integer) -> nil /// @brief audio.pause(speakerid: integer) -> nil
static int l_audio_pause(lua_State* L) { static int l_audio_pause(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
speaker->pause(); speaker->pause();
} }
@ -196,7 +192,7 @@ static int l_audio_pause(lua_State* L) {
/// @brief audio.resume(speakerid: integer) -> nil /// @brief audio.resume(speakerid: integer) -> nil
static int l_audio_resume(lua_State* L) { static int l_audio_resume(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr && speaker->isPaused()) { if (speaker != nullptr && speaker->isPaused()) {
speaker->play(); speaker->play();
} }
@ -205,48 +201,47 @@ static int l_audio_resume(lua_State* L) {
/// @brief audio.set_loop(speakerid: integer, value: bool) -> nil /// @brief audio.set_loop(speakerid: integer, value: bool) -> nil
static int l_audio_set_loop(lua_State* L) { static int l_audio_set_loop(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
bool value = lua_toboolean(L, 2); speaker->setLoop(lua::toboolean(L, 2));
speaker->setLoop(value);
} }
return 0; return 0;
} }
/// @brief audio.set_volume(speakerid: integer, value: number) -> nil /// @brief audio.set_volume(speakerid: integer, value: number) -> nil
static int l_audio_set_volume(lua_State* L) { static int l_audio_set_volume(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
speaker->setVolume(static_cast<float>(lua_tonumber(L, 2))); speaker->setVolume(static_cast<float>(lua::tonumber(L, 2)));
} }
return 0; return 0;
} }
/// @brief audio.set_pitch(speakerid: integer, value: number) -> nil /// @brief audio.set_pitch(speakerid: integer, value: number) -> nil
static int l_audio_set_pitch(lua_State* L) { static int l_audio_set_pitch(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
speaker->setPitch(static_cast<float>(lua_tonumber(L, 2))); speaker->setPitch(static_cast<float>(lua::tonumber(L, 2)));
} }
return 0; return 0;
} }
/// @brief audio.set_time(speakerid: integer, value: number) -> nil /// @brief audio.set_time(speakerid: integer, value: number) -> nil
static int l_audio_set_time(lua_State* L) { static int l_audio_set_time(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
speaker->setTime(static_cast<audio::duration_t>(lua_tonumber(L, 2))); speaker->setTime(static_cast<audio::duration_t>(lua::tonumber(L, 2)));
} }
return 0; return 0;
} }
/// @brief audio.set_position(speakerid: integer, x: number, y: number, z: number) -> nil /// @brief audio.set_position(speakerid: integer, x: number, y: number, z: number) -> nil
static int l_audio_set_position(lua_State* L) { static int l_audio_set_position(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
auto x = lua_tonumber(L, 2); auto x = lua::tonumber(L, 2);
auto y = lua_tonumber(L, 3); auto y = lua::tonumber(L, 3);
auto z = lua_tonumber(L, 4); auto z = lua::tonumber(L, 4);
speaker->setPosition(glm::vec3( speaker->setPosition(glm::vec3(
static_cast<float>(x), static_cast<float>(x),
static_cast<float>(y), static_cast<float>(y),
@ -258,11 +253,11 @@ static int l_audio_set_position(lua_State* L) {
/// @brief audio.set_velocity(speakerid: integer, x: number, y: number, z: number) -> nil /// @brief audio.set_velocity(speakerid: integer, x: number, y: number, z: number) -> nil
static int l_audio_set_velocity(lua_State* L) { static int l_audio_set_velocity(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
auto x = lua_tonumber(L, 2); auto x = lua::tonumber(L, 2);
auto y = lua_tonumber(L, 3); auto y = lua::tonumber(L, 3);
auto z = lua_tonumber(L, 4); auto z = lua::tonumber(L, 4);
speaker->setVelocity(glm::vec3( speaker->setVelocity(glm::vec3(
static_cast<float>(x), static_cast<float>(x),
static_cast<float>(y), static_cast<float>(y),
@ -274,112 +269,93 @@ static int l_audio_set_velocity(lua_State* L) {
/// @brief audio.is_playing(speakerid: integer) -> bool /// @brief audio.is_playing(speakerid: integer) -> bool
static int l_audio_is_playing(lua_State* L) { static int l_audio_is_playing(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua_pushboolean(L, speaker->isPlaying()); return lua::pushboolean(L, speaker->isPlaying());
return 1;
} }
lua_pushboolean(L, false); return lua::pushboolean(L, false);
return 1;
} }
/// @brief audio.is_paused(speakerid: integer) -> bool /// @brief audio.is_paused(speakerid: integer) -> bool
static int l_audio_is_paused(lua_State* L) { static int l_audio_is_paused(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua_pushboolean(L, speaker->isPaused()); return lua::pushboolean(L, speaker->isPaused());
return 1;
} }
lua_pushboolean(L, false); return lua::pushboolean(L, false);
return 1;
} }
/// @brief audio.is_loop(speakerid: integer) -> bool /// @brief audio.is_loop(speakerid: integer) -> bool
static int l_audio_is_loop(lua_State* L) { static int l_audio_is_loop(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua_pushboolean(L, speaker->isLoop()); return lua::pushboolean(L, speaker->isLoop());
return 1;
} }
lua_pushboolean(L, false); return lua::pushboolean(L, false);
return 1;
} }
/// @brief audio.get_volume(speakerid: integer) -> number /// @brief audio.get_volume(speakerid: integer) -> number
static int l_audio_get_volume(lua_State* L) { static int l_audio_get_volume(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua_pushnumber(L, speaker->getVolume()); return lua::pushnumber(L, speaker->getVolume());
return 1;
} }
lua_pushnumber(L, 0.0); return lua::pushnumber(L, 0.0);
return 1;
} }
/// @brief audio.get_pitch(speakerid: integer) -> number /// @brief audio.get_pitch(speakerid: integer) -> number
static int l_audio_get_pitch(lua_State* L) { static int l_audio_get_pitch(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua_pushnumber(L, speaker->getPitch()); return lua::pushnumber(L, speaker->getPitch());
return 1;
} }
lua_pushnumber(L, 1.0); return lua::pushnumber(L, 1.0);
return 1;
} }
/// @brief audio.get_time(speakerid: integer) -> number /// @brief audio.get_time(speakerid: integer) -> number
static int l_audio_get_time(lua_State* L) { static int l_audio_get_time(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua_pushnumber(L, speaker->getTime()); return lua::pushnumber(L, speaker->getTime());
return 1;
} }
lua_pushnumber(L, 0.0); return lua::pushnumber(L, 0.0);
return 1;
} }
/// @brief audio.get_duration(speakerid: integer) -> number /// @brief audio.get_duration(speakerid: integer) -> number
static int l_audio_get_duration(lua_State* L) { static int l_audio_get_duration(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua_pushnumber(L, speaker->getDuration()); return lua::pushnumber(L, speaker->getDuration());
return 1;
} }
lua_pushnumber(L, 0.0); return lua::pushnumber(L, 0.0);
return 1;
} }
/// @brief audio.get_position(speakerid: integer) -> number, number, number /// @brief audio.get_position(speakerid: integer) -> number, number, number
static int l_audio_get_position(lua_State* L) { static int l_audio_get_position(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
lua::pushvec3(L, speaker->getPosition()); return lua::pushvec3(L, speaker->getPosition());
return 1;
} }
return 0; return 0;
} }
/// @brief audio.get_velocity(speakerid: integer) -> number, number, number /// @brief audio.get_velocity(speakerid: integer) -> number, number, number
static int l_audio_get_velocity(lua_State* L) { static int l_audio_get_velocity(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1)); auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) { if (speaker != nullptr) {
auto vec = speaker->getVelocity(); return lua::pushvec3(L, speaker->getVelocity());
lua::pushvec3(L, vec);
return 1;
} }
return 0; return 0;
} }
// @brief audio.count_speakers() -> integer // @brief audio.count_speakers() -> integer
static int l_audio_count_speakers(lua_State* L) { static int l_audio_count_speakers(lua_State* L) {
lua_pushinteger(L, audio::count_speakers()); return lua::pushinteger(L, audio::count_speakers());
return 1;
} }
// @brief audio.count_streams() -> integer // @brief audio.count_streams() -> integer
static int l_audio_count_streams(lua_State* L) { static int l_audio_count_streams(lua_State* L) {
lua_pushinteger(L, audio::count_streams()); return lua::pushinteger(L, audio::count_streams());
return 1;
} }
const luaL_Reg audiolib [] = { const luaL_Reg audiolib [] = {

View File

@ -9,9 +9,11 @@
#include "../../../content/Content.hpp" #include "../../../content/Content.hpp"
#include "../../../logic/BlocksController.hpp" #include "../../../logic/BlocksController.hpp"
using namespace scripting;
static Block* require_block(lua_State* L) { static Block* require_block(lua_State* L) {
auto indices = scripting::content->getIndices(); auto indices = content->getIndices();
lua_Integer id = lua_tointeger(L, 1); auto id = lua::tointeger(L, 1);
if (static_cast<size_t>(id) >= indices->countBlockDefs()) { if (static_cast<size_t>(id) >= indices->countBlockDefs()) {
return nullptr; return nullptr;
} }
@ -20,44 +22,38 @@ static Block* require_block(lua_State* L) {
static int l_name(lua_State* L) { static int l_name(lua_State* L) {
if (auto def = require_block(L)) { if (auto def = require_block(L)) {
lua_pushstring(L, def->name.c_str()); return lua::pushstring(L, def->name);
return 1;
} }
return 0; return 0;
} }
static int l_material(lua_State* L) { static int l_material(lua_State* L) {
if (auto def = require_block(L)) { if (auto def = require_block(L)) {
lua_pushstring(L, def->material.c_str()); return lua::pushstring(L, def->material);
return 1;
} }
return 0; return 0;
} }
static int l_is_solid_at(lua_State* L) { static int l_is_solid_at(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
lua_pushboolean(L, scripting::level->chunks->isSolidBlock(x, y, z)); return lua::pushboolean(L, level->chunks->isSolidBlock(x, y, z));
return 1;
} }
static int l_count(lua_State* L) { static int l_count(lua_State* L) {
lua_pushinteger(L, scripting::indices->countBlockDefs()); return lua::pushinteger(L, indices->countBlockDefs());
return 1;
} }
static int l_index(lua_State* L) { static int l_index(lua_State* L) {
std::string name = lua_tostring(L, 1); auto name = lua::require_string(L, 1);
lua_pushinteger(L, scripting::content->requireBlock(name).rt.id); return lua::pushinteger(L, content->requireBlock(name).rt.id);
return 1;
} }
static int l_is_extended(lua_State* L) { static int l_is_extended(lua_State* L) {
if (auto def = require_block(L)) { if (auto def = require_block(L)) {
lua_pushboolean(L, def->rt.extended); return lua::pushboolean(L, def->rt.extended);
return 1;
} }
return 0; return 0;
} }
@ -70,65 +66,61 @@ static int l_get_size(lua_State* L) {
} }
static int l_is_segment(lua_State* L) { static int l_is_segment(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
auto vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
return lua::pushboolean(L, vox->state.segment);
lua_pushboolean(L, vox->state.segment);
return 1;
} }
static int l_seek_origin(lua_State* L) { static int l_seek_origin(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
auto vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
auto def = scripting::indices->getBlockDef(vox->id); auto def = indices->getBlockDef(vox->id);
return lua::pushivec3(L, level->chunks->seekOrigin({x, y, z}, def, vox->state));
return lua::pushivec3(L, scripting::level->chunks->seekOrigin({x, y, z}, def, vox->state));
} }
static int l_set(lua_State* L) { static int l_set(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
lua_Integer id = lua_tointeger(L, 4); auto id = lua::tointeger(L, 4);
lua_Integer state = lua_tointeger(L, 5); auto state = lua::tointeger(L, 5);
bool noupdate = lua_toboolean(L, 6); bool noupdate = lua::toboolean(L, 6);
if (static_cast<size_t>(id) >= scripting::indices->countBlockDefs()) { if (static_cast<size_t>(id) >= indices->countBlockDefs()) {
return 0; return 0;
} }
if (!scripting::level->chunks->get(x, y, z)) { if (!level->chunks->get(x, y, z)) {
return 0; return 0;
} }
scripting::level->chunks->set(x, y, z, id, int2blockstate(state)); level->chunks->set(x, y, z, id, int2blockstate(state));
scripting::level->lighting->onBlockSet(x,y,z, id); level->lighting->onBlockSet(x,y,z, id);
if (!noupdate) { if (!noupdate) {
scripting::blocks->updateSides(x, y, z); blocks->updateSides(x, y, z);
} }
return 0; return 0;
} }
static int l_get(lua_State* L) { static int l_get(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
int id = vox == nullptr ? -1 : vox->id; int id = vox == nullptr ? -1 : vox->id;
lua_pushinteger(L, id); return lua::pushinteger(L, id);
return 1;
} }
static int l_get_x(lua_State* L) { static int l_get_x(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) { if (vox == nullptr) {
return lua::pushivec3(L, 1, 0, 0); return lua::pushivec3(L, 1, 0, 0);
} }
auto def = scripting::level->content->getIndices()->getBlockDef(vox->id); auto def = level->content->getIndices()->getBlockDef(vox->id);
if (!def->rotatable) { if (!def->rotatable) {
return lua::pushivec3(L, 1, 0, 0); return lua::pushivec3(L, 1, 0, 0);
} else { } else {
@ -138,14 +130,14 @@ static int l_get_x(lua_State* L) {
} }
static int l_get_y(lua_State* L) { static int l_get_y(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) { if (vox == nullptr) {
return lua::pushivec3(L, 0, 1, 0); return lua::pushivec3(L, 0, 1, 0);
} }
auto def = scripting::level->content->getIndices()->getBlockDef(vox->id); auto def = level->content->getIndices()->getBlockDef(vox->id);
if (!def->rotatable) { if (!def->rotatable) {
return lua::pushivec3(L, 0, 1, 0); return lua::pushivec3(L, 0, 1, 0);
} else { } else {
@ -155,14 +147,14 @@ static int l_get_y(lua_State* L) {
} }
static int l_get_z(lua_State* L) { static int l_get_z(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) { if (vox == nullptr) {
return lua::pushivec3(L, 0, 0, 1); return lua::pushivec3(L, 0, 0, 1);
} }
auto def = scripting::level->content->getIndices()->getBlockDef(vox->id); auto def = level->content->getIndices()->getBlockDef(vox->id);
if (!def->rotatable) { if (!def->rotatable) {
return lua::pushivec3(L, 0, 0, 1); return lua::pushivec3(L, 0, 0, 1);
} else { } else {
@ -172,83 +164,79 @@ static int l_get_z(lua_State* L) {
} }
static int l_get_rotation(lua_State* L) { static int l_get_rotation(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z); voxel* vox = level->chunks->get(x, y, z);
int rotation = vox == nullptr ? 0 : vox->state.rotation; int rotation = vox == nullptr ? 0 : vox->state.rotation;
lua_pushinteger(L, rotation); return lua::pushinteger(L, rotation);
return 1;
} }
static int l_set_rotation(lua_State* L) { static int l_set_rotation(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
lua_Integer value = lua_tointeger(L, 4); auto value = lua::tointeger(L, 4);
scripting::level->chunks->setRotation(x, y, z, value); level->chunks->setRotation(x, y, z, value);
return 0; return 0;
} }
static int l_get_states(lua_State* L) { static int l_get_states(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
int states = vox == nullptr ? 0 : blockstate2int(vox->state); int states = vox == nullptr ? 0 : blockstate2int(vox->state);
lua_pushinteger(L, states); return lua::pushinteger(L, states);
return 1;
} }
static int l_set_states(lua_State* L) { static int l_set_states(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
lua_Integer states = lua_tointeger(L, 4); auto states = lua::tointeger(L, 4);
Chunk* chunk = scripting::level->chunks->getChunkByVoxel(x, y, z); auto chunk = level->chunks->getChunkByVoxel(x, y, z);
if (chunk == nullptr) { if (chunk == nullptr) {
return 0; return 0;
} }
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
vox->state = int2blockstate(states); vox->state = int2blockstate(states);
chunk->setModifiedAndUnsaved(); chunk->setModifiedAndUnsaved();
return 0; return 0;
} }
static int l_get_user_bits(lua_State* L) { static int l_get_user_bits(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
lua_Integer offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET; auto offset = lua::tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
lua_Integer bits = lua_tointeger(L, 5); auto bits = lua::tointeger(L, 5);
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) { if (vox == nullptr) {
lua_pushinteger(L, 0); return lua::pushinteger(L, 0);
return 1;
} }
uint mask = ((1 << bits) - 1) << offset; uint mask = ((1 << bits) - 1) << offset;
uint data = (blockstate2int(vox->state) & mask) >> offset; uint data = (blockstate2int(vox->state) & mask) >> offset;
lua_pushinteger(L, data); return lua::pushinteger(L, data);
return 1;
} }
static int l_set_user_bits(lua_State* L) { static int l_set_user_bits(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
lua_Integer offset = lua_tointeger(L, 4); auto offset = lua::tointeger(L, 4);
lua_Integer bits = lua_tointeger(L, 5); auto bits = lua::tointeger(L, 5);
size_t mask = ((1 << bits) - 1) << offset; size_t mask = ((1 << bits) - 1) << offset;
lua_Integer value = (lua_tointeger(L, 6) << offset) & mask; auto value = (lua::tointeger(L, 6) << offset) & mask;
Chunk* chunk = scripting::level->chunks->getChunkByVoxel(x, y, z); auto chunk = level->chunks->getChunkByVoxel(x, y, z);
if (chunk == nullptr) { if (chunk == nullptr) {
return 0; return 0;
} }
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) { if (vox == nullptr) {
return 0; return 0;
} }
@ -258,18 +246,15 @@ static int l_set_user_bits(lua_State* L) {
} }
static int l_is_replaceable_at(lua_State* L) { static int l_is_replaceable_at(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
return lua::pushboolean(L, level->chunks->isReplaceableBlock(x, y, z));
lua_pushboolean(L, scripting::level->chunks->isReplaceableBlock(x, y, z));
return 1;
} }
static int l_caption(lua_State* L) { static int l_caption(lua_State* L) {
if (auto def = require_block(L)) { if (auto def = require_block(L)) {
lua_pushstring(L, def->caption.c_str()); return lua::pushstring(L, def->caption);
return 1;
} }
return 0; return 0;
} }

View File

@ -7,7 +7,7 @@
using namespace scripting; using namespace scripting;
static int l_add_command(lua_State* L) { static int l_add_command(lua_State* L) {
if (!lua_isfunction(L, 3)) { if (!lua::isfunction(L, 3)) {
throw std::runtime_error("invalid callback"); throw std::runtime_error("invalid callback");
} }
auto scheme = lua::require_string(L, 1); auto scheme = lua::require_string(L, 1);
@ -45,11 +45,11 @@ static int l_get_commands_list(lua_State* L) {
auto repo = interpreter->getRepository(); auto repo = interpreter->getRepository();
const auto& commands = repo->getCommands(); const auto& commands = repo->getCommands();
lua_createtable(L, commands.size(), 0); lua::createtable(L, commands.size(), 0);
size_t index = 1; size_t index = 1;
for (const auto& entry : commands) { for (const auto& entry : commands) {
lua_pushstring(L, entry.first.c_str()); lua::pushstring(L, entry.first);
lua_rawseti(L, -2, index++); lua::rawseti(L, index++);
} }
return 1; return 1;
} }
@ -65,44 +65,44 @@ static int l_get_command_info(lua_State* L) {
const auto& args = command->getArgs(); const auto& args = command->getArgs();
const auto& kwargs = command->getKwArgs(); const auto& kwargs = command->getKwArgs();
lua_createtable(L, 0, 4); lua::createtable(L, 0, 4);
lua_pushstring(L, name); lua::pushstring(L, name);
lua_setfield(L, -2, "name"); lua::setfield(L, "name");
lua_pushstring(L, command->getDescription().c_str()); lua::pushstring(L, command->getDescription());
lua_setfield(L, -2, "description"); lua::setfield(L, "description");
lua_createtable(L, args.size(), 0); lua::createtable(L, args.size(), 0);
for (size_t i = 0; i < args.size(); i++) { for (size_t i = 0; i < args.size(); i++) {
auto& arg = args.at(i); auto& arg = args.at(i);
lua_createtable(L, 0, 2); lua::createtable(L, 0, 2);
lua_pushstring(L, arg.name.c_str()); lua::pushstring(L, arg.name);
lua_setfield(L, -2, "name"); lua::setfield(L, "name");
lua_pushstring(L, cmd::argtype_name(arg.type).c_str()); lua::pushstring(L, cmd::argtype_name(arg.type));
lua_setfield(L, -2, "type"); lua::setfield(L, "type");
if (arg.optional) { if (arg.optional) {
lua_pushboolean(L, true); lua::pushboolean(L, true);
lua_setfield(L, -2, "optional"); lua::setfield(L, "optional");
} }
lua_rawseti(L, -2, i+1); lua::rawseti(L, i+1);
} }
lua_setfield(L, -2, "args"); lua::setfield(L, "args");
lua_createtable(L, 0, kwargs.size()); lua::createtable(L, 0, kwargs.size());
for (auto& entry : kwargs) { for (auto& entry : kwargs) {
auto& arg = entry.second; auto& arg = entry.second;
lua_createtable(L, 0, 1); lua::createtable(L, 0, 1);
lua_pushstring(L, cmd::argtype_name(arg.type).c_str()); lua::pushstring(L, cmd::argtype_name(arg.type));
lua_setfield(L, -2, "type"); lua::setfield(L, "type");
lua_setfield(L, -2, arg.name.c_str()); lua::setfield(L, arg.name);
} }
lua_setfield(L, -2, "kwargs"); lua::setfield(L, "kwargs");
return 1; return 1;
} }

View File

@ -44,7 +44,7 @@ static int l_close_world(lua_State* L) {
if (controller == nullptr) { if (controller == nullptr) {
throw std::runtime_error("no world open"); throw std::runtime_error("no world open");
} }
bool save_world = lua_toboolean(L, 1); bool save_world = lua::toboolean(L, 1);
if (save_world) { if (save_world) {
controller->saveWorld(); controller->saveWorld();
} }
@ -63,32 +63,32 @@ static int l_delete_world(lua_State* L) {
} }
static int l_reconfig_packs(lua_State* L) { static int l_reconfig_packs(lua_State* L) {
if (!lua_istable(L, 1)) { if (!lua::istable(L, 1)) {
throw std::runtime_error("strings array expected as the first argument"); throw std::runtime_error("strings array expected as the first argument");
} }
if (!lua_istable(L, 2)) { if (!lua::istable(L, 2)) {
throw std::runtime_error("strings array expected as the second argument"); throw std::runtime_error("strings array expected as the second argument");
} }
std::vector<std::string> addPacks; std::vector<std::string> addPacks;
if (!lua_istable(L, 1)) { if (!lua::istable(L, 1)) {
throw std::runtime_error("an array expected as argument 1"); throw std::runtime_error("an array expected as argument 1");
} }
int addLen = lua_objlen(L, 1); int addLen = lua::objlen(L, 1);
for (int i = 0; i < addLen; i++) { for (int i = 0; i < addLen; i++) {
lua_rawgeti(L, 1, i+1); lua::rawgeti(L, i+1, 1);
addPacks.emplace_back(lua_tostring(L, -1)); addPacks.emplace_back(lua::tostring(L, -1));
lua_pop(L, 1); lua::pop(L);
} }
std::vector<std::string> remPacks; std::vector<std::string> remPacks;
if (!lua_istable(L, 2)) { if (!lua::istable(L, 2)) {
throw std::runtime_error("an array expected as argument 2"); throw std::runtime_error("an array expected as argument 2");
} }
int remLen = lua_objlen(L, 2); int remLen = lua::objlen(L, 2);
for (int i = 0; i < remLen; i++) { for (int i = 0; i < remLen; i++) {
lua_rawgeti(L, 2, i+1); lua::rawgeti(L, i+1, 2);
remPacks.emplace_back(lua_tostring(L, -1)); remPacks.emplace_back(lua::tostring(L, -1));
lua_pop(L, 1); lua::pop(L);
} }
auto engine_controller = engine->getController(); auto engine_controller = engine->getController();
engine_controller->reconfigPacks(controller, addPacks, remPacks); engine_controller->reconfigPacks(controller, addPacks, remPacks);
@ -98,8 +98,7 @@ static int l_reconfig_packs(lua_State* L) {
static int l_get_setting(lua_State* L) { static int l_get_setting(lua_State* L) {
auto name = lua::require_string(L, 1); auto name = lua::require_string(L, 1);
const auto value = engine->getSettingsHandler().getValue(name); const auto value = engine->getSettingsHandler().getValue(name);
lua::pushvalue(L, value); return lua::pushvalue(L, value);
return 1;
} }
static int l_set_setting(lua_State* L) { static int l_set_setting(lua_State* L) {
@ -112,14 +111,13 @@ static int l_set_setting(lua_State* L) {
static int l_str_setting(lua_State* L) { static int l_str_setting(lua_State* L) {
auto name = lua::require_string(L, 1); auto name = lua::require_string(L, 1);
const auto string = engine->getSettingsHandler().toString(name); const auto string = engine->getSettingsHandler().toString(name);
lua::pushstring(L, string); return lua::pushstring(L, string);
return 1;
} }
static int l_get_setting_info(lua_State* L) { static int l_get_setting_info(lua_State* L) {
auto name = lua::require_string(L, 1); auto name = lua::require_string(L, 1);
auto setting = engine->getSettingsHandler().getSetting(name); auto setting = engine->getSettingsHandler().getSetting(name);
lua_createtable(L, 0, 1); lua::createtable(L, 0, 1);
if (auto number = dynamic_cast<NumberSetting*>(setting)) { if (auto number = dynamic_cast<NumberSetting*>(setting)) {
lua::pushnumber(L, number->getMin()); lua::pushnumber(L, number->getMin());
lua::setfield(L, "min"); lua::setfield(L, "min");
@ -134,7 +132,7 @@ static int l_get_setting_info(lua_State* L) {
lua::setfield(L, "max"); lua::setfield(L, "max");
return 1; return 1;
} }
lua_pop(L, 1); lua::pop(L);
throw std::runtime_error("unsupported setting type"); throw std::runtime_error("unsupported setting type");
} }
@ -144,18 +142,17 @@ static int l_quit(lua_State*) {
} }
static int l_get_default_generator(lua_State* L) { static int l_get_default_generator(lua_State* L) {
lua::pushstring(L, WorldGenerators::getDefaultGeneratorID().c_str()); return lua::pushstring(L, WorldGenerators::getDefaultGeneratorID());
return 1;
} }
static int l_get_generators(lua_State* L) { static int l_get_generators(lua_State* L) {
const auto& generators = WorldGenerators::getGeneratorsIDs(); const auto& generators = WorldGenerators::getGeneratorsIDs();
lua_createtable(L, generators.size(), 0); lua::createtable(L, generators.size(), 0);
int i = 0; int i = 0;
for (auto& id : generators) { for (auto& id : generators) {
lua::pushstring(L, id.c_str()); lua::pushstring(L, id);
lua_rawseti(L, -2, i + 1); lua::rawseti(L, i + 1);
i++; i++;
} }
return 1; return 1;

View File

@ -26,8 +26,7 @@ static fs::path resolve_path_soft(const std::string& path) {
static int l_file_find(lua_State* L) { static int l_file_find(lua_State* L) {
auto path = lua::require_string(L, 1); auto path = lua::require_string(L, 1);
try { try {
lua_pushstring(L, engine->getResPaths()->findRaw(path).c_str()); return lua::pushstring(L, engine->getResPaths()->findRaw(path));
return 1;
} catch (const std::runtime_error& err) { } catch (const std::runtime_error& err) {
return 0; return 0;
} }
@ -35,15 +34,13 @@ static int l_file_find(lua_State* L) {
static int l_file_resolve(lua_State* L) { static int l_file_resolve(lua_State* L) {
fs::path path = resolve_path(lua::require_string(L, 1)); fs::path path = resolve_path(lua::require_string(L, 1));
lua_pushstring(L, path.u8string().c_str()); return lua::pushstring(L, path.u8string());
return 1;
} }
static int l_file_read(lua_State* L) { static int l_file_read(lua_State* L) {
fs::path path = resolve_path(lua::require_string(L, 1)); fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::is_regular_file(path)) { if (fs::is_regular_file(path)) {
lua_pushstring(L, files::read_string(path).c_str()); return lua::pushstring(L, files::read_string(path));
return 1;
} }
throw std::runtime_error("file does not exists "+util::quote(path.u8string())); throw std::runtime_error("file does not exists "+util::quote(path.u8string()));
} }
@ -93,11 +90,10 @@ static int l_file_isdir(lua_State* L) {
static int l_file_length(lua_State* L) { static int l_file_length(lua_State* L) {
fs::path path = resolve_path(lua::require_string(L, 1)); fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::exists(path)){ if (fs::exists(path)){
lua_pushinteger(L, fs::file_size(path)); return lua::pushinteger(L, fs::file_size(path));
} else { } else {
lua_pushinteger(L, -1); return lua::pushinteger(L, -1);
} }
return 1;
} }
static int l_file_mkdir(lua_State* L) { static int l_file_mkdir(lua_State* L) {
@ -117,12 +113,12 @@ static int l_file_read_bytes(lua_State* L) {
auto bytes = files::read_bytes(path, length); auto bytes = files::read_bytes(path, length);
lua_createtable(L, length, 0); lua::createtable(L, length, 0);
int newTable = lua_gettop(L); int newTable = lua::gettop(L);
for(size_t i = 0; i < length; i++) { for(size_t i = 0; i < length; i++) {
lua_pushinteger(L, bytes[i]); lua::pushinteger(L, bytes[i]);
lua_rawseti(L, newTable, i+1); lua::rawseti(L, i+1, newTable);
} }
return 1; return 1;
} }
@ -130,17 +126,17 @@ static int l_file_read_bytes(lua_State* L) {
} }
static int read_bytes_from_table(lua_State* L, int tableIndex, std::vector<ubyte>& bytes) { static int read_bytes_from_table(lua_State* L, int tableIndex, std::vector<ubyte>& bytes) {
if(!lua_istable(L, tableIndex)) { if(!lua::istable(L, tableIndex)) {
throw std::runtime_error("table expected"); throw std::runtime_error("table expected");
} else { } else {
lua_pushnil(L); lua::pushnil(L);
while(lua_next(L, tableIndex - 1) != 0) { while(lua_next(L, tableIndex - 1) != 0) {
const int byte = lua_tointeger(L, -1); const int byte = lua::tointeger(L, -1);
if(byte < 0 || byte > 255) { if(byte < 0 || byte > 255) {
throw std::runtime_error("invalid byte '"+std::to_string(byte)+"'"); throw std::runtime_error("invalid byte '"+std::to_string(byte)+"'");
} }
bytes.push_back(byte); bytes.push_back(byte);
lua_pop(L, 1); lua::pop(L);
} }
return 1; return 1;
} }
@ -149,7 +145,7 @@ static int read_bytes_from_table(lua_State* L, int tableIndex, std::vector<ubyte
static int l_file_write_bytes(lua_State* L) { static int l_file_write_bytes(lua_State* L) {
int pathIndex = 1; int pathIndex = 1;
if(!lua_isstring(L, pathIndex)) { if(!lua::isstring(L, pathIndex)) {
throw std::runtime_error("string expected"); throw std::runtime_error("string expected");
} }
@ -168,10 +164,10 @@ static int l_file_write_bytes(lua_State* L) {
static int l_file_list_all_res(lua_State* L, const std::string& path) { static int l_file_list_all_res(lua_State* L, const std::string& path) {
auto files = engine->getResPaths()->listdirRaw(path); auto files = engine->getResPaths()->listdirRaw(path);
lua_createtable(L, files.size(), 0); lua::createtable(L, files.size(), 0);
for (size_t i = 0; i < files.size(); i++) { for (size_t i = 0; i < files.size(); i++) {
lua_pushstring(L, files[i].c_str()); lua::pushstring(L, files[i]);
lua_rawseti(L, -2, i+1); lua::rawseti(L, i+1);
} }
return 1; return 1;
} }
@ -185,13 +181,13 @@ static int l_file_list(lua_State* L) {
if (!fs::is_directory(path)) { if (!fs::is_directory(path)) {
throw std::runtime_error(util::quote(path.u8string())+" is not a directory"); throw std::runtime_error(util::quote(path.u8string())+" is not a directory");
} }
lua_createtable(L, 0, 0); lua::createtable(L, 0, 0);
size_t index = 1; size_t index = 1;
for (auto& entry : fs::directory_iterator(path)) { for (auto& entry : fs::directory_iterator(path)) {
auto name = entry.path().filename().u8string(); auto name = entry.path().filename().u8string();
auto file = dirname + "/" + name; auto file = dirname + "/" + name;
lua_pushstring(L, file.c_str()); lua::pushstring(L, file);
lua_rawseti(L, -2, index); lua::rawseti(L, index);
index++; index++;
} }
return 1; return 1;
@ -204,8 +200,7 @@ static int l_file_gzip_compress(lua_State* L) {
auto compressed_bytes = gzip::compress(files::read_bytes(path, length).get(), length); auto compressed_bytes = gzip::compress(files::read_bytes(path, length).get(), length);
lua_pushboolean(L, files::write_bytes(path, compressed_bytes.data(), compressed_bytes.size())); return lua::pushboolean(L, files::write_bytes(path, compressed_bytes.data(), compressed_bytes.size()));
return 1;
} }
throw std::runtime_error("file does not exist " + util::quote(path.u8string())); throw std::runtime_error("file does not exist " + util::quote(path.u8string()));
} }
@ -217,8 +212,7 @@ static int l_file_gzip_decompress(lua_State* L) {
auto decompressed_bytes = gzip::decompress(files::read_bytes(path, length).get(), length); auto decompressed_bytes = gzip::decompress(files::read_bytes(path, length).get(), length);
lua_pushboolean(L, files::write_bytes(path, decompressed_bytes.data(), decompressed_bytes.size())); return lua::pushboolean(L, files::write_bytes(path, decompressed_bytes.data(), decompressed_bytes.size()));
return 1;
} }
throw std::runtime_error("file does not exist " + util::quote(path.u8string())); throw std::runtime_error("file does not exist " + util::quote(path.u8string()));
} }

View File

@ -554,7 +554,7 @@ static int l_gui_get_env(lua_State* L) {
static int l_gui_str(lua_State* L) { static int l_gui_str(lua_State* L) {
auto text = lua::require_wstring(L, 1); auto text = lua::require_wstring(L, 1);
if (!lua_isnoneornil(L, 2)) { if (!lua::isnoneornil(L, 2)) {
auto context = lua::require_wstring(L, 2); auto context = lua::require_wstring(L, 2);
lua::pushwstring(L, langs::get(text, context)); lua::pushwstring(L, langs::get(text, context));
} else { } else {
@ -576,9 +576,9 @@ static int l_gui_reindex(lua_State* L) {
/// @brief gui.get_locales_info() -> table of tables /// @brief gui.get_locales_info() -> table of tables
static int l_gui_get_locales_info(lua_State* L) { static int l_gui_get_locales_info(lua_State* L) {
auto& locales = langs::locales_info; auto& locales = langs::locales_info;
lua_createtable(L, 0, locales.size()); lua::createtable(L, 0, locales.size());
for (auto& entry : locales) { for (auto& entry : locales) {
lua_createtable(L, 0, 1); lua::createtable(L, 0, 1);
lua::pushstring(L, entry.second.name); lua::pushstring(L, entry.second.name);
lua::setfield(L, "name"); lua::setfield(L, "name");
lua::setfield(L, entry.first); lua::setfield(L, entry.first);

View File

@ -21,65 +21,66 @@
namespace scripting { namespace scripting {
extern Hud* hud; extern Hud* hud;
} }
using namespace scripting;
static int l_hud_open_inventory(lua_State*) { static int l_hud_open_inventory(lua_State*) {
if (!scripting::hud->isInventoryOpen()) { if (!hud->isInventoryOpen()) {
scripting::hud->openInventory(); hud->openInventory();
} }
return 0; return 0;
} }
static int l_hud_close_inventory(lua_State*) { static int l_hud_close_inventory(lua_State*) {
if (scripting::hud->isInventoryOpen()) { if (hud->isInventoryOpen()) {
scripting::hud->closeInventory(); hud->closeInventory();
} }
return 0; return 0;
} }
static int l_hud_open_block(lua_State* L) { static int l_hud_open_block(lua_State* L) {
auto x = lua_tointeger(L, 1); auto x = lua::tointeger(L, 1);
auto y = lua_tointeger(L, 2); auto y = lua::tointeger(L, 2);
auto z = lua_tointeger(L, 3); auto z = lua::tointeger(L, 3);
bool playerInventory = !lua_toboolean(L, 4); bool playerInventory = !lua::toboolean(L, 4);
voxel* vox = scripting::level->chunks->get(x, y, z); auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) { 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) std::to_string(x) + " " + std::to_string(y) + " " + std::to_string(z)
); );
} }
auto def = scripting::content->getIndices()->getBlockDef(vox->id); auto def = content->getIndices()->getBlockDef(vox->id);
auto assets = scripting::engine->getAssets(); auto assets = engine->getAssets();
auto layout = assets->getLayout(def->uiLayout); auto layout = assets->getLayout(def->uiLayout);
if (layout == nullptr) { if (layout == nullptr) {
throw std::runtime_error("block '"+def->name+"' has no ui layout"); throw std::runtime_error("block '"+def->name+"' has no ui layout");
} }
auto id = scripting::blocks->createBlockInventory(x, y, z); auto id = blocks->createBlockInventory(x, y, z);
scripting::hud->openInventory( hud->openInventory(
glm::ivec3(x, y, z), layout, scripting::level->inventories->get(id), playerInventory glm::ivec3(x, y, z), layout, level->inventories->get(id), playerInventory
); );
lua_pushinteger(L, id); lua::pushinteger(L, id);
lua_pushstring(L, def->uiLayout.c_str()); lua::pushstring(L, def->uiLayout);
return 2; return 2;
} }
static int l_hud_show_overlay(lua_State* L) { static int l_hud_show_overlay(lua_State* L) {
const char* name = lua_tostring(L, 1); auto name = lua::tostring(L, 1);
bool playerInventory = lua_toboolean(L, 2); bool playerInventory = lua::toboolean(L, 2);
auto assets = scripting::engine->getAssets(); auto assets = engine->getAssets();
auto layout = assets->getLayout(name); auto layout = assets->getLayout(name);
if (layout == nullptr) { if (layout == nullptr) {
throw std::runtime_error("there is no ui layout "+util::quote(name)); throw std::runtime_error("there is no ui layout "+util::quote(name));
} }
scripting::hud->showOverlay(layout, playerInventory); hud->showOverlay(layout, playerInventory);
return 0; return 0;
} }
static UiDocument* require_layout(lua_State* L, const char* name) { static UiDocument* require_layout(const char* name) {
auto assets = scripting::engine->getAssets(); auto assets = engine->getAssets();
auto layout = assets->getLayout(name); auto layout = assets->getLayout(name);
if (layout == nullptr) { if (layout == nullptr) {
throw std::runtime_error("layout '"+std::string(name)+"' is not found"); throw std::runtime_error("layout '"+std::string(name)+"' is not found");
@ -88,41 +89,39 @@ static UiDocument* require_layout(lua_State* L, const char* name) {
} }
static int l_hud_open_permanent(lua_State* L) { static int l_hud_open_permanent(lua_State* L) {
auto layout = require_layout(L, lua_tostring(L, 1)); auto layout = require_layout(lua::tostring(L, 1));
scripting::hud->openPermanent(layout); hud->openPermanent(layout);
return 0; return 0;
} }
static int l_hud_close(lua_State* L) { static int l_hud_close(lua_State* L) {
auto layout = require_layout(L, lua_tostring(L, 1)); auto layout = require_layout(lua::tostring(L, 1));
scripting::hud->remove(layout->getRoot()); hud->remove(layout->getRoot());
return 0; return 0;
} }
static int l_hud_pause(lua_State*) { static int l_hud_pause(lua_State*) {
scripting::hud->setPause(true); hud->setPause(true);
return 0; return 0;
} }
static int l_hud_resume(lua_State*) { static int l_hud_resume(lua_State*) {
scripting::hud->setPause(false); hud->setPause(false);
return 0; return 0;
} }
static int l_hud_get_block_inventory(lua_State* L) { static int l_hud_get_block_inventory(lua_State* L) {
auto inventory = scripting::hud->getBlockInventory(); auto inventory = hud->getBlockInventory();
if (inventory == nullptr) { if (inventory == nullptr) {
lua_pushinteger(L, 0); return lua::pushinteger(L, 0);
} else { } else {
lua_pushinteger(L, inventory->getId()); return lua::pushinteger(L, inventory->getId());
} }
return 1;
} }
static int l_hud_get_player(lua_State* L) { static int l_hud_get_player(lua_State* L) {
auto player = scripting::hud->getPlayer(); auto player = hud->getPlayer();
lua_pushinteger(L, player->getId()); return lua::pushinteger(L, player->getId());
return 1;
} }
const luaL_Reg hudlib [] = { const luaL_Reg hudlib [] = {

View File

@ -15,14 +15,12 @@ using namespace scripting;
static int l_keycode(lua_State* L) { static int l_keycode(lua_State* L) {
auto name = lua::require_string(L, 1); auto name = lua::require_string(L, 1);
lua_pushinteger(L, static_cast<int>(input_util::keycode_from(name))); return lua::pushinteger(L, static_cast<int>(input_util::keycode_from(name)));
return 1;
} }
static int l_mousecode(lua_State* L) { static int l_mousecode(lua_State* L) {
auto name = lua::require_string(L, 1); auto name = lua::require_string(L, 1);
lua_pushinteger(L, static_cast<int>(input_util::mousecode_from(name))); return lua::pushinteger(L, static_cast<int>(input_util::mousecode_from(name)));
return 1;
} }
static int l_add_callback(lua_State* L) { static int l_add_callback(lua_State* L) {
@ -31,7 +29,7 @@ static int l_add_callback(lua_State* L) {
if (bind == Events::bindings.end()) { if (bind == Events::bindings.end()) {
throw std::runtime_error("unknown binding "+util::quote(bindname)); throw std::runtime_error("unknown binding "+util::quote(bindname));
} }
lua_pushvalue(L, 2); lua::pushvalue(L, 2);
runnable actual_callback = lua::create_runnable(L); runnable actual_callback = lua::create_runnable(L);
runnable callback = [=]() { runnable callback = [=]() {
if (!scripting::engine->getGUI()->isFocusCaught()) { if (!scripting::engine->getGUI()->isFocusCaught()) {
@ -52,12 +50,12 @@ static int l_get_mouse_pos(lua_State* L) {
static int l_get_bindings(lua_State* L) { static int l_get_bindings(lua_State* L) {
auto& bindings = Events::bindings; auto& bindings = Events::bindings;
lua_createtable(L, bindings.size(), 0); lua::createtable(L, bindings.size(), 0);
int i = 0; int i = 0;
for (auto& entry : bindings) { for (auto& entry : bindings) {
lua_pushstring(L, entry.first.c_str()); lua::pushstring(L, entry.first);
lua_rawseti(L, -2, i + 1); lua::rawseti(L, i + 1);
i++; i++;
} }
return 1; return 1;

View File

@ -122,7 +122,7 @@ static int l_inventory_move(lua_State* L) {
validate_slotid(slotAid, invA.get()); validate_slotid(slotAid, invA.get());
auto invBid = lua::tointeger(L, 3); auto invBid = lua::tointeger(L, 3);
auto slotBid = lua_isnil(L, 4) ? -1 : lua::tointeger(L, 4); auto slotBid = lua::isnil(L, 4) ? -1 : lua::tointeger(L, 4);
auto invB = get_inventory(invBid, 3); auto invB = get_inventory(invBid, 3);
auto& slot = invA->getSlot(slotAid); auto& slot = invA->getSlot(slotAid);
if (slotBid == -1) { if (slotBid == -1) {

View File

@ -9,7 +9,7 @@ static int l_json_stringify(lua_State* L) {
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) { if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
bool nice = lua::toboolean(L, 2); bool nice = lua::toboolean(L, 2);
auto string = json::stringify(mapptr->get(), nice, " "); auto string = json::stringify(mapptr->get(), nice, " ");
return lua::pushstring(L, string.c_str()); return lua::pushstring(L, string);
} else { } else {
throw std::runtime_error("table expected"); throw std::runtime_error("table expected");
} }

View File

@ -31,10 +31,10 @@ static int l_pack_get_folder(lua_State* L) {
/// @brief pack.get_installed() -> array<string> /// @brief pack.get_installed() -> array<string>
static int l_pack_get_installed(lua_State* L) { static int l_pack_get_installed(lua_State* L) {
auto& packs = engine->getContentPacks(); auto& packs = engine->getContentPacks();
lua_createtable(L, packs.size(), 0); lua::createtable(L, packs.size(), 0);
for (size_t i = 0; i < packs.size(); i++) { for (size_t i = 0; i < packs.size(); i++) {
lua::pushstring(L, packs[i].id); lua::pushstring(L, packs[i].id);
lua_rawseti(L, -2, i + 1); lua::rawseti(L, i + 1);
} }
return 1; return 1;
} }
@ -54,16 +54,16 @@ static int l_pack_get_available(lua_State* L) {
} }
auto names = manager.getAllNames(); auto names = manager.getAllNames();
lua_createtable(L, names.size(), 0); lua::createtable(L, names.size(), 0);
for (size_t i = 0; i < names.size(); i++) { for (size_t i = 0; i < names.size(); i++) {
lua::pushstring(L, names[i]); lua::pushstring(L, names[i]);
lua_rawseti(L, -2, i + 1); lua::rawseti(L, i + 1);
} }
return 1; return 1;
} }
static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content* content) { static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content* content) {
lua_createtable(L, 0, 5); lua::createtable(L, 0, 5);
lua::pushstring(L, pack.id); lua::pushstring(L, pack.id);
lua::setfield(L, "id"); lua::setfield(L, "id");
@ -92,7 +92,7 @@ static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content*
lua::setfield(L, "icon"); lua::setfield(L, "icon");
if (!pack.dependencies.empty()) { if (!pack.dependencies.empty()) {
lua_createtable(L, pack.dependencies.size(), 0); lua::createtable(L, pack.dependencies.size(), 0);
for (size_t i = 0; i < pack.dependencies.size(); i++) { for (size_t i = 0; i < pack.dependencies.size(); i++) {
auto& dpack = pack.dependencies.at(i); auto& dpack = pack.dependencies.at(i);
std::string prefix; std::string prefix;
@ -102,8 +102,8 @@ static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content*
case DependencyLevel::weak: prefix = "~"; break; case DependencyLevel::weak: prefix = "~"; break;
default: throw std::runtime_error(""); default: throw std::runtime_error("");
} }
lua_pushfstring(L, "%s%s", prefix.c_str(), dpack.id.c_str()); lua::pushfstring(L, "%s%s", prefix.c_str(), dpack.id.c_str());
lua_rawseti(L, -2, i+1); lua::rawseti(L, i+1);
} }
lua::setfield(L, "dependencies"); lua::setfield(L, "dependencies");
} }
@ -124,20 +124,20 @@ static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content*
/// [optional] has_indices: bool /// [optional] has_indices: bool
/// } or nil /// } or nil
static int l_pack_get_info(lua_State* L) { static int l_pack_get_info(lua_State* L) {
auto packid = lua_tostring(L, 1); auto packid = lua::tostring(L, 1);
auto content = scripting::engine->getContent(); auto content = engine->getContent();
auto& packs = scripting::engine->getContentPacks(); auto& packs = engine->getContentPacks();
auto found = std::find_if(packs.begin(), packs.end(), [packid](const auto& pack) { auto found = std::find_if(packs.begin(), packs.end(), [packid](const auto& pack) {
return pack.id == packid; return pack.id == packid;
}); });
if (found == packs.end()) { if (found == packs.end()) {
// TODO: optimize // TODO: optimize
fs::path worldFolder(""); fs::path worldFolder("");
if (scripting::level) { if (level) {
worldFolder = scripting::level->getWorld()->wfile->getFolder(); worldFolder = level->getWorld()->wfile->getFolder();
} }
auto manager = scripting::engine->createPacksManager(worldFolder); auto manager = engine->createPacksManager(worldFolder);
manager.scan(); manager.scan();
auto vec = manager.getAll({packid}); auto vec = manager.getAll({packid});
if (!vec.empty()) { if (!vec.empty()) {
@ -150,11 +150,11 @@ static int l_pack_get_info(lua_State* L) {
} }
static int l_pack_get_base_packs(lua_State* L) { static int l_pack_get_base_packs(lua_State* L) {
auto& packs = scripting::engine->getBasePacks(); auto& packs = engine->getBasePacks();
lua_createtable(L, packs.size(), 0); lua::createtable(L, packs.size(), 0);
for (size_t i = 0; i < packs.size(); i++) { for (size_t i = 0; i < packs.size(); i++) {
lua_pushstring(L, packs[i].c_str()); lua::pushstring(L, packs[i]);
lua_rawseti(L, -2, i + 1); lua::rawseti(L, i + 1);
} }
return 1; return 1;
} }

View File

@ -69,7 +69,7 @@ static int l_player_set_rot(lua_State* L) {
lua_Number x = lua::tonumber(L, 2); lua_Number x = lua::tonumber(L, 2);
lua_Number y = lua::tonumber(L, 3); lua_Number y = lua::tonumber(L, 3);
lua_Number z = cam.z; lua_Number z = cam.z;
if (lua_isnumber(L, 4)) { if (lua::isnumber(L, 4)) {
z = lua::tonumber(L, 4); z = lua::tonumber(L, 4);
} }
cam.x = x; cam.x = x;

View File

@ -17,9 +17,9 @@ static int l_world_get_list(lua_State* L) {
auto paths = engine->getPaths(); auto paths = engine->getPaths();
auto worlds = paths->scanForWorlds(); auto worlds = paths->scanForWorlds();
lua_createtable(L, worlds.size(), 0); lua::createtable(L, worlds.size(), 0);
for (size_t i = 0; i < worlds.size(); i++) { for (size_t i = 0; i < worlds.size(); i++) {
lua_createtable(L, 0, 1); lua::createtable(L, 0, 1);
auto name = worlds[i].filename().u8string(); auto name = worlds[i].filename().u8string();
lua::pushstring(L, name); lua::pushstring(L, name);
@ -35,8 +35,7 @@ static int l_world_get_list(lua_State* L) {
} }
lua::pushstring(L, icon); lua::pushstring(L, icon);
lua::setfield(L, "icon"); lua::setfield(L, "icon");
lua::rawseti(L, i + 1);
lua_rawseti(L, -2, i + 1);
} }
return 1; return 1;
} }

View File

@ -1,6 +1,5 @@
#include "LuaState.hpp" #include "lua_engine.hpp"
#include "lua_util.hpp"
#include "api_lua.hpp" #include "api_lua.hpp"
#include "../../../debug/Logger.hpp" #include "../../../debug/Logger.hpp"
#include "../../../util/stringutil.hpp" #include "../../../util/stringutil.hpp"
@ -9,70 +8,23 @@
#include <iostream> #include <iostream>
static debug::Logger logger("lua-state"); static debug::Logger logger("lua-state");
static lua_State* main_thread = nullptr;
using namespace lua; using namespace lua;
luaerror::luaerror(const std::string& message) : std::runtime_error(message) { luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
} }
void LuaState::removeLibFuncs(lua_State* L, const char* libname, const char* funcs[]) { static void remove_lib_funcs(lua_State* L, const char* libname, const char* funcs[]) {
if (getglobal(L, libname)) { if (getglobal(L, libname)) {
for (uint i = 0; funcs[i]; i++) { for (uint i = 0; funcs[i]; i++) {
lua_pushnil(L); pushnil(L);
setfield(L, funcs[i], -2); setfield(L, funcs[i], -2);
} }
} }
} }
LuaState::LuaState() { static void create_libs(lua_State* L) {
logger.info() << LUA_VERSION;
logger.info() << LUAJIT_VERSION;
auto L = luaL_newstate();
if (L == nullptr) {
throw luaerror("could not to initialize Lua");
}
mainThread = L;
// Allowed standard libraries
luaopen_base(L);
luaopen_math(L);
luaopen_string(L);
luaopen_table(L);
luaopen_debug(L);
luaopen_jit(L);
luaopen_bit(L);
luaopen_os(L);
const char* removed_os[] {
"execute",
"exit",
"remove",
"rename",
"setlocale",
"tmpname",
nullptr
};
removeLibFuncs(L, "os", removed_os);
createLibs(L);
pushglobals(L);
setglobal(L, env_name(0));
lua_createtable(L, 0, 0);
setglobal(L, LAMBDAS_TABLE);
}
LuaState::~LuaState() {
lua_close(mainThread);
}
void LuaState::addfunc(lua_State* L, const std::string& name, lua_CFunction func) {
lua_pushcfunction(L, func);
lua_setglobal(L, name.c_str());
}
void LuaState::createLibs(lua_State* L) {
openlib(L, "audio", audiolib); openlib(L, "audio", audiolib);
openlib(L, "block", blocklib); openlib(L, "block", blocklib);
openlib(L, "console", consolelib); openlib(L, "console", consolelib);
@ -92,13 +44,49 @@ void LuaState::createLibs(lua_State* L) {
addfunc(L, "print", lua::wrap<l_print>); addfunc(L, "print", lua::wrap<l_print>);
} }
void LuaState::openlib(lua_State* L, const std::string& name, const luaL_Reg* libfuncs) { void lua::initialize() {
lua_newtable(L); logger.info() << LUA_VERSION;
luaL_setfuncs(L, libfuncs, 0); logger.info() << LUAJIT_VERSION;
lua_setglobal(L, name.c_str());
auto L = luaL_newstate();
if (L == nullptr) {
throw luaerror("could not to initialize Lua");
}
main_thread = L;
// Allowed standard libraries
luaopen_base(L);
luaopen_math(L);
luaopen_string(L);
luaopen_table(L);
luaopen_debug(L);
luaopen_jit(L);
luaopen_bit(L);
luaopen_os(L);
const char* removed_os[] {
"execute",
"exit",
"remove",
"rename",
"setlocale",
"tmpname",
nullptr
};
remove_lib_funcs(L, "os", removed_os);
create_libs(L);
pushglobals(L);
setglobal(L, env_name(0));
createtable(L, 0, 0);
setglobal(L, LAMBDAS_TABLE);
} }
bool LuaState::emitEvent(lua_State* L, const std::string &name, std::function<int(lua_State*)> args) { void lua::finalize() {
lua_close(main_thread);
}
bool lua::emit_event(lua_State* L, const std::string &name, std::function<int(lua_State*)> args) {
getglobal(L, "events"); getglobal(L, "events");
getfield(L, "emit"); getfield(L, "emit");
pushstring(L, name); pushstring(L, name);
@ -108,6 +96,6 @@ bool LuaState::emitEvent(lua_State* L, const std::string &name, std::function<in
return result; return result;
} }
lua_State* LuaState::getMainThread() const { lua_State* lua::get_main_thread() {
return mainThread; return main_thread;
} }

View File

@ -0,0 +1,21 @@
#ifndef LOGIC_SCRIPTING_LUA_STATE_HPP_
#define LOGIC_SCRIPTING_LUA_STATE_HPP_
#include "lua_util.hpp"
#include "../scripting_functional.hpp"
#include "../../../data/dynamic.hpp"
#include "../../../delegates.hpp"
#include <string>
#include <stdexcept>
namespace lua {
void initialize();
void finalize();
bool emit_event(lua_State*, const std::string& name, std::function<int(lua_State*)> args=[](auto*){return 0;});
lua_State* get_main_thread();
}
#endif // LOGIC_SCRIPTING_LUA_STATE_HPP_

View File

@ -1,24 +1,23 @@
#include "api_lua.hpp" #include "api_lua.hpp"
#include "lua_commons.hpp"
#include <iostream> #include <iostream>
/// @brief Modified version of luaB_print from lbaselib.c /// @brief Modified version of luaB_print from lbaselib.c
int l_print(lua_State* L) { int l_print(lua_State* L) {
int n = lua_gettop(L); /* number of arguments */ int n = lua_gettop(L); /* number of arguments */
lua_getglobal(L, "tostring"); lua::getglobal(L, "tostring");
for (int i=1; i<=n; i++) { for (int i=1; i<=n; i++) {
lua_pushvalue(L, -1); /* function to be called */ lua::pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */ lua::pushvalue(L, i); /* value to print */
lua_call(L, 1, 1); lua::call(L, 1, 1);
const char* s = lua_tostring(L, -1); /* get result */ const char* s = lua::tostring(L, -1); /* get result */
if (s == NULL) if (s == NULL)
return luaL_error(L, LUA_QL("tostring") " must return a string to " return luaL_error(L, LUA_QL("tostring") " must return a string to "
LUA_QL("print")); LUA_QL("print"));
if (i > 1) if (i > 1)
std::cout << "\t"; std::cout << "\t";
std::cout << s; std::cout << s;
lua_pop(L, 1); /* pop result */ lua::pop(L); /* pop result */
} }
std::cout << std::endl; std::cout << std::endl;
return 0; return 0;

View File

@ -17,29 +17,29 @@ int lua::pushvalue(lua_State* L, const dynamic::Value& value) {
using namespace dynamic; using namespace dynamic;
if (auto* flag = std::get_if<bool>(&value)) { if (auto* flag = std::get_if<bool>(&value)) {
lua_pushboolean(L, *flag); pushboolean(L, *flag);
} else if (auto* num = std::get_if<integer_t>(&value)) { } else if (auto* num = std::get_if<integer_t>(&value)) {
lua_pushinteger(L, *num); pushinteger(L, *num);
} else if (auto* num = std::get_if<number_t>(&value)) { } else if (auto* num = std::get_if<number_t>(&value)) {
lua_pushnumber(L, *num); pushnumber(L, *num);
} else if (auto* str = std::get_if<std::string>(&value)) { } else if (auto* str = std::get_if<std::string>(&value)) {
lua_pushstring(L, str->c_str()); pushstring(L, *str);
} else if (auto listptr = std::get_if<List_sptr>(&value)) { } else if (auto listptr = std::get_if<List_sptr>(&value)) {
auto list = *listptr; auto list = *listptr;
lua_createtable(L, list->size(), 0); createtable(L, list->size(), 0);
for (size_t i = 0; i < list->size(); i++) { for (size_t i = 0; i < list->size(); i++) {
pushvalue(L, list->get(i)); pushvalue(L, list->get(i));
lua_rawseti(L, -2, i+1); rawseti(L, i+1);
} }
} else if (auto mapptr = std::get_if<Map_sptr>(&value)) { } else if (auto mapptr = std::get_if<Map_sptr>(&value)) {
auto map = *mapptr; auto map = *mapptr;
lua_createtable(L, 0, map->size()); createtable(L, 0, map->size());
for (auto& entry : map->values) { for (auto& entry : map->values) {
pushvalue(L, entry.second); pushvalue(L, entry.second);
lua_setfield(L, -2, entry.first.c_str()); setfield(L, entry.first);
} }
} else { } else {
lua_pushnil(L); pushnil(L);
} }
return 1; return 1;
} }
@ -54,47 +54,47 @@ int lua::pushwstring(lua_State* L, const std::wstring& str) {
dynamic::Value lua::tovalue(lua_State* L, int idx) { dynamic::Value lua::tovalue(lua_State* L, int idx) {
using namespace dynamic; using namespace dynamic;
auto type = lua_type(L, idx); auto type = lua::type(L, idx);
switch (type) { switch (type) {
case LUA_TNIL: case LUA_TNIL:
case LUA_TNONE: case LUA_TNONE:
return dynamic::NONE; return dynamic::NONE;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
return lua_toboolean(L, idx) == 1; return toboolean(L, idx) == 1;
case LUA_TNUMBER: { case LUA_TNUMBER: {
auto number = lua_tonumber(L, idx); auto number = tonumber(L, idx);
auto integer = lua_tointeger(L, idx); auto integer = tointeger(L, idx);
if (number == (lua_Number)integer) { if (number == static_cast<lua_Number>(integer)) {
return integer; return integer;
} else { } else {
return number; return number;
} }
} }
case LUA_TSTRING: case LUA_TSTRING:
return std::string(lua_tostring(L, idx)); return std::string(tostring(L, idx));
case LUA_TTABLE: { case LUA_TTABLE: {
int len = lua_objlen(L, idx); int len = lua::objlen(L, idx);
if (len) { if (len) {
// array // array
auto list = create_list(); auto list = create_list();
for (int i = 1; i <= len; i++) { for (int i = 1; i <= len; i++) {
lua_rawgeti(L, idx, i); rawgeti(L, i, idx);
list->put(tovalue(L, -1)); list->put(tovalue(L, -1));
lua_pop(L, 1); pop(L);
} }
return list; return list;
} else { } else {
// table // table
auto map = create_map(); auto map = create_map();
lua_pushvalue(L, idx); pushvalue(L, idx);
lua_pushnil(L); pushnil(L);
while (lua_next(L, -2)) { while (lua_next(L, -2)) {
lua_pushvalue(L, -2); pushvalue(L, -2);
auto key = lua_tostring(L, -1); auto key = tostring(L, -1);
map->put(key, tovalue(L, -2)); map->put(key, tovalue(L, -2));
lua_pop(L, 2); pop(L, 2);
} }
lua_pop(L, 1); pop(L);
return map; return map;
} }
} }
@ -107,38 +107,38 @@ dynamic::Value lua::tovalue(lua_State* L, int idx) {
int lua::call(lua_State* L, int argc, int nresults) { int lua::call(lua_State* L, int argc, int nresults) {
if (lua_pcall(L, argc, nresults, 0)) { if (lua_pcall(L, argc, nresults, 0)) {
throw luaerror(lua_tostring(L, -1)); throw luaerror(tostring(L, -1));
} }
return 1; return 1;
} }
int lua::call_nothrow(lua_State* L, int argc) { int lua::call_nothrow(lua_State* L, int argc) {
if (lua_pcall(L, argc, LUA_MULTRET, 0)) { if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
log_error(lua_tostring(L, -1)); log_error(tostring(L, -1));
return 0; return 0;
} }
return 1; return 1;
} }
void lua::dump_stack(lua_State* L) { void lua::dump_stack(lua_State* L) {
int top = lua_gettop(L); int top = gettop(L);
for (int i = 1; i <= top; i++) { for (int i = 1; i <= top; i++) {
std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30); std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30);
switch (lua_type(L, i)) { switch (lua::type(L, i)) {
case LUA_TNUMBER: case LUA_TNUMBER:
std::cout << lua_tonumber(L, i); std::cout << tonumber(L, i);
break; break;
case LUA_TSTRING: case LUA_TSTRING:
std::cout << lua_tostring(L, i); std::cout << tostring(L, i);
break; break;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
std::cout << (lua_toboolean(L, i) ? "true" : "false"); std::cout << (toboolean(L, i) ? "true" : "false");
break; break;
case LUA_TNIL: case LUA_TNIL:
std::cout << "nil"; std::cout << "nil";
break; break;
default: default:
std::cout << lua_topointer(L, i); std::cout << topointer(L, i);
break; break;
} }
std::cout << std::endl; std::cout << std::endl;
@ -146,7 +146,7 @@ void lua::dump_stack(lua_State* L) {
} }
static std::shared_ptr<std::string> createLambdaHandler(lua_State* L) { static std::shared_ptr<std::string> createLambdaHandler(lua_State* L) {
auto ptr = reinterpret_cast<ptrdiff_t>(lua_topointer(L, -1)); auto ptr = reinterpret_cast<ptrdiff_t>(topointer(L, -1));
auto name = util::mangleid(ptr); auto name = util::mangleid(ptr);
getglobal(L, LAMBDAS_TABLE); getglobal(L, LAMBDAS_TABLE);
pushvalue(L, -2); pushvalue(L, -2);
@ -174,14 +174,14 @@ runnable lua::create_runnable(lua_State* L) {
scripting::common_func lua::create_lambda(lua_State* L) { scripting::common_func lua::create_lambda(lua_State* L) {
auto funcptr = createLambdaHandler(L); auto funcptr = createLambdaHandler(L);
return [=](const std::vector<dynamic::Value>& args) { return [=](const std::vector<dynamic::Value>& args) {
lua_getglobal(L, LAMBDAS_TABLE.c_str()); getglobal(L, LAMBDAS_TABLE);
lua_getfield(L, -1, funcptr->c_str()); getfield(L, *funcptr);
for (const auto& arg : args) { for (const auto& arg : args) {
pushvalue(L, arg); pushvalue(L, arg);
} }
if (call(L, args.size(), 1)) { if (call(L, args.size(), 1)) {
auto result = tovalue(L, -1); auto result = tovalue(L, -1);
lua_pop(L, 1); pop(L);
return result; return result;
} }
return dynamic::Value(dynamic::NONE); return dynamic::Value(dynamic::NONE);
@ -192,10 +192,10 @@ int lua::createEnvironment(lua_State* L, int parent) {
int id = nextEnvironment++; int id = nextEnvironment++;
// local env = {} // local env = {}
lua_createtable(L, 0, 1); createtable(L, 0, 1);
// setmetatable(env, {__index=_G}) // setmetatable(env, {__index=_G})
lua_createtable(L, 0, 1); createtable(L, 0, 1);
if (parent == 0) { if (parent == 0) {
pushglobals(L); pushglobals(L);
} else { } else {

View File

@ -27,6 +27,53 @@ namespace lua {
inline void pop(lua_State* L, int n=1) { inline void pop(lua_State* L, int n=1) {
lua_pop(L, n); lua_pop(L, n);
} }
inline int gettop(lua_State* L) {
return lua_gettop(L);
}
inline size_t objlen(lua_State* L, int idx) {
return lua_objlen(L, idx);
}
inline int type(lua_State* L, int idx) {
return lua_type(L, idx);
}
inline const char* type_name(lua_State* L, int idx) {
return lua_typename(L, idx);
}
inline int rawgeti(lua_State* L, int n, int idx=-1) {
lua_rawgeti(L, idx, n);
return 1;
}
inline void rawseti(lua_State* L, int n, int idx=-2) {
lua_rawseti(L, idx, n);
}
inline int createtable(lua_State* L, int narr, int nrec) {
lua_createtable(L, narr, nrec);
return 1;
}
inline bool isnil(lua_State* L, int idx) {
return lua_isnil(L, idx);
}
inline bool getglobal(lua_State* L, const std::string& name) {
lua_getglobal(L, name.c_str());
if (isnil(L, -1)) {
pop(L);
return false;
}
return true;
}
inline bool hasglobal(lua_State* L, const std::string& name) {
lua_getglobal(L, name.c_str());
if (isnil(L, -1)) {
pop(L);
return false;
}
pop(L);
return true;
}
// function wrappers with number of pushed values as return value // function wrappers with number of pushed values as return value
@ -46,88 +93,88 @@ namespace lua {
} }
inline int pushivec3(lua_State* L, lua_Integer x, lua_Integer y, lua_Integer z) { inline int pushivec3(lua_State* L, lua_Integer x, lua_Integer y, lua_Integer z) {
lua_pushinteger(L, x); pushinteger(L, x);
lua_pushinteger(L, y); pushinteger(L, y);
lua_pushinteger(L, z); pushinteger(L, z);
return 3; return 3;
} }
inline int pushivec3(lua_State* L, glm::ivec3 vec) { inline int pushivec3(lua_State* L, glm::ivec3 vec) {
lua_pushinteger(L, vec.x); pushinteger(L, vec.x);
lua_pushinteger(L, vec.y); pushinteger(L, vec.y);
lua_pushinteger(L, vec.z); pushinteger(L, vec.z);
return 3; return 3;
} }
inline int pushvec3(lua_State* L, glm::vec3 vec) { inline int pushvec3(lua_State* L, glm::vec3 vec) {
lua_pushnumber(L, vec.x); pushnumber(L, vec.x);
lua_pushnumber(L, vec.y); pushnumber(L, vec.y);
lua_pushnumber(L, vec.z); pushnumber(L, vec.z);
return 3; return 3;
} }
inline int pushvec4(lua_State* L, glm::vec4 vec) { inline int pushvec4(lua_State* L, glm::vec4 vec) {
lua_pushnumber(L, vec.x); pushnumber(L, vec.x);
lua_pushnumber(L, vec.y); pushnumber(L, vec.y);
lua_pushnumber(L, vec.z); pushnumber(L, vec.z);
lua_pushnumber(L, vec.w); pushnumber(L, vec.w);
return 4; return 4;
} }
inline int pushvec2_arr(lua_State* L, glm::vec2 vec) { inline int pushvec2_arr(lua_State* L, glm::vec2 vec) {
lua_createtable(L, 2, 0); createtable(L, 2, 0);
lua_getglobal(L, "vec2_mt"); getglobal(L, "vec2_mt");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_pushnumber(L, vec.x); pushnumber(L, vec.x);
lua_rawseti(L, -2, 1); rawseti(L, 1);
lua_pushnumber(L, vec.y); pushnumber(L, vec.y);
lua_rawseti(L, -2, 2); rawseti(L, 2);
return 1; return 1;
} }
inline int pushvec3_arr(lua_State* L, glm::vec3 vec) { inline int pushvec3_arr(lua_State* L, glm::vec3 vec) {
lua_createtable(L, 3, 0); createtable(L, 3, 0);
lua_getglobal(L, "vec3_mt"); getglobal(L, "vec3_mt");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_pushnumber(L, vec.x); pushnumber(L, vec.x);
lua_rawseti(L, -2, 1); rawseti(L, 1);
lua_pushnumber(L, vec.y); pushnumber(L, vec.y);
lua_rawseti(L, -2, 2); rawseti(L, 2);
lua_pushnumber(L, vec.z); pushnumber(L, vec.z);
lua_rawseti(L, -2, 3); rawseti(L, 3);
return 1; return 1;
} }
inline int pushvec4_arr(lua_State* L, glm::vec4 vec) { inline int pushvec4_arr(lua_State* L, glm::vec4 vec) {
lua_createtable(L, 4, 0); createtable(L, 4, 0);
lua_getglobal(L, "vec4_mt"); getglobal(L, "vec4_mt");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_pushnumber(L, vec.x); pushnumber(L, vec.x);
lua_rawseti(L, -2, 1); rawseti(L, 1);
lua_pushnumber(L, vec.y); pushnumber(L, vec.y);
lua_rawseti(L, -2, 2); rawseti(L, 2);
lua_pushnumber(L, vec.z); pushnumber(L, vec.z);
lua_rawseti(L, -2, 3); rawseti(L, 3);
lua_pushnumber(L, vec.w); pushnumber(L, vec.w);
lua_rawseti(L, -2, 4); rawseti(L, 4);
return 1; return 1;
} }
inline int pushcolor_arr(lua_State* L, glm::vec4 vec) { inline int pushcolor_arr(lua_State* L, glm::vec4 vec) {
lua_createtable(L, 4, 0); createtable(L, 4, 0);
lua_getglobal(L, "color_mt"); getglobal(L, "color_mt");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_pushinteger(L, vec.x*255); pushinteger(L, vec.x*255);
lua_rawseti(L, -2, 1); rawseti(L, 1);
lua_pushinteger(L, vec.y*255); pushinteger(L, vec.y*255);
lua_rawseti(L, -2, 2); rawseti(L, 2);
lua_pushinteger(L, vec.z*255); pushinteger(L, vec.z*255);
lua_rawseti(L, -2, 3); rawseti(L, 3);
lua_pushinteger(L, vec.w*255); pushinteger(L, vec.w*255);
lua_rawseti(L, -2, 4); rawseti(L, 4);
return 1; return 1;
} }
inline int pushcfunction(lua_State* L, lua_CFunction func) { inline int pushcfunction(lua_State* L, lua_CFunction func) {
@ -139,63 +186,84 @@ namespace lua {
return 1; return 1;
} }
template<typename... Args>
inline int pushfstring(lua_State *L, const char * fmt, Args... args) {
lua_pushfstring(L, fmt, args...);
return 1;
}
int pushwstring(lua_State* L, const std::wstring& str); int pushwstring(lua_State* L, const std::wstring& str);
inline int pushboolean(lua_State* L, bool value) { inline int pushboolean(lua_State* L, bool value) {
lua_pushboolean(L, value); lua_pushboolean(L, value);
return 1; return 1;
} }
inline int pushglobals(lua_State* L) {
lua_pushvalue(L, LUA_GLOBALSINDEX);
return 1;
}
inline int pushvalue(lua_State* L, int idx) { inline int pushvalue(lua_State* L, int idx) {
lua_pushvalue(L, idx); lua_pushvalue(L, idx);
return 1; return 1;
} }
inline int pushglobals(lua_State* L) {
return pushvalue(L, LUA_GLOBALSINDEX);
}
inline bool isnoneornil(lua_State* L, int idx) {
return lua_isnoneornil(L, idx);
}
inline bool isboolean(lua_State* L, int idx) {
return lua_isboolean(L, idx);
}
inline bool isnumber(lua_State* L, int idx) {
return lua_isnumber(L, idx);
}
inline bool isstring(lua_State* L, int idx) {
return lua_isstring(L, idx);
}
inline bool istable(lua_State* L, int idx) {
return lua_istable(L, idx);
}
inline bool isfunction(lua_State* L, int idx) {
return lua_isfunction(L, idx);
}
inline bool toboolean(lua_State* L, int idx) { inline bool toboolean(lua_State* L, int idx) {
return lua_toboolean(L, idx); return lua_toboolean(L, idx);
} }
inline lua_Integer tointeger(lua_State* L, int idx) { inline lua_Integer tointeger(lua_State* L, int idx) {
return lua_tointeger(L, idx); return lua_tointeger(L, idx);
} }
inline lua_Number tonumber(lua_State* L, int idx) { inline lua_Number tonumber(lua_State* L, int idx) {
return lua_tonumber(L, idx); return lua_tonumber(L, idx);
} }
inline const char* tostring(lua_State* L, int idx) { inline const char* tostring(lua_State* L, int idx) {
return lua_tostring(L, idx); return lua_tostring(L, idx);
} }
inline const void* topointer(lua_State* L, int idx) {
return lua_topointer(L, idx);
}
inline glm::vec2 tovec2(lua_State* L, int idx) { inline glm::vec2 tovec2(lua_State* L, int idx) {
lua_pushvalue(L, idx); pushvalue(L, idx);
if (!lua_istable(L, idx) || lua_objlen(L, idx) < 2) { if (!istable(L, idx) || objlen(L, idx) < 2) {
throw std::runtime_error("value must be an array of two numbers"); throw std::runtime_error("value must be an array of two numbers");
} }
lua_rawgeti(L, -1, 1); rawgeti(L, 1);
lua_Number x = lua_tonumber(L, -1); lua_pop(L, 1); auto x = tonumber(L, -1); pop(L);
lua_rawgeti(L, -1, 2); rawgeti(L, 2);
lua_Number y = lua_tonumber(L, -1); lua_pop(L, 1); auto y = tonumber(L, -1); pop(L);
pop(L); pop(L);
return glm::vec2(x, y); return glm::vec2(x, y);
} }
inline glm::vec4 tocolor(lua_State* L, int idx) { inline glm::vec4 tocolor(lua_State* L, int idx) {
pushvalue(L, idx); pushvalue(L, idx);
if (!lua_istable(L, -1) || lua_objlen(L, idx) < 4) { if (!istable(L, -1) || objlen(L, idx) < 4) {
throw std::runtime_error("RGBA array required"); throw std::runtime_error("RGBA array required");
} }
lua_rawgeti(L, -1, 1); rawgeti(L, 1);
lua_Number r = tonumber(L, -1); pop(L); auto r = tonumber(L, -1); pop(L);
lua_rawgeti(L, -1, 2); rawgeti(L, 2);
lua_Number g = tonumber(L, -1); pop(L); auto g = tonumber(L, -1); pop(L);
lua_rawgeti(L, -1, 3); rawgeti(L, 3);
lua_Number b = tonumber(L, -1); pop(L); auto b = tonumber(L, -1); pop(L);
lua_rawgeti(L, -1, 4); rawgeti(L, 4);
lua_Number a = tonumber(L, -1); pop(L); auto a = tonumber(L, -1); pop(L);
pop(L); pop(L);
return glm::vec4(r/255, g/255, b/255, a/255); return glm::vec4(r/255, g/255, b/255, a/255);
} }
@ -205,8 +273,8 @@ namespace lua {
inline bool getfield(lua_State* L, const std::string& name, int idx=-1) { inline bool getfield(lua_State* L, const std::string& name, int idx=-1) {
lua_getfield(L, idx, name.c_str()); lua_getfield(L, idx, name.c_str());
if (lua_isnil(L, -1)) { if (isnil(L, -1)) {
lua_pop(L, -1); pop(L);
return false; return false;
} }
return true; return true;
@ -216,31 +284,12 @@ namespace lua {
lua_setfield(L, idx, name.c_str()); lua_setfield(L, idx, name.c_str());
} }
inline bool getglobal(lua_State* L, const std::string& name) {
lua_getglobal(L, name.c_str());
if (lua_isnil(L, -1)) {
pop(L);
return false;
}
return true;
}
inline bool hasglobal(lua_State* L, const std::string& name) {
lua_getglobal(L, name.c_str());
if (lua_isnil(L, -1)) {
lua_pop(L, -1);
return false;
}
pop(L);
return true;
}
inline void setglobal(lua_State* L, const std::string& name) { inline void setglobal(lua_State* L, const std::string& name) {
lua_setglobal(L, name.c_str()); lua_setglobal(L, name.c_str());
} }
inline const char* require_string(lua_State* L, int idx) { inline const char* require_string(lua_State* L, int idx) {
if (!lua_isstring(L, idx)) { if (!isstring(L, idx)) {
throw luaerror("string expected at "+std::to_string(idx)); throw luaerror("string expected at "+std::to_string(idx));
} }
return tostring(L, idx); return tostring(L, idx);
@ -249,28 +298,27 @@ namespace lua {
std::wstring require_wstring(lua_State*, int idx); std::wstring require_wstring(lua_State*, int idx);
inline bool rename(lua_State* L, const std::string& from, const std::string& to) { inline bool rename(lua_State* L, const std::string& from, const std::string& to) {
const char* src = from.c_str(); getglobal(L, from);
lua_getglobal(L, src); if (lua_isnil(L, -1)) {
if (lua_isnil(L, lua_gettop(L))) { pop(L, 1);
lua_pop(L, lua_gettop(L));
return false; return false;
} }
lua_setglobal(L, to.c_str()); setglobal(L, to);
// remove previous // remove previous
lua_pushnil(L); pushnil(L);
lua_setglobal(L, src); setglobal(L, from);
return true; return true;
} }
inline void remove(lua_State* L, const std::string& name) { inline void remove(lua_State* L, const std::string& name) {
lua_pushnil(L); pushnil(L);
lua_setglobal(L, name.c_str()); setglobal(L, name);
} }
inline void loadbuffer(lua_State* L, int env, const std::string& src, const std::string& file) { inline void loadbuffer(lua_State* L, int env, const std::string& src, const std::string& file) {
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) { if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
throw luaerror(lua_tostring(L, -1)); throw luaerror(tostring(L, -1));
} }
if (env && getglobal(L, env_name(env))) { if (env && getglobal(L, env_name(env))) {
lua_setfenv(L, -2); lua_setfenv(L, -2);
@ -303,6 +351,17 @@ namespace lua {
int createEnvironment(lua_State*, int parent); int createEnvironment(lua_State*, int parent);
void removeEnvironment(lua_State*, int id); void removeEnvironment(lua_State*, int id);
void dump_stack(lua_State*); void dump_stack(lua_State*);
inline void addfunc(lua_State* L, const std::string& name, lua_CFunction func) {
pushcfunction(L, func);
setglobal(L, name);
}
inline void openlib(lua_State* L, const std::string& name, const luaL_Reg* libfuncs) {
createtable(L, 0, 0);
luaL_setfuncs(L, libfuncs, 0);
setglobal(L, name);
}
} }
#endif // LOGIC_SCRIPTING_LUA_UTIL_HPP_ #endif // LOGIC_SCRIPTING_LUA_UTIL_HPP_

View File

@ -1,5 +1,7 @@
#include "scripting.hpp" #include "scripting.hpp"
#include "lua/lua_engine.hpp"
#include "../../content/ContentPack.hpp" #include "../../content/ContentPack.hpp"
#include "../../debug/Logger.hpp" #include "../../debug/Logger.hpp"
#include "../../engine.hpp" #include "../../engine.hpp"
@ -16,22 +18,15 @@
#include "../../util/timeutil.hpp" #include "../../util/timeutil.hpp"
#include "../../voxels/Block.hpp" #include "../../voxels/Block.hpp"
#include "../../world/Level.hpp" #include "../../world/Level.hpp"
#include "lua/LuaState.hpp"
#include "lua/lua_util.hpp"
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
using namespace scripting; using namespace scripting;
namespace scripting {
extern lua::LuaState* state;
}
static debug::Logger logger("scripting"); static debug::Logger logger("scripting");
Engine* scripting::engine = nullptr; Engine* scripting::engine = nullptr;
lua::LuaState* scripting::state = nullptr;
Level* scripting::level = nullptr; Level* scripting::level = nullptr;
const Content* scripting::content = nullptr; const Content* scripting::content = nullptr;
const ContentIndices* scripting::indices = nullptr; const ContentIndices* scripting::indices = nullptr;
@ -43,13 +38,12 @@ static void load_script(const fs::path& name) {
fs::path file = paths->getResources()/fs::path("scripts")/name; fs::path file = paths->getResources()/fs::path("scripts")/name;
std::string src = files::read_string(file); std::string src = files::read_string(file);
lua::execute(state->getMainThread(), 0, src, file.u8string()); lua::execute(lua::get_main_thread(), 0, src, file.u8string());
} }
void scripting::initialize(Engine* engine) { void scripting::initialize(Engine* engine) {
scripting::engine = engine; scripting::engine = engine;
lua::initialize();
state = new lua::LuaState();
load_script(fs::path("stdlib.lua")); load_script(fs::path("stdlib.lua"));
load_script(fs::path("stdcmd.lua")); load_script(fs::path("stdcmd.lua"));
@ -60,7 +54,7 @@ scriptenv scripting::get_root_environment() {
} }
scriptenv scripting::create_pack_environment(const ContentPack& pack) { scriptenv scripting::create_pack_environment(const ContentPack& pack) {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
int id = lua::createEnvironment(L, 0); int id = lua::createEnvironment(L, 0);
lua::pushenv(L, id); lua::pushenv(L, id);
lua::pushvalue(L, -1); lua::pushvalue(L, -1);
@ -75,7 +69,7 @@ scriptenv scripting::create_pack_environment(const ContentPack& pack) {
} }
scriptenv scripting::create_doc_environment(const scriptenv& parent, const std::string& name) { scriptenv scripting::create_doc_environment(const scriptenv& parent, const std::string& name) {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
int id = lua::createEnvironment(L, *parent); int id = lua::createEnvironment(L, *parent);
lua::pushenv(L, id); lua::pushenv(L, id);
lua::pushvalue(L, -1); lua::pushvalue(L, -1);
@ -100,7 +94,7 @@ scriptenv scripting::create_doc_environment(const scriptenv& parent, const std::
} }
void scripting::process_post_runnables() { void scripting::process_post_runnables() {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
if (lua::getglobal(L, "__process_post_runnables")) { if (lua::getglobal(L, "__process_post_runnables")) {
lua::call_nothrow(L, 0); lua::call_nothrow(L, 0);
} }
@ -114,30 +108,30 @@ void scripting::on_world_load(LevelController* controller) {
scripting::controller = controller; scripting::controller = controller;
load_script("world.lua"); load_script("world.lua");
auto L = state->getMainThread(); auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emitEvent(L, pack.id + ".worldopen"); lua::emit_event(L, pack.id + ".worldopen");
} }
} }
void scripting::on_world_tick() { void scripting::on_world_tick() {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emitEvent(L, pack.id + ".worldtick"); lua::emit_event(L, pack.id + ".worldtick");
} }
} }
void scripting::on_world_save() { void scripting::on_world_save() {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emitEvent(L, pack.id + ".worldsave"); lua::emit_event(L, pack.id + ".worldsave");
} }
} }
void scripting::on_world_quit() { void scripting::on_world_quit() {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emitEvent(L, pack.id + ".worldquit"); lua::emit_event(L, pack.id + ".worldquit");
} }
lua::getglobal(L, "pack"); lua::getglobal(L, "pack");
@ -160,28 +154,28 @@ void scripting::on_world_quit() {
void scripting::on_blocks_tick(const Block* block, int tps) { void scripting::on_blocks_tick(const Block* block, int tps) {
std::string name = block->name + ".blockstick"; std::string name = block->name + ".blockstick";
state->emitEvent(state->getMainThread(), name, [tps] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [tps] (lua_State* L) {
return lua::pushinteger(L, tps); return lua::pushinteger(L, tps);
}); });
} }
void scripting::update_block(const Block* block, int x, int y, int z) { void scripting::update_block(const Block* block, int x, int y, int z) {
std::string name = block->name + ".update"; std::string name = block->name + ".update";
state->emitEvent(state->getMainThread(), name, [x, y, z] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [x, y, z] (lua_State* L) {
return lua::pushivec3(L, x, y, z); return lua::pushivec3(L, x, y, z);
}); });
} }
void scripting::random_update_block(const Block* block, int x, int y, int z) { void scripting::random_update_block(const Block* block, int x, int y, int z) {
std::string name = block->name + ".randupdate"; std::string name = block->name + ".randupdate";
state->emitEvent(state->getMainThread(), name, [x, y, z] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [x, y, z] (lua_State* L) {
return lua::pushivec3(L, x, y, z); return lua::pushivec3(L, x, y, z);
}); });
} }
void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) { void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) {
std::string name = block->name + ".placed"; std::string name = block->name + ".placed";
state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (lua_State* L) {
lua::pushivec3(L, x, y, z); lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
@ -190,7 +184,7 @@ void scripting::on_block_placed(Player* player, const Block* block, int x, int y
void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) { void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) {
std::string name = block->name + ".broken"; std::string name = block->name + ".broken";
state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (lua_State* L) {
lua::pushivec3(L, x, y, z); lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
@ -199,7 +193,7 @@ void scripting::on_block_broken(Player* player, const Block* block, int x, int y
bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3 pos) { bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3 pos) {
std::string name = block->name + ".interact"; std::string name = block->name + ".interact";
return state->emitEvent(state->getMainThread(), name, [pos, player] (lua_State* L) { return lua::emit_event(lua::get_main_thread(), name, [pos, player] (lua_State* L) {
lua::pushivec3(L, pos.x, pos.y, pos.z); lua::pushivec3(L, pos.x, pos.y, pos.z);
lua::pushinteger(L, player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
@ -208,14 +202,14 @@ bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3
bool scripting::on_item_use(Player* player, const ItemDef* item) { bool scripting::on_item_use(Player* player, const ItemDef* item) {
std::string name = item->name + ".use"; std::string name = item->name + ".use";
return state->emitEvent(state->getMainThread(), name, [player] (lua_State* L) { return lua::emit_event(lua::get_main_thread(), name, [player] (lua_State* L) {
return lua::pushinteger(L, player->getId()); return lua::pushinteger(L, player->getId());
}); });
} }
bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) { bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) {
std::string name = item->name + ".useon"; std::string name = item->name + ".useon";
return state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { return lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (lua_State* L) {
lua::pushivec3(L, x, y, z); lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
@ -224,7 +218,7 @@ bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x,
bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) { bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) {
std::string name = item->name + ".blockbreakby"; std::string name = item->name + ".blockbreakby";
return state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { return lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (lua_State* L) {
lua::pushivec3(L, x, y, z); lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
@ -237,7 +231,7 @@ void scripting::on_ui_open(
) { ) {
auto argsptr = std::make_shared<std::vector<dynamic::Value>>(std::move(args)); auto argsptr = std::make_shared<std::vector<dynamic::Value>>(std::move(args));
std::string name = layout->getId() + ".open"; std::string name = layout->getId() + ".open";
state->emitEvent(state->getMainThread(), name, [=] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [=] (lua_State* L) {
for (const auto& value : *argsptr) { for (const auto& value : *argsptr) {
lua::pushvalue(L, value); lua::pushvalue(L, value);
} }
@ -247,7 +241,7 @@ void scripting::on_ui_open(
void scripting::on_ui_progress(UiDocument* layout, int workDone, int workTotal) { void scripting::on_ui_progress(UiDocument* layout, int workDone, int workTotal) {
std::string name = layout->getId() + ".progress"; std::string name = layout->getId() + ".progress";
state->emitEvent(state->getMainThread(), name, [=] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [=] (lua_State* L) {
lua::pushinteger(L, workDone); lua::pushinteger(L, workDone);
lua::pushinteger(L, workTotal); lua::pushinteger(L, workTotal);
return 2; return 2;
@ -256,13 +250,13 @@ void scripting::on_ui_progress(UiDocument* layout, int workDone, int workTotal)
void scripting::on_ui_close(UiDocument* layout, Inventory* inventory) { void scripting::on_ui_close(UiDocument* layout, Inventory* inventory) {
std::string name = layout->getId() + ".close"; std::string name = layout->getId() + ".close";
state->emitEvent(state->getMainThread(), name, [inventory] (lua_State* L) { lua::emit_event(lua::get_main_thread(), name, [inventory] (lua_State* L) {
return lua::pushinteger(L, inventory ? inventory->getId() : 0); return lua::pushinteger(L, inventory ? inventory->getId() : 0);
}); });
} }
bool scripting::register_event(int env, const std::string& name, const std::string& id) { bool scripting::register_event(int env, const std::string& name, const std::string& id) {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
if (lua::pushenv(L, env) == 0) { if (lua::pushenv(L, env) == 0) {
lua::pushglobals(L); lua::pushglobals(L);
} }
@ -287,7 +281,7 @@ void scripting::load_block_script(const scriptenv& senv, const std::string& pref
int env = *senv; int env = *senv;
std::string src = files::read_string(file); std::string src = files::read_string(file);
logger.info() << "script (block) " << file.u8string(); logger.info() << "script (block) " << file.u8string();
lua::execute(state->getMainThread(), env, src, file.u8string()); lua::execute(lua::get_main_thread(), env, src, file.u8string());
funcsset.init = register_event(env, "init", prefix+".init"); funcsset.init = register_event(env, "init", prefix+".init");
funcsset.update = register_event(env, "on_update", prefix+".update"); funcsset.update = register_event(env, "on_update", prefix+".update");
funcsset.randupdate = register_event(env, "on_random_update", prefix+".randupdate"); funcsset.randupdate = register_event(env, "on_random_update", prefix+".randupdate");
@ -301,7 +295,7 @@ void scripting::load_item_script(const scriptenv& senv, const std::string& prefi
int env = *senv; int env = *senv;
std::string src = files::read_string(file); std::string src = files::read_string(file);
logger.info() << "script (item) " << file.u8string(); logger.info() << "script (item) " << file.u8string();
lua::execute(state->getMainThread(), env, src, file.u8string()); lua::execute(lua::get_main_thread(), env, src, file.u8string());
funcsset.init = register_event(env, "init", prefix+".init"); funcsset.init = register_event(env, "init", prefix+".init");
funcsset.on_use = register_event(env, "on_use", prefix+".use"); funcsset.on_use = register_event(env, "on_use", prefix+".use");
@ -314,7 +308,7 @@ void scripting::load_world_script(const scriptenv& senv, const std::string& pref
std::string src = files::read_string(file); std::string src = files::read_string(file);
logger.info() << "loading world script for " << prefix; logger.info() << "loading world script for " << prefix;
lua::execute(state->getMainThread(), env, src, file.u8string()); lua::execute(lua::get_main_thread(), env, src, file.u8string());
register_event(env, "init", prefix+".init"); register_event(env, "init", prefix+".init");
register_event(env, "on_world_open", prefix+".worldopen"); register_event(env, "on_world_open", prefix+".worldopen");
@ -329,16 +323,14 @@ void scripting::load_layout_script(const scriptenv& senv, const std::string& pre
std::string src = files::read_string(file); std::string src = files::read_string(file);
logger.info() << "loading script " << file.u8string(); logger.info() << "loading script " << file.u8string();
lua::execute(state->getMainThread(), env, src, file.u8string()); lua::execute(lua::get_main_thread(), env, src, file.u8string());
script.onopen = register_event(env, "on_open", prefix+".open"); script.onopen = register_event(env, "on_open", prefix+".open");
script.onprogress = register_event(env, "on_progress", prefix+".progress"); script.onprogress = register_event(env, "on_progress", prefix+".progress");
script.onclose = register_event(env, "on_close", prefix+".close"); script.onclose = register_event(env, "on_close", prefix+".close");
} }
void scripting::close() { void scripting::close() {
delete state; lua::finalize();
state = nullptr;
content = nullptr; content = nullptr;
indices = nullptr; indices = nullptr;
level = nullptr; level = nullptr;

View File

@ -1,13 +1,9 @@
#include "scripting_functional.hpp" #include "scripting_functional.hpp"
#include "lua/lua_util.hpp" #include "lua/lua_engine.hpp"
#include "lua/LuaState.hpp"
#include "../../debug/Logger.hpp" #include "../../debug/Logger.hpp"
#include "../../util/stringutil.hpp" #include "../../util/stringutil.hpp"
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting; using namespace scripting;
static debug::Logger logger("scripting_func"); static debug::Logger logger("scripting_func");
@ -17,7 +13,7 @@ runnable scripting::create_runnable(
const std::string& src, const std::string& src,
const std::string& file const std::string& file
) { ) {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
try { try {
lua::loadbuffer(L, *env, src, file); lua::loadbuffer(L, *env, src, file);
return lua::create_runnable(L); return lua::create_runnable(L);
@ -27,12 +23,12 @@ runnable scripting::create_runnable(
} }
} }
static lua_State* processCallback( static lua_State* process_callback(
const scriptenv& env, const scriptenv& env,
const std::string& src, const std::string& src,
const std::string& file const std::string& file
) { ) {
auto L = state->getMainThread(); auto L = lua::get_main_thread();
try { try {
if (lua::eval(L, *env, src, file) != 0) { if (lua::eval(L, *env, src, file) != 0) {
return L; return L;
@ -49,7 +45,7 @@ wstringconsumer scripting::create_wstring_consumer(
const std::string& file const std::string& file
) { ) {
return [=](const std::wstring& x){ return [=](const std::wstring& x){
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
lua::pushwstring(L, x); lua::pushwstring(L, x);
lua::call_nothrow(L, 1); lua::call_nothrow(L, 1);
} }
@ -62,11 +58,11 @@ wstringsupplier scripting::create_wstring_supplier(
const std::string& file const std::string& file
) { ) {
return [=](){ return [=](){
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
if (lua_isfunction(L, -1)) { if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0); lua::call_nothrow(L, 0);
} }
auto str = lua::require_wstring(L, -1); lua_pop(L, 1); auto str = lua::require_wstring(L, -1); lua::pop(L);
return str; return str;
} }
return std::wstring(L""); return std::wstring(L"");
@ -79,7 +75,7 @@ wstringchecker scripting::create_wstring_validator(
const std::string& file const std::string& file
) { ) {
return [=](const std::wstring& x){ return [=](const std::wstring& x){
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
lua::pushwstring(L, x); lua::pushwstring(L, x);
if (lua::call_nothrow(L, 1)) if (lua::call_nothrow(L, 1))
return lua::toboolean(L, -1); return lua::toboolean(L, -1);
@ -94,7 +90,7 @@ boolconsumer scripting::create_bool_consumer(
const std::string& file const std::string& file
) { ) {
return [=](bool x){ return [=](bool x){
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
lua::pushboolean(L, x); lua::pushboolean(L, x);
lua::call_nothrow(L, 1); lua::call_nothrow(L, 1);
} }
@ -107,11 +103,11 @@ boolsupplier scripting::create_bool_supplier(
const std::string& file const std::string& file
) { ) {
return [=](){ return [=](){
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
if (lua_isfunction(L, -1)) { if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0); lua::call_nothrow(L, 0);
} }
bool x = lua::toboolean(L,-1); lua_pop(L, 1); bool x = lua::toboolean(L,-1); lua::pop(L);
return x; return x;
} }
return false; return false;
@ -124,7 +120,7 @@ doubleconsumer scripting::create_number_consumer(
const std::string& file const std::string& file
) { ) {
return [=](double x){ return [=](double x){
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
lua::pushnumber(L, x); lua::pushnumber(L, x);
lua::call_nothrow(L, 1); lua::call_nothrow(L, 1);
} }
@ -137,11 +133,11 @@ doublesupplier scripting::create_number_supplier(
const std::string& file const std::string& file
) { ) {
return [=](){ return [=](){
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
if (lua_isfunction(L, -1)) { if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0); lua::call_nothrow(L, 0);
} }
auto x = lua_tonumber(L, -1); auto x = lua::tonumber(L, -1);
lua::pop(L); lua::pop(L);
return x; return x;
} }
@ -155,7 +151,7 @@ int_array_consumer scripting::create_int_array_consumer(
const std::string& file const std::string& file
) { ) {
return [=](const int arr[], size_t len) { return [=](const int arr[], size_t len) {
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
for (uint i = 0; i < len; i++) { for (uint i = 0; i < len; i++) {
lua::pushinteger(L, arr[i]); lua::pushinteger(L, arr[i]);
} }
@ -170,12 +166,12 @@ vec2supplier scripting::create_vec2_supplier(
const std::string& file const std::string& file
) { ) {
return [=]() { return [=]() {
if (auto L = processCallback(env, src, file)) { if (auto L = process_callback(env, src, file)) {
if (lua_isfunction(L, -1)) { if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0); lua::call_nothrow(L, 0);
} }
auto y = lua_tonumber(L, -1); lua::pop(L); auto y = lua::tonumber(L, -1); lua::pop(L);
auto x = lua_tonumber(L, -1); lua::pop(L); auto x = lua::tonumber(L, -1); lua::pop(L);
return glm::vec2(x, y); return glm::vec2(x, y);
} }
return glm::vec2(0, 0); return glm::vec2(0, 0);

View File

@ -1,9 +1,8 @@
#include "scripting_hud.hpp" #include "scripting_hud.hpp"
#include "scripting.hpp" #include "scripting.hpp"
#include "lua/lua_util.hpp"
#include "lua/api_lua.hpp" #include "lua/api_lua.hpp"
#include "lua/LuaState.hpp" #include "lua/lua_engine.hpp"
#include "../../debug/Logger.hpp" #include "../../debug/Logger.hpp"
#include "../../frontend/hud.hpp" #include "../../frontend/hud.hpp"
@ -11,9 +10,6 @@
#include "../../files/files.hpp" #include "../../files/files.hpp"
#include "../../engine.hpp" #include "../../engine.hpp"
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting; using namespace scripting;
static debug::Logger logger("scripting-hud"); static debug::Logger logger("scripting-hud");
@ -22,10 +18,10 @@ Hud* scripting::hud = nullptr;
void scripting::on_frontend_init(Hud* hud) { void scripting::on_frontend_init(Hud* hud) {
scripting::hud = hud; scripting::hud = hud;
state->openlib(state->getMainThread(), "hud", hudlib); lua::openlib(lua::get_main_thread(), "hud", hudlib);
for (auto& pack : engine->getContentPacks()) { for (auto& pack : engine->getContentPacks()) {
state->emitEvent(state->getMainThread(), pack.id + ".hudopen", lua::emit_event(lua::get_main_thread(), pack.id + ".hudopen",
[&] (lua_State* L) { [&] (lua_State* L) {
return lua::pushinteger(L, hud->getPlayer()->getId()); return lua::pushinteger(L, hud->getPlayer()->getId());
}); });
@ -34,7 +30,7 @@ void scripting::on_frontend_init(Hud* hud) {
void scripting::on_frontend_close() { void scripting::on_frontend_close() {
for (auto& pack : engine->getContentPacks()) { for (auto& pack : engine->getContentPacks()) {
state->emitEvent(state->getMainThread(), pack.id + ".hudclose", lua::emit_event(lua::get_main_thread(), pack.id + ".hudclose",
[&] (lua_State* L) { [&] (lua_State* L) {
return lua::pushinteger(L, hud->getPlayer()->getId()); return lua::pushinteger(L, hud->getPlayer()->getId());
}); });
@ -47,7 +43,7 @@ void scripting::load_hud_script(const scriptenv& senv, const std::string& packid
std::string src = files::read_string(file); std::string src = files::read_string(file);
logger.info() << "loading script " << file.u8string(); logger.info() << "loading script " << file.u8string();
lua::execute(state->getMainThread(), env, src, file.u8string()); lua::execute(lua::get_main_thread(), env, src, file.u8string());
register_event(env, "init", packid+".init"); register_event(env, "init", packid+".init");
register_event(env, "on_hud_open", packid+".hudopen"); register_event(env, "on_hud_open", packid+".hudopen");