Add files via upload
This commit is contained in:
parent
2e17095765
commit
37b8dd27e1
21
src/script/CMakeLists.txt
Normal file
21
src/script/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(cpp_api)
|
||||
add_subdirectory(lua_api)
|
||||
|
||||
# Used by server and client
|
||||
set(common_SCRIPT_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scripting_server.cpp
|
||||
${common_SCRIPT_COMMON_SRCS}
|
||||
${common_SCRIPT_CPP_API_SRCS}
|
||||
${common_SCRIPT_LUA_API_SRCS}
|
||||
PARENT_SCOPE)
|
||||
|
||||
# Used by client only
|
||||
set(client_SCRIPT_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scripting_mainmenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scripting_client.cpp
|
||||
${client_SCRIPT_COMMON_SRCS}
|
||||
${client_SCRIPT_CPP_API_SRCS}
|
||||
${client_SCRIPT_LUA_API_SRCS}
|
||||
PARENT_SCOPE)
|
||||
|
41
src/script/lua_api/CMakeLists.txt
Normal file
41
src/script/lua_api/CMakeLists.txt
Normal file
@ -0,0 +1,41 @@
|
||||
set(common_SCRIPT_LUA_API_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_areastore.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_auth.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_base.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_craft.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_http.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_inventoryaction.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_metadata.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_modchannels.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_nodetimer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_object.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_particles.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_playermeta.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_rollback.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_util.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_vmanip.cpp
|
||||
PARENT_SCOPE)
|
||||
|
||||
set(client_SCRIPT_LUA_API_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_clientobject.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_inventoryaction.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_particles_local.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l_clientobject.cpp
|
||||
PARENT_SCOPE)
|
396
src/script/lua_api/l_areastore.cpp
Normal file
396
src/script/lua_api/l_areastore.cpp
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2015 est31 <mtest31@outlook.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "lua_api/l_areastore.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "cpp_api/s_security.h"
|
||||
#include "irr_v3d.h"
|
||||
#include "util/areastore.h"
|
||||
#include "filesys.h"
|
||||
#include <fstream>
|
||||
|
||||
static inline void get_data_and_border_flags(lua_State *L, u8 start_i,
|
||||
bool *borders, bool *data)
|
||||
{
|
||||
if (!lua_isboolean(L, start_i))
|
||||
return;
|
||||
*borders = lua_toboolean(L, start_i);
|
||||
if (!lua_isboolean(L, start_i + 1))
|
||||
return;
|
||||
*data = lua_toboolean(L, start_i + 1);
|
||||
}
|
||||
|
||||
static void push_area(lua_State *L, const Area *a,
|
||||
bool include_borders, bool include_data)
|
||||
{
|
||||
if (!include_borders && !include_data) {
|
||||
lua_pushboolean(L, true);
|
||||
return;
|
||||
}
|
||||
lua_newtable(L);
|
||||
if (include_borders) {
|
||||
push_v3s16(L, a->minedge);
|
||||
lua_setfield(L, -2, "min");
|
||||
push_v3s16(L, a->maxedge);
|
||||
lua_setfield(L, -2, "max");
|
||||
}
|
||||
if (include_data) {
|
||||
lua_pushlstring(L, a->data.c_str(), a->data.size());
|
||||
lua_setfield(L, -2, "data");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void push_areas(lua_State *L, const std::vector<Area *> &areas,
|
||||
bool borders, bool data)
|
||||
{
|
||||
lua_newtable(L);
|
||||
size_t cnt = areas.size();
|
||||
for (size_t i = 0; i < cnt; i++) {
|
||||
lua_pushnumber(L, areas[i]->id);
|
||||
push_area(L, areas[i], borders, data);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
|
||||
// Deserializes value and handles errors
|
||||
static int deserialization_helper(lua_State *L, AreaStore *as,
|
||||
std::istream &is)
|
||||
{
|
||||
try {
|
||||
as->deserialize(is);
|
||||
} catch (const SerializationError &e) {
|
||||
lua_pushboolean(L, false);
|
||||
lua_pushstring(L, e.what());
|
||||
return 2;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// garbage collector
|
||||
int LuaAreaStore::gc_object(lua_State *L)
|
||||
{
|
||||
LuaAreaStore *o = *(LuaAreaStore **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_area(id, include_borders, include_data)
|
||||
int LuaAreaStore::l_get_area(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
u32 id = luaL_checknumber(L, 2);
|
||||
|
||||
bool include_borders = true;
|
||||
bool include_data = false;
|
||||
get_data_and_border_flags(L, 3, &include_borders, &include_data);
|
||||
|
||||
const Area *res;
|
||||
|
||||
res = ast->getArea(id);
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
push_area(L, res, include_borders, include_data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_areas_for_pos(pos, include_borders, include_data)
|
||||
int LuaAreaStore::l_get_areas_for_pos(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
v3s16 pos = check_v3s16(L, 2);
|
||||
|
||||
bool include_borders = true;
|
||||
bool include_data = false;
|
||||
get_data_and_border_flags(L, 3, &include_borders, &include_data);
|
||||
|
||||
std::vector<Area *> res;
|
||||
|
||||
ast->getAreasForPos(&res, pos);
|
||||
push_areas(L, res, include_borders, include_data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_areas_in_area(edge1, edge2, accept_overlap, include_borders, include_data)
|
||||
int LuaAreaStore::l_get_areas_in_area(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
v3s16 minedge = check_v3s16(L, 2);
|
||||
v3s16 maxedge = check_v3s16(L, 3);
|
||||
|
||||
bool include_borders = true;
|
||||
bool include_data = false;
|
||||
bool accept_overlap = false;
|
||||
if (lua_isboolean(L, 4)) {
|
||||
accept_overlap = readParam<bool>(L, 4);
|
||||
get_data_and_border_flags(L, 5, &include_borders, &include_data);
|
||||
}
|
||||
std::vector<Area *> res;
|
||||
|
||||
ast->getAreasInArea(&res, minedge, maxedge, accept_overlap);
|
||||
push_areas(L, res, include_borders, include_data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// insert_area(edge1, edge2, data, id)
|
||||
int LuaAreaStore::l_insert_area(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
Area a(check_v3s16(L, 2), check_v3s16(L, 3));
|
||||
|
||||
size_t d_len;
|
||||
const char *data = luaL_checklstring(L, 4, &d_len);
|
||||
|
||||
a.data = std::string(data, d_len);
|
||||
|
||||
if (lua_isnumber(L, 5))
|
||||
a.id = lua_tonumber(L, 5);
|
||||
|
||||
// Insert & assign a new ID if necessary
|
||||
if (!ast->insertArea(&a))
|
||||
return 0;
|
||||
|
||||
lua_pushnumber(L, a.id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// reserve(count)
|
||||
int LuaAreaStore::l_reserve(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
size_t count = luaL_checknumber(L, 2);
|
||||
ast->reserve(count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// remove_area(id)
|
||||
int LuaAreaStore::l_remove_area(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
u32 id = luaL_checknumber(L, 2);
|
||||
bool success = ast->removeArea(id);
|
||||
|
||||
lua_pushboolean(L, success);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_cache_params(params)
|
||||
int LuaAreaStore::l_set_cache_params(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
|
||||
bool enabled = getboolfield_default(L, 2, "enabled", true);
|
||||
u8 block_radius = getintfield_default(L, 2, "block_radius", 64);
|
||||
size_t limit = getintfield_default(L, 2, "block_radius", 1000);
|
||||
|
||||
ast->setCacheParams(enabled, block_radius, limit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// to_string()
|
||||
int LuaAreaStore::l_to_string(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
o->as->serialize(os);
|
||||
std::string str = os.str();
|
||||
|
||||
lua_pushlstring(L, str.c_str(), str.length());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// to_file(filename)
|
||||
int LuaAreaStore::l_to_file(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
AreaStore *ast = o->as;
|
||||
|
||||
const char *filename = luaL_checkstring(L, 2);
|
||||
CHECK_SECURE_PATH(L, filename, true);
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
ast->serialize(os);
|
||||
|
||||
lua_pushboolean(L, fs::safeWriteToFile(filename, os.str()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// from_string(str)
|
||||
int LuaAreaStore::l_from_string(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
|
||||
size_t len;
|
||||
const char *str = luaL_checklstring(L, 2, &len);
|
||||
|
||||
std::istringstream is(std::string(str, len), std::ios::binary);
|
||||
return deserialization_helper(L, o->as, is);
|
||||
}
|
||||
|
||||
// from_file(filename)
|
||||
int LuaAreaStore::l_from_file(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = checkobject(L, 1);
|
||||
|
||||
const char *filename = luaL_checkstring(L, 2);
|
||||
CHECK_SECURE_PATH(L, filename, false);
|
||||
|
||||
std::ifstream is(filename, std::ios::binary);
|
||||
return deserialization_helper(L, o->as, is);
|
||||
}
|
||||
|
||||
LuaAreaStore::LuaAreaStore() : as(AreaStore::getOptimalImplementation())
|
||||
{
|
||||
}
|
||||
|
||||
LuaAreaStore::LuaAreaStore(const std::string &type)
|
||||
{
|
||||
#if USE_SPATIAL
|
||||
if (type == "LibSpatial") {
|
||||
as = new SpatialAreaStore();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
as = new VectorAreaStore();
|
||||
}
|
||||
}
|
||||
|
||||
LuaAreaStore::~LuaAreaStore()
|
||||
{
|
||||
delete as;
|
||||
}
|
||||
|
||||
// LuaAreaStore()
|
||||
// Creates an LuaAreaStore and leaves it on top of stack
|
||||
int LuaAreaStore::create_object(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaAreaStore *o = (lua_isstring(L, 1)) ?
|
||||
new LuaAreaStore(readParam<std::string>(L, 1)) :
|
||||
new LuaAreaStore();
|
||||
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaAreaStore *LuaAreaStore::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(LuaAreaStore **)ud; // unbox pointer
|
||||
}
|
||||
|
||||
void LuaAreaStore::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
|
||||
// Can be created from Lua (AreaStore())
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char LuaAreaStore::className[] = "AreaStore";
|
||||
const luaL_Reg LuaAreaStore::methods[] = {
|
||||
luamethod(LuaAreaStore, get_area),
|
||||
luamethod(LuaAreaStore, get_areas_for_pos),
|
||||
luamethod(LuaAreaStore, get_areas_in_area),
|
||||
luamethod(LuaAreaStore, insert_area),
|
||||
luamethod(LuaAreaStore, reserve),
|
||||
luamethod(LuaAreaStore, remove_area),
|
||||
luamethod(LuaAreaStore, set_cache_params),
|
||||
luamethod(LuaAreaStore, to_string),
|
||||
luamethod(LuaAreaStore, to_file),
|
||||
luamethod(LuaAreaStore, from_string),
|
||||
luamethod(LuaAreaStore, from_file),
|
||||
{0,0}
|
||||
};
|
64
src/script/lua_api/l_areastore.h
Normal file
64
src/script/lua_api/l_areastore.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2015 est31 <mtest31@outlook.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class AreaStore;
|
||||
|
||||
class LuaAreaStore : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static int l_get_area(lua_State *L);
|
||||
|
||||
static int l_get_areas_for_pos(lua_State *L);
|
||||
static int l_get_areas_in_area(lua_State *L);
|
||||
static int l_insert_area(lua_State *L);
|
||||
static int l_reserve(lua_State *L);
|
||||
static int l_remove_area(lua_State *L);
|
||||
|
||||
static int l_set_cache_params(lua_State *L);
|
||||
|
||||
static int l_to_string(lua_State *L);
|
||||
static int l_to_file(lua_State *L);
|
||||
|
||||
static int l_from_string(lua_State *L);
|
||||
static int l_from_file(lua_State *L);
|
||||
|
||||
public:
|
||||
AreaStore *as = nullptr;
|
||||
|
||||
LuaAreaStore();
|
||||
LuaAreaStore(const std::string &type);
|
||||
~LuaAreaStore();
|
||||
|
||||
// AreaStore()
|
||||
// Creates a AreaStore and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaAreaStore *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
216
src/script/lua_api/l_auth.cpp
Normal file
216
src/script/lua_api/l_auth.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2018 bendeutsch, Ben Deutsch <ben@bendeutsch.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_auth.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "cpp_api/s_base.h"
|
||||
#include "server.h"
|
||||
#include "environment.h"
|
||||
#include "database/database.h"
|
||||
#include <algorithm>
|
||||
|
||||
// common start: ensure auth db
|
||||
AuthDatabase *ModApiAuth::getAuthDb(lua_State *L)
|
||||
{
|
||||
ServerEnvironment *server_environment =
|
||||
dynamic_cast<ServerEnvironment *>(getEnv(L));
|
||||
if (!server_environment)
|
||||
return nullptr;
|
||||
return server_environment->getAuthDatabase();
|
||||
}
|
||||
|
||||
void ModApiAuth::pushAuthEntry(lua_State *L, const AuthEntry &authEntry)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int table = lua_gettop(L);
|
||||
// id
|
||||
lua_pushnumber(L, authEntry.id);
|
||||
lua_setfield(L, table, "id");
|
||||
// name
|
||||
lua_pushstring(L, authEntry.name.c_str());
|
||||
lua_setfield(L, table, "name");
|
||||
// password
|
||||
lua_pushstring(L, authEntry.password.c_str());
|
||||
lua_setfield(L, table, "password");
|
||||
// privileges
|
||||
lua_newtable(L);
|
||||
int privtable = lua_gettop(L);
|
||||
for (const std::string &privs : authEntry.privileges) {
|
||||
lua_pushboolean(L, true);
|
||||
lua_setfield(L, privtable, privs.c_str());
|
||||
}
|
||||
lua_setfield(L, table, "privileges");
|
||||
// last_login
|
||||
lua_pushnumber(L, authEntry.last_login);
|
||||
lua_setfield(L, table, "last_login");
|
||||
|
||||
lua_pushvalue(L, table);
|
||||
}
|
||||
|
||||
// auth_read(name)
|
||||
int ModApiAuth::l_auth_read(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
AuthDatabase *auth_db = getAuthDb(L);
|
||||
if (!auth_db)
|
||||
return 0;
|
||||
AuthEntry authEntry;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
bool success = auth_db->getAuth(std::string(name), authEntry);
|
||||
if (!success)
|
||||
return 0;
|
||||
|
||||
pushAuthEntry(L, authEntry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// auth_save(table)
|
||||
int ModApiAuth::l_auth_save(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
AuthDatabase *auth_db = getAuthDb(L);
|
||||
if (!auth_db)
|
||||
return 0;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int table = 1;
|
||||
AuthEntry authEntry;
|
||||
bool success;
|
||||
success = getintfield(L, table, "id", authEntry.id);
|
||||
success = success && getstringfield(L, table, "name", authEntry.name);
|
||||
success = success && getstringfield(L, table, "password", authEntry.password);
|
||||
lua_getfield(L, table, "privileges");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
authEntry.privileges.emplace_back(
|
||||
lua_tostring(L, -2)); // the key, not the value
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
lua_pop(L, 1); // the table
|
||||
success = success && getintfield(L, table, "last_login", authEntry.last_login);
|
||||
|
||||
if (!success) {
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, auth_db->saveAuth(authEntry));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// auth_create(table)
|
||||
int ModApiAuth::l_auth_create(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
AuthDatabase *auth_db = getAuthDb(L);
|
||||
if (!auth_db)
|
||||
return 0;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int table = 1;
|
||||
AuthEntry authEntry;
|
||||
bool success;
|
||||
// no meaningful id field, we assume
|
||||
success = getstringfield(L, table, "name", authEntry.name);
|
||||
success = success && getstringfield(L, table, "password", authEntry.password);
|
||||
lua_getfield(L, table, "privileges");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
authEntry.privileges.emplace_back(
|
||||
lua_tostring(L, -2)); // the key, not the value
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
lua_pop(L, 1); // the table
|
||||
success = success && getintfield(L, table, "last_login", authEntry.last_login);
|
||||
|
||||
if (!success)
|
||||
return 0;
|
||||
|
||||
if (auth_db->createAuth(authEntry)) {
|
||||
pushAuthEntry(L, authEntry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// auth_delete(name)
|
||||
int ModApiAuth::l_auth_delete(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
AuthDatabase *auth_db = getAuthDb(L);
|
||||
if (!auth_db)
|
||||
return 0;
|
||||
std::string name(luaL_checkstring(L, 1));
|
||||
lua_pushboolean(L, auth_db->deleteAuth(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// auth_list_names()
|
||||
int ModApiAuth::l_auth_list_names(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
AuthDatabase *auth_db = getAuthDb(L);
|
||||
if (!auth_db)
|
||||
return 0;
|
||||
std::vector<std::string> names;
|
||||
auth_db->listNames(names);
|
||||
lua_createtable(L, names.size(), 0);
|
||||
int table = lua_gettop(L);
|
||||
int i = 1;
|
||||
for (const std::string &name : names) {
|
||||
lua_pushstring(L, name.c_str());
|
||||
lua_rawseti(L, table, i++);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// auth_reload()
|
||||
int ModApiAuth::l_auth_reload(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
AuthDatabase *auth_db = getAuthDb(L);
|
||||
if (auth_db)
|
||||
auth_db->reload();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ModApiAuth::Initialize(lua_State *L, int top)
|
||||
{
|
||||
|
||||
lua_newtable(L);
|
||||
int auth_top = lua_gettop(L);
|
||||
|
||||
registerFunction(L, "read", l_auth_read, auth_top);
|
||||
registerFunction(L, "save", l_auth_save, auth_top);
|
||||
registerFunction(L, "create", l_auth_create, auth_top);
|
||||
registerFunction(L, "delete", l_auth_delete, auth_top);
|
||||
registerFunction(L, "list_names", l_auth_list_names, auth_top);
|
||||
registerFunction(L, "reload", l_auth_reload, auth_top);
|
||||
|
||||
lua_setfield(L, top, "auth");
|
||||
}
|
54
src/script/lua_api/l_auth.h
Normal file
54
src/script/lua_api/l_auth.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2018 bendeutsch, Ben Deutsch <ben@bendeutsch.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class AuthDatabase;
|
||||
struct AuthEntry;
|
||||
|
||||
class ModApiAuth : public ModApiBase
|
||||
{
|
||||
private:
|
||||
// auth_read(name)
|
||||
static int l_auth_read(lua_State *L);
|
||||
|
||||
// auth_save(table)
|
||||
static int l_auth_save(lua_State *L);
|
||||
|
||||
// auth_create(table)
|
||||
static int l_auth_create(lua_State *L);
|
||||
|
||||
// auth_delete(name)
|
||||
static int l_auth_delete(lua_State *L);
|
||||
|
||||
// auth_list_names()
|
||||
static int l_auth_list_names(lua_State *L);
|
||||
|
||||
// auth_reload()
|
||||
static int l_auth_reload(lua_State *L);
|
||||
|
||||
// helper for auth* methods
|
||||
static AuthDatabase *getAuthDb(lua_State *L);
|
||||
static void pushAuthEntry(lua_State *L, const AuthEntry &authEntry);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
144
src/script/lua_api/l_base.cpp
Normal file
144
src/script/lua_api/l_base.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "cpp_api/s_base.h"
|
||||
#include "content/mods.h"
|
||||
#include "profiler.h"
|
||||
#include "server.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
ScriptApiBase *ModApiBase::getScriptApiBase(lua_State *L)
|
||||
{
|
||||
// Get server from registry
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
|
||||
ScriptApiBase *sapi_ptr;
|
||||
#if INDIRECT_SCRIPTAPI_RIDX
|
||||
sapi_ptr = (ScriptApiBase*) *(void**)(lua_touserdata(L, -1));
|
||||
#else
|
||||
sapi_ptr = (ScriptApiBase*) lua_touserdata(L, -1);
|
||||
#endif
|
||||
lua_pop(L, 1);
|
||||
return sapi_ptr;
|
||||
}
|
||||
|
||||
Server *ModApiBase::getServer(lua_State *L)
|
||||
{
|
||||
return getScriptApiBase(L)->getServer();
|
||||
}
|
||||
|
||||
ServerInventoryManager *ModApiBase::getServerInventoryMgr(lua_State *L)
|
||||
{
|
||||
return getScriptApiBase(L)->getServer()->getInventoryMgr();
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
Client *ModApiBase::getClient(lua_State *L)
|
||||
{
|
||||
return getScriptApiBase(L)->getClient();
|
||||
}
|
||||
|
||||
Game *ModApiBase::getGame(lua_State *L)
|
||||
{
|
||||
return getScriptApiBase(L)->getGame();
|
||||
}
|
||||
#endif
|
||||
|
||||
IGameDef *ModApiBase::getGameDef(lua_State *L)
|
||||
{
|
||||
return getScriptApiBase(L)->getGameDef();
|
||||
}
|
||||
|
||||
Environment *ModApiBase::getEnv(lua_State *L)
|
||||
{
|
||||
return getScriptApiBase(L)->getEnv();
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
GUIEngine *ModApiBase::getGuiEngine(lua_State *L)
|
||||
{
|
||||
return getScriptApiBase(L)->getGuiEngine();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string ModApiBase::getCurrentModPath(lua_State *L)
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
std::string current_mod_name = readParam<std::string>(L, -1, "");
|
||||
if (current_mod_name.empty())
|
||||
return ".";
|
||||
|
||||
const ModSpec *mod = getServer(L)->getModSpec(current_mod_name);
|
||||
if (!mod)
|
||||
return ".";
|
||||
|
||||
return mod->path;
|
||||
}
|
||||
|
||||
|
||||
bool ModApiBase::registerFunction(lua_State *L, const char *name,
|
||||
lua_CFunction func, int top)
|
||||
{
|
||||
// TODO: Check presence first!
|
||||
|
||||
lua_pushcfunction(L, func);
|
||||
lua_setfield(L, top, name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int ModApiBase::l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func)
|
||||
{
|
||||
thread_local std::vector<u64> deprecated_logged;
|
||||
|
||||
DeprecatedHandlingMode dep_mode = get_deprecated_handling_mode();
|
||||
if (dep_mode == DeprecatedHandlingMode::Ignore)
|
||||
return func(L);
|
||||
|
||||
u64 start_time = porting::getTimeUs();
|
||||
lua_Debug ar;
|
||||
|
||||
// Get caller name with line and script backtrace
|
||||
FATAL_ERROR_IF(!lua_getstack(L, 1, &ar), "lua_getstack() failed");
|
||||
FATAL_ERROR_IF(!lua_getinfo(L, "Sl", &ar), "lua_getinfo() failed");
|
||||
|
||||
// Get backtrace and hash it to reduce the warning flood
|
||||
std::string backtrace = ar.short_src;
|
||||
backtrace.append(":").append(std::to_string(ar.currentline));
|
||||
u64 hash = murmur_hash_64_ua(backtrace.data(), backtrace.length(), 0xBADBABE);
|
||||
|
||||
if (std::find(deprecated_logged.begin(), deprecated_logged.end(), hash)
|
||||
== deprecated_logged.end()) {
|
||||
|
||||
deprecated_logged.emplace_back(hash);
|
||||
warningstream << "Call to deprecated function '" << bad << "', please use '"
|
||||
<< good << "' at " << backtrace << std::endl;
|
||||
|
||||
if (dep_mode == DeprecatedHandlingMode::Error)
|
||||
script_error(L, LUA_ERRRUN, NULL, NULL);
|
||||
}
|
||||
|
||||
u64 end_time = porting::getTimeUs();
|
||||
g_profiler->avg("l_deprecated_function", end_time - start_time);
|
||||
|
||||
return func(L);
|
||||
}
|
||||
|
92
src/script/lua_api/l_base.h
Normal file
92
src/script/lua_api/l_base.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/c_types.h"
|
||||
#include "common/c_internal.h"
|
||||
#include "common/helper.h"
|
||||
#include "gamedef.h"
|
||||
#include <unordered_map>
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
class Client;
|
||||
class Game;
|
||||
class GUIEngine;
|
||||
#endif
|
||||
|
||||
class ScriptApiBase;
|
||||
class Server;
|
||||
class Environment;
|
||||
class ServerInventoryManager;
|
||||
|
||||
class ModApiBase : protected LuaHelper {
|
||||
public:
|
||||
static ScriptApiBase* getScriptApiBase(lua_State *L);
|
||||
static Server* getServer(lua_State *L);
|
||||
static ServerInventoryManager *getServerInventoryMgr(lua_State *L);
|
||||
#ifndef SERVER
|
||||
static Client* getClient(lua_State *L);
|
||||
static Game* getGame(lua_State *L);
|
||||
static GUIEngine* getGuiEngine(lua_State *L);
|
||||
#endif // !SERVER
|
||||
|
||||
static IGameDef* getGameDef(lua_State *L);
|
||||
static Environment* getEnv(lua_State *L);
|
||||
|
||||
// When we are not loading the mod, this function returns "."
|
||||
static std::string getCurrentModPath(lua_State *L);
|
||||
|
||||
// Get an arbitrary subclass of ScriptApiBase
|
||||
// by using dynamic_cast<> on getScriptApiBase()
|
||||
template<typename T>
|
||||
static T* getScriptApi(lua_State *L) {
|
||||
ScriptApiBase *scriptIface = getScriptApiBase(L);
|
||||
T *scriptIfaceDowncast = dynamic_cast<T*>(scriptIface);
|
||||
if (!scriptIfaceDowncast) {
|
||||
throw LuaError("Requested unavailable ScriptApi - core engine bug!");
|
||||
}
|
||||
return scriptIfaceDowncast;
|
||||
}
|
||||
|
||||
static bool registerFunction(lua_State *L,
|
||||
const char* name,
|
||||
lua_CFunction func,
|
||||
int top);
|
||||
|
||||
/**
|
||||
* A wrapper for deprecated functions.
|
||||
*
|
||||
* When called, handles the deprecation according to user settings and then calls `func`.
|
||||
*
|
||||
* @throws Lua Error if required by the user settings.
|
||||
*
|
||||
* @param L Lua state
|
||||
* @param good Name of good function/method
|
||||
* @param bad Name of deprecated function/method
|
||||
* @param func Actual implementation of function
|
||||
* @return value from `func`
|
||||
*/
|
||||
static int l_deprecated_function(lua_State *L, const char *good, const char *bad, lua_CFunction func);
|
||||
};
|
241
src/script/lua_api/l_camera.cpp
Normal file
241
src/script/lua_api/l_camera.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "l_camera.h"
|
||||
#include <cmath>
|
||||
#include "script/common/c_converter.h"
|
||||
#include "l_internal.h"
|
||||
#include "client/content_cao.h"
|
||||
#include "client/camera.h"
|
||||
#include "client/client.h"
|
||||
|
||||
LuaCamera::LuaCamera(Camera *m) : m_camera(m)
|
||||
{
|
||||
}
|
||||
|
||||
void LuaCamera::create(lua_State *L, Camera *m)
|
||||
{
|
||||
lua_getglobal(L, "core");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int objectstable = lua_gettop(L);
|
||||
lua_getfield(L, -1, "camera");
|
||||
|
||||
// Duplication check
|
||||
if (lua_type(L, -1) == LUA_TUSERDATA) {
|
||||
lua_pop(L, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
LuaCamera *o = new LuaCamera(m);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
lua_pushvalue(L, lua_gettop(L));
|
||||
lua_setfield(L, objectstable, "camera");
|
||||
}
|
||||
|
||||
// set_camera_mode(self, mode)
|
||||
int LuaCamera::l_set_camera_mode(lua_State *L)
|
||||
{
|
||||
Camera *camera = getobject(L, 1);
|
||||
GenericCAO *playercao = getClient(L)->getEnv().getLocalPlayer()->getCAO();
|
||||
if (!camera)
|
||||
return 0;
|
||||
sanity_check(playercao);
|
||||
if (!lua_isnumber(L, 2))
|
||||
return 0;
|
||||
|
||||
camera->setCameraMode((CameraMode)((int)lua_tonumber(L, 2)));
|
||||
// Make the player visible depending on camera mode.
|
||||
playercao->updateMeshCulling();
|
||||
playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_camera_mode(self)
|
||||
int LuaCamera::l_get_camera_mode(lua_State *L)
|
||||
{
|
||||
Camera *camera = getobject(L, 1);
|
||||
if (!camera)
|
||||
return 0;
|
||||
|
||||
lua_pushinteger(L, (int)camera->getCameraMode());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_fov(self)
|
||||
int LuaCamera::l_get_fov(lua_State *L)
|
||||
{
|
||||
Camera *camera = getobject(L, 1);
|
||||
if (!camera)
|
||||
return 0;
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushnumber(L, camera->getFovX() * core::RADTODEG);
|
||||
lua_setfield(L, -2, "x");
|
||||
lua_pushnumber(L, camera->getFovY() * core::RADTODEG);
|
||||
lua_setfield(L, -2, "y");
|
||||
lua_pushnumber(L, camera->getCameraNode()->getFOV() * core::RADTODEG);
|
||||
lua_setfield(L, -2, "actual");
|
||||
lua_pushnumber(L, camera->getFovMax() * core::RADTODEG);
|
||||
lua_setfield(L, -2, "max");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_pos(self)
|
||||
int LuaCamera::l_get_pos(lua_State *L)
|
||||
{
|
||||
Camera *camera = getobject(L, 1);
|
||||
if (!camera)
|
||||
return 0;
|
||||
|
||||
push_v3f(L, camera->getPosition() / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_offset(self)
|
||||
int LuaCamera::l_get_offset(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer();
|
||||
sanity_check(player);
|
||||
|
||||
push_v3f(L, player->getEyeOffset() / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_look_dir(self)
|
||||
int LuaCamera::l_get_look_dir(lua_State *L)
|
||||
{
|
||||
Camera *camera = getobject(L, 1);
|
||||
if (!camera)
|
||||
return 0;
|
||||
|
||||
push_v3f(L, camera->getDirection());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_look_horizontal(self)
|
||||
// FIXME: wouldn't localplayer be a better place for this?
|
||||
int LuaCamera::l_get_look_horizontal(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer();
|
||||
sanity_check(player);
|
||||
|
||||
lua_pushnumber(L, (player->getYaw() + 90.f) * core::DEGTORAD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_look_vertical(self)
|
||||
// FIXME: wouldn't localplayer be a better place for this?
|
||||
int LuaCamera::l_get_look_vertical(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer();
|
||||
sanity_check(player);
|
||||
|
||||
lua_pushnumber(L, -1.0f * player->getPitch() * core::DEGTORAD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_aspect_ratio(self)
|
||||
int LuaCamera::l_get_aspect_ratio(lua_State *L)
|
||||
{
|
||||
Camera *camera = getobject(L, 1);
|
||||
if (!camera)
|
||||
return 0;
|
||||
|
||||
lua_pushnumber(L, camera->getCameraNode()->getAspectRatio());
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaCamera *LuaCamera::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(LuaCamera **)ud;
|
||||
}
|
||||
|
||||
Camera *LuaCamera::getobject(LuaCamera *ref)
|
||||
{
|
||||
return ref->m_camera;
|
||||
}
|
||||
|
||||
Camera *LuaCamera::getobject(lua_State *L, int narg)
|
||||
{
|
||||
LuaCamera *ref = checkobject(L, narg);
|
||||
assert(ref);
|
||||
Camera *camera = getobject(ref);
|
||||
if (!camera)
|
||||
return NULL;
|
||||
return camera;
|
||||
}
|
||||
|
||||
int LuaCamera::gc_object(lua_State *L)
|
||||
{
|
||||
LuaCamera *o = *(LuaCamera **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LuaCamera::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const char LuaCamera::className[] = "Camera";
|
||||
const luaL_Reg LuaCamera::methods[] = {
|
||||
luamethod(LuaCamera, set_camera_mode),
|
||||
luamethod(LuaCamera, get_camera_mode),
|
||||
luamethod(LuaCamera, get_fov),
|
||||
luamethod(LuaCamera, get_pos),
|
||||
luamethod(LuaCamera, get_offset),
|
||||
luamethod(LuaCamera, get_look_dir),
|
||||
luamethod(LuaCamera, get_look_vertical),
|
||||
luamethod(LuaCamera, get_look_horizontal),
|
||||
luamethod(LuaCamera, get_aspect_ratio),
|
||||
|
||||
{0, 0}
|
||||
};
|
||||
// clang-format on
|
60
src/script/lua_api/l_camera.h
Normal file
60
src/script/lua_api/l_camera.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013-2017 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "l_base.h"
|
||||
|
||||
class Camera;
|
||||
|
||||
class LuaCamera : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static int l_set_camera_mode(lua_State *L);
|
||||
static int l_get_camera_mode(lua_State *L);
|
||||
|
||||
static int l_get_fov(lua_State *L);
|
||||
|
||||
static int l_get_pos(lua_State *L);
|
||||
static int l_get_offset(lua_State *L);
|
||||
static int l_get_look_dir(lua_State *L);
|
||||
static int l_get_look_vertical(lua_State *L);
|
||||
static int l_get_look_horizontal(lua_State *L);
|
||||
static int l_get_aspect_ratio(lua_State *L);
|
||||
|
||||
Camera *m_camera = nullptr;
|
||||
|
||||
public:
|
||||
LuaCamera(Camera *m);
|
||||
~LuaCamera() = default;
|
||||
|
||||
static void create(lua_State *L, Camera *m);
|
||||
|
||||
static LuaCamera *checkobject(lua_State *L, int narg);
|
||||
static Camera *getobject(LuaCamera *ref);
|
||||
static Camera *getobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
706
src/script/lua_api/l_client.cpp
Normal file
706
src/script/lua_api/l_client.cpp
Normal file
@ -0,0 +1,706 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "l_client.h"
|
||||
#include "chatmessage.h"
|
||||
#include "client/client.h"
|
||||
#include "client/clientevent.h"
|
||||
#include "client/sound.h"
|
||||
#include "client/clientenvironment.h"
|
||||
#include "client/game.h"
|
||||
#include "common/c_content.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "cpp_api/s_base.h"
|
||||
#include "gettext.h"
|
||||
#include "l_internal.h"
|
||||
#include "l_clientobject.h"
|
||||
#include "lua_api/l_nodemeta.h"
|
||||
#include "gui/mainmenumanager.h"
|
||||
#include "map.h"
|
||||
#include "util/string.h"
|
||||
#include "nodedef.h"
|
||||
#include "client/keycode.h"
|
||||
|
||||
#define checkCSMRestrictionFlag(flag) \
|
||||
( getClient(L)->checkCSMRestrictionFlag(CSMRestrictionFlags::flag) )
|
||||
|
||||
// Not the same as FlagDesc, which contains an `u32 flag`
|
||||
struct CSMFlagDesc {
|
||||
const char *name;
|
||||
u64 flag;
|
||||
};
|
||||
|
||||
/*
|
||||
FIXME: This should eventually be moved somewhere else
|
||||
It also needs to be kept in sync with the definition of CSMRestrictionFlags
|
||||
in network/networkprotocol.h
|
||||
*/
|
||||
const static CSMFlagDesc flagdesc_csm_restriction[] = {
|
||||
{"load_client_mods", CSM_RF_LOAD_CLIENT_MODS},
|
||||
{"chat_messages", CSM_RF_CHAT_MESSAGES},
|
||||
{"read_itemdefs", CSM_RF_READ_ITEMDEFS},
|
||||
{"read_nodedefs", CSM_RF_READ_NODEDEFS},
|
||||
{"lookup_nodes", CSM_RF_LOOKUP_NODES},
|
||||
{"read_playerinfo", CSM_RF_READ_PLAYERINFO},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
// get_current_modname()
|
||||
int ModApiClient::l_get_current_modname(lua_State *L)
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_modpath(modname)
|
||||
int ModApiClient::l_get_modpath(lua_State *L)
|
||||
{
|
||||
std::string modname = readParam<std::string>(L, 1);
|
||||
// Client mods use a virtual filesystem, see Client::scanModSubfolder()
|
||||
std::string path = modname + ":";
|
||||
lua_pushstring(L, path.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_last_run_mod()
|
||||
int ModApiClient::l_get_last_run_mod(lua_State *L)
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
std::string current_mod = readParam<std::string>(L, -1, "");
|
||||
if (current_mod.empty()) {
|
||||
lua_pop(L, 1);
|
||||
lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_last_run_mod(modname)
|
||||
int ModApiClient::l_set_last_run_mod(lua_State *L)
|
||||
{
|
||||
if (!lua_isstring(L, 1))
|
||||
return 0;
|
||||
|
||||
const char *mod = lua_tostring(L, 1);
|
||||
getScriptApiBase(L)->setOriginDirect(mod);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// print(text)
|
||||
int ModApiClient::l_print(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string text = luaL_checkstring(L, 1);
|
||||
rawstream << text << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// display_chat_message(message)
|
||||
int ModApiClient::l_display_chat_message(lua_State *L)
|
||||
{
|
||||
if (!lua_isstring(L, 1))
|
||||
return 0;
|
||||
|
||||
std::string message = luaL_checkstring(L, 1);
|
||||
getClient(L)->pushToChatQueue(new ChatMessage(utf8_to_wide(message)));
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send_chat_message(message)
|
||||
int ModApiClient::l_send_chat_message(lua_State *L)
|
||||
{
|
||||
if (!lua_isstring(L, 1))
|
||||
return 0;
|
||||
|
||||
// If server disabled this API, discard
|
||||
|
||||
if (checkCSMRestrictionFlag(CSM_RF_CHAT_MESSAGES))
|
||||
return 0;
|
||||
|
||||
std::string message = luaL_checkstring(L, 1);
|
||||
getClient(L)->sendChatMessage(utf8_to_wide(message));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clear_out_chat_queue()
|
||||
int ModApiClient::l_clear_out_chat_queue(lua_State *L)
|
||||
{
|
||||
getClient(L)->clearOutChatQueue();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_player_names()
|
||||
int ModApiClient::l_get_player_names(lua_State *L)
|
||||
{
|
||||
if (checkCSMRestrictionFlag(CSM_RF_READ_PLAYERINFO))
|
||||
return 0;
|
||||
|
||||
const std::list<std::string> &plist = getClient(L)->getConnectedPlayerNames();
|
||||
lua_createtable(L, plist.size(), 0);
|
||||
int newTable = lua_gettop(L);
|
||||
int index = 1;
|
||||
std::list<std::string>::const_iterator iter;
|
||||
for (iter = plist.begin(); iter != plist.end(); ++iter) {
|
||||
lua_pushstring(L, (*iter).c_str());
|
||||
lua_rawseti(L, newTable, index);
|
||||
index++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// show_formspec(formspec)
|
||||
int ModApiClient::l_show_formspec(lua_State *L)
|
||||
{
|
||||
if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
|
||||
return 0;
|
||||
|
||||
ClientEvent *event = new ClientEvent();
|
||||
event->type = CE_SHOW_LOCAL_FORMSPEC;
|
||||
event->show_formspec.formname = new std::string(luaL_checkstring(L, 1));
|
||||
event->show_formspec.formspec = new std::string(luaL_checkstring(L, 2));
|
||||
getClient(L)->pushToEventQueue(event);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send_respawn()
|
||||
int ModApiClient::l_send_respawn(lua_State *L)
|
||||
{
|
||||
getClient(L)->sendRespawn();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// disconnect()
|
||||
int ModApiClient::l_disconnect(lua_State *L)
|
||||
{
|
||||
// Stops badly written Lua code form causing boot loops
|
||||
if (getClient(L)->isShutdown()) {
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_gamecallback->disconnect();
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// gettext(text)
|
||||
int ModApiClient::l_gettext(lua_State *L)
|
||||
{
|
||||
std::string text = strgettext(std::string(luaL_checkstring(L, 1)));
|
||||
lua_pushstring(L, text.c_str());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_node_or_nil(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
int ModApiClient::l_get_node_or_nil(lua_State *L)
|
||||
{
|
||||
// pos
|
||||
v3s16 pos = read_v3s16(L, 1);
|
||||
|
||||
// Do it
|
||||
bool pos_ok;
|
||||
MapNode n = getClient(L)->CSMGetNode(pos, &pos_ok);
|
||||
if (pos_ok) {
|
||||
// Return node
|
||||
pushnode(L, n, getClient(L)->ndef());
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_langauge()
|
||||
int ModApiClient::l_get_language(lua_State *L)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char *locale = setlocale(LC_ALL, NULL);
|
||||
#else
|
||||
char *locale = setlocale(LC_MESSAGES, NULL);
|
||||
#endif
|
||||
std::string lang = gettext("LANG_CODE");
|
||||
if (lang == "LANG_CODE")
|
||||
lang = "";
|
||||
|
||||
lua_pushstring(L, locale);
|
||||
lua_pushstring(L, lang.c_str());
|
||||
return 2;
|
||||
}
|
||||
|
||||
// get_meta(pos)
|
||||
int ModApiClient::l_get_meta(lua_State *L)
|
||||
{
|
||||
v3s16 p = read_v3s16(L, 1);
|
||||
|
||||
// check restrictions first
|
||||
bool pos_ok;
|
||||
getClient(L)->CSMGetNode(p, &pos_ok);
|
||||
if (!pos_ok)
|
||||
return 0;
|
||||
|
||||
NodeMetadata *meta = getEnv(L)->getMap().getNodeMetadata(p);
|
||||
NodeMetaRef::createClient(L, meta);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// sound_play(spec, parameters)
|
||||
int ModApiClient::l_sound_play(lua_State *L)
|
||||
{
|
||||
ISoundManager *sound = getClient(L)->getSoundManager();
|
||||
|
||||
SimpleSoundSpec spec;
|
||||
read_soundspec(L, 1, spec);
|
||||
|
||||
float gain = 1.0f;
|
||||
float pitch = 1.0f;
|
||||
bool looped = false;
|
||||
s32 handle;
|
||||
|
||||
if (lua_istable(L, 2)) {
|
||||
getfloatfield(L, 2, "gain", gain);
|
||||
getfloatfield(L, 2, "pitch", pitch);
|
||||
getboolfield(L, 2, "loop", looped);
|
||||
|
||||
lua_getfield(L, 2, "pos");
|
||||
if (!lua_isnil(L, -1)) {
|
||||
v3f pos = read_v3f(L, -1) * BS;
|
||||
lua_pop(L, 1);
|
||||
handle = sound->playSoundAt(
|
||||
spec.name, looped, gain * spec.gain, pos, pitch);
|
||||
lua_pushinteger(L, handle);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
handle = sound->playSound(spec.name, looped, gain * spec.gain, spec.fade, pitch);
|
||||
lua_pushinteger(L, handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// sound_stop(handle)
|
||||
int ModApiClient::l_sound_stop(lua_State *L)
|
||||
{
|
||||
s32 handle = luaL_checkinteger(L, 1);
|
||||
|
||||
getClient(L)->getSoundManager()->stopSound(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sound_fade(handle, step, gain)
|
||||
int ModApiClient::l_sound_fade(lua_State *L)
|
||||
{
|
||||
s32 handle = luaL_checkinteger(L, 1);
|
||||
float step = readParam<float>(L, 2);
|
||||
float gain = readParam<float>(L, 3);
|
||||
getClient(L)->getSoundManager()->fadeSound(handle, step, gain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_server_info()
|
||||
int ModApiClient::l_get_server_info(lua_State *L)
|
||||
{
|
||||
Client *client = getClient(L);
|
||||
Address serverAddress = client->getServerAddress();
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, client->getAddressName().c_str());
|
||||
lua_setfield(L, -2, "address");
|
||||
lua_pushstring(L, serverAddress.serializeString().c_str());
|
||||
lua_setfield(L, -2, "ip");
|
||||
lua_pushinteger(L, serverAddress.getPort());
|
||||
lua_setfield(L, -2, "port");
|
||||
lua_pushinteger(L, client->getProtoVersion());
|
||||
lua_setfield(L, -2, "protocol_version");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_item_def(itemstring)
|
||||
int ModApiClient::l_get_item_def(lua_State *L)
|
||||
{
|
||||
IGameDef *gdef = getGameDef(L);
|
||||
assert(gdef);
|
||||
|
||||
IItemDefManager *idef = gdef->idef();
|
||||
assert(idef);
|
||||
|
||||
if (checkCSMRestrictionFlag(CSM_RF_READ_ITEMDEFS))
|
||||
return 0;
|
||||
|
||||
if (!lua_isstring(L, 1))
|
||||
return 0;
|
||||
|
||||
std::string name = readParam<std::string>(L, 1);
|
||||
if (!idef->isKnown(name))
|
||||
return 0;
|
||||
const ItemDefinition &def = idef->get(name);
|
||||
|
||||
push_item_definition_full(L, def);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_node_def(nodename)
|
||||
int ModApiClient::l_get_node_def(lua_State *L)
|
||||
{
|
||||
IGameDef *gdef = getGameDef(L);
|
||||
assert(gdef);
|
||||
|
||||
const NodeDefManager *ndef = gdef->ndef();
|
||||
assert(ndef);
|
||||
|
||||
if (!lua_isstring(L, 1))
|
||||
return 0;
|
||||
|
||||
if (checkCSMRestrictionFlag(CSM_RF_READ_NODEDEFS))
|
||||
return 0;
|
||||
|
||||
std::string name = readParam<std::string>(L, 1);
|
||||
const ContentFeatures &cf = ndef->get(ndef->getId(name));
|
||||
if (cf.name != name) // Unknown node. | name = <whatever>, cf.name = ignore
|
||||
return 0;
|
||||
|
||||
push_content_features(L, cf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_privilege_list()
|
||||
int ModApiClient::l_get_privilege_list(lua_State *L)
|
||||
{
|
||||
const Client *client = getClient(L);
|
||||
lua_newtable(L);
|
||||
for (const std::string &priv : client->getPrivilegeList()) {
|
||||
lua_pushboolean(L, true);
|
||||
lua_setfield(L, -2, priv.c_str());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_builtin_path()
|
||||
int ModApiClient::l_get_builtin_path(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, BUILTIN_MOD_NAME ":");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_csm_restrictions()
|
||||
int ModApiClient::l_get_csm_restrictions(lua_State *L)
|
||||
{
|
||||
u64 flags = getClient(L)->getCSMRestrictionFlags();
|
||||
const CSMFlagDesc *flagdesc = flagdesc_csm_restriction;
|
||||
|
||||
lua_newtable(L);
|
||||
for (int i = 0; flagdesc[i].name; i++) {
|
||||
setboolfield(L, -1, flagdesc[i].name, !!(flags & flagdesc[i].flag));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send_damage(damage)
|
||||
int ModApiClient::l_send_damage(lua_State *L)
|
||||
{
|
||||
u16 damage = luaL_checknumber(L, 1);
|
||||
getClient(L)->sendDamage(damage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// place_node(pos)
|
||||
int ModApiClient::l_place_node(lua_State *L)
|
||||
{
|
||||
Client *client = getClient(L);
|
||||
ClientMap &map = client->getEnv().getClientMap();
|
||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||
ItemStack selected_item, hand_item;
|
||||
player->getWieldedItem(&selected_item, &hand_item);
|
||||
const ItemDefinition &selected_def = selected_item.getDefinition(getGameDef(L)->idef());
|
||||
v3s16 pos = read_v3s16(L, 1);
|
||||
PointedThing pointed;
|
||||
pointed.type = POINTEDTHING_NODE;
|
||||
pointed.node_abovesurface = pos;
|
||||
pointed.node_undersurface = pos;
|
||||
NodeMetadata *meta = map.getNodeMetadata(pos);
|
||||
g_game->nodePlacement(selected_def, selected_item, pos, pos, pointed, meta, true); // always force sneak
|
||||
return 0;
|
||||
}
|
||||
|
||||
// dig_node(pos)
|
||||
int ModApiClient::l_dig_node(lua_State *L)
|
||||
{
|
||||
Client *client = getClient(L);
|
||||
v3s16 pos = read_v3s16(L, 1);
|
||||
PointedThing pointed;
|
||||
pointed.type = POINTEDTHING_NODE;
|
||||
pointed.node_abovesurface = pos;
|
||||
pointed.node_undersurface = pos;
|
||||
client->interact(INTERACT_START_DIGGING, pointed);
|
||||
client->interact(INTERACT_DIGGING_COMPLETED, pointed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_inventory(location)
|
||||
int ModApiClient::l_get_inventory(lua_State *L)
|
||||
{
|
||||
Client *client = getClient(L);
|
||||
InventoryLocation inventory_location;
|
||||
Inventory *inventory;
|
||||
std::string location;
|
||||
|
||||
location = readParam<std::string>(L, 1);
|
||||
|
||||
try {
|
||||
inventory_location.deSerialize(location);
|
||||
inventory = client->getInventory(inventory_location);
|
||||
|
||||
if (!inventory) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
push_inventory(L, inventory);
|
||||
} catch (SerializationError &) {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_keypress(key_setting, pressed) -> returns true on success
|
||||
int ModApiClient::l_set_keypress(lua_State *L)
|
||||
{
|
||||
std::string setting_name = "keymap_" + readParam<std::string>(L, 1);
|
||||
bool pressed = lua_isboolean(L, 2) && readParam<bool>(L, 2);
|
||||
try {
|
||||
KeyPress keyCode = getKeySetting(setting_name.c_str());
|
||||
if (pressed)
|
||||
g_game->input->setKeypress(keyCode);
|
||||
else
|
||||
g_game->input->unsetKeypress(keyCode);
|
||||
lua_pushboolean(L, true);
|
||||
} catch (SettingNotFoundException &) {
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// drop_selected_item()
|
||||
int ModApiClient::l_drop_selected_item(lua_State *L)
|
||||
{
|
||||
g_game->dropSelectedItem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//take_screenshot()
|
||||
int ModApiClient::l_take_screenshot(lua_State *L)
|
||||
{
|
||||
getClient(L)->makeScreenshot(true);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
StringMap *table_to_stringmap(lua_State *L, int index)
|
||||
{
|
||||
StringMap *m = new StringMap;
|
||||
|
||||
lua_pushvalue(L, index);
|
||||
lua_pushnil(L);
|
||||
|
||||
while (lua_next(L, -2)) {
|
||||
lua_pushvalue(L, -2);
|
||||
std::basic_string<char> key = lua_tostring(L, -1);
|
||||
std::basic_string<char> value = lua_tostring(L, -2);
|
||||
(*m)[key] = value;
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
// send_inventory_fields(formname, fields)
|
||||
// Only works if the inventory form was opened beforehand.
|
||||
int ModApiClient::l_send_inventory_fields(lua_State *L)
|
||||
{
|
||||
std::string formname = luaL_checkstring(L, 1);
|
||||
StringMap *fields = table_to_stringmap(L, 2);
|
||||
|
||||
getClient(L)->sendInventoryFields(formname, *fields);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// send_nodemeta_fields(position, formname, fields)
|
||||
int ModApiClient::l_send_nodemeta_fields(lua_State *L)
|
||||
{
|
||||
v3s16 pos = check_v3s16(L, 1);
|
||||
std::string formname = luaL_checkstring(L, 2);
|
||||
StringMap *m = table_to_stringmap(L, 3);
|
||||
|
||||
getClient(L)->sendNodemetaFields(pos, formname, *m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// interact(mode, pointed)
|
||||
int ModApiClient::l_interact(lua_State *L)
|
||||
{
|
||||
std::string mode = luaL_checkstring(L, 1);
|
||||
PointedThing pointed;
|
||||
int imode;
|
||||
|
||||
if (lua_gettop(L) > 1) {
|
||||
v3s16 pos = check_v3s16(L, 2);
|
||||
pointed.type = POINTEDTHING_NODE;
|
||||
pointed.node_abovesurface = pos;
|
||||
pointed.node_undersurface = pos;
|
||||
} else {
|
||||
Camera *camera = getClient(L)->getCamera();
|
||||
const v3f camera_direction = camera->getDirection();
|
||||
const v3s16 camera_offset = camera->getOffset();
|
||||
|
||||
IItemDefManager *itemdef_manager = createItemDefManager();
|
||||
ItemStack selected_item, hand_item;
|
||||
const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager);
|
||||
f32 d = getToolRange(selected_def, hand_item.getDefinition(itemdef_manager));
|
||||
|
||||
if (g_settings->getBool("increase_tool_range"))
|
||||
d += 2;
|
||||
if (g_settings->getBool("increase_tool_range_plus"))
|
||||
d = 1000;
|
||||
|
||||
core::line3d<f32> shootline;
|
||||
|
||||
switch (camera->getCameraMode()) {
|
||||
case CAMERA_MODE_FIRST:
|
||||
// Shoot from camera position, with bobbing
|
||||
shootline.start = camera->getPosition();
|
||||
break;
|
||||
case CAMERA_MODE_THIRD:
|
||||
// Shoot from player head, no bobbing
|
||||
shootline.start = camera->getHeadPosition();
|
||||
break;
|
||||
case CAMERA_MODE_THIRD_FRONT:
|
||||
shootline.start = camera->getHeadPosition();
|
||||
// prevent player pointing anything in front-view
|
||||
d = 0;
|
||||
break;
|
||||
}
|
||||
shootline.end = shootline.start + camera_direction * BS * d;
|
||||
GameRunData runData = GameRunData();
|
||||
|
||||
pointed = g_game->updatePointedThing(shootline,
|
||||
selected_def.liquids_pointable,
|
||||
!runData.btn_down_for_dig,
|
||||
camera_offset);
|
||||
}
|
||||
|
||||
struct EnumString interact_modes[] = {
|
||||
{INTERACT_START_DIGGING, "start_digging"},
|
||||
{INTERACT_STOP_DIGGING, "stop_digging"},
|
||||
{INTERACT_DIGGING_COMPLETED, "digging_completed"},
|
||||
{INTERACT_PLACE, "place"},
|
||||
{INTERACT_USE, "use"},
|
||||
{INTERACT_ACTIVATE, "activate"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
string_to_enum(interact_modes, imode, mode);
|
||||
|
||||
getClient(L)->interact((InteractAction)imode, pointed);
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 0;
|
||||
}
|
||||
//show_huds()
|
||||
int ModApiClient::l_show_huds(lua_State *L)
|
||||
{
|
||||
g_game->show_huds();
|
||||
return 0;
|
||||
}
|
||||
//hide_huds()
|
||||
int ModApiClient::l_hide_huds(lua_State *L)
|
||||
{
|
||||
g_game->hide_huds();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_objects_inside_radius(pos, radius)
|
||||
int ModApiClient::l_get_objects_inside_radius(lua_State *L)
|
||||
{
|
||||
ClientEnvironment &env = getClient(L)->getEnv();
|
||||
|
||||
v3f pos = checkFloatPos(L, 1);
|
||||
float radius = readParam<float>(L, 2) * BS;
|
||||
|
||||
std::vector<DistanceSortedActiveObject> objs;
|
||||
env.getActiveObjects(pos, radius, objs);
|
||||
|
||||
int i = 0;
|
||||
lua_createtable(L, objs.size(), 0);
|
||||
for (const auto obj : objs) {
|
||||
ClientObjectRef::create(L, obj.obj); // TODO: getObjectRefOrCreate
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiClient::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(get_current_modname);
|
||||
API_FCT(get_modpath);
|
||||
API_FCT(print);
|
||||
API_FCT(display_chat_message);
|
||||
API_FCT(send_chat_message);
|
||||
API_FCT(clear_out_chat_queue);
|
||||
API_FCT(get_player_names);
|
||||
API_FCT(set_last_run_mod);
|
||||
API_FCT(get_last_run_mod);
|
||||
API_FCT(show_formspec);
|
||||
API_FCT(send_respawn);
|
||||
API_FCT(gettext);
|
||||
API_FCT(get_node_or_nil);
|
||||
API_FCT(disconnect);
|
||||
API_FCT(get_meta);
|
||||
API_FCT(sound_play);
|
||||
API_FCT(sound_stop);
|
||||
API_FCT(sound_fade);
|
||||
API_FCT(get_server_info);
|
||||
API_FCT(get_item_def);
|
||||
API_FCT(get_node_def);
|
||||
API_FCT(get_privilege_list);
|
||||
API_FCT(get_builtin_path);
|
||||
API_FCT(get_language);
|
||||
API_FCT(get_csm_restrictions);
|
||||
API_FCT(send_damage);
|
||||
API_FCT(place_node);
|
||||
API_FCT(dig_node);
|
||||
API_FCT(get_inventory);
|
||||
API_FCT(set_keypress);
|
||||
API_FCT(drop_selected_item);
|
||||
API_FCT(take_screenshot);
|
||||
API_FCT(send_inventory_fields);
|
||||
API_FCT(send_nodemeta_fields);
|
||||
API_FCT(interact);
|
||||
API_FCT(show_huds);
|
||||
API_FCT(hide_huds);
|
||||
API_FCT(get_objects_inside_radius);
|
||||
}
|
149
src/script/lua_api/l_client.h
Normal file
149
src/script/lua_api/l_client.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "itemdef.h"
|
||||
#include "tool.h"
|
||||
|
||||
class ModApiClient : public ModApiBase
|
||||
{
|
||||
private:
|
||||
// get_current_modname()
|
||||
static int l_get_current_modname(lua_State *L);
|
||||
|
||||
// get_modpath(modname)
|
||||
static int l_get_modpath(lua_State *L);
|
||||
|
||||
// print(text)
|
||||
static int l_print(lua_State *L);
|
||||
|
||||
// display_chat_message(message)
|
||||
static int l_display_chat_message(lua_State *L);
|
||||
|
||||
// send_chat_message(message)
|
||||
static int l_send_chat_message(lua_State *L);
|
||||
|
||||
// clear_out_chat_queue()
|
||||
static int l_clear_out_chat_queue(lua_State *L);
|
||||
|
||||
// get_player_names()
|
||||
static int l_get_player_names(lua_State *L);
|
||||
|
||||
// show_formspec(name, formspec)
|
||||
static int l_show_formspec(lua_State *L);
|
||||
|
||||
// send_respawn()
|
||||
static int l_send_respawn(lua_State *L);
|
||||
|
||||
// disconnect()
|
||||
static int l_disconnect(lua_State *L);
|
||||
|
||||
// gettext(text)
|
||||
static int l_gettext(lua_State *L);
|
||||
|
||||
// get_last_run_mod(n)
|
||||
static int l_get_last_run_mod(lua_State *L);
|
||||
|
||||
// set_last_run_mod(modname)
|
||||
static int l_set_last_run_mod(lua_State *L);
|
||||
|
||||
// get_node(pos)
|
||||
static int l_get_node_or_nil(lua_State *L);
|
||||
|
||||
// get_language()
|
||||
static int l_get_language(lua_State *L);
|
||||
|
||||
// get_wielded_item()
|
||||
static int l_get_wielded_item(lua_State *L);
|
||||
|
||||
// get_meta(pos)
|
||||
static int l_get_meta(lua_State *L);
|
||||
|
||||
// sound_play(spec, parameters)
|
||||
static int l_sound_play(lua_State *L);
|
||||
|
||||
// sound_stop(handle)
|
||||
static int l_sound_stop(lua_State *L);
|
||||
|
||||
// sound_fade(handle, step, gain)
|
||||
static int l_sound_fade(lua_State *L);
|
||||
|
||||
// get_server_info()
|
||||
static int l_get_server_info(lua_State *L);
|
||||
|
||||
// get_item_def(itemstring)
|
||||
static int l_get_item_def(lua_State *L);
|
||||
|
||||
// get_node_def(nodename)
|
||||
static int l_get_node_def(lua_State *L);
|
||||
|
||||
// get_privilege_list()
|
||||
static int l_get_privilege_list(lua_State *L);
|
||||
|
||||
// get_builtin_path()
|
||||
static int l_get_builtin_path(lua_State *L);
|
||||
|
||||
// get_csm_restrictions()
|
||||
static int l_get_csm_restrictions(lua_State *L);
|
||||
|
||||
// send_damage(damage)
|
||||
static int l_send_damage(lua_State *L);
|
||||
|
||||
// place_node(pos)
|
||||
static int l_place_node(lua_State *L);
|
||||
|
||||
// dig_node(pos)
|
||||
static int l_dig_node(lua_State *L);
|
||||
|
||||
// get_inventory(location)
|
||||
static int l_get_inventory(lua_State *L);
|
||||
|
||||
// set_keypress(key_setting, pressed)
|
||||
static int l_set_keypress(lua_State *L);
|
||||
|
||||
// drop_selected_item()
|
||||
static int l_drop_selected_item(lua_State *L);
|
||||
|
||||
// take_screenshot()
|
||||
static int l_take_screenshot(lua_State *L);
|
||||
|
||||
// send_inventory_fields(formname, fields)
|
||||
static int l_send_inventory_fields(lua_State *L);
|
||||
|
||||
// send_nodemeta_fields(position, formname, fields)
|
||||
static int l_send_nodemeta_fields(lua_State *L);
|
||||
|
||||
// interact(0-5)
|
||||
static int l_interact(lua_State *L);
|
||||
|
||||
// show_huds
|
||||
static int l_show_huds(lua_State *L);
|
||||
|
||||
// hide_huds
|
||||
static int l_hide_huds(lua_State *L);
|
||||
|
||||
// get_objects_inside_radius(pos, radius)
|
||||
static int l_get_objects_inside_radius(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
287
src/script/lua_api/l_clientobject.cpp
Normal file
287
src/script/lua_api/l_clientobject.cpp
Normal file
@ -0,0 +1,287 @@
|
||||
// CC0/Unlicense system32 2020
|
||||
|
||||
#include "lua_api/l_clientobject.h"
|
||||
#include "l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "client/client.h"
|
||||
#include "object_properties.h"
|
||||
#include "util/pointedthing.h"
|
||||
|
||||
// should prob do some more NULL checking
|
||||
|
||||
|
||||
ClientObjectRef *ClientObjectRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *userdata = luaL_checkudata(L, narg, className);
|
||||
if (!userdata)
|
||||
luaL_typerror(L, narg, className);
|
||||
return *(ClientObjectRef**)userdata;
|
||||
}
|
||||
|
||||
ClientActiveObject *ClientObjectRef::get_cao(ClientObjectRef *ref)
|
||||
{
|
||||
ClientActiveObject *obj = ref->m_object;
|
||||
return obj;
|
||||
}
|
||||
|
||||
GenericCAO *ClientObjectRef::get_generic_cao(ClientObjectRef *ref, lua_State *L)
|
||||
{
|
||||
ClientActiveObject *obj = get_cao(ref);
|
||||
ClientEnvironment &env = getClient(L)->getEnv();
|
||||
GenericCAO *gcao = env.getGenericCAO(obj->getId());
|
||||
return gcao;
|
||||
}
|
||||
int ClientObjectRef::l_get_id(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
if(!gcao) return 0;
|
||||
lua_pushvalue(L, gcao->getId());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_pos(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
ClientActiveObject *gcao = get_cao(ref);
|
||||
if(!gcao) return 0;
|
||||
push_v3f(L, gcao->getPosition() / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_velocity(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
if(!gcao) return 0;
|
||||
push_v3f(L, gcao->getVelocity() / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_acceleration(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
if(!gcao) return 0;
|
||||
push_v3f(L, gcao->getAcceleration() / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_rotation(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
push_v3f(L, gcao->getRotation());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_is_player(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
lua_pushboolean(L, gcao->isPlayer());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_is_local_player(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
lua_pushboolean(L, gcao->isLocalPlayer());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_name(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
lua_pushstring(L, gcao->getName().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_parent(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
create(L, gcao->getParent());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_nametag(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
ObjectProperties *props = gcao->getProperties();
|
||||
lua_pushstring(L, props->nametag.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_item_textures(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
ObjectProperties *props = gcao->getProperties();
|
||||
lua_newtable(L);
|
||||
|
||||
for (std::string &texture : props->textures) {
|
||||
lua_pushstring(L, texture.c_str());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_set_visible(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
if(!gcao) return 0;
|
||||
gcao->setVisible(readParam<bool>(L, -1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_remove_from_scene(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
if(!gcao) return 0;
|
||||
gcao->removeFromScene(readParam<bool>(L, -1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_remove(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
ClientActiveObject *cao = get_cao(ref);
|
||||
if (! cao)
|
||||
return 0;
|
||||
getClient(L)->getEnv().removeActiveObject(cao->getId());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_hp(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
lua_pushnumber(L, gcao->getHp());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_get_max_hp(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
ObjectProperties *props = gcao->getProperties();
|
||||
lua_pushnumber(L, props->hp_max);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_punch(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
if(!gcao) return 0;
|
||||
PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0);
|
||||
getClient(L)->interact(INTERACT_START_DIGGING, pointed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ClientObjectRef::l_rightclick(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *ref = checkobject(L, 1);
|
||||
GenericCAO *gcao = get_generic_cao(ref, L);
|
||||
if(!gcao) return 0;
|
||||
PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0);
|
||||
getClient(L)->interact(INTERACT_PLACE, pointed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClientObjectRef::ClientObjectRef(ClientActiveObject *object) : m_object(object)
|
||||
{
|
||||
}
|
||||
|
||||
void ClientObjectRef::create(lua_State *L, ClientActiveObject *object)
|
||||
{
|
||||
if (object) {
|
||||
ClientObjectRef *o = new ClientObjectRef(object);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientObjectRef::create(lua_State *L, s16 id)
|
||||
{
|
||||
create(L, ((ClientEnvironment *)getEnv(L))->getActiveObject(id));
|
||||
}
|
||||
|
||||
int ClientObjectRef::gc_object(lua_State *L)
|
||||
{
|
||||
ClientObjectRef *obj = *(ClientObjectRef **)(lua_touserdata(L, 1));
|
||||
delete obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// taken from LuaLocalPlayer
|
||||
void ClientObjectRef::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // Drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // Drop methodtable
|
||||
}
|
||||
|
||||
const char ClientObjectRef::className[] = "ClientObjectRef";
|
||||
luaL_Reg ClientObjectRef::methods[] = {
|
||||
luamethod(ClientObjectRef, get_id),
|
||||
luamethod(ClientObjectRef, get_pos),
|
||||
luamethod(ClientObjectRef, get_velocity),
|
||||
luamethod(ClientObjectRef, get_acceleration),
|
||||
luamethod(ClientObjectRef, get_rotation),
|
||||
luamethod(ClientObjectRef, is_player),
|
||||
luamethod(ClientObjectRef, get_name),
|
||||
luamethod(ClientObjectRef, get_parent),
|
||||
luamethod(ClientObjectRef, get_nametag),
|
||||
luamethod(ClientObjectRef, get_item_textures),
|
||||
luamethod(ClientObjectRef, get_max_hp),
|
||||
luamethod(ClientObjectRef, set_visible),
|
||||
luamethod(ClientObjectRef, remove_from_scene),
|
||||
luamethod(ClientObjectRef, remove),
|
||||
luamethod(ClientObjectRef, is_local_player),
|
||||
luamethod(ClientObjectRef, get_hp),
|
||||
luamethod(ClientObjectRef, punch),
|
||||
luamethod(ClientObjectRef, rightclick),
|
||||
{0, 0}
|
||||
};
|
85
src/script/lua_api/l_clientobject.h
Normal file
85
src/script/lua_api/l_clientobject.h
Normal file
@ -0,0 +1,85 @@
|
||||
// CC0/Unlicense system32 2020
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "client/clientobject.h"
|
||||
#include "client/content_cao.h"
|
||||
|
||||
class ClientObjectRef : public ModApiBase
|
||||
{
|
||||
public:
|
||||
ClientObjectRef(ClientActiveObject *object);
|
||||
|
||||
~ClientObjectRef() = default;
|
||||
|
||||
static void Register(lua_State *L);
|
||||
|
||||
static void create(lua_State *L, ClientActiveObject *object);
|
||||
|
||||
static void create(lua_State *L, s16 id);
|
||||
|
||||
static ClientObjectRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
private:
|
||||
ClientActiveObject *m_object = nullptr;
|
||||
static const char className[];
|
||||
static luaL_Reg methods[];
|
||||
|
||||
static ClientActiveObject *get_cao(ClientObjectRef *ref);
|
||||
static GenericCAO *get_generic_cao(ClientObjectRef *ref, lua_State *L);
|
||||
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static int l_get_id(lua_State *L);
|
||||
|
||||
// get_pos(self)
|
||||
// returns: {x=num, y=num, z=num}
|
||||
static int l_get_pos(lua_State *L);
|
||||
|
||||
// get_velocity(self)
|
||||
static int l_get_velocity(lua_State *L);
|
||||
|
||||
// get_acceleration(self)
|
||||
static int l_get_acceleration(lua_State *L);
|
||||
|
||||
// get_rotation(self)
|
||||
static int l_get_rotation(lua_State *L);
|
||||
|
||||
// is_player(self)
|
||||
static int l_is_player(lua_State *L);
|
||||
|
||||
// is_local_player(self)
|
||||
static int l_is_local_player(lua_State *L);
|
||||
|
||||
// get_name(self)
|
||||
static int l_get_name(lua_State *L);
|
||||
|
||||
// get_parent(self)
|
||||
static int l_get_parent(lua_State *L);
|
||||
|
||||
// get_nametag(self)
|
||||
static int l_get_nametag(lua_State *L);
|
||||
|
||||
// get_textures(self)
|
||||
static int l_get_item_textures(lua_State *L);
|
||||
|
||||
// get_hp(self)
|
||||
static int l_get_max_hp(lua_State *L);
|
||||
|
||||
// set_visible(self, visible)
|
||||
static int l_set_visible(lua_State *L);
|
||||
|
||||
// remove_from_scene(self, permanent)
|
||||
static int l_remove_from_scene(lua_State *L);
|
||||
static int l_remove(lua_State *L);
|
||||
|
||||
// get_hp(self)
|
||||
static int l_get_hp(lua_State *L);
|
||||
|
||||
// punch(self)
|
||||
static int l_punch(lua_State *L);
|
||||
|
||||
// rightclick(self)
|
||||
static int l_rightclick(lua_State *L);
|
||||
};
|
529
src/script/lua_api/l_craft.cpp
Normal file
529
src/script/lua_api/l_craft.cpp
Normal file
@ -0,0 +1,529 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "lua_api/l_craft.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "lua_api/l_item.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "server.h"
|
||||
#include "craftdef.h"
|
||||
|
||||
struct EnumString ModApiCraft::es_CraftMethod[] =
|
||||
{
|
||||
{CRAFT_METHOD_NORMAL, "normal"},
|
||||
{CRAFT_METHOD_COOKING, "cooking"},
|
||||
{CRAFT_METHOD_FUEL, "fuel"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
// helper for register_craft
|
||||
bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index,
|
||||
int &width, std::vector<std::string> &recipe)
|
||||
{
|
||||
if(index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
|
||||
if(!lua_istable(L, index))
|
||||
return false;
|
||||
|
||||
lua_pushnil(L);
|
||||
int rowcount = 0;
|
||||
while(lua_next(L, index) != 0){
|
||||
int colcount = 0;
|
||||
// key at index -2 and value at index -1
|
||||
if(!lua_istable(L, -1))
|
||||
return false;
|
||||
int table2 = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, table2) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
if(!lua_isstring(L, -1))
|
||||
return false;
|
||||
recipe.emplace_back(readParam<std::string>(L, -1));
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
colcount++;
|
||||
}
|
||||
if(rowcount == 0){
|
||||
width = colcount;
|
||||
} else {
|
||||
if(colcount != width)
|
||||
return false;
|
||||
}
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
rowcount++;
|
||||
}
|
||||
return width != 0;
|
||||
}
|
||||
|
||||
// helper for register_craft
|
||||
bool ModApiCraft::readCraftRecipeShapeless(lua_State *L, int index,
|
||||
std::vector<std::string> &recipe)
|
||||
{
|
||||
if(index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
|
||||
if(!lua_istable(L, index))
|
||||
return false;
|
||||
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, index) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
if(!lua_isstring(L, -1))
|
||||
return false;
|
||||
recipe.emplace_back(readParam<std::string>(L, -1));
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// helper for register_craft
|
||||
bool ModApiCraft::readCraftReplacements(lua_State *L, int index,
|
||||
CraftReplacements &replacements)
|
||||
{
|
||||
if(index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
|
||||
if(!lua_istable(L, index))
|
||||
return false;
|
||||
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, index) != 0){
|
||||
// key at index -2 and value at index -1
|
||||
if(!lua_istable(L, -1))
|
||||
return false;
|
||||
lua_rawgeti(L, -1, 1);
|
||||
if(!lua_isstring(L, -1))
|
||||
return false;
|
||||
std::string replace_from = readParam<std::string>(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 2);
|
||||
if(!lua_isstring(L, -1))
|
||||
return false;
|
||||
std::string replace_to = readParam<std::string>(L, -1);
|
||||
lua_pop(L, 1);
|
||||
replacements.pairs.emplace_back(replace_from, replace_to);
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
|
||||
int ModApiCraft::l_register_craft(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
//infostream<<"register_craft"<<std::endl;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int table = 1;
|
||||
|
||||
// Get the writable craft definition manager from the server
|
||||
IWritableCraftDefManager *craftdef =
|
||||
getServer(L)->getWritableCraftDefManager();
|
||||
|
||||
std::string type = getstringfield_default(L, table, "type", "shaped");
|
||||
|
||||
/*
|
||||
CraftDefinitionShaped
|
||||
*/
|
||||
if(type == "shaped"){
|
||||
std::string output = getstringfield_default(L, table, "output", "");
|
||||
if (output.empty())
|
||||
throw LuaError("Crafting definition is missing an output");
|
||||
|
||||
int width = 0;
|
||||
std::vector<std::string> recipe;
|
||||
lua_getfield(L, table, "recipe");
|
||||
if(lua_isnil(L, -1))
|
||||
throw LuaError("Crafting definition is missing a recipe"
|
||||
" (output=\"" + output + "\")");
|
||||
if(!readCraftRecipeShaped(L, -1, width, recipe))
|
||||
throw LuaError("Invalid crafting recipe"
|
||||
" (output=\"" + output + "\")");
|
||||
|
||||
CraftReplacements replacements;
|
||||
lua_getfield(L, table, "replacements");
|
||||
if(!lua_isnil(L, -1))
|
||||
{
|
||||
if(!readCraftReplacements(L, -1, replacements))
|
||||
throw LuaError("Invalid replacements"
|
||||
" (output=\"" + output + "\")");
|
||||
}
|
||||
|
||||
CraftDefinition *def = new CraftDefinitionShaped(
|
||||
output, width, recipe, replacements);
|
||||
craftdef->registerCraft(def, getServer(L));
|
||||
}
|
||||
/*
|
||||
CraftDefinitionShapeless
|
||||
*/
|
||||
else if(type == "shapeless"){
|
||||
std::string output = getstringfield_default(L, table, "output", "");
|
||||
if (output.empty())
|
||||
throw LuaError("Crafting definition (shapeless)"
|
||||
" is missing an output");
|
||||
|
||||
std::vector<std::string> recipe;
|
||||
lua_getfield(L, table, "recipe");
|
||||
if(lua_isnil(L, -1))
|
||||
throw LuaError("Crafting definition (shapeless)"
|
||||
" is missing a recipe"
|
||||
" (output=\"" + output + "\")");
|
||||
if(!readCraftRecipeShapeless(L, -1, recipe))
|
||||
throw LuaError("Invalid crafting recipe"
|
||||
" (output=\"" + output + "\")");
|
||||
|
||||
CraftReplacements replacements;
|
||||
lua_getfield(L, table, "replacements");
|
||||
if(!lua_isnil(L, -1))
|
||||
{
|
||||
if(!readCraftReplacements(L, -1, replacements))
|
||||
throw LuaError("Invalid replacements"
|
||||
" (output=\"" + output + "\")");
|
||||
}
|
||||
|
||||
CraftDefinition *def = new CraftDefinitionShapeless(
|
||||
output, recipe, replacements);
|
||||
craftdef->registerCraft(def, getServer(L));
|
||||
}
|
||||
/*
|
||||
CraftDefinitionToolRepair
|
||||
*/
|
||||
else if(type == "toolrepair"){
|
||||
float additional_wear = getfloatfield_default(L, table,
|
||||
"additional_wear", 0.0);
|
||||
|
||||
CraftDefinition *def = new CraftDefinitionToolRepair(
|
||||
additional_wear);
|
||||
craftdef->registerCraft(def, getServer(L));
|
||||
}
|
||||
/*
|
||||
CraftDefinitionCooking
|
||||
*/
|
||||
else if(type == "cooking"){
|
||||
std::string output = getstringfield_default(L, table, "output", "");
|
||||
if (output.empty())
|
||||
throw LuaError("Crafting definition (cooking)"
|
||||
" is missing an output");
|
||||
|
||||
std::string recipe = getstringfield_default(L, table, "recipe", "");
|
||||
if (recipe.empty())
|
||||
throw LuaError("Crafting definition (cooking)"
|
||||
" is missing a recipe"
|
||||
" (output=\"" + output + "\")");
|
||||
|
||||
float cooktime = getfloatfield_default(L, table, "cooktime", 3.0);
|
||||
|
||||
CraftReplacements replacements;
|
||||
lua_getfield(L, table, "replacements");
|
||||
if(!lua_isnil(L, -1))
|
||||
{
|
||||
if(!readCraftReplacements(L, -1, replacements))
|
||||
throw LuaError("Invalid replacements"
|
||||
" (cooking output=\"" + output + "\")");
|
||||
}
|
||||
|
||||
CraftDefinition *def = new CraftDefinitionCooking(
|
||||
output, recipe, cooktime, replacements);
|
||||
craftdef->registerCraft(def, getServer(L));
|
||||
}
|
||||
/*
|
||||
CraftDefinitionFuel
|
||||
*/
|
||||
else if(type == "fuel"){
|
||||
std::string recipe = getstringfield_default(L, table, "recipe", "");
|
||||
if (recipe.empty())
|
||||
throw LuaError("Crafting definition (fuel)"
|
||||
" is missing a recipe");
|
||||
|
||||
float burntime = getfloatfield_default(L, table, "burntime", 1.0);
|
||||
|
||||
CraftReplacements replacements;
|
||||
lua_getfield(L, table, "replacements");
|
||||
if(!lua_isnil(L, -1))
|
||||
{
|
||||
if(!readCraftReplacements(L, -1, replacements))
|
||||
throw LuaError("Invalid replacements"
|
||||
" (fuel recipe=\"" + recipe + "\")");
|
||||
}
|
||||
|
||||
CraftDefinition *def = new CraftDefinitionFuel(
|
||||
recipe, burntime, replacements);
|
||||
craftdef->registerCraft(def, getServer(L));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw LuaError("Unknown crafting definition type: \"" + type + "\"");
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
return 0; /* number of results */
|
||||
}
|
||||
|
||||
// clear_craft({[output=item], [recipe={{item00,item10},{item01,item11}}])
|
||||
int ModApiCraft::l_clear_craft(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int table = 1;
|
||||
|
||||
// Get the writable craft definition manager from the server
|
||||
IWritableCraftDefManager *craftdef =
|
||||
getServer(L)->getWritableCraftDefManager();
|
||||
|
||||
std::string output = getstringfield_default(L, table, "output", "");
|
||||
std::string type = getstringfield_default(L, table, "type", "shaped");
|
||||
CraftOutput c_output(output, 0);
|
||||
if (!output.empty()) {
|
||||
if (craftdef->clearCraftsByOutput(c_output, getServer(L))) {
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
warningstream << "No craft recipe known for output" << std::endl;
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
std::vector<std::string> recipe;
|
||||
int width = 0;
|
||||
CraftMethod method = CRAFT_METHOD_NORMAL;
|
||||
/*
|
||||
CraftDefinitionShaped
|
||||
*/
|
||||
if (type == "shaped") {
|
||||
lua_getfield(L, table, "recipe");
|
||||
if (lua_isnil(L, -1))
|
||||
throw LuaError("Either output or recipe has to be defined");
|
||||
if (!readCraftRecipeShaped(L, -1, width, recipe))
|
||||
throw LuaError("Invalid crafting recipe");
|
||||
}
|
||||
/*
|
||||
CraftDefinitionShapeless
|
||||
*/
|
||||
else if (type == "shapeless") {
|
||||
lua_getfield(L, table, "recipe");
|
||||
if (lua_isnil(L, -1))
|
||||
throw LuaError("Either output or recipe has to be defined");
|
||||
if (!readCraftRecipeShapeless(L, -1, recipe))
|
||||
throw LuaError("Invalid crafting recipe");
|
||||
}
|
||||
/*
|
||||
CraftDefinitionCooking
|
||||
*/
|
||||
else if (type == "cooking") {
|
||||
method = CRAFT_METHOD_COOKING;
|
||||
std::string rec = getstringfield_default(L, table, "recipe", "");
|
||||
if (rec.empty())
|
||||
throw LuaError("Crafting definition (cooking)"
|
||||
" is missing a recipe");
|
||||
recipe.push_back(rec);
|
||||
}
|
||||
/*
|
||||
CraftDefinitionFuel
|
||||
*/
|
||||
else if (type == "fuel") {
|
||||
method = CRAFT_METHOD_FUEL;
|
||||
std::string rec = getstringfield_default(L, table, "recipe", "");
|
||||
if (rec.empty())
|
||||
throw LuaError("Crafting definition (fuel)"
|
||||
" is missing a recipe");
|
||||
recipe.push_back(rec);
|
||||
} else {
|
||||
throw LuaError("Unknown crafting definition type: \"" + type + "\"");
|
||||
}
|
||||
|
||||
std::vector<ItemStack> items;
|
||||
items.reserve(recipe.size());
|
||||
for (const auto &item : recipe)
|
||||
items.emplace_back(item, 1, 0, getServer(L)->idef());
|
||||
CraftInput input(method, width, items);
|
||||
|
||||
if (!craftdef->clearCraftsByInput(input, getServer(L))) {
|
||||
warningstream << "No craft recipe matches input" << std::endl;
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_craft_result(input)
|
||||
int ModApiCraft::l_get_craft_result(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
int input_i = 1;
|
||||
std::string method_s = getstringfield_default(L, input_i, "method", "normal");
|
||||
enum CraftMethod method = (CraftMethod)getenumfield(L, input_i, "method",
|
||||
es_CraftMethod, CRAFT_METHOD_NORMAL);
|
||||
int width = 1;
|
||||
lua_getfield(L, input_i, "width");
|
||||
if(lua_isnumber(L, -1))
|
||||
width = luaL_checkinteger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, input_i, "items");
|
||||
std::vector<ItemStack> items = read_items(L, -1,getServer(L));
|
||||
lua_pop(L, 1); // items
|
||||
|
||||
IGameDef *gdef = getServer(L);
|
||||
ICraftDefManager *cdef = gdef->cdef();
|
||||
CraftInput input(method, width, items);
|
||||
CraftOutput output;
|
||||
std::vector<ItemStack> output_replacements;
|
||||
bool got = cdef->getCraftResult(input, output, output_replacements, true, gdef);
|
||||
lua_newtable(L); // output table
|
||||
if (got) {
|
||||
ItemStack item;
|
||||
item.deSerialize(output.item, gdef->idef());
|
||||
LuaItemStack::create(L, item);
|
||||
lua_setfield(L, -2, "item");
|
||||
setintfield(L, -1, "time", output.time);
|
||||
push_items(L, output_replacements);
|
||||
lua_setfield(L, -2, "replacements");
|
||||
} else {
|
||||
LuaItemStack::create(L, ItemStack());
|
||||
lua_setfield(L, -2, "item");
|
||||
setintfield(L, -1, "time", 0);
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "replacements");
|
||||
}
|
||||
lua_newtable(L); // decremented input table
|
||||
lua_pushstring(L, method_s.c_str());
|
||||
lua_setfield(L, -2, "method");
|
||||
lua_pushinteger(L, width);
|
||||
lua_setfield(L, -2, "width");
|
||||
push_items(L, input.items);
|
||||
lua_setfield(L, -2, "items");
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
static void push_craft_recipe(lua_State *L, IGameDef *gdef,
|
||||
const CraftDefinition *recipe,
|
||||
const CraftOutput &tmpout)
|
||||
{
|
||||
CraftInput input = recipe->getInput(tmpout, gdef);
|
||||
CraftOutput output = recipe->getOutput(input, gdef);
|
||||
|
||||
lua_newtable(L); // items
|
||||
std::vector<ItemStack>::const_iterator iter = input.items.begin();
|
||||
for (u16 j = 1; iter != input.items.end(); ++iter, j++) {
|
||||
if (iter->empty())
|
||||
continue;
|
||||
lua_pushstring(L, iter->name.c_str());
|
||||
lua_rawseti(L, -2, j);
|
||||
}
|
||||
lua_setfield(L, -2, "items");
|
||||
setintfield(L, -1, "width", input.width);
|
||||
|
||||
std::string method_s;
|
||||
switch (input.method) {
|
||||
case CRAFT_METHOD_NORMAL:
|
||||
method_s = "normal";
|
||||
break;
|
||||
case CRAFT_METHOD_COOKING:
|
||||
method_s = "cooking";
|
||||
break;
|
||||
case CRAFT_METHOD_FUEL:
|
||||
method_s = "fuel";
|
||||
break;
|
||||
default:
|
||||
method_s = "unknown";
|
||||
}
|
||||
lua_pushstring(L, method_s.c_str());
|
||||
lua_setfield(L, -2, "method");
|
||||
|
||||
// Deprecated, only for compatibility's sake
|
||||
lua_pushstring(L, method_s.c_str());
|
||||
lua_setfield(L, -2, "type");
|
||||
|
||||
lua_pushstring(L, output.item.c_str());
|
||||
lua_setfield(L, -2, "output");
|
||||
}
|
||||
|
||||
static void push_craft_recipes(lua_State *L, IGameDef *gdef,
|
||||
const std::vector<CraftDefinition*> &recipes,
|
||||
const CraftOutput &output)
|
||||
{
|
||||
lua_createtable(L, recipes.size(), 0);
|
||||
|
||||
if (recipes.empty()) {
|
||||
lua_pushnil(L);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<CraftDefinition*>::const_iterator it = recipes.begin();
|
||||
for (unsigned i = 0; it != recipes.end(); ++it) {
|
||||
lua_newtable(L);
|
||||
push_craft_recipe(L, gdef, *it, output);
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// get_craft_recipe(result item)
|
||||
int ModApiCraft::l_get_craft_recipe(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
std::string item = luaL_checkstring(L, 1);
|
||||
Server *server = getServer(L);
|
||||
CraftOutput output(item, 0);
|
||||
std::vector<CraftDefinition*> recipes = server->cdef()
|
||||
->getCraftRecipes(output, server, 1);
|
||||
|
||||
lua_createtable(L, 1, 0);
|
||||
|
||||
if (recipes.empty()) {
|
||||
lua_pushnil(L);
|
||||
lua_setfield(L, -2, "items");
|
||||
setintfield(L, -1, "width", 0);
|
||||
return 1;
|
||||
}
|
||||
push_craft_recipe(L, server, recipes[0], output);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_all_craft_recipes(result item)
|
||||
int ModApiCraft::l_get_all_craft_recipes(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
std::string item = luaL_checkstring(L, 1);
|
||||
Server *server = getServer(L);
|
||||
CraftOutput output(item, 0);
|
||||
std::vector<CraftDefinition*> recipes = server->cdef()
|
||||
->getCraftRecipes(output, server);
|
||||
|
||||
push_craft_recipes(L, server, recipes, output);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiCraft::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(get_all_craft_recipes);
|
||||
API_FCT(get_craft_recipe);
|
||||
API_FCT(get_craft_result);
|
||||
API_FCT(register_craft);
|
||||
API_FCT(clear_craft);
|
||||
}
|
48
src/script/lua_api/l_craft.h
Normal file
48
src/script/lua_api/l_craft.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
struct CraftReplacements;
|
||||
|
||||
class ModApiCraft : public ModApiBase {
|
||||
private:
|
||||
static int l_register_craft(lua_State *L);
|
||||
static int l_get_craft_recipe(lua_State *L);
|
||||
static int l_get_all_craft_recipes(lua_State *L);
|
||||
static int l_get_craft_result(lua_State *L);
|
||||
static int l_clear_craft(lua_State *L);
|
||||
|
||||
static bool readCraftReplacements(lua_State *L, int index,
|
||||
CraftReplacements &replacements);
|
||||
static bool readCraftRecipeShapeless(lua_State *L, int index,
|
||||
std::vector<std::string> &recipe);
|
||||
static bool readCraftRecipeShaped(lua_State *L, int index,
|
||||
int &width, std::vector<std::string> &recipe);
|
||||
|
||||
static struct EnumString es_CraftMethod[];
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
1616
src/script/lua_api/l_env.cpp
Normal file
1616
src/script/lua_api/l_env.cpp
Normal file
File diff suppressed because it is too large
Load Diff
333
src/script/lua_api/l_env.h
Normal file
333
src/script/lua_api/l_env.h
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "serverenvironment.h"
|
||||
#include "raycast.h"
|
||||
|
||||
class ModApiEnvMod : public ModApiBase {
|
||||
private:
|
||||
// set_node(pos, node)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_set_node(lua_State *L);
|
||||
|
||||
// bulk_set_node([pos1, pos2, ...], node)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_bulk_set_node(lua_State *L);
|
||||
|
||||
static int l_add_node(lua_State *L);
|
||||
|
||||
// remove_node(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_remove_node(lua_State *L);
|
||||
|
||||
// swap_node(pos, node)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_swap_node(lua_State *L);
|
||||
|
||||
// get_node(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_get_node(lua_State *L);
|
||||
|
||||
// get_node_or_nil(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_get_node_or_nil(lua_State *L);
|
||||
|
||||
// get_node_light(pos, timeofday)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
// timeofday: nil = current time, 0 = night, 0.5 = day
|
||||
static int l_get_node_light(lua_State *L);
|
||||
|
||||
// get_natural_light(pos, timeofday)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
// timeofday: nil = current time, 0 = night, 0.5 = day
|
||||
static int l_get_natural_light(lua_State *L);
|
||||
|
||||
// place_node(pos, node)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_place_node(lua_State *L);
|
||||
|
||||
// dig_node(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_dig_node(lua_State *L);
|
||||
|
||||
// punch_node(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_punch_node(lua_State *L);
|
||||
|
||||
// get_node_max_level(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_get_node_max_level(lua_State *L);
|
||||
|
||||
// get_node_level(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_get_node_level(lua_State *L);
|
||||
|
||||
// set_node_level(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_set_node_level(lua_State *L);
|
||||
|
||||
// add_node_level(pos)
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_add_node_level(lua_State *L);
|
||||
|
||||
// find_nodes_with_meta(pos1, pos2)
|
||||
static int l_find_nodes_with_meta(lua_State *L);
|
||||
|
||||
// get_meta(pos)
|
||||
static int l_get_meta(lua_State *L);
|
||||
|
||||
// get_node_timer(pos)
|
||||
static int l_get_node_timer(lua_State *L);
|
||||
|
||||
// add_entity(pos, entityname) -> ObjectRef or nil
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_add_entity(lua_State *L);
|
||||
|
||||
// add_item(pos, itemstack or itemstring or table) -> ObjectRef or nil
|
||||
// pos = {x=num, y=num, z=num}
|
||||
static int l_add_item(lua_State *L);
|
||||
|
||||
// get_connected_players()
|
||||
static int l_get_connected_players(lua_State *L);
|
||||
|
||||
// get_player_by_name(name)
|
||||
static int l_get_player_by_name(lua_State *L);
|
||||
|
||||
// get_objects_inside_radius(pos, radius)
|
||||
static int l_get_objects_inside_radius(lua_State *L);
|
||||
|
||||
// set_timeofday(val)
|
||||
// val = 0...1
|
||||
static int l_set_timeofday(lua_State *L);
|
||||
|
||||
// get_timeofday() -> 0...1
|
||||
static int l_get_timeofday(lua_State *L);
|
||||
|
||||
// get_gametime()
|
||||
static int l_get_gametime(lua_State *L);
|
||||
|
||||
// get_day_count() -> int
|
||||
static int l_get_day_count(lua_State *L);
|
||||
|
||||
// find_node_near(pos, radius, nodenames, search_center) -> pos or nil
|
||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
||||
static int l_find_node_near(lua_State *L);
|
||||
|
||||
// find_nodes_near(pos, radius, nodenames, search_center) -> list of positions
|
||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
||||
static int l_find_nodes_near(lua_State *L);
|
||||
|
||||
// find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions
|
||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
||||
static int l_find_nodes_near_under_air(lua_State *L);
|
||||
|
||||
// find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions
|
||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
||||
static int l_find_nodes_near_under_air_except(lua_State *L);
|
||||
|
||||
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions
|
||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
||||
static int l_find_nodes_in_area(lua_State *L);
|
||||
|
||||
// find_surface_nodes_in_area(minp, maxp, nodenames) -> list of positions
|
||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
|
||||
static int l_find_nodes_in_area_under_air(lua_State *L);
|
||||
|
||||
// fix_light(p1, p2) -> true/false
|
||||
static int l_fix_light(lua_State *L);
|
||||
|
||||
// load_area(p1)
|
||||
static int l_load_area(lua_State *L);
|
||||
|
||||
// emerge_area(p1, p2)
|
||||
static int l_emerge_area(lua_State *L);
|
||||
|
||||
// delete_area(p1, p2) -> true/false
|
||||
static int l_delete_area(lua_State *L);
|
||||
|
||||
// get_perlin(seeddiff, octaves, persistence, scale)
|
||||
// returns world-specific PerlinNoise
|
||||
static int l_get_perlin(lua_State *L);
|
||||
|
||||
// get_perlin_map(noiseparams, size)
|
||||
// returns world-specific PerlinNoiseMap
|
||||
static int l_get_perlin_map(lua_State *L);
|
||||
|
||||
// get_voxel_manip()
|
||||
// returns world-specific voxel manipulator
|
||||
static int l_get_voxel_manip(lua_State *L);
|
||||
|
||||
// clear_objects()
|
||||
// clear all objects in the environment
|
||||
static int l_clear_objects(lua_State *L);
|
||||
|
||||
// spawn_tree(pos, treedef)
|
||||
static int l_spawn_tree(lua_State *L);
|
||||
|
||||
// line_of_sight(pos1, pos2) -> true/false
|
||||
static int l_line_of_sight(lua_State *L);
|
||||
|
||||
// raycast(pos1, pos2, objects, liquids) -> Raycast
|
||||
static int l_raycast(lua_State *L);
|
||||
|
||||
// find_path(pos1, pos2, searchdistance,
|
||||
// max_jump, max_drop, algorithm) -> table containing path
|
||||
static int l_find_path(lua_State *L);
|
||||
|
||||
// transforming_liquid_add(pos)
|
||||
static int l_transforming_liquid_add(lua_State *L);
|
||||
|
||||
// forceload_block(blockpos)
|
||||
// forceloads a block
|
||||
static int l_forceload_block(lua_State *L);
|
||||
|
||||
// forceload_free_block(blockpos)
|
||||
// stops forceloading a position
|
||||
static int l_forceload_free_block(lua_State *L);
|
||||
|
||||
// Get a string translated server side
|
||||
static int l_get_translated_string(lua_State * L);
|
||||
|
||||
/* Helpers */
|
||||
|
||||
static void collectNodeIds(lua_State *L, int idx,
|
||||
const NodeDefManager *ndef, std::vector<content_t> &filter);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
static void InitializeClient(lua_State *L, int top);
|
||||
|
||||
static struct EnumString es_ClearObjectsMode[];
|
||||
};
|
||||
|
||||
class LuaABM : public ActiveBlockModifier {
|
||||
private:
|
||||
int m_id;
|
||||
|
||||
std::vector<std::string> m_trigger_contents;
|
||||
std::vector<std::string> m_required_neighbors;
|
||||
float m_trigger_interval;
|
||||
u32 m_trigger_chance;
|
||||
bool m_simple_catch_up;
|
||||
public:
|
||||
LuaABM(lua_State *L, int id,
|
||||
const std::vector<std::string> &trigger_contents,
|
||||
const std::vector<std::string> &required_neighbors,
|
||||
float trigger_interval, u32 trigger_chance, bool simple_catch_up):
|
||||
m_id(id),
|
||||
m_trigger_contents(trigger_contents),
|
||||
m_required_neighbors(required_neighbors),
|
||||
m_trigger_interval(trigger_interval),
|
||||
m_trigger_chance(trigger_chance),
|
||||
m_simple_catch_up(simple_catch_up)
|
||||
{
|
||||
}
|
||||
virtual const std::vector<std::string> &getTriggerContents() const
|
||||
{
|
||||
return m_trigger_contents;
|
||||
}
|
||||
virtual const std::vector<std::string> &getRequiredNeighbors() const
|
||||
{
|
||||
return m_required_neighbors;
|
||||
}
|
||||
virtual float getTriggerInterval()
|
||||
{
|
||||
return m_trigger_interval;
|
||||
}
|
||||
virtual u32 getTriggerChance()
|
||||
{
|
||||
return m_trigger_chance;
|
||||
}
|
||||
virtual bool getSimpleCatchUp()
|
||||
{
|
||||
return m_simple_catch_up;
|
||||
}
|
||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
|
||||
u32 active_object_count, u32 active_object_count_wider);
|
||||
};
|
||||
|
||||
class LuaLBM : public LoadingBlockModifierDef
|
||||
{
|
||||
private:
|
||||
int m_id;
|
||||
public:
|
||||
LuaLBM(lua_State *L, int id,
|
||||
const std::set<std::string> &trigger_contents,
|
||||
const std::string &name,
|
||||
bool run_at_every_load):
|
||||
m_id(id)
|
||||
{
|
||||
this->run_at_every_load = run_at_every_load;
|
||||
this->trigger_contents = trigger_contents;
|
||||
this->name = name;
|
||||
}
|
||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n);
|
||||
};
|
||||
|
||||
//! Lua wrapper for RaycastState objects
|
||||
class LuaRaycast : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
//! Inner state
|
||||
RaycastState state;
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
/*!
|
||||
* Raycast:next() -> pointed_thing
|
||||
* Returns the next pointed thing on the ray.
|
||||
*/
|
||||
static int l_next(lua_State *L);
|
||||
public:
|
||||
//! Constructor with the same arguments as RaycastState.
|
||||
LuaRaycast(
|
||||
const core::line3d<f32> &shootline,
|
||||
bool objects_pointable,
|
||||
bool liquids_pointable) :
|
||||
state(shootline, objects_pointable, liquids_pointable)
|
||||
{}
|
||||
|
||||
//! Creates a LuaRaycast and leaves it on top of the stack.
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
/*!
|
||||
* Returns the Raycast from the stack or throws an error.
|
||||
* @param narg location of the RaycastState in the stack
|
||||
*/
|
||||
static LuaRaycast *checkobject(lua_State *L, int narg);
|
||||
|
||||
//! Registers Raycast as a Lua userdata type.
|
||||
static void Register(lua_State *L);
|
||||
};
|
||||
|
||||
struct ScriptCallbackState {
|
||||
ServerScripting *script;
|
||||
int callback_ref;
|
||||
int args_ref;
|
||||
unsigned int refcount;
|
||||
std::string origin;
|
||||
};
|
251
src/script/lua_api/l_http.cpp
Normal file
251
src/script/lua_api/l_http.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "lua_api/l_http.h"
|
||||
#include "httpfetch.h"
|
||||
#include "settings.h"
|
||||
#include "debug.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <cctype>
|
||||
|
||||
#define HTTP_API(name) \
|
||||
lua_pushstring(L, #name); \
|
||||
lua_pushcfunction(L, l_http_##name); \
|
||||
lua_settable(L, -3);
|
||||
|
||||
#if USE_CURL
|
||||
void ModApiHttp::read_http_fetch_request(lua_State *L, HTTPFetchRequest &req)
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
req.caller = httpfetch_caller_alloc_secure();
|
||||
getstringfield(L, 1, "url", req.url);
|
||||
lua_getfield(L, 1, "user_agent");
|
||||
if (lua_isstring(L, -1))
|
||||
req.useragent = getstringfield_default(L, 1, "user_agent", "");
|
||||
lua_pop(L, 1);
|
||||
req.multipart = getboolfield_default(L, 1, "multipart", false);
|
||||
req.timeout = getintfield_default(L, 1, "timeout", 3) * 1000;
|
||||
|
||||
lua_getfield(L, 1, "method");
|
||||
if (lua_isstring(L, -1)) {
|
||||
std::string mth = getstringfield_default(L, 1, "method", "");
|
||||
if (mth == "GET")
|
||||
req.method = HTTP_GET;
|
||||
else if (mth == "POST")
|
||||
req.method = HTTP_POST;
|
||||
else if (mth == "PUT")
|
||||
req.method = HTTP_PUT;
|
||||
else if (mth == "DELETE")
|
||||
req.method = HTTP_DELETE;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
// post_data: if table, post form data, otherwise raw data DEPRECATED use data and method instead
|
||||
lua_getfield(L, 1, "post_data");
|
||||
if (lua_isnil(L, 2)) {
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, 1, "data");
|
||||
}
|
||||
else {
|
||||
req.method = HTTP_POST;
|
||||
}
|
||||
|
||||
if (lua_istable(L, 2)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 2) != 0) {
|
||||
req.fields[readParam<std::string>(L, -2)] = readParam<std::string>(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (lua_isstring(L, 2)) {
|
||||
req.raw_data = readParam<std::string>(L, 2);
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "extra_headers");
|
||||
if (lua_istable(L, 2)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 2) != 0) {
|
||||
req.extra_headers.emplace_back(readParam<std::string>(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void ModApiHttp::push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool completed)
|
||||
{
|
||||
lua_newtable(L);
|
||||
setboolfield(L, -1, "succeeded", res.succeeded);
|
||||
setboolfield(L, -1, "timeout", res.timeout);
|
||||
setboolfield(L, -1, "completed", completed);
|
||||
setintfield(L, -1, "code", res.response_code);
|
||||
setstringfield(L, -1, "data", res.data);
|
||||
}
|
||||
|
||||
// http_api.fetch_sync(HTTPRequest definition)
|
||||
int ModApiHttp::l_http_fetch_sync(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
HTTPFetchRequest req;
|
||||
read_http_fetch_request(L, req);
|
||||
|
||||
infostream << "Mod performs HTTP request with URL " << req.url << std::endl;
|
||||
|
||||
HTTPFetchResult res;
|
||||
httpfetch_sync(req, res);
|
||||
|
||||
push_http_fetch_result(L, res, true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// http_api.fetch_async(HTTPRequest definition)
|
||||
int ModApiHttp::l_http_fetch_async(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
HTTPFetchRequest req;
|
||||
read_http_fetch_request(L, req);
|
||||
|
||||
infostream << "Mod performs HTTP request with URL " << req.url << std::endl;
|
||||
httpfetch_async(req);
|
||||
|
||||
// Convert handle to hex string since lua can't handle 64-bit integers
|
||||
std::stringstream handle_conversion_stream;
|
||||
handle_conversion_stream << std::hex << req.caller;
|
||||
std::string caller_handle(handle_conversion_stream.str());
|
||||
|
||||
lua_pushstring(L, caller_handle.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// http_api.fetch_async_get(handle)
|
||||
int ModApiHttp::l_http_fetch_async_get(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
std::string handle_str = luaL_checkstring(L, 1);
|
||||
|
||||
// Convert hex string back to 64-bit handle
|
||||
u64 handle;
|
||||
std::stringstream handle_conversion_stream;
|
||||
handle_conversion_stream << std::hex << handle_str;
|
||||
handle_conversion_stream >> handle;
|
||||
|
||||
HTTPFetchResult res;
|
||||
bool completed = httpfetch_async_get(handle, res);
|
||||
|
||||
push_http_fetch_result(L, res, completed);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ModApiHttp::l_request_http_api(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
// We have to make sure that this function is being called directly by
|
||||
// a mod, otherwise a malicious mod could override this function and
|
||||
// steal its return value.
|
||||
lua_Debug info;
|
||||
|
||||
// Make sure there's only one item below this function on the stack...
|
||||
if (lua_getstack(L, 2, &info)) {
|
||||
return 0;
|
||||
}
|
||||
FATAL_ERROR_IF(!lua_getstack(L, 1, &info), "lua_getstack() failed");
|
||||
FATAL_ERROR_IF(!lua_getinfo(L, "S", &info), "lua_getinfo() failed");
|
||||
|
||||
// ...and that that item is the main file scope.
|
||||
if (strcmp(info.what, "main") != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Mod must be listed in secure.http_mods or secure.trusted_mods
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
if (!lua_isstring(L, -1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string mod_name = readParam<std::string>(L, -1);
|
||||
std::string http_mods = g_settings->get("secure.http_mods");
|
||||
http_mods.erase(std::remove(http_mods.begin(), http_mods.end(), ' '), http_mods.end());
|
||||
std::vector<std::string> mod_list_http = str_split(http_mods, ',');
|
||||
|
||||
std::string trusted_mods = g_settings->get("secure.trusted_mods");
|
||||
trusted_mods.erase(std::remove(trusted_mods.begin(), trusted_mods.end(), ' '), trusted_mods.end());
|
||||
std::vector<std::string> mod_list_trusted = str_split(trusted_mods, ',');
|
||||
|
||||
mod_list_http.insert(mod_list_http.end(), mod_list_trusted.begin(), mod_list_trusted.end());
|
||||
if (std::find(mod_list_http.begin(), mod_list_http.end(), mod_name) == mod_list_http.end()) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "http_add_fetch");
|
||||
|
||||
lua_newtable(L);
|
||||
HTTP_API(fetch_async);
|
||||
HTTP_API(fetch_async_get);
|
||||
|
||||
// Stack now looks like this:
|
||||
// <core.http_add_fetch> <table with fetch_async, fetch_async_get>
|
||||
// Now call core.http_add_fetch to append .fetch(request, callback) to table
|
||||
lua_call(L, 1, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ModApiHttp::l_get_http_api(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
lua_newtable(L);
|
||||
HTTP_API(fetch_async);
|
||||
HTTP_API(fetch_async_get);
|
||||
HTTP_API(fetch_sync);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ModApiHttp::Initialize(lua_State *L, int top)
|
||||
{
|
||||
#if USE_CURL
|
||||
API_FCT(get_http_api);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ModApiHttp::InitializeAsync(lua_State *L, int top)
|
||||
{
|
||||
#if USE_CURL
|
||||
API_FCT(get_http_api);
|
||||
#endif
|
||||
}
|
54
src/script/lua_api/l_http.h
Normal file
54
src/script/lua_api/l_http.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "config.h"
|
||||
|
||||
struct HTTPFetchRequest;
|
||||
struct HTTPFetchResult;
|
||||
|
||||
class ModApiHttp : public ModApiBase {
|
||||
private:
|
||||
#if USE_CURL
|
||||
// Helpers for HTTP fetch functions
|
||||
static void read_http_fetch_request(lua_State *L, HTTPFetchRequest &req);
|
||||
static void push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool completed = true);
|
||||
|
||||
// http_fetch_sync({url=, timeout=, data=})
|
||||
static int l_http_fetch_sync(lua_State *L);
|
||||
|
||||
// http_fetch_async({url=, timeout=, data=})
|
||||
static int l_http_fetch_async(lua_State *L);
|
||||
|
||||
// http_fetch_async_get(handle)
|
||||
static int l_http_fetch_async_get(lua_State *L);
|
||||
|
||||
// request_http_api()
|
||||
static int l_request_http_api(lua_State *L);
|
||||
|
||||
// get_http_api()
|
||||
static int l_get_http_api(lua_State *L);
|
||||
#endif
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
static void InitializeAsync(lua_State *L, int top);
|
||||
};
|
79
src/script/lua_api/l_internal.h
Normal file
79
src/script/lua_api/l_internal.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
/* WARNING!!!! do NOT add this header in any include file or any code file */
|
||||
/* not being a modapi file!!!!!!!! */
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/c_internal.h"
|
||||
|
||||
#define luamethod(class, name) {#name, class::l_##name}
|
||||
|
||||
#define luamethod_dep(class, good, bad) \
|
||||
{#bad, [](lua_State *L) -> int { \
|
||||
return l_deprecated_function(L, #good, #bad, &class::l_##good); \
|
||||
}}
|
||||
|
||||
#define luamethod_aliased(class, good, bad) \
|
||||
luamethod(class, good), \
|
||||
luamethod_dep(class, good, bad)
|
||||
|
||||
#define API_FCT(name) registerFunction(L, #name, l_##name, top)
|
||||
|
||||
// For future use
|
||||
#define MAP_LOCK_REQUIRED ((void)0)
|
||||
#define NO_MAP_LOCK_REQUIRED ((void)0)
|
||||
|
||||
/* In debug mode ensure no code tries to retrieve the server env when it isn't
|
||||
* actually available (in CSM) */
|
||||
#if !defined(SERVER) && !defined(NDEBUG)
|
||||
#define DEBUG_ASSERT_NO_CLIENTAPI \
|
||||
FATAL_ERROR_IF(getClient(L) != nullptr, "Tried " \
|
||||
"to retrieve ServerEnvironment on client")
|
||||
#else
|
||||
#define DEBUG_ASSERT_NO_CLIENTAPI ((void)0)
|
||||
#endif
|
||||
|
||||
// Retrieve ServerEnvironment pointer as `env` (no map lock)
|
||||
#define GET_ENV_PTR_NO_MAP_LOCK \
|
||||
DEBUG_ASSERT_NO_CLIENTAPI; \
|
||||
ServerEnvironment *env = (ServerEnvironment *)getEnv(L); \
|
||||
if (env == NULL) \
|
||||
return 0
|
||||
|
||||
// Retrieve ServerEnvironment pointer as `env`
|
||||
#define GET_ENV_PTR \
|
||||
MAP_LOCK_REQUIRED; \
|
||||
GET_ENV_PTR_NO_MAP_LOCK
|
||||
|
||||
// Retrieve Environment pointer as `env` (no map lock)
|
||||
#define GET_PLAIN_ENV_PTR_NO_MAP_LOCK \
|
||||
Environment *env = (Environment *)getEnv(L); \
|
||||
if (env == NULL) \
|
||||
return 0
|
||||
|
||||
// Retrieve Environment pointer as `env`
|
||||
#define GET_PLAIN_ENV_PTR \
|
||||
MAP_LOCK_REQUIRED; \
|
||||
GET_PLAIN_ENV_PTR_NO_MAP_LOCK
|
559
src/script/lua_api/l_inventory.cpp
Normal file
559
src/script/lua_api/l_inventory.cpp
Normal file
@ -0,0 +1,559 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_inventory.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "lua_api/l_item.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "server.h"
|
||||
#include "server/serverinventorymgr.h"
|
||||
#include "remoteplayer.h"
|
||||
|
||||
/*
|
||||
InvRef
|
||||
*/
|
||||
InvRef* InvRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if(!ud) luaL_typerror(L, narg, className);
|
||||
return *(InvRef**)ud; // unbox pointer
|
||||
}
|
||||
|
||||
Inventory* InvRef::getinv(lua_State *L, InvRef *ref)
|
||||
{
|
||||
return getServerInventoryMgr(L)->getInventory(ref->m_loc);
|
||||
}
|
||||
|
||||
InventoryList* InvRef::getlist(lua_State *L, InvRef *ref,
|
||||
const char *listname)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
Inventory *inv = getinv(L, ref);
|
||||
if(!inv)
|
||||
return NULL;
|
||||
return inv->getList(listname);
|
||||
}
|
||||
|
||||
void InvRef::reportInventoryChange(lua_State *L, InvRef *ref)
|
||||
{
|
||||
// Inform other things that the inventory has changed
|
||||
getServerInventoryMgr(L)->setInventoryModified(ref->m_loc);
|
||||
}
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
int InvRef::gc_object(lua_State *L) {
|
||||
InvRef *o = *(InvRef **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// is_empty(self, listname) -> true/false
|
||||
int InvRef::l_is_empty(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
if(list && list->getUsedSlots() > 0){
|
||||
lua_pushboolean(L, false);
|
||||
} else {
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_size(self, listname)
|
||||
int InvRef::l_get_size(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
if(list){
|
||||
lua_pushinteger(L, list->getSize());
|
||||
} else {
|
||||
lua_pushinteger(L, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_width(self, listname)
|
||||
int InvRef::l_get_width(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
if(list){
|
||||
lua_pushinteger(L, list->getWidth());
|
||||
} else {
|
||||
lua_pushinteger(L, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_size(self, listname, size)
|
||||
int InvRef::l_set_size(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
|
||||
int newsize = luaL_checknumber(L, 3);
|
||||
if (newsize < 0) {
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Inventory *inv = getinv(L, ref);
|
||||
if(inv == NULL){
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
if(newsize == 0){
|
||||
inv->deleteList(listname);
|
||||
reportInventoryChange(L, ref);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
InventoryList *list = inv->getList(listname);
|
||||
if(list){
|
||||
list->setSize(newsize);
|
||||
} else {
|
||||
list = inv->addList(listname, newsize);
|
||||
if (!list)
|
||||
{
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
reportInventoryChange(L, ref);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_width(self, listname, size)
|
||||
int InvRef::l_set_width(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
int newwidth = luaL_checknumber(L, 3);
|
||||
Inventory *inv = getinv(L, ref);
|
||||
if(inv == NULL){
|
||||
return 0;
|
||||
}
|
||||
InventoryList *list = inv->getList(listname);
|
||||
if(list){
|
||||
list->setWidth(newwidth);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
reportInventoryChange(L, ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_stack(self, listname, i) -> itemstack
|
||||
int InvRef::l_get_stack(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
int i = luaL_checknumber(L, 3) - 1;
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
ItemStack item;
|
||||
if(list != NULL && i >= 0 && i < (int) list->getSize())
|
||||
item = list->getItem(i);
|
||||
LuaItemStack::create(L, item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_stack(self, listname, i, stack) -> true/false
|
||||
int InvRef::l_set_stack(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
int i = luaL_checknumber(L, 3) - 1;
|
||||
ItemStack newitem = read_item(L, 4, getServer(L)->idef());
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
if(list != NULL && i >= 0 && i < (int) list->getSize()){
|
||||
list->changeItem(i, newitem);
|
||||
reportInventoryChange(L, ref);
|
||||
lua_pushboolean(L, true);
|
||||
} else {
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_list(self, listname) -> list or nil
|
||||
int InvRef::l_get_list(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
Inventory *inv = getinv(L, ref);
|
||||
if(inv){
|
||||
push_inventory_list(L, inv, listname);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_list(self, listname, list)
|
||||
int InvRef::l_set_list(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
Inventory *inv = getinv(L, ref);
|
||||
if(inv == NULL){
|
||||
return 0;
|
||||
}
|
||||
InventoryList *list = inv->getList(listname);
|
||||
if(list)
|
||||
read_inventory_list(L, 3, inv, listname,
|
||||
getServer(L), list->getSize());
|
||||
else
|
||||
read_inventory_list(L, 3, inv, listname, getServer(L));
|
||||
reportInventoryChange(L, ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_lists(self) -> list of InventoryLists
|
||||
int InvRef::l_get_lists(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
Inventory *inv = getinv(L, ref);
|
||||
if (!inv) {
|
||||
return 0;
|
||||
}
|
||||
std::vector<const InventoryList*> lists = inv->getLists();
|
||||
std::vector<const InventoryList*>::iterator iter = lists.begin();
|
||||
lua_createtable(L, 0, lists.size());
|
||||
for (; iter != lists.end(); iter++) {
|
||||
const char* name = (*iter)->getName().c_str();
|
||||
lua_pushstring(L, name);
|
||||
push_inventory_list(L, inv, name);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_lists(self, lists)
|
||||
int InvRef::l_set_lists(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
Inventory *inv = getinv(L, ref);
|
||||
if (!inv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make a temporary inventory in case reading fails
|
||||
Inventory *tempInv(inv);
|
||||
tempInv->clear();
|
||||
|
||||
Server *server = getServer(L);
|
||||
|
||||
lua_pushnil(L);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
while (lua_next(L, 2)) {
|
||||
const char *listname = lua_tostring(L, -2);
|
||||
read_inventory_list(L, -1, tempInv, listname, server);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
inv = tempInv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
|
||||
// Returns the leftover stack
|
||||
int InvRef::l_add_item(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
ItemStack item = read_item(L, 3, getServer(L)->idef());
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
if(list){
|
||||
ItemStack leftover = list->addItem(item);
|
||||
if(leftover.count != item.count)
|
||||
reportInventoryChange(L, ref);
|
||||
LuaItemStack::create(L, leftover);
|
||||
} else {
|
||||
LuaItemStack::create(L, item);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false
|
||||
// Returns true if the item completely fits into the list
|
||||
int InvRef::l_room_for_item(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
ItemStack item = read_item(L, 3, getServer(L)->idef());
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
if(list){
|
||||
lua_pushboolean(L, list->roomForItem(item));
|
||||
} else {
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// contains_item(self, listname, itemstack or itemstring or table or nil, [match_meta]) -> true/false
|
||||
// Returns true if the list contains the given count of the given item
|
||||
int InvRef::l_contains_item(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
ItemStack item = read_item(L, 3, getServer(L)->idef());
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
bool match_meta = false;
|
||||
if (lua_isboolean(L, 4))
|
||||
match_meta = readParam<bool>(L, 4);
|
||||
if (list) {
|
||||
lua_pushboolean(L, list->containsItem(item, match_meta));
|
||||
} else {
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
|
||||
// Returns the items that were actually removed
|
||||
int InvRef::l_remove_item(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const char *listname = luaL_checkstring(L, 2);
|
||||
ItemStack item = read_item(L, 3, getServer(L)->idef());
|
||||
InventoryList *list = getlist(L, ref, listname);
|
||||
if(list){
|
||||
ItemStack removed = list->removeItem(item);
|
||||
if(!removed.empty())
|
||||
reportInventoryChange(L, ref);
|
||||
LuaItemStack::create(L, removed);
|
||||
} else {
|
||||
LuaItemStack::create(L, ItemStack());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_location() -> location (like get_inventory(location))
|
||||
int InvRef::l_get_location(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *ref = checkobject(L, 1);
|
||||
const InventoryLocation &loc = ref->m_loc;
|
||||
switch(loc.type){
|
||||
case InventoryLocation::PLAYER:
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "player");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, loc.name.c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
return 1;
|
||||
case InventoryLocation::NODEMETA:
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "node");
|
||||
lua_setfield(L, -2, "type");
|
||||
push_v3s16(L, loc.p);
|
||||
lua_setfield(L, -2, "pos");
|
||||
return 1;
|
||||
case InventoryLocation::DETACHED:
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "detached");
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushstring(L, loc.name.c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
return 1;
|
||||
case InventoryLocation::UNDEFINED:
|
||||
case InventoryLocation::CURRENT_PLAYER:
|
||||
break;
|
||||
}
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "undefined");
|
||||
lua_setfield(L, -2, "type");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
InvRef::InvRef(const InventoryLocation &loc):
|
||||
m_loc(loc)
|
||||
{
|
||||
}
|
||||
|
||||
// Creates an InvRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
void InvRef::create(lua_State *L, const InventoryLocation &loc)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InvRef *o = new InvRef(loc);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
void InvRef::createPlayer(lua_State *L, RemotePlayer *player)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
InventoryLocation loc;
|
||||
loc.setPlayer(player->getName());
|
||||
create(L, loc);
|
||||
}
|
||||
void InvRef::createNodeMeta(lua_State *L, v3s16 p)
|
||||
{
|
||||
InventoryLocation loc;
|
||||
loc.setNodeMeta(p);
|
||||
create(L, loc);
|
||||
}
|
||||
|
||||
void InvRef::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
|
||||
// Cannot be created from Lua
|
||||
//lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char InvRef::className[] = "InvRef";
|
||||
const luaL_Reg InvRef::methods[] = {
|
||||
luamethod(InvRef, is_empty),
|
||||
luamethod(InvRef, get_size),
|
||||
luamethod(InvRef, set_size),
|
||||
luamethod(InvRef, get_width),
|
||||
luamethod(InvRef, set_width),
|
||||
luamethod(InvRef, get_stack),
|
||||
luamethod(InvRef, set_stack),
|
||||
luamethod(InvRef, get_list),
|
||||
luamethod(InvRef, set_list),
|
||||
luamethod(InvRef, get_lists),
|
||||
luamethod(InvRef, set_lists),
|
||||
luamethod(InvRef, add_item),
|
||||
luamethod(InvRef, room_for_item),
|
||||
luamethod(InvRef, contains_item),
|
||||
luamethod(InvRef, remove_item),
|
||||
luamethod(InvRef, get_location),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
// get_inventory(location)
|
||||
int ModApiInventory::l_get_inventory(lua_State *L)
|
||||
{
|
||||
InventoryLocation loc;
|
||||
|
||||
lua_getfield(L, 1, "type");
|
||||
std::string type = luaL_checkstring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if(type == "node"){
|
||||
MAP_LOCK_REQUIRED;
|
||||
lua_getfield(L, 1, "pos");
|
||||
v3s16 pos = check_v3s16(L, -1);
|
||||
loc.setNodeMeta(pos);
|
||||
|
||||
if (getServerInventoryMgr(L)->getInventory(loc) != NULL)
|
||||
InvRef::create(L, loc);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
if (type == "player") {
|
||||
lua_getfield(L, 1, "name");
|
||||
loc.setPlayer(luaL_checkstring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
} else if (type == "detached") {
|
||||
lua_getfield(L, 1, "name");
|
||||
loc.setDetached(luaL_checkstring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
if (getServerInventoryMgr(L)->getInventory(loc) != NULL)
|
||||
InvRef::create(L, loc);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
// END NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
}
|
||||
|
||||
// create_detached_inventory_raw(name, [player_name])
|
||||
int ModApiInventory::l_create_detached_inventory_raw(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
std::string player = readParam<std::string>(L, 2, "");
|
||||
if (getServerInventoryMgr(L)->createDetachedInventory(name, getServer(L)->idef(), player) != NULL) {
|
||||
InventoryLocation loc;
|
||||
loc.setDetached(name);
|
||||
InvRef::create(L, loc);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remove_detached_inventory_raw(name)
|
||||
int ModApiInventory::l_remove_detached_inventory_raw(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const std::string &name = luaL_checkstring(L, 1);
|
||||
lua_pushboolean(L, getServerInventoryMgr(L)->removeDetachedInventory(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiInventory::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(create_detached_inventory_raw);
|
||||
API_FCT(remove_detached_inventory_raw);
|
||||
API_FCT(get_inventory);
|
||||
}
|
129
src/script/lua_api/l_inventory.h
Normal file
129
src/script/lua_api/l_inventory.h
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
#include "inventory.h"
|
||||
#include "inventorymanager.h"
|
||||
|
||||
class RemotePlayer;
|
||||
|
||||
/*
|
||||
InvRef
|
||||
*/
|
||||
|
||||
class InvRef : public ModApiBase {
|
||||
private:
|
||||
InventoryLocation m_loc;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
static InvRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
static Inventory* getinv(lua_State *L, InvRef *ref);
|
||||
|
||||
static InventoryList* getlist(lua_State *L, InvRef *ref,
|
||||
const char *listname);
|
||||
|
||||
static void reportInventoryChange(lua_State *L, InvRef *ref);
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// is_empty(self, listname) -> true/false
|
||||
static int l_is_empty(lua_State *L);
|
||||
|
||||
// get_size(self, listname)
|
||||
static int l_get_size(lua_State *L);
|
||||
|
||||
// get_width(self, listname)
|
||||
static int l_get_width(lua_State *L);
|
||||
|
||||
// set_size(self, listname, size)
|
||||
static int l_set_size(lua_State *L);
|
||||
|
||||
// set_width(self, listname, size)
|
||||
static int l_set_width(lua_State *L);
|
||||
|
||||
// get_stack(self, listname, i) -> itemstack
|
||||
static int l_get_stack(lua_State *L);
|
||||
|
||||
// set_stack(self, listname, i, stack) -> true/false
|
||||
static int l_set_stack(lua_State *L);
|
||||
|
||||
// get_list(self, listname) -> list or nil
|
||||
static int l_get_list(lua_State *L);
|
||||
|
||||
// set_list(self, listname, list)
|
||||
static int l_set_list(lua_State *L);
|
||||
|
||||
// get_lists(self) -> list of InventoryLists
|
||||
static int l_get_lists(lua_State *L);
|
||||
|
||||
// set_lists(self, lists)
|
||||
static int l_set_lists(lua_State *L);
|
||||
|
||||
// add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
|
||||
// Returns the leftover stack
|
||||
static int l_add_item(lua_State *L);
|
||||
|
||||
// room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false
|
||||
// Returns true if the item completely fits into the list
|
||||
static int l_room_for_item(lua_State *L);
|
||||
|
||||
// contains_item(self, listname, itemstack or itemstring or table or nil, [match_meta]) -> true/false
|
||||
// Returns true if the list contains the given count of the given item name
|
||||
static int l_contains_item(lua_State *L);
|
||||
|
||||
// remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
|
||||
// Returns the items that were actually removed
|
||||
static int l_remove_item(lua_State *L);
|
||||
|
||||
// get_location() -> location (like get_inventory(location))
|
||||
static int l_get_location(lua_State *L);
|
||||
|
||||
public:
|
||||
InvRef(const InventoryLocation &loc);
|
||||
|
||||
~InvRef() = default;
|
||||
|
||||
// Creates an InvRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
static void create(lua_State *L, const InventoryLocation &loc);
|
||||
static void createPlayer(lua_State *L, RemotePlayer *player);
|
||||
static void createNodeMeta(lua_State *L, v3s16 p);
|
||||
static void Register(lua_State *L);
|
||||
};
|
||||
|
||||
class ModApiInventory : public ModApiBase {
|
||||
private:
|
||||
static int l_create_detached_inventory_raw(lua_State *L);
|
||||
|
||||
static int l_remove_detached_inventory_raw(lua_State *L);
|
||||
|
||||
static int l_get_inventory(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
273
src/script/lua_api/l_inventoryaction.cpp
Normal file
273
src/script/lua_api/l_inventoryaction.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
Dragonfire
|
||||
Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "l_inventoryaction.h"
|
||||
#include "l_internal.h"
|
||||
#include "client/client.h"
|
||||
|
||||
int LuaInventoryAction::gc_object(lua_State *L)
|
||||
{
|
||||
LuaInventoryAction *o = *(LuaInventoryAction **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::mt_tostring(lua_State *L)
|
||||
{
|
||||
LuaInventoryAction *o = checkobject(L, 1);
|
||||
std::ostringstream os(std::ios::binary);
|
||||
o->m_action->serialize(os);
|
||||
lua_pushfstring(L, "InventoryAction(\"%s\")", os.str().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::l_apply(lua_State *L)
|
||||
{
|
||||
LuaInventoryAction *o = checkobject(L, 1);
|
||||
|
||||
std::ostringstream os(std::ios::binary);
|
||||
o->m_action->serialize(os);
|
||||
|
||||
std::istringstream is(os.str(), std::ios_base::binary);
|
||||
|
||||
InventoryAction *a = InventoryAction::deSerialize(is);
|
||||
|
||||
getClient(L)->inventoryAction(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::l_from(lua_State *L)
|
||||
{
|
||||
GET_MOVE_ACTION
|
||||
readFullInventoryLocationInto(L, &act->from_inv, &act->from_list, &act->from_i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::l_to(lua_State *L)
|
||||
{
|
||||
GET_MOVE_ACTION
|
||||
readFullInventoryLocationInto(L, &act->to_inv, &act->to_list, &act->to_i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::l_craft(lua_State *L)
|
||||
{
|
||||
LuaInventoryAction *o = checkobject(L, 1);
|
||||
|
||||
if (o->m_action->getType() != IAction::Craft)
|
||||
return 0;
|
||||
|
||||
std::string locStr;
|
||||
InventoryLocation loc;
|
||||
|
||||
locStr = readParam<std::string>(L, 2);
|
||||
|
||||
try {
|
||||
loc.deSerialize(locStr);
|
||||
dynamic_cast<ICraftAction *>(o->m_action)->craft_inv = loc;
|
||||
} catch (SerializationError &) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::l_set_count(lua_State *L)
|
||||
{
|
||||
LuaInventoryAction *o = checkobject(L, 1);
|
||||
|
||||
s16 count = luaL_checkinteger(L, 2);
|
||||
|
||||
switch (o->m_action->getType()) {
|
||||
case IAction::Move:
|
||||
((IMoveAction *)o->m_action)->count = count;
|
||||
break;
|
||||
case IAction::Drop:
|
||||
((IDropAction *)o->m_action)->count = count;
|
||||
break;
|
||||
case IAction::Craft:
|
||||
((ICraftAction *)o->m_action)->count = count;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::l_to_table(lua_State *L)
|
||||
{
|
||||
LuaInventoryAction *o = checkobject(L, 1);
|
||||
MoveAction *act = dynamic_cast<MoveAction *>(o->m_action);
|
||||
|
||||
std::string type = "";
|
||||
u16 count = 0;
|
||||
switch (o->m_action->getType()) {
|
||||
case IAction::Move:
|
||||
count = ((IMoveAction *)o->m_action)->count;
|
||||
type = "move";
|
||||
break;
|
||||
case IAction::Drop:
|
||||
count = ((IDropAction *)o->m_action)->count;
|
||||
type = "drop";
|
||||
break;
|
||||
case IAction::Craft:
|
||||
count = ((ICraftAction *)o->m_action)->count;
|
||||
type = "craft";
|
||||
break;
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, count);
|
||||
lua_setfield(L, -2, "count");
|
||||
lua_pushstring(L, type.c_str());
|
||||
lua_setfield(L, -2, "type");
|
||||
|
||||
lua_newtable(L);
|
||||
std::ostringstream from_loc;
|
||||
act->from_inv.serialize(from_loc);
|
||||
lua_pushstring(L, from_loc.str().c_str());
|
||||
lua_setfield(L, -2, "location");
|
||||
lua_pushstring(L, act->from_list.c_str());
|
||||
lua_setfield(L, -2, "inventory");
|
||||
lua_pushinteger(L, act->from_i + 1);
|
||||
lua_setfield(L, -2, "slot");
|
||||
lua_setfield(L, -2, "from");
|
||||
|
||||
lua_newtable(L);
|
||||
std::ostringstream to_loc;
|
||||
act->to_inv.serialize(to_loc);
|
||||
lua_pushstring(L, to_loc.str().c_str());
|
||||
lua_setfield(L, -2, "location");
|
||||
lua_pushstring(L, act->to_list.c_str());
|
||||
lua_setfield(L, -2, "inventory");
|
||||
lua_pushinteger(L, act->to_i + 1);
|
||||
lua_setfield(L, -2, "slot");
|
||||
lua_setfield(L, -2, "to");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaInventoryAction::LuaInventoryAction(const IAction &type) : m_action(nullptr)
|
||||
{
|
||||
switch (type) {
|
||||
case IAction::Move:
|
||||
m_action = new IMoveAction();
|
||||
break;
|
||||
case IAction::Drop:
|
||||
m_action = new IDropAction();
|
||||
break;
|
||||
case IAction::Craft:
|
||||
m_action = new ICraftAction();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LuaInventoryAction::~LuaInventoryAction()
|
||||
{
|
||||
delete m_action;
|
||||
}
|
||||
|
||||
void LuaInventoryAction::readFullInventoryLocationInto(
|
||||
lua_State *L, InventoryLocation *loc, std::string *list, s16 *index)
|
||||
{
|
||||
try {
|
||||
loc->deSerialize(readParam<std::string>(L, 2));
|
||||
std::string l = readParam<std::string>(L, 3);
|
||||
*list = l;
|
||||
*index = luaL_checkinteger(L, 4) - 1;
|
||||
} catch (SerializationError &) {
|
||||
}
|
||||
}
|
||||
|
||||
int LuaInventoryAction::create_object(lua_State *L)
|
||||
{
|
||||
IAction type;
|
||||
std::string typeStr;
|
||||
|
||||
typeStr = readParam<std::string>(L, 1);
|
||||
|
||||
if (typeStr == "move")
|
||||
type = IAction::Move;
|
||||
else if (typeStr == "drop")
|
||||
type = IAction::Drop;
|
||||
else if (typeStr == "craft")
|
||||
type = IAction::Craft;
|
||||
else
|
||||
return 0;
|
||||
|
||||
LuaInventoryAction *o = new LuaInventoryAction(type);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaInventoryAction::create(lua_State *L, const IAction &type)
|
||||
{
|
||||
LuaInventoryAction *o = new LuaInventoryAction(type);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaInventoryAction *LuaInventoryAction::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
return *(LuaInventoryAction **)luaL_checkudata(L, narg, className);
|
||||
}
|
||||
|
||||
void LuaInventoryAction::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__tostring");
|
||||
lua_pushcfunction(L, mt_tostring);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char LuaInventoryAction::className[] = "InventoryAction";
|
||||
const luaL_Reg LuaInventoryAction::methods[] = {
|
||||
luamethod(LuaInventoryAction, apply),
|
||||
luamethod(LuaInventoryAction, from),
|
||||
luamethod(LuaInventoryAction, to),
|
||||
luamethod(LuaInventoryAction, craft),
|
||||
luamethod(LuaInventoryAction, set_count),
|
||||
luamethod(LuaInventoryAction, to_table),
|
||||
{0,0}
|
||||
};
|
76
src/script/lua_api/l_inventoryaction.h
Normal file
76
src/script/lua_api/l_inventoryaction.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Dragonfire
|
||||
Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "inventorymanager.h"
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
#define GET_MOVE_ACTION \
|
||||
LuaInventoryAction *o = checkobject(L, 1); \
|
||||
if (o->m_action->getType() == IAction::Craft) \
|
||||
return 0; \
|
||||
MoveAction *act = dynamic_cast<MoveAction *>(o->m_action);
|
||||
|
||||
class LuaInventoryAction : public ModApiBase {
|
||||
private:
|
||||
InventoryAction *m_action;
|
||||
|
||||
static void readFullInventoryLocationInto(lua_State *L, InventoryLocation *loc, std::string *list, s16 *index);
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// __tostring metamethod
|
||||
static int mt_tostring(lua_State *L);
|
||||
|
||||
// apply(self)
|
||||
static int l_apply(lua_State *L);
|
||||
|
||||
// from(self, location, list, index)
|
||||
static int l_from(lua_State *L);
|
||||
|
||||
// to(self, location, list, index)
|
||||
static int l_to(lua_State *L);
|
||||
|
||||
// craft(self, location)
|
||||
static int l_craft(lua_State *L);
|
||||
|
||||
// set_count(self, count)
|
||||
static int l_set_count(lua_State *L);
|
||||
|
||||
// to_table(self)
|
||||
static int l_to_table(lua_State *L);
|
||||
public:
|
||||
LuaInventoryAction(const IAction &type);
|
||||
~LuaInventoryAction();
|
||||
|
||||
// LuaInventoryAction(inventory action type)
|
||||
// Creates an LuaInventoryAction and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
// Not callable from Lua
|
||||
static int create(lua_State *L, const IAction &type);
|
||||
static LuaInventoryAction *checkobject(lua_State *L, int narg);
|
||||
static void Register(lua_State *L);
|
||||
};
|
681
src/script/lua_api/l_item.cpp
Normal file
681
src/script/lua_api/l_item.cpp
Normal file
@ -0,0 +1,681 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_item.h"
|
||||
#include "lua_api/l_itemstackmeta.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "itemdef.h"
|
||||
#include "nodedef.h"
|
||||
#include "server.h"
|
||||
#include "inventory.h"
|
||||
#include "log.h"
|
||||
#include "script/cpp_api/s_base.h"
|
||||
#ifndef SERVER
|
||||
#include "client/client.h"
|
||||
#include "client/renderingengine.h"
|
||||
#include "client/shader.h"
|
||||
#endif
|
||||
|
||||
// garbage collector
|
||||
int LuaItemStack::gc_object(lua_State *L)
|
||||
{
|
||||
LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// __tostring metamethod
|
||||
int LuaItemStack::mt_tostring(lua_State *L)
|
||||
{
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
std::string itemstring = o->m_stack.getItemString(false);
|
||||
lua_pushfstring(L, "ItemStack(\"%s\")", itemstring.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_empty(self) -> true/false
|
||||
int LuaItemStack::l_is_empty(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
lua_pushboolean(L, item.empty());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_name(self) -> string
|
||||
int LuaItemStack::l_get_name(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
lua_pushstring(L, item.name.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_name(self, name)
|
||||
int LuaItemStack::l_set_name(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
|
||||
bool status = true;
|
||||
item.name = luaL_checkstring(L, 2);
|
||||
if (item.name.empty() || item.empty()) {
|
||||
item.clear();
|
||||
status = false;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_count(self) -> number
|
||||
int LuaItemStack::l_get_count(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
lua_pushinteger(L, item.count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_count(self, number)
|
||||
int LuaItemStack::l_set_count(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
|
||||
bool status;
|
||||
lua_Integer count = luaL_checkinteger(L, 2);
|
||||
if (count > 0 && count <= 65535) {
|
||||
item.count = count;
|
||||
status = true;
|
||||
} else {
|
||||
item.clear();
|
||||
status = false;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_wear(self) -> number
|
||||
int LuaItemStack::l_get_wear(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
lua_pushinteger(L, item.wear);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_wear(self, number)
|
||||
int LuaItemStack::l_set_wear(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
|
||||
bool status;
|
||||
lua_Integer wear = luaL_checkinteger(L, 2);
|
||||
if (wear <= 65535) {
|
||||
item.wear = wear;
|
||||
status = true;
|
||||
} else {
|
||||
item.clear();
|
||||
status = false;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_meta(self) -> string
|
||||
int LuaItemStack::l_get_meta(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStackMetaRef::create(L, &o->m_stack);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// get_metadata(self) -> string
|
||||
int LuaItemStack::l_get_metadata(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
const std::string &value = item.metadata.getString("");
|
||||
lua_pushlstring(L, value.c_str(), value.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// set_metadata(self, string)
|
||||
int LuaItemStack::l_set_metadata(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
|
||||
size_t len = 0;
|
||||
const char *ptr = luaL_checklstring(L, 2, &len);
|
||||
item.metadata.setString("", std::string(ptr, len));
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_description(self)
|
||||
int LuaItemStack::l_get_description(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
std::string desc = o->m_stack.getDescription(getGameDef(L)->idef());
|
||||
lua_pushstring(L, desc.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_short_description(self)
|
||||
int LuaItemStack::l_get_short_description(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
std::string desc = o->m_stack.getShortDescription(getGameDef(L)->idef());
|
||||
lua_pushstring(L, desc.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// clear(self) -> true
|
||||
int LuaItemStack::l_clear(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
o->m_stack.clear();
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// replace(self, itemstack or itemstring or table or nil) -> true
|
||||
int LuaItemStack::l_replace(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
o->m_stack = read_item(L, 2, getGameDef(L)->idef());
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// to_string(self) -> string
|
||||
int LuaItemStack::l_to_string(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
std::string itemstring = o->m_stack.getItemString();
|
||||
lua_pushstring(L, itemstring.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// to_table(self) -> table or nil
|
||||
int LuaItemStack::l_to_table(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
const ItemStack &item = o->m_stack;
|
||||
if(item.empty())
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, item.name.c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
lua_pushinteger(L, item.count);
|
||||
lua_setfield(L, -2, "count");
|
||||
lua_pushinteger(L, item.wear);
|
||||
lua_setfield(L, -2, "wear");
|
||||
|
||||
const std::string &metadata_str = item.metadata.getString("");
|
||||
lua_pushlstring(L, metadata_str.c_str(), metadata_str.size());
|
||||
lua_setfield(L, -2, "metadata");
|
||||
|
||||
lua_newtable(L);
|
||||
const StringMap &fields = item.metadata.getStrings();
|
||||
for (const auto &field : fields) {
|
||||
const std::string &name = field.first;
|
||||
if (name.empty())
|
||||
continue;
|
||||
const std::string &value = field.second;
|
||||
lua_pushlstring(L, name.c_str(), name.size());
|
||||
lua_pushlstring(L, value.c_str(), value.size());
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
lua_setfield(L, -2, "meta");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_stack_max(self) -> number
|
||||
int LuaItemStack::l_get_stack_max(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
lua_pushinteger(L, item.getStackMax(getGameDef(L)->idef()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_free_space(self) -> number
|
||||
int LuaItemStack::l_get_free_space(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
lua_pushinteger(L, item.freeSpace(getGameDef(L)->idef()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_known(self) -> true/false
|
||||
// Checks if the item is defined.
|
||||
int LuaItemStack::l_is_known(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
bool is_known = item.isKnown(getGameDef(L)->idef());
|
||||
lua_pushboolean(L, is_known);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_definition(self) -> table
|
||||
// Returns the item definition table from registered_items,
|
||||
// or a fallback one (name="unknown")
|
||||
int LuaItemStack::l_get_definition(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
|
||||
// Get registered_items[name]
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "registered_items");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
lua_getfield(L, -1, item.name.c_str());
|
||||
if(lua_isnil(L, -1))
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, -1, "unknown");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_tool_capabilities(self) -> table
|
||||
// Returns the effective tool digging properties.
|
||||
// Returns those of the hand ("") if this item has none associated.
|
||||
int LuaItemStack::l_get_tool_capabilities(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
const ToolCapabilities &prop =
|
||||
item.getToolCapabilities(getGameDef(L)->idef());
|
||||
push_tool_capabilities(L, prop);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// add_wear(self, amount) -> true/false
|
||||
// The range for "amount" is [0,65535]. Wear is only added if the item
|
||||
// is a tool. Adding wear might destroy the item.
|
||||
// Returns true if the item is (or was) a tool.
|
||||
int LuaItemStack::l_add_wear(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
int amount = lua_tointeger(L, 2);
|
||||
bool result = item.addWear(amount, getGameDef(L)->idef());
|
||||
lua_pushboolean(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// add_item(self, itemstack or itemstring or table or nil) -> itemstack
|
||||
// Returns leftover item stack
|
||||
int LuaItemStack::l_add_item(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
ItemStack newitem = read_item(L, -1, getGameDef(L)->idef());
|
||||
ItemStack leftover = item.addItem(newitem, getGameDef(L)->idef());
|
||||
create(L, leftover);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
|
||||
// First return value is true iff the new item fits fully into the stack
|
||||
// Second return value is the would-be-left-over item stack
|
||||
int LuaItemStack::l_item_fits(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
ItemStack newitem = read_item(L, 2, getGameDef(L)->idef());
|
||||
ItemStack restitem;
|
||||
bool fits = item.itemFits(newitem, &restitem, getGameDef(L)->idef());
|
||||
lua_pushboolean(L, fits); // first return value
|
||||
create(L, restitem); // second return value
|
||||
return 2;
|
||||
}
|
||||
|
||||
// take_item(self, takecount=1) -> itemstack
|
||||
int LuaItemStack::l_take_item(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
u32 takecount = 1;
|
||||
if(!lua_isnone(L, 2))
|
||||
takecount = luaL_checkinteger(L, 2);
|
||||
ItemStack taken = item.takeItem(takecount);
|
||||
create(L, taken);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// peek_item(self, peekcount=1) -> itemstack
|
||||
int LuaItemStack::l_peek_item(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = checkobject(L, 1);
|
||||
ItemStack &item = o->m_stack;
|
||||
u32 peekcount = 1;
|
||||
if(!lua_isnone(L, 2))
|
||||
peekcount = lua_tointeger(L, 2);
|
||||
ItemStack peekaboo = item.peekItem(peekcount);
|
||||
create(L, peekaboo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaItemStack::LuaItemStack(const ItemStack &item):
|
||||
m_stack(item)
|
||||
{
|
||||
}
|
||||
|
||||
const ItemStack& LuaItemStack::getItem() const
|
||||
{
|
||||
return m_stack;
|
||||
}
|
||||
ItemStack& LuaItemStack::getItem()
|
||||
{
|
||||
return m_stack;
|
||||
}
|
||||
|
||||
// LuaItemStack(itemstack or itemstring or table or nil)
|
||||
// Creates an LuaItemStack and leaves it on top of stack
|
||||
int LuaItemStack::create_object(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
ItemStack item;
|
||||
if (!lua_isnone(L, 1))
|
||||
item = read_item(L, 1, getGameDef(L)->idef());
|
||||
LuaItemStack *o = new LuaItemStack(item);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
// Not callable from Lua
|
||||
int LuaItemStack::create(lua_State *L, const ItemStack &item)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaItemStack *o = new LuaItemStack(item);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaItemStack *LuaItemStack::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
return *(LuaItemStack **)luaL_checkudata(L, narg, className);
|
||||
}
|
||||
|
||||
void LuaItemStack::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
// hide metatable from Lua getmetatable()
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__tostring");
|
||||
lua_pushcfunction(L, mt_tostring);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
|
||||
// Can be created from Lua (ItemStack(itemstack or itemstring or table or nil))
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char LuaItemStack::className[] = "ItemStack";
|
||||
const luaL_Reg LuaItemStack::methods[] = {
|
||||
luamethod(LuaItemStack, is_empty),
|
||||
luamethod(LuaItemStack, get_name),
|
||||
luamethod(LuaItemStack, set_name),
|
||||
luamethod(LuaItemStack, get_count),
|
||||
luamethod(LuaItemStack, set_count),
|
||||
luamethod(LuaItemStack, get_wear),
|
||||
luamethod(LuaItemStack, set_wear),
|
||||
luamethod(LuaItemStack, get_meta),
|
||||
luamethod(LuaItemStack, get_metadata),
|
||||
luamethod(LuaItemStack, set_metadata),
|
||||
luamethod(LuaItemStack, get_description),
|
||||
luamethod(LuaItemStack, get_short_description),
|
||||
luamethod(LuaItemStack, clear),
|
||||
luamethod(LuaItemStack, replace),
|
||||
luamethod(LuaItemStack, to_string),
|
||||
luamethod(LuaItemStack, to_table),
|
||||
luamethod(LuaItemStack, get_stack_max),
|
||||
luamethod(LuaItemStack, get_free_space),
|
||||
luamethod(LuaItemStack, is_known),
|
||||
luamethod(LuaItemStack, get_definition),
|
||||
luamethod(LuaItemStack, get_tool_capabilities),
|
||||
luamethod(LuaItemStack, add_wear),
|
||||
luamethod(LuaItemStack, add_item),
|
||||
luamethod(LuaItemStack, item_fits),
|
||||
luamethod(LuaItemStack, take_item),
|
||||
luamethod(LuaItemStack, peek_item),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
/*
|
||||
ItemDefinition
|
||||
*/
|
||||
|
||||
// register_item_raw({lots of stuff})
|
||||
int ModApiItemMod::l_register_item_raw(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
int table = 1;
|
||||
|
||||
// Get the writable item and node definition managers from the server
|
||||
IWritableItemDefManager *idef =
|
||||
getGameDef(L)->getWritableItemDefManager();
|
||||
NodeDefManager *ndef =
|
||||
getGameDef(L)->getWritableNodeDefManager();
|
||||
|
||||
// Check if name is defined
|
||||
std::string name;
|
||||
lua_getfield(L, table, "name");
|
||||
if(lua_isstring(L, -1)){
|
||||
name = readParam<std::string>(L, -1);
|
||||
} else {
|
||||
throw LuaError("register_item_raw: name is not defined or not a string");
|
||||
}
|
||||
|
||||
// Check if on_use is defined
|
||||
|
||||
ItemDefinition def;
|
||||
// Set a distinctive default value to check if this is set
|
||||
def.node_placement_prediction = "__default";
|
||||
|
||||
// Read the item definition
|
||||
read_item_definition(L, table, def, def);
|
||||
|
||||
// Default to having client-side placement prediction for nodes
|
||||
// ("" in item definition sets it off)
|
||||
if(def.node_placement_prediction == "__default"){
|
||||
if(def.type == ITEM_NODE)
|
||||
def.node_placement_prediction = name;
|
||||
else
|
||||
def.node_placement_prediction = "";
|
||||
}
|
||||
|
||||
// Register item definition
|
||||
idef->registerItem(def);
|
||||
|
||||
// Read the node definition (content features) and register it
|
||||
if (def.type == ITEM_NODE) {
|
||||
ContentFeatures f;
|
||||
read_content_features(L, f, table);
|
||||
// when a mod reregisters ignore, only texture changes and such should
|
||||
// be done
|
||||
if (f.name == "ignore")
|
||||
return 0;
|
||||
|
||||
content_t id = ndef->set(f.name, f);
|
||||
|
||||
if (id > MAX_REGISTERED_CONTENT) {
|
||||
throw LuaError("Number of registerable nodes ("
|
||||
+ itos(MAX_REGISTERED_CONTENT+1)
|
||||
+ ") exceeded (" + name + ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0; /* number of results */
|
||||
}
|
||||
|
||||
// unregister_item(name)
|
||||
int ModApiItemMod::l_unregister_item_raw(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
|
||||
IWritableItemDefManager *idef =
|
||||
getGameDef(L)->getWritableItemDefManager();
|
||||
|
||||
// Unregister the node
|
||||
if (idef->get(name).type == ITEM_NODE) {
|
||||
NodeDefManager *ndef =
|
||||
getGameDef(L)->getWritableNodeDefManager();
|
||||
ndef->removeNode(name);
|
||||
}
|
||||
|
||||
idef->unregisterItem(name);
|
||||
|
||||
return 0; /* number of results */
|
||||
}
|
||||
|
||||
// register_alias_raw(name, convert_to_name)
|
||||
int ModApiItemMod::l_register_alias_raw(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
std::string convert_to = luaL_checkstring(L, 2);
|
||||
|
||||
// Get the writable item definition manager from the server
|
||||
IWritableItemDefManager *idef =
|
||||
getGameDef(L)->getWritableItemDefManager();
|
||||
|
||||
idef->registerAlias(name, convert_to);
|
||||
|
||||
return 0; /* number of results */
|
||||
}
|
||||
|
||||
// get_content_id(name)
|
||||
int ModApiItemMod::l_get_content_id(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
|
||||
const IItemDefManager *idef = getGameDef(L)->getItemDefManager();
|
||||
const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
|
||||
|
||||
// If this is called at mod load time, NodeDefManager isn't aware of
|
||||
// aliases yet, so we need to handle them manually
|
||||
std::string alias_name = idef->getAlias(name);
|
||||
|
||||
content_t content_id;
|
||||
if (alias_name != name) {
|
||||
if (!ndef->getId(alias_name, content_id))
|
||||
throw LuaError("Unknown node: " + alias_name +
|
||||
" (from alias " + name + ")");
|
||||
} else if (!ndef->getId(name, content_id)) {
|
||||
throw LuaError("Unknown node: " + name);
|
||||
}
|
||||
|
||||
lua_pushinteger(L, content_id);
|
||||
return 1; /* number of results */
|
||||
}
|
||||
|
||||
// get_name_from_content_id(name)
|
||||
int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
content_t c = luaL_checkint(L, 1);
|
||||
|
||||
const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
|
||||
const char *name = ndef->get(c).name.c_str();
|
||||
|
||||
lua_pushstring(L, name);
|
||||
return 1; /* number of results */
|
||||
}
|
||||
|
||||
void ModApiItemMod::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(register_item_raw);
|
||||
API_FCT(unregister_item_raw);
|
||||
API_FCT(register_alias_raw);
|
||||
API_FCT(get_content_id);
|
||||
API_FCT(get_name_from_content_id);
|
||||
}
|
157
src/script/lua_api/l_item.h
Normal file
157
src/script/lua_api/l_item.h
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "inventory.h" // ItemStack
|
||||
|
||||
class LuaItemStack : public ModApiBase {
|
||||
private:
|
||||
ItemStack m_stack;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// __tostring metamethod
|
||||
static int mt_tostring(lua_State *L);
|
||||
|
||||
// is_empty(self) -> true/false
|
||||
static int l_is_empty(lua_State *L);
|
||||
|
||||
// get_name(self) -> string
|
||||
static int l_get_name(lua_State *L);
|
||||
|
||||
// set_name(self, name)
|
||||
static int l_set_name(lua_State *L);
|
||||
|
||||
// get_count(self) -> number
|
||||
static int l_get_count(lua_State *L);
|
||||
|
||||
// set_count(self, number)
|
||||
static int l_set_count(lua_State *L);
|
||||
|
||||
// get_wear(self) -> number
|
||||
static int l_get_wear(lua_State *L);
|
||||
|
||||
// set_wear(self, number)
|
||||
static int l_set_wear(lua_State *L);
|
||||
|
||||
// get_meta(self) -> string
|
||||
static int l_get_meta(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// get_metadata(self) -> string
|
||||
static int l_get_metadata(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// set_metadata(self, string)
|
||||
static int l_set_metadata(lua_State *L);
|
||||
|
||||
// get_description(self)
|
||||
static int l_get_description(lua_State *L);
|
||||
|
||||
// get_short_description(self)
|
||||
static int l_get_short_description(lua_State *L);
|
||||
|
||||
// clear(self) -> true
|
||||
static int l_clear(lua_State *L);
|
||||
|
||||
// replace(self, itemstack or itemstring or table or nil) -> true
|
||||
static int l_replace(lua_State *L);
|
||||
|
||||
// to_string(self) -> string
|
||||
static int l_to_string(lua_State *L);
|
||||
|
||||
// to_table(self) -> table or nil
|
||||
static int l_to_table(lua_State *L);
|
||||
|
||||
// get_stack_max(self) -> number
|
||||
static int l_get_stack_max(lua_State *L);
|
||||
|
||||
// get_free_space(self) -> number
|
||||
static int l_get_free_space(lua_State *L);
|
||||
|
||||
// is_known(self) -> true/false
|
||||
// Checks if the item is defined.
|
||||
static int l_is_known(lua_State *L);
|
||||
|
||||
// get_definition(self) -> table
|
||||
// Returns the item definition table from core.registered_items,
|
||||
// or a fallback one (name="unknown")
|
||||
static int l_get_definition(lua_State *L);
|
||||
|
||||
// get_tool_capabilities(self) -> table
|
||||
// Returns the effective tool digging properties.
|
||||
// Returns those of the hand ("") if this item has none associated.
|
||||
static int l_get_tool_capabilities(lua_State *L);
|
||||
|
||||
// add_wear(self, amount) -> true/false
|
||||
// The range for "amount" is [0,65535]. Wear is only added if the item
|
||||
// is a tool. Adding wear might destroy the item.
|
||||
// Returns true if the item is (or was) a tool.
|
||||
static int l_add_wear(lua_State *L);
|
||||
|
||||
// add_item(self, itemstack or itemstring or table or nil) -> itemstack
|
||||
// Returns leftover item stack
|
||||
static int l_add_item(lua_State *L);
|
||||
|
||||
// item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
|
||||
// First return value is true iff the new item fits fully into the stack
|
||||
// Second return value is the would-be-left-over item stack
|
||||
static int l_item_fits(lua_State *L);
|
||||
|
||||
// take_item(self, takecount=1) -> itemstack
|
||||
static int l_take_item(lua_State *L);
|
||||
|
||||
// peek_item(self, peekcount=1) -> itemstack
|
||||
static int l_peek_item(lua_State *L);
|
||||
|
||||
public:
|
||||
LuaItemStack(const ItemStack &item);
|
||||
~LuaItemStack() = default;
|
||||
|
||||
const ItemStack& getItem() const;
|
||||
ItemStack& getItem();
|
||||
|
||||
// LuaItemStack(itemstack or itemstring or table or nil)
|
||||
// Creates an LuaItemStack and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
// Not callable from Lua
|
||||
static int create(lua_State *L, const ItemStack &item);
|
||||
static LuaItemStack* checkobject(lua_State *L, int narg);
|
||||
static void Register(lua_State *L);
|
||||
|
||||
};
|
||||
|
||||
class ModApiItemMod : public ModApiBase {
|
||||
private:
|
||||
static int l_register_item_raw(lua_State *L);
|
||||
static int l_unregister_item_raw(lua_State *L);
|
||||
static int l_register_alias_raw(lua_State *L);
|
||||
static int l_get_content_id(lua_State *L);
|
||||
static int l_get_name_from_content_id(lua_State *L);
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
139
src/script/lua_api/l_itemstackmeta.cpp
Normal file
139
src/script/lua_api/l_itemstackmeta.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||
Copyright (C) 2017 raymoo
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_itemstackmeta.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_content.h"
|
||||
|
||||
/*
|
||||
NodeMetaRef
|
||||
*/
|
||||
ItemStackMetaRef* ItemStackMetaRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(ItemStackMetaRef**)ud; // unbox pointer
|
||||
}
|
||||
|
||||
Metadata* ItemStackMetaRef::getmeta(bool auto_create)
|
||||
{
|
||||
return &istack->metadata;
|
||||
}
|
||||
|
||||
void ItemStackMetaRef::clearMeta()
|
||||
{
|
||||
istack->metadata.clear();
|
||||
}
|
||||
|
||||
void ItemStackMetaRef::reportMetadataChange(const std::string *name)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Exported functions
|
||||
int ItemStackMetaRef::l_set_tool_capabilities(lua_State *L)
|
||||
{
|
||||
ItemStackMetaRef *metaref = checkobject(L, 1);
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
metaref->clearToolCapabilities();
|
||||
} else if (lua_istable(L, 2)) {
|
||||
ToolCapabilities caps = read_tool_capabilities(L, 2);
|
||||
metaref->setToolCapabilities(caps);
|
||||
} else {
|
||||
luaL_typerror(L, 2, "table or nil");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// garbage collector
|
||||
int ItemStackMetaRef::gc_object(lua_State *L) {
|
||||
ItemStackMetaRef *o = *(ItemStackMetaRef **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Creates an NodeMetaRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
void ItemStackMetaRef::create(lua_State *L, ItemStack *istack)
|
||||
{
|
||||
ItemStackMetaRef *o = new ItemStackMetaRef(istack);
|
||||
//infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
void ItemStackMetaRef::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "metadata_class");
|
||||
lua_pushlstring(L, className, strlen(className));
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__eq");
|
||||
lua_pushcfunction(L, l_equals);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
|
||||
// Cannot be created from Lua
|
||||
//lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char ItemStackMetaRef::className[] = "ItemStackMetaRef";
|
||||
const luaL_Reg ItemStackMetaRef::methods[] = {
|
||||
luamethod(MetaDataRef, contains),
|
||||
luamethod(MetaDataRef, get),
|
||||
luamethod(MetaDataRef, get_string),
|
||||
luamethod(MetaDataRef, set_string),
|
||||
luamethod(MetaDataRef, get_int),
|
||||
luamethod(MetaDataRef, set_int),
|
||||
luamethod(MetaDataRef, get_float),
|
||||
luamethod(MetaDataRef, set_float),
|
||||
luamethod(MetaDataRef, to_table),
|
||||
luamethod(MetaDataRef, from_table),
|
||||
luamethod(MetaDataRef, equals),
|
||||
luamethod(ItemStackMetaRef, set_tool_capabilities),
|
||||
{0,0}
|
||||
};
|
69
src/script/lua_api/l_itemstackmeta.h
Normal file
69
src/script/lua_api/l_itemstackmeta.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||
Copyright (C) 2017 raymoo
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "lua_api/l_metadata.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "inventory.h"
|
||||
|
||||
class ItemStackMetaRef : public MetaDataRef
|
||||
{
|
||||
private:
|
||||
ItemStack *istack = nullptr;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
static ItemStackMetaRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
virtual Metadata* getmeta(bool auto_create);
|
||||
|
||||
virtual void clearMeta();
|
||||
|
||||
virtual void reportMetadataChange(const std::string *name = nullptr);
|
||||
|
||||
void setToolCapabilities(const ToolCapabilities &caps)
|
||||
{
|
||||
istack->metadata.setToolCapabilities(caps);
|
||||
}
|
||||
|
||||
void clearToolCapabilities()
|
||||
{
|
||||
istack->metadata.clearToolCapabilities();
|
||||
}
|
||||
|
||||
// Exported functions
|
||||
static int l_set_tool_capabilities(lua_State *L);
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
public:
|
||||
ItemStackMetaRef(ItemStack *istack): istack(istack) {}
|
||||
~ItemStackMetaRef() = default;
|
||||
|
||||
// Creates an ItemStackMetaRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
static void create(lua_State *L, ItemStack *istack);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
638
src/script/lua_api/l_localplayer.cpp
Normal file
638
src/script/lua_api/l_localplayer.cpp
Normal file
@ -0,0 +1,638 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2017 Dumbeldor, Vincent Glize <vincent.glize@live.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "l_clientobject.h"
|
||||
#include "l_localplayer.h"
|
||||
#include "l_internal.h"
|
||||
#include "lua_api/l_item.h"
|
||||
#include "script/common/c_converter.h"
|
||||
#include "client/localplayer.h"
|
||||
#include "hud.h"
|
||||
#include "common/c_content.h"
|
||||
#include "client/client.h"
|
||||
#include "client/content_cao.h"
|
||||
#include "client/game.h"
|
||||
#include "l_clientobject.h"
|
||||
#include <vector>
|
||||
|
||||
LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m)
|
||||
{
|
||||
}
|
||||
|
||||
void LuaLocalPlayer::create(lua_State *L, LocalPlayer *m)
|
||||
{
|
||||
lua_getglobal(L, "core");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int objectstable = lua_gettop(L);
|
||||
lua_getfield(L, -1, "localplayer");
|
||||
|
||||
// Duplication check
|
||||
if (lua_type(L, -1) == LUA_TUSERDATA) {
|
||||
lua_pop(L, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
LuaLocalPlayer *o = new LuaLocalPlayer(m);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
lua_pushvalue(L, lua_gettop(L));
|
||||
lua_setfield(L, objectstable, "localplayer");
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_velocity(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
push_v3f(L, player->getSpeed() / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_set_velocity(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
v3f pos = checkFloatPos(L, 2);
|
||||
player->setSpeed(pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_yaw(lua_State *L)
|
||||
{
|
||||
lua_pushnumber(L, wrapDegrees_0_360(g_game->cam_view.camera_yaw));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_pitch(lua_State *L)
|
||||
{
|
||||
lua_pushnumber(L, -wrapDegrees_180(g_game->cam_view.camera_pitch) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_hp(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushinteger(L, player->hp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_name(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushstring(L, player->getName());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_wield_index(self)
|
||||
int LuaLocalPlayer::l_get_wield_index(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushinteger(L, player->getWieldIndex() + 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_wield_index(self)
|
||||
int LuaLocalPlayer::l_set_wield_index(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
u32 index = luaL_checkinteger(L, 2) - 1;
|
||||
|
||||
player->setWieldIndex(index);
|
||||
g_game->processItemSelection(&g_game->runData.new_playeritem);
|
||||
ItemStack selected_item, hand_item;
|
||||
ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
|
||||
g_game->camera->wield(tool_item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_wielded_item(self)
|
||||
int LuaLocalPlayer::l_get_wielded_item(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
ItemStack selected_item;
|
||||
player->getWieldedItem(&selected_item, nullptr);
|
||||
LuaItemStack::create(L, selected_item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_is_attached(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushboolean(L, player->getParent() != nullptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_is_touching_ground(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushboolean(L, player->touching_ground);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_is_in_liquid(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushboolean(L, player->in_liquid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_is_in_liquid_stable(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushboolean(L, player->in_liquid_stable);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_liquid_viscosity(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushinteger(L, player->liquid_viscosity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_is_climbing(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushboolean(L, player->is_climbing);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_swimming_vertical(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushboolean(L, player->swimming_vertical);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_physics_override(self)
|
||||
int LuaLocalPlayer::l_get_physics_override(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
push_physics_override(L, player->physics_override_speed, player->physics_override_jump, player->physics_override_gravity, player->physics_override_sneak, player->physics_override_sneak_glitch, player->physics_override_new_move);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_physics_override(self, override)
|
||||
int LuaLocalPlayer::l_set_physics_override(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
player->physics_override_speed = getfloatfield_default(
|
||||
L, 2, "speed", player->physics_override_speed);
|
||||
player->physics_override_jump = getfloatfield_default(
|
||||
L, 2, "jump", player->physics_override_jump);
|
||||
player->physics_override_gravity = getfloatfield_default(
|
||||
L, 2, "gravity", player->physics_override_gravity);
|
||||
player->physics_override_sneak = getboolfield_default(
|
||||
L, 2, "sneak", player->physics_override_sneak);
|
||||
player->physics_override_sneak_glitch = getboolfield_default(
|
||||
L, 2, "sneak_glitch", player->physics_override_sneak_glitch);
|
||||
player->physics_override_new_move = getboolfield_default(
|
||||
L, 2, "new_move", player->physics_override_new_move);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_last_pos(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
push_v3f(L, player->last_position / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_last_velocity(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
push_v3f(L, player->last_speed);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_last_look_vertical(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushnumber(L, -1.0 * player->last_pitch * core::DEGTORAD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_last_look_horizontal(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushnumber(L, (player->last_yaw + 90.) * core::DEGTORAD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_control(self)
|
||||
int LuaLocalPlayer::l_get_control(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
const PlayerControl &c = player->getPlayerControl();
|
||||
|
||||
auto set = [L] (const char *name, bool value) {
|
||||
lua_pushboolean(L, value);
|
||||
lua_setfield(L, -2, name);
|
||||
};
|
||||
|
||||
lua_createtable(L, 0, 12);
|
||||
set("up", c.up);
|
||||
set("down", c.down);
|
||||
set("left", c.left);
|
||||
set("right", c.right);
|
||||
set("jump", c.jump);
|
||||
set("aux1", c.aux1);
|
||||
set("sneak", c.sneak);
|
||||
set("zoom", c.zoom);
|
||||
set("dig", c.dig);
|
||||
set("place", c.place);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_breath(self)
|
||||
int LuaLocalPlayer::l_get_breath(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_pushinteger(L, player->getBreath());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_pos(self)
|
||||
int LuaLocalPlayer::l_get_pos(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
push_v3f(L, player->getPosition() / BS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_pos(self, pos)
|
||||
int LuaLocalPlayer::l_set_pos(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
v3f pos = checkFloatPos(L, 2);
|
||||
player->setPosition(pos);
|
||||
getClient(L)->sendPlayerPos(true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_set_yaw(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
f32 p = (float) luaL_checknumber(L, 2);
|
||||
//* 0.01745329252f;
|
||||
g_game->cam_view.camera_yaw = p;
|
||||
g_game->cam_view_target.camera_yaw = p;
|
||||
player->setYaw(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_set_pitch(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
f32 p = (float) luaL_checknumber(L, 2);
|
||||
//* 0.01745329252f ;
|
||||
g_game->cam_view.camera_pitch = p;
|
||||
g_game->cam_view_target.camera_pitch = p;
|
||||
player->setPitch(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_movement_acceleration(self)
|
||||
int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushnumber(L, player->movement_acceleration_default);
|
||||
lua_setfield(L, -2, "default");
|
||||
|
||||
lua_pushnumber(L, player->movement_acceleration_air);
|
||||
lua_setfield(L, -2, "air");
|
||||
|
||||
lua_pushnumber(L, player->movement_acceleration_fast);
|
||||
lua_setfield(L, -2, "fast");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_movement_speed(self)
|
||||
int LuaLocalPlayer::l_get_movement_speed(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushnumber(L, player->movement_speed_walk);
|
||||
lua_setfield(L, -2, "walk");
|
||||
|
||||
lua_pushnumber(L, player->movement_speed_crouch);
|
||||
lua_setfield(L, -2, "crouch");
|
||||
|
||||
lua_pushnumber(L, player->movement_speed_fast);
|
||||
lua_setfield(L, -2, "fast");
|
||||
|
||||
lua_pushnumber(L, player->movement_speed_climb);
|
||||
lua_setfield(L, -2, "climb");
|
||||
|
||||
lua_pushnumber(L, player->movement_speed_jump);
|
||||
lua_setfield(L, -2, "jump");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_movement(self)
|
||||
int LuaLocalPlayer::l_get_movement(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushnumber(L, player->movement_liquid_fluidity);
|
||||
lua_setfield(L, -2, "liquid_fluidity");
|
||||
|
||||
lua_pushnumber(L, player->movement_liquid_fluidity_smooth);
|
||||
lua_setfield(L, -2, "liquid_fluidity_smooth");
|
||||
|
||||
lua_pushnumber(L, player->movement_liquid_sink);
|
||||
lua_setfield(L, -2, "liquid_sink");
|
||||
|
||||
lua_pushnumber(L, player->movement_gravity);
|
||||
lua_setfield(L, -2, "gravity");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_armor_groups(self)
|
||||
int LuaLocalPlayer::l_get_armor_groups(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
push_groups(L, player->getCAO()->getGroups());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// hud_add(self, form)
|
||||
int LuaLocalPlayer::l_hud_add(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
HudElement *elem = new HudElement;
|
||||
read_hud_element(L, elem);
|
||||
|
||||
u32 id = player->addHud(elem);
|
||||
if (id == U32_MAX) {
|
||||
delete elem;
|
||||
return 0;
|
||||
}
|
||||
lua_pushnumber(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// hud_remove(self, id)
|
||||
int LuaLocalPlayer::l_hud_remove(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
u32 id = luaL_checkinteger(L, 2);
|
||||
HudElement *element = player->removeHud(id);
|
||||
if (!element)
|
||||
lua_pushboolean(L, false);
|
||||
else
|
||||
lua_pushboolean(L, true);
|
||||
delete element;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// hud_change(self, id, stat, data)
|
||||
int LuaLocalPlayer::l_hud_change(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
u32 id = luaL_checkinteger(L, 2);
|
||||
|
||||
HudElement *element = player->getHud(id);
|
||||
if (!element)
|
||||
return 0;
|
||||
|
||||
void *unused;
|
||||
read_hud_change(L, element, &unused);
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// hud_get(self, id)
|
||||
int LuaLocalPlayer::l_hud_get(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
|
||||
u32 id = luaL_checkinteger(L, -1);
|
||||
|
||||
HudElement *e = player->getHud(id);
|
||||
if (!e) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
push_hud_element(L, e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_nearby_objects(self, radius)
|
||||
int LuaLocalPlayer::l_get_nearby_objects(lua_State *L)
|
||||
{
|
||||
// should this be a double?
|
||||
float radius = readParam<float>(L, 1) * BS;
|
||||
std::vector<DistanceSortedActiveObject> objs;
|
||||
|
||||
ClientEnvironment &env = getClient(L)->getEnv();
|
||||
v3f pos = env.getLocalPlayer()->getPosition();
|
||||
env.getActiveObjects(pos, radius, objs);
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
int i = 0;
|
||||
lua_createtable(L, objs.size(), 0);
|
||||
for (const auto obj : objs) {
|
||||
ClientObjectRef::create(L, obj.obj);
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_get_object(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
ClientEnvironment &env = getClient(L)->getEnv();
|
||||
ClientActiveObject *obj = env.getGenericCAO(player->getCAO()->getId());
|
||||
|
||||
ClientObjectRef::create(L, obj);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaLocalPlayer *LuaLocalPlayer::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(LuaLocalPlayer **)ud;
|
||||
}
|
||||
|
||||
LocalPlayer *LuaLocalPlayer::getobject(LuaLocalPlayer *ref)
|
||||
{
|
||||
return ref->m_localplayer;
|
||||
}
|
||||
|
||||
LocalPlayer *LuaLocalPlayer::getobject(lua_State *L, int narg)
|
||||
{
|
||||
LuaLocalPlayer *ref = checkobject(L, narg);
|
||||
assert(ref);
|
||||
LocalPlayer *player = getobject(ref);
|
||||
assert(player);
|
||||
return player;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_set_override_speed(lua_State *L)
|
||||
{
|
||||
LocalPlayer *player = getobject(L, 1);
|
||||
f32 s = (float) luaL_checknumber(L, 2);
|
||||
g_settings->setBool("movement_ignore_server_speed",true);
|
||||
g_settings->setFloat("movement_speed_walk",s);
|
||||
player->movement_speed_walk = g_settings->getFloat("movement_speed_walk") * BS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::l_set_speeds_from_local_settings(lua_State *L)
|
||||
{
|
||||
g_settings->setBool("movement_ignore_server_speed",true);
|
||||
getClient(L)->set_speeds_from_local_settings();
|
||||
return 0;
|
||||
}
|
||||
int LuaLocalPlayer::l_set_speeds_from_server_settings(lua_State *L)
|
||||
{
|
||||
g_settings->setBool("movement_ignore_server_speed",false);
|
||||
getClient(L)->set_speeds_from_server_settings();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaLocalPlayer::gc_object(lua_State *L)
|
||||
{
|
||||
LuaLocalPlayer *o = *(LuaLocalPlayer **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LuaLocalPlayer::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // Drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // Drop methodtable
|
||||
}
|
||||
|
||||
const char LuaLocalPlayer::className[] = "LocalPlayer";
|
||||
const luaL_Reg LuaLocalPlayer::methods[] = {
|
||||
luamethod(LuaLocalPlayer, get_velocity),
|
||||
luamethod(LuaLocalPlayer, set_velocity),
|
||||
luamethod(LuaLocalPlayer, get_hp),
|
||||
luamethod(LuaLocalPlayer, get_name),
|
||||
luamethod(LuaLocalPlayer, get_wield_index),
|
||||
luamethod(LuaLocalPlayer, set_wield_index),
|
||||
luamethod(LuaLocalPlayer, get_wielded_item),
|
||||
luamethod(LuaLocalPlayer, is_attached),
|
||||
luamethod(LuaLocalPlayer, is_touching_ground),
|
||||
luamethod(LuaLocalPlayer, is_in_liquid),
|
||||
luamethod(LuaLocalPlayer, is_in_liquid_stable),
|
||||
luamethod(LuaLocalPlayer, get_liquid_viscosity),
|
||||
luamethod(LuaLocalPlayer, is_climbing),
|
||||
luamethod(LuaLocalPlayer, swimming_vertical),
|
||||
luamethod(LuaLocalPlayer, get_physics_override),
|
||||
luamethod(LuaLocalPlayer, set_physics_override),
|
||||
// TODO: figure our if these are useful in any way
|
||||
luamethod(LuaLocalPlayer, get_last_pos),
|
||||
luamethod(LuaLocalPlayer, get_last_velocity),
|
||||
luamethod(LuaLocalPlayer, get_last_look_horizontal),
|
||||
luamethod(LuaLocalPlayer, get_last_look_vertical),
|
||||
//
|
||||
luamethod(LuaLocalPlayer, get_control),
|
||||
luamethod(LuaLocalPlayer, get_breath),
|
||||
luamethod(LuaLocalPlayer, get_pos),
|
||||
luamethod(LuaLocalPlayer, set_pos),
|
||||
luamethod(LuaLocalPlayer, get_yaw),
|
||||
luamethod(LuaLocalPlayer, set_yaw),
|
||||
luamethod(LuaLocalPlayer, get_pitch),
|
||||
luamethod(LuaLocalPlayer, set_pitch),
|
||||
luamethod(LuaLocalPlayer, get_movement_acceleration),
|
||||
luamethod(LuaLocalPlayer, get_movement_speed),
|
||||
luamethod(LuaLocalPlayer, get_movement),
|
||||
luamethod(LuaLocalPlayer, get_armor_groups),
|
||||
luamethod(LuaLocalPlayer, hud_add),
|
||||
luamethod(LuaLocalPlayer, hud_remove),
|
||||
luamethod(LuaLocalPlayer, hud_change),
|
||||
luamethod(LuaLocalPlayer, hud_get),
|
||||
luamethod(LuaLocalPlayer, get_object),
|
||||
|
||||
luamethod(LuaLocalPlayer, get_nearby_objects),
|
||||
luamethod(LuaLocalPlayer, get_object),
|
||||
luamethod(LuaLocalPlayer, set_override_speed),
|
||||
luamethod(LuaLocalPlayer, set_speeds_from_server_settings),
|
||||
luamethod(LuaLocalPlayer, set_speeds_from_local_settings),
|
||||
|
||||
{0, 0}
|
||||
};
|
147
src/script/lua_api/l_localplayer.h
Normal file
147
src/script/lua_api/l_localplayer.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2017 Dumbeldor, Vincent Glize <vincent.glize@live.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "l_base.h"
|
||||
|
||||
class LocalPlayer;
|
||||
|
||||
class LuaLocalPlayer : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// get_velocity(self)
|
||||
static int l_get_velocity(lua_State *L);
|
||||
|
||||
// set_velocity(self, vel)
|
||||
static int l_set_velocity(lua_State *L);
|
||||
|
||||
// get_hp(self)
|
||||
static int l_get_hp(lua_State *L);
|
||||
|
||||
// get_name(self)
|
||||
static int l_get_name(lua_State *L);
|
||||
|
||||
// get_wield_index(self)
|
||||
static int l_get_wield_index(lua_State *L);
|
||||
|
||||
// set_wield_index(self)
|
||||
static int l_set_wield_index(lua_State *L);
|
||||
|
||||
// get_wielded_item(self)
|
||||
static int l_get_wielded_item(lua_State *L);
|
||||
|
||||
static int l_is_attached(lua_State *L);
|
||||
static int l_is_touching_ground(lua_State *L);
|
||||
static int l_is_in_liquid(lua_State *L);
|
||||
static int l_is_in_liquid_stable(lua_State *L);
|
||||
static int l_get_liquid_viscosity(lua_State *L);
|
||||
static int l_is_climbing(lua_State *L);
|
||||
static int l_swimming_vertical(lua_State *L);
|
||||
|
||||
static int l_get_physics_override(lua_State *L);
|
||||
static int l_set_physics_override(lua_State *L);
|
||||
|
||||
static int l_get_override_pos(lua_State *L);
|
||||
|
||||
static int l_get_last_pos(lua_State *L);
|
||||
static int l_get_last_velocity(lua_State *L);
|
||||
static int l_get_last_look_vertical(lua_State *L);
|
||||
static int l_get_last_look_horizontal(lua_State *L);
|
||||
|
||||
// get_control(self)
|
||||
static int l_get_control(lua_State *L);
|
||||
|
||||
// get_breath(self)
|
||||
static int l_get_breath(lua_State *L);
|
||||
|
||||
// get_pos(self)
|
||||
static int l_get_pos(lua_State *L);
|
||||
|
||||
// set_pos(self, pos)
|
||||
static int l_set_pos(lua_State *L);
|
||||
|
||||
// get_yaw(self)
|
||||
static int l_get_yaw(lua_State *L);
|
||||
|
||||
// set_yaw(self, yaw)
|
||||
static int l_set_yaw(lua_State *L);
|
||||
|
||||
// get_pitch(self)
|
||||
static int l_get_pitch(lua_State *L);
|
||||
|
||||
// set_pitch(self, pitch)
|
||||
static int l_set_pitch(lua_State *L);
|
||||
|
||||
// get_movement_acceleration(self)
|
||||
static int l_get_movement_acceleration(lua_State *L);
|
||||
|
||||
// get_movement_speed(self)
|
||||
static int l_get_movement_speed(lua_State *L);
|
||||
|
||||
// get_movement(self)
|
||||
static int l_get_movement(lua_State *L);
|
||||
|
||||
// get_armor_groups(self)
|
||||
static int l_get_armor_groups(lua_State *L);
|
||||
|
||||
// hud_add(self, id, form)
|
||||
static int l_hud_add(lua_State *L);
|
||||
|
||||
// hud_rm(self, id)
|
||||
static int l_hud_remove(lua_State *L);
|
||||
|
||||
// hud_change(self, id, stat, data)
|
||||
static int l_hud_change(lua_State *L);
|
||||
// hud_get(self, id)
|
||||
static int l_hud_get(lua_State *L);
|
||||
|
||||
// get_nearby_objects(self, radius)
|
||||
static int l_get_nearby_objects(lua_State *L);
|
||||
|
||||
// get_object(self)
|
||||
static int l_get_object(lua_State *L);
|
||||
|
||||
// set_override_speed
|
||||
static int l_set_override_speed(lua_State *L);
|
||||
|
||||
static int l_set_speeds_from_local_settings(lua_State *L);
|
||||
|
||||
static int l_set_speeds_from_server_settings(lua_State *L);
|
||||
|
||||
LocalPlayer *m_localplayer = nullptr;
|
||||
|
||||
public:
|
||||
LuaLocalPlayer(LocalPlayer *m);
|
||||
~LuaLocalPlayer() = default;
|
||||
|
||||
static void create(lua_State *L, LocalPlayer *m);
|
||||
|
||||
static LuaLocalPlayer *checkobject(lua_State *L, int narg);
|
||||
static LocalPlayer *getobject(LuaLocalPlayer *ref);
|
||||
static LocalPlayer *getobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
1163
src/script/lua_api/l_mainmenu.cpp
Normal file
1163
src/script/lua_api/l_mainmenu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
166
src/script/lua_api/l_mainmenu.h
Normal file
166
src/script/lua_api/l_mainmenu.h
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 sapier
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class AsyncEngine;
|
||||
|
||||
/** Implementation of lua api support for mainmenu */
|
||||
class ModApiMainMenu: public ModApiBase
|
||||
{
|
||||
|
||||
private:
|
||||
/**
|
||||
* read a text variable from gamedata table within lua stack
|
||||
* @param L stack to read variable from
|
||||
* @param name name of variable to read
|
||||
* @return string value of requested variable
|
||||
*/
|
||||
static std::string getTextData(lua_State *L, std::string name);
|
||||
|
||||
/**
|
||||
* read a integer variable from gamedata table within lua stack
|
||||
* @param L stack to read variable from
|
||||
* @param name name of variable to read
|
||||
* @return integer value of requested variable
|
||||
*/
|
||||
static int getIntegerData(lua_State *L, std::string name,bool& valid);
|
||||
|
||||
/**
|
||||
* read a bool variable from gamedata table within lua stack
|
||||
* @param L stack to read variable from
|
||||
* @param name name of variable to read
|
||||
* @return bool value of requested variable
|
||||
*/
|
||||
static int getBoolData(lua_State *L, std::string name,bool& valid);
|
||||
|
||||
/**
|
||||
* Checks if a path may be modified. Paths in the temp directory or the user
|
||||
* games, mods, textures, or worlds directories may be modified.
|
||||
* @param path path to check
|
||||
* @return true if the path may be modified
|
||||
*/
|
||||
static bool mayModifyPath(const std::string &path);
|
||||
|
||||
//api calls
|
||||
|
||||
static int l_start(lua_State *L);
|
||||
|
||||
static int l_close(lua_State *L);
|
||||
|
||||
static int l_create_world(lua_State *L);
|
||||
|
||||
static int l_delete_world(lua_State *L);
|
||||
|
||||
static int l_get_worlds(lua_State *L);
|
||||
|
||||
static int l_get_mapgen_names(lua_State *L);
|
||||
|
||||
static int l_get_favorites(lua_State *L);
|
||||
|
||||
static int l_delete_favorite(lua_State *L);
|
||||
|
||||
static int l_gettext(lua_State *L);
|
||||
|
||||
//packages
|
||||
|
||||
static int l_get_games(lua_State *L);
|
||||
|
||||
static int l_get_content_info(lua_State *L);
|
||||
|
||||
//gui
|
||||
|
||||
static int l_show_keys_menu(lua_State *L);
|
||||
|
||||
static int l_show_path_select_dialog(lua_State *L);
|
||||
|
||||
static int l_set_topleft_text(lua_State *L);
|
||||
|
||||
static int l_set_clouds(lua_State *L);
|
||||
|
||||
static int l_get_textlist_index(lua_State *L);
|
||||
|
||||
static int l_get_table_index(lua_State *L);
|
||||
|
||||
static int l_set_background(lua_State *L);
|
||||
|
||||
static int l_update_formspec(lua_State *L);
|
||||
|
||||
static int l_set_formspec_prepend(lua_State *L);
|
||||
|
||||
static int l_get_screen_info(lua_State *L);
|
||||
|
||||
//filesystem
|
||||
|
||||
static int l_get_mainmenu_path(lua_State *L);
|
||||
|
||||
static int l_get_modpath(lua_State *L);
|
||||
|
||||
static int l_get_clientmodpath(lua_State *L);
|
||||
|
||||
static int l_get_gamepath(lua_State *L);
|
||||
|
||||
static int l_get_texturepath(lua_State *L);
|
||||
|
||||
static int l_get_texturepath_share(lua_State *L);
|
||||
|
||||
static int l_get_cache_path(lua_State *L);
|
||||
|
||||
static int l_create_dir(lua_State *L);
|
||||
|
||||
static int l_delete_dir(lua_State *L);
|
||||
|
||||
static int l_copy_dir(lua_State *L);
|
||||
|
||||
static int l_extract_zip(lua_State *L);
|
||||
|
||||
static int l_may_modify_path(lua_State *L);
|
||||
|
||||
static int l_download_file(lua_State *L);
|
||||
|
||||
static int l_get_video_drivers(lua_State *L);
|
||||
|
||||
static int l_get_video_modes(lua_State *L);
|
||||
|
||||
//version compatibility
|
||||
static int l_get_min_supp_proto(lua_State *L);
|
||||
|
||||
static int l_get_max_supp_proto(lua_State *L);
|
||||
|
||||
// other
|
||||
static int l_open_url(lua_State *L);
|
||||
|
||||
|
||||
// async
|
||||
static int l_do_async_callback(lua_State *L);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* initialize this API module
|
||||
* @param L lua stack to initialize
|
||||
* @param top index (in lua stack) of global API table
|
||||
*/
|
||||
static void Initialize(lua_State *L, int top);
|
||||
|
||||
static void InitializeAsync(lua_State *L, int top);
|
||||
|
||||
};
|
1878
src/script/lua_api/l_mapgen.cpp
Normal file
1878
src/script/lua_api/l_mapgen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
149
src/script/lua_api/l_mapgen.h
Normal file
149
src/script/lua_api/l_mapgen.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include
|
||||
|
||||
class ModApiMapgen : public ModApiBase
|
||||
{
|
||||
private:
|
||||
// get_biome_id(biomename)
|
||||
// returns the biome id as used in biomemap and returned by 'get_biome_data()'
|
||||
static int l_get_biome_id(lua_State *L);
|
||||
|
||||
// get_biome_name(biome_id)
|
||||
// returns the biome name string
|
||||
static int l_get_biome_name(lua_State *L);
|
||||
|
||||
// get_heat(pos)
|
||||
// returns the heat at the position
|
||||
static int l_get_heat(lua_State *L);
|
||||
|
||||
// get_humidity(pos)
|
||||
// returns the humidity at the position
|
||||
static int l_get_humidity(lua_State *L);
|
||||
|
||||
// get_biome_data(pos)
|
||||
// returns a table containing the biome id, heat and humidity at the position
|
||||
static int l_get_biome_data(lua_State *L);
|
||||
|
||||
// get_mapgen_object(objectname)
|
||||
// returns the requested object used during map generation
|
||||
static int l_get_mapgen_object(lua_State *L);
|
||||
|
||||
// get_spawn_level(x = num, z = num)
|
||||
static int l_get_spawn_level(lua_State *L);
|
||||
|
||||
// get_mapgen_params()
|
||||
// returns the currently active map generation parameter set
|
||||
static int l_get_mapgen_params(lua_State *L);
|
||||
|
||||
// set_mapgen_params(params)
|
||||
// set mapgen parameters
|
||||
static int l_set_mapgen_params(lua_State *L);
|
||||
|
||||
// get_mapgen_setting(name)
|
||||
static int l_get_mapgen_setting(lua_State *L);
|
||||
|
||||
// set_mapgen_setting(name, value, override_meta)
|
||||
static int l_set_mapgen_setting(lua_State *L);
|
||||
|
||||
// get_mapgen_setting_noiseparams(name)
|
||||
static int l_get_mapgen_setting_noiseparams(lua_State *L);
|
||||
|
||||
// set_mapgen_setting_noiseparams(name, value, override_meta)
|
||||
static int l_set_mapgen_setting_noiseparams(lua_State *L);
|
||||
|
||||
// set_noiseparam_defaults(name, noiseparams, set_default)
|
||||
static int l_set_noiseparams(lua_State *L);
|
||||
|
||||
// get_noiseparam_defaults(name)
|
||||
static int l_get_noiseparams(lua_State *L);
|
||||
|
||||
// set_gen_notify(flags, {deco_id_table})
|
||||
static int l_set_gen_notify(lua_State *L);
|
||||
|
||||
// get_gen_notify()
|
||||
static int l_get_gen_notify(lua_State *L);
|
||||
|
||||
// get_decoration_id(decoration_name)
|
||||
// returns the decoration ID as used in gennotify
|
||||
static int l_get_decoration_id(lua_State *L);
|
||||
|
||||
// register_biome({lots of stuff})
|
||||
static int l_register_biome(lua_State *L);
|
||||
|
||||
// register_decoration({lots of stuff})
|
||||
static int l_register_decoration(lua_State *L);
|
||||
|
||||
// register_ore({lots of stuff})
|
||||
static int l_register_ore(lua_State *L);
|
||||
|
||||
// register_schematic({schematic}, replacements={})
|
||||
static int l_register_schematic(lua_State *L);
|
||||
|
||||
// clear_registered_biomes()
|
||||
static int l_clear_registered_biomes(lua_State *L);
|
||||
|
||||
// clear_registered_decorations()
|
||||
static int l_clear_registered_decorations(lua_State *L);
|
||||
|
||||
// clear_registered_schematics()
|
||||
static int l_clear_registered_schematics(lua_State *L);
|
||||
|
||||
// generate_ores(vm, p1, p2)
|
||||
static int l_generate_ores(lua_State *L);
|
||||
|
||||
// generate_decorations(vm, p1, p2)
|
||||
static int l_generate_decorations(lua_State *L);
|
||||
|
||||
// clear_registered_ores
|
||||
static int l_clear_registered_ores(lua_State *L);
|
||||
|
||||
// create_schematic(p1, p2, probability_list, filename)
|
||||
static int l_create_schematic(lua_State *L);
|
||||
|
||||
// place_schematic(p, schematic, rotation,
|
||||
// replacements, force_placement, flagstring)
|
||||
static int l_place_schematic(lua_State *L);
|
||||
|
||||
// place_schematic_on_vmanip(vm, p, schematic, rotation,
|
||||
// replacements, force_placement, flagstring)
|
||||
static int l_place_schematic_on_vmanip(lua_State *L);
|
||||
|
||||
// serialize_schematic(schematic, format, options={...})
|
||||
static int l_serialize_schematic(lua_State *L);
|
||||
|
||||
// read_schematic(schematic, options={...})
|
||||
static int l_read_schematic(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
|
||||
static struct EnumString es_BiomeTerrainType[];
|
||||
static struct EnumString es_DecorationType[];
|
||||
static struct EnumString es_MapgenObject[];
|
||||
static struct EnumString es_OreType[];
|
||||
static struct EnumString es_Rotation[];
|
||||
static struct EnumString es_SchematicFormatType[];
|
||||
static struct EnumString es_NodeResolveMethod[];
|
||||
};
|
302
src/script/lua_api/l_metadata.cpp
Normal file
302
src/script/lua_api/l_metadata.cpp
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_metadata.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_content.h"
|
||||
#include "serverenvironment.h"
|
||||
#include "map.h"
|
||||
#include "server.h"
|
||||
|
||||
// LUALIB_API
|
||||
void *luaL_checkudata_is_metadataref(lua_State *L, int ud) {
|
||||
void *p = lua_touserdata(L, ud);
|
||||
if (p != NULL && // value is a userdata?
|
||||
lua_getmetatable(L, ud)) { // does it have a metatable?
|
||||
lua_getfield(L, -1, "metadata_class");
|
||||
if (lua_type(L, -1) == LUA_TSTRING) { // does it have a metadata_class field?
|
||||
return p;
|
||||
}
|
||||
}
|
||||
luaL_typerror(L, ud, "MetaDataRef");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MetaDataRef* MetaDataRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata_is_metadataref(L, narg);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, "MetaDataRef");
|
||||
|
||||
return *(MetaDataRef**)ud; // unbox pointer
|
||||
}
|
||||
|
||||
// Exported functions
|
||||
|
||||
// contains(self, name)
|
||||
int MetaDataRef::l_contains(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
|
||||
Metadata *meta = ref->getmeta(false);
|
||||
if (meta == NULL)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(L, meta->contains(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get(self, name)
|
||||
int MetaDataRef::l_get(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
|
||||
Metadata *meta = ref->getmeta(false);
|
||||
if (meta == NULL)
|
||||
return 0;
|
||||
|
||||
std::string str;
|
||||
if (meta->getStringToRef(name, str)) {
|
||||
lua_pushlstring(L, str.c_str(), str.size());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_string(self, name)
|
||||
int MetaDataRef::l_get_string(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
|
||||
Metadata *meta = ref->getmeta(false);
|
||||
if (meta == NULL) {
|
||||
lua_pushlstring(L, "", 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const std::string &str = meta->getString(name);
|
||||
lua_pushlstring(L, str.c_str(), str.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_string(self, name, var)
|
||||
int MetaDataRef::l_set_string(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
size_t len = 0;
|
||||
const char *s = lua_tolstring(L, 3, &len);
|
||||
std::string str(s, len);
|
||||
|
||||
Metadata *meta = ref->getmeta(!str.empty());
|
||||
if (meta == NULL || str == meta->getString(name))
|
||||
return 0;
|
||||
|
||||
meta->setString(name, str);
|
||||
ref->reportMetadataChange(&name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_int(self, name)
|
||||
int MetaDataRef::l_get_int(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
|
||||
Metadata *meta = ref->getmeta(false);
|
||||
if (meta == NULL) {
|
||||
lua_pushnumber(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const std::string &str = meta->getString(name);
|
||||
lua_pushnumber(L, stoi(str));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_int(self, name, var)
|
||||
int MetaDataRef::l_set_int(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
int a = luaL_checkint(L, 3);
|
||||
std::string str = itos(a);
|
||||
|
||||
Metadata *meta = ref->getmeta(true);
|
||||
if (meta == NULL || str == meta->getString(name))
|
||||
return 0;
|
||||
|
||||
meta->setString(name, str);
|
||||
ref->reportMetadataChange(&name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_float(self, name)
|
||||
int MetaDataRef::l_get_float(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
|
||||
Metadata *meta = ref->getmeta(false);
|
||||
if (meta == NULL) {
|
||||
lua_pushnumber(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const std::string &str = meta->getString(name);
|
||||
lua_pushnumber(L, stof(str));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_float(self, name, var)
|
||||
int MetaDataRef::l_set_float(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
std::string name = luaL_checkstring(L, 2);
|
||||
float a = readParam<float>(L, 3);
|
||||
std::string str = ftos(a);
|
||||
|
||||
Metadata *meta = ref->getmeta(true);
|
||||
if (meta == NULL || str == meta->getString(name))
|
||||
return 0;
|
||||
|
||||
meta->setString(name, str);
|
||||
ref->reportMetadataChange(&name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// to_table(self)
|
||||
int MetaDataRef::l_to_table(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
|
||||
Metadata *meta = ref->getmeta(true);
|
||||
if (meta == NULL) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
lua_newtable(L);
|
||||
|
||||
ref->handleToTable(L, meta);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// from_table(self, table)
|
||||
int MetaDataRef::l_from_table(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
MetaDataRef *ref = checkobject(L, 1);
|
||||
int base = 2;
|
||||
|
||||
ref->clearMeta();
|
||||
|
||||
if (!lua_istable(L, base)) {
|
||||
// No metadata
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create new metadata
|
||||
Metadata *meta = ref->getmeta(true);
|
||||
if (meta == NULL) {
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool was_successful = ref->handleFromTable(L, base, meta);
|
||||
ref->reportMetadataChange();
|
||||
lua_pushboolean(L, was_successful);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MetaDataRef::handleToTable(lua_State *L, Metadata *meta)
|
||||
{
|
||||
lua_newtable(L);
|
||||
{
|
||||
const StringMap &fields = meta->getStrings();
|
||||
for (const auto &field : fields) {
|
||||
const std::string &name = field.first;
|
||||
const std::string &value = field.second;
|
||||
lua_pushlstring(L, name.c_str(), name.size());
|
||||
lua_pushlstring(L, value.c_str(), value.size());
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
lua_setfield(L, -2, "fields");
|
||||
}
|
||||
|
||||
bool MetaDataRef::handleFromTable(lua_State *L, int table, Metadata *meta)
|
||||
{
|
||||
// Set fields
|
||||
lua_getfield(L, table, "fields");
|
||||
if (lua_istable(L, -1)) {
|
||||
int fieldstable = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, fieldstable) != 0) {
|
||||
// key at index -2 and value at index -1
|
||||
std::string name = readParam<std::string>(L, -2);
|
||||
size_t cl;
|
||||
const char *cs = lua_tolstring(L, -1, &cl);
|
||||
meta->setString(name, std::string(cs, cl));
|
||||
lua_pop(L, 1); // Remove value, keep key for next iteration
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// equals(self, other)
|
||||
int MetaDataRef::l_equals(lua_State *L)
|
||||
{
|
||||
MetaDataRef *ref1 = checkobject(L, 1);
|
||||
Metadata *data1 = ref1->getmeta(false);
|
||||
MetaDataRef *ref2 = checkobject(L, 2);
|
||||
Metadata *data2 = ref2->getmeta(false);
|
||||
if (data1 == NULL || data2 == NULL)
|
||||
lua_pushboolean(L, data1 == data2);
|
||||
else
|
||||
lua_pushboolean(L, *data1 == *data2);
|
||||
return 1;
|
||||
}
|
81
src/script/lua_api/l_metadata.h
Normal file
81
src/script/lua_api/l_metadata.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013-8 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class Metadata;
|
||||
|
||||
/*
|
||||
NodeMetaRef
|
||||
*/
|
||||
|
||||
class MetaDataRef : public ModApiBase
|
||||
{
|
||||
public:
|
||||
virtual ~MetaDataRef() = default;
|
||||
|
||||
protected:
|
||||
static MetaDataRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
virtual void reportMetadataChange(const std::string *name = nullptr) {}
|
||||
virtual Metadata *getmeta(bool auto_create) = 0;
|
||||
virtual void clearMeta() = 0;
|
||||
|
||||
virtual void handleToTable(lua_State *L, Metadata *meta);
|
||||
virtual bool handleFromTable(lua_State *L, int table, Metadata *meta);
|
||||
|
||||
// Exported functions
|
||||
|
||||
// contains(self, name)
|
||||
static int l_contains(lua_State *L);
|
||||
|
||||
// get(self, name)
|
||||
static int l_get(lua_State *L);
|
||||
|
||||
// get_string(self, name)
|
||||
static int l_get_string(lua_State *L);
|
||||
|
||||
// set_string(self, name, var)
|
||||
static int l_set_string(lua_State *L);
|
||||
|
||||
// get_int(self, name)
|
||||
static int l_get_int(lua_State *L);
|
||||
|
||||
// set_int(self, name, var)
|
||||
static int l_set_int(lua_State *L);
|
||||
|
||||
// get_float(self, name)
|
||||
static int l_get_float(lua_State *L);
|
||||
|
||||
// set_float(self, name, var)
|
||||
static int l_set_float(lua_State *L);
|
||||
|
||||
// to_table(self)
|
||||
static int l_to_table(lua_State *L);
|
||||
|
||||
// from_table(self, table)
|
||||
static int l_from_table(lua_State *L);
|
||||
|
||||
// equals(self, other)
|
||||
static int l_equals(lua_State *L);
|
||||
};
|
231
src/script/lua_api/l_minimap.cpp
Normal file
231
src/script/lua_api/l_minimap.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2017 Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "lua_api/l_minimap.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "client/client.h"
|
||||
#include "client/minimap.h"
|
||||
#include "settings.h"
|
||||
|
||||
LuaMinimap::LuaMinimap(Minimap *m) : m_minimap(m)
|
||||
{
|
||||
}
|
||||
|
||||
void LuaMinimap::create(lua_State *L, Minimap *m)
|
||||
{
|
||||
LuaMinimap *o = new LuaMinimap(m);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// Keep minimap object stack id
|
||||
int minimap_object = lua_gettop(L);
|
||||
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "ui");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int uitable = lua_gettop(L);
|
||||
|
||||
lua_pushvalue(L, minimap_object); // Copy object to top of stack
|
||||
lua_setfield(L, uitable, "minimap");
|
||||
}
|
||||
|
||||
int LuaMinimap::l_get_pos(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
push_v3s16(L, m->getPos());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_set_pos(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
m->setPos(read_v3s16(L, 2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_get_angle(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
lua_pushinteger(L, m->getAngle());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_set_angle(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
m->setAngle(lua_tointeger(L, 2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_get_mode(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
lua_pushinteger(L, m->getModeIndex());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_set_mode(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
u32 mode = lua_tointeger(L, 2);
|
||||
if (mode >= m->getMaxModeIndex())
|
||||
return 0;
|
||||
|
||||
m->setModeIndex(mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_set_shape(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
if (!lua_isnumber(L, 2))
|
||||
return 0;
|
||||
|
||||
m->setMinimapShape((MinimapShape)((int)lua_tonumber(L, 2)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_get_shape(lua_State *L)
|
||||
{
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
lua_pushnumber(L, (int)m->getMinimapShape());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_show(lua_State *L)
|
||||
{
|
||||
// If minimap is disabled by config, don't show it.
|
||||
if (!g_settings->getBool("enable_minimap"))
|
||||
return 1;
|
||||
|
||||
Client *client = getClient(L);
|
||||
assert(client);
|
||||
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
// This is not very adapted to new minimap mode management. Btw, tried
|
||||
// to do something compatible.
|
||||
|
||||
if (m->getModeIndex() == 0 && m->getMaxModeIndex() > 0)
|
||||
m->setModeIndex(1);
|
||||
|
||||
client->showMinimap(true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaMinimap::l_hide(lua_State *L)
|
||||
{
|
||||
Client *client = getClient(L);
|
||||
assert(client);
|
||||
|
||||
LuaMinimap *ref = checkobject(L, 1);
|
||||
Minimap *m = getobject(ref);
|
||||
|
||||
// This is not very adapted to new minimap mode management. Btw, tried
|
||||
// to do something compatible.
|
||||
|
||||
if (m->getModeIndex() != 0)
|
||||
m->setModeIndex(0);
|
||||
|
||||
client->showMinimap(false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaMinimap *LuaMinimap::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(LuaMinimap **)ud; // unbox pointer
|
||||
}
|
||||
|
||||
Minimap* LuaMinimap::getobject(LuaMinimap *ref)
|
||||
{
|
||||
return ref->m_minimap;
|
||||
}
|
||||
|
||||
int LuaMinimap::gc_object(lua_State *L) {
|
||||
LuaMinimap *o = *(LuaMinimap **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LuaMinimap::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
}
|
||||
|
||||
const char LuaMinimap::className[] = "Minimap";
|
||||
const luaL_Reg LuaMinimap::methods[] = {
|
||||
luamethod(LuaMinimap, show),
|
||||
luamethod(LuaMinimap, hide),
|
||||
luamethod(LuaMinimap, get_pos),
|
||||
luamethod(LuaMinimap, set_pos),
|
||||
luamethod(LuaMinimap, get_angle),
|
||||
luamethod(LuaMinimap, set_angle),
|
||||
luamethod(LuaMinimap, get_mode),
|
||||
luamethod(LuaMinimap, set_mode),
|
||||
luamethod(LuaMinimap, set_shape),
|
||||
luamethod(LuaMinimap, get_shape),
|
||||
{0,0}
|
||||
};
|
62
src/script/lua_api/l_minimap.h
Normal file
62
src/script/lua_api/l_minimap.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2017 Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "l_base.h"
|
||||
|
||||
class Minimap;
|
||||
|
||||
class LuaMinimap : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static int l_get_pos(lua_State *L);
|
||||
static int l_set_pos(lua_State *L);
|
||||
|
||||
static int l_get_angle(lua_State *L);
|
||||
static int l_set_angle(lua_State *L);
|
||||
|
||||
static int l_get_mode(lua_State *L);
|
||||
static int l_set_mode(lua_State *L);
|
||||
|
||||
static int l_show(lua_State *L);
|
||||
static int l_hide(lua_State *L);
|
||||
|
||||
static int l_set_shape(lua_State *L);
|
||||
static int l_get_shape(lua_State *L);
|
||||
|
||||
Minimap *m_minimap = nullptr;
|
||||
|
||||
public:
|
||||
LuaMinimap(Minimap *m);
|
||||
~LuaMinimap() = default;
|
||||
|
||||
static void create(lua_State *L, Minimap *object);
|
||||
|
||||
static LuaMinimap *checkobject(lua_State *L, int narg);
|
||||
static Minimap *getobject(LuaMinimap *ref);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
153
src/script/lua_api/l_modchannels.cpp
Normal file
153
src/script/lua_api/l_modchannels.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <log.h>
|
||||
#include "lua_api/l_modchannels.h"
|
||||
#include "l_internal.h"
|
||||
#include "modchannels.h"
|
||||
|
||||
int ModApiChannels::l_mod_channel_join(lua_State *L)
|
||||
{
|
||||
if (!lua_isstring(L, 1))
|
||||
return 0;
|
||||
|
||||
std::string channel = luaL_checkstring(L, 1);
|
||||
if (channel.empty())
|
||||
return 0;
|
||||
|
||||
getGameDef(L)->joinModChannel(channel);
|
||||
assert(getGameDef(L)->getModChannel(channel) != nullptr);
|
||||
ModChannelRef::create(L, channel);
|
||||
|
||||
int object = lua_gettop(L);
|
||||
lua_pushvalue(L, object);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiChannels::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(mod_channel_join);
|
||||
}
|
||||
|
||||
/*
|
||||
* ModChannelRef
|
||||
*/
|
||||
|
||||
ModChannelRef::ModChannelRef(const std::string &modchannel) :
|
||||
m_modchannel_name(modchannel)
|
||||
{
|
||||
}
|
||||
|
||||
int ModChannelRef::l_leave(lua_State *L)
|
||||
{
|
||||
ModChannelRef *ref = checkobject(L, 1);
|
||||
getGameDef(L)->leaveModChannel(ref->m_modchannel_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModChannelRef::l_send_all(lua_State *L)
|
||||
{
|
||||
ModChannelRef *ref = checkobject(L, 1);
|
||||
ModChannel *channel = getobject(L, ref);
|
||||
if (!channel || !channel->canWrite())
|
||||
return 0;
|
||||
|
||||
// @TODO serialize message
|
||||
std::string message = luaL_checkstring(L, 2);
|
||||
|
||||
getGameDef(L)->sendModChannelMessage(channel->getName(), message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModChannelRef::l_is_writeable(lua_State *L)
|
||||
{
|
||||
ModChannelRef *ref = checkobject(L, 1);
|
||||
ModChannel *channel = getobject(L, ref);
|
||||
if (!channel)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(L, channel->canWrite());
|
||||
return 1;
|
||||
}
|
||||
void ModChannelRef::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // Drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // Drop methodtable
|
||||
}
|
||||
|
||||
void ModChannelRef::create(lua_State *L, const std::string &channel)
|
||||
{
|
||||
ModChannelRef *o = new ModChannelRef(channel);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
int ModChannelRef::gc_object(lua_State *L)
|
||||
{
|
||||
ModChannelRef *o = *(ModChannelRef **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ModChannelRef *ModChannelRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(ModChannelRef **)ud; // unbox pointer
|
||||
}
|
||||
|
||||
ModChannel *ModChannelRef::getobject(lua_State *L, ModChannelRef *ref)
|
||||
{
|
||||
return getGameDef(L)->getModChannel(ref->m_modchannel_name);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const char ModChannelRef::className[] = "ModChannelRef";
|
||||
const luaL_Reg ModChannelRef::methods[] = {
|
||||
luamethod(ModChannelRef, leave),
|
||||
luamethod(ModChannelRef, is_writeable),
|
||||
luamethod(ModChannelRef, send_all),
|
||||
{0, 0},
|
||||
};
|
||||
// clang-format on
|
66
src/script/lua_api/l_modchannels.h
Normal file
66
src/script/lua_api/l_modchannels.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "config.h"
|
||||
|
||||
class ModChannel;
|
||||
|
||||
class ModApiChannels : public ModApiBase
|
||||
{
|
||||
private:
|
||||
// mod_channel_join(name)
|
||||
static int l_mod_channel_join(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
||||
|
||||
class ModChannelRef : public ModApiBase
|
||||
{
|
||||
public:
|
||||
ModChannelRef(const std::string &modchannel);
|
||||
~ModChannelRef() = default;
|
||||
|
||||
static void Register(lua_State *L);
|
||||
static void create(lua_State *L, const std::string &channel);
|
||||
|
||||
// leave()
|
||||
static int l_leave(lua_State *L);
|
||||
|
||||
// send(message)
|
||||
static int l_send_all(lua_State *L);
|
||||
|
||||
// is_writeable()
|
||||
static int l_is_writeable(lua_State *L);
|
||||
|
||||
private:
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static ModChannelRef *checkobject(lua_State *L, int narg);
|
||||
static ModChannel *getobject(lua_State *L, ModChannelRef *ref);
|
||||
|
||||
std::string m_modchannel_name;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
};
|
276
src/script/lua_api/l_nodemeta.cpp
Normal file
276
src/script/lua_api/l_nodemeta.cpp
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_nodemeta.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "lua_api/l_inventory.h"
|
||||
#include "common/c_content.h"
|
||||
#include "serverenvironment.h"
|
||||
#include "map.h"
|
||||
#include "mapblock.h"
|
||||
#include "server.h"
|
||||
|
||||
/*
|
||||
NodeMetaRef
|
||||
*/
|
||||
NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if(!ud) luaL_typerror(L, narg, className);
|
||||
return *(NodeMetaRef**)ud; // unbox pointer
|
||||
}
|
||||
|
||||
Metadata* NodeMetaRef::getmeta(bool auto_create)
|
||||
{
|
||||
if (m_is_local)
|
||||
return m_meta;
|
||||
|
||||
NodeMetadata *meta = m_env->getMap().getNodeMetadata(m_p);
|
||||
if (meta == NULL && auto_create) {
|
||||
meta = new NodeMetadata(m_env->getGameDef()->idef());
|
||||
if (!m_env->getMap().setNodeMetadata(m_p, meta)) {
|
||||
delete meta;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
void NodeMetaRef::clearMeta()
|
||||
{
|
||||
SANITY_CHECK(!m_is_local);
|
||||
m_env->getMap().removeNodeMetadata(m_p);
|
||||
}
|
||||
|
||||
void NodeMetaRef::reportMetadataChange(const std::string *name)
|
||||
{
|
||||
SANITY_CHECK(!m_is_local);
|
||||
// NOTE: This same code is in rollback_interface.cpp
|
||||
// Inform other things that the metadata has changed
|
||||
NodeMetadata *meta = dynamic_cast<NodeMetadata*>(m_meta);
|
||||
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = m_p;
|
||||
event.is_private_change = name && meta && meta->isPrivate(*name);
|
||||
m_env->getMap().dispatchEvent(event);
|
||||
}
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
int NodeMetaRef::gc_object(lua_State *L) {
|
||||
NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_inventory(self)
|
||||
int NodeMetaRef::l_get_inventory(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
ref->getmeta(true); // try to ensure the metadata exists
|
||||
InvRef::createNodeMeta(L, ref->m_p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// mark_as_private(self, <string> or {<string>, <string>, ...})
|
||||
int NodeMetaRef::l_mark_as_private(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
NodeMetaRef *ref = checkobject(L, 1);
|
||||
NodeMetadata *meta = dynamic_cast<NodeMetadata*>(ref->getmeta(true));
|
||||
assert(meta);
|
||||
|
||||
if (lua_istable(L, 2)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 2) != 0) {
|
||||
// key at index -2 and value at index -1
|
||||
luaL_checktype(L, -1, LUA_TSTRING);
|
||||
meta->markPrivate(readParam<std::string>(L, -1), true);
|
||||
// removes value, keeps key for next iteration
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (lua_isstring(L, 2)) {
|
||||
meta->markPrivate(readParam<std::string>(L, 2), true);
|
||||
}
|
||||
ref->reportMetadataChange();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NodeMetaRef::handleToTable(lua_State *L, Metadata *_meta)
|
||||
{
|
||||
// fields
|
||||
MetaDataRef::handleToTable(L, _meta);
|
||||
|
||||
NodeMetadata *meta = (NodeMetadata*) _meta;
|
||||
|
||||
// inventory
|
||||
lua_newtable(L);
|
||||
Inventory *inv = meta->getInventory();
|
||||
if (inv) {
|
||||
std::vector<const InventoryList *> lists = inv->getLists();
|
||||
for(std::vector<const InventoryList *>::const_iterator
|
||||
i = lists.begin(); i != lists.end(); ++i) {
|
||||
push_inventory_list(L, inv, (*i)->getName().c_str());
|
||||
lua_setfield(L, -2, (*i)->getName().c_str());
|
||||
}
|
||||
}
|
||||
lua_setfield(L, -2, "inventory");
|
||||
}
|
||||
|
||||
// from_table(self, table)
|
||||
bool NodeMetaRef::handleFromTable(lua_State *L, int table, Metadata *_meta)
|
||||
{
|
||||
// fields
|
||||
if (!MetaDataRef::handleFromTable(L, table, _meta))
|
||||
return false;
|
||||
|
||||
NodeMetadata *meta = (NodeMetadata*) _meta;
|
||||
|
||||
// inventory
|
||||
Inventory *inv = meta->getInventory();
|
||||
lua_getfield(L, table, "inventory");
|
||||
if (lua_istable(L, -1)) {
|
||||
int inventorytable = lua_gettop(L);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, inventorytable) != 0) {
|
||||
// key at index -2 and value at index -1
|
||||
std::string name = luaL_checkstring(L, -2);
|
||||
read_inventory_list(L, -1, inv, name.c_str(), getServer(L));
|
||||
lua_pop(L, 1); // Remove value, keep key for next iteration
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NodeMetaRef::NodeMetaRef(v3s16 p, ServerEnvironment *env):
|
||||
m_p(p),
|
||||
m_env(env)
|
||||
{
|
||||
}
|
||||
|
||||
NodeMetaRef::NodeMetaRef(Metadata *meta):
|
||||
m_meta(meta),
|
||||
m_is_local(true)
|
||||
{
|
||||
}
|
||||
|
||||
// Creates an NodeMetaRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
void NodeMetaRef::create(lua_State *L, v3s16 p, ServerEnvironment *env)
|
||||
{
|
||||
NodeMetaRef *o = new NodeMetaRef(p, env);
|
||||
//infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
// Client-sided version of the above
|
||||
void NodeMetaRef::createClient(lua_State *L, Metadata *meta)
|
||||
{
|
||||
NodeMetaRef *o = new NodeMetaRef(meta);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
const char NodeMetaRef::className[] = "NodeMetaRef";
|
||||
void NodeMetaRef::RegisterCommon(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "metadata_class");
|
||||
lua_pushlstring(L, className, strlen(className));
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__eq");
|
||||
lua_pushcfunction(L, l_equals);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
}
|
||||
|
||||
void NodeMetaRef::Register(lua_State *L)
|
||||
{
|
||||
RegisterCommon(L);
|
||||
luaL_openlib(L, 0, methodsServer, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
}
|
||||
|
||||
|
||||
const luaL_Reg NodeMetaRef::methodsServer[] = {
|
||||
luamethod(MetaDataRef, contains),
|
||||
luamethod(MetaDataRef, get),
|
||||
luamethod(MetaDataRef, get_string),
|
||||
luamethod(MetaDataRef, set_string),
|
||||
luamethod(MetaDataRef, get_int),
|
||||
luamethod(MetaDataRef, set_int),
|
||||
luamethod(MetaDataRef, get_float),
|
||||
luamethod(MetaDataRef, set_float),
|
||||
luamethod(MetaDataRef, to_table),
|
||||
luamethod(MetaDataRef, from_table),
|
||||
luamethod(NodeMetaRef, get_inventory),
|
||||
luamethod(NodeMetaRef, mark_as_private),
|
||||
luamethod(MetaDataRef, equals),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
|
||||
void NodeMetaRef::RegisterClient(lua_State *L)
|
||||
{
|
||||
RegisterCommon(L);
|
||||
luaL_openlib(L, 0, methodsClient, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
}
|
||||
|
||||
|
||||
const luaL_Reg NodeMetaRef::methodsClient[] = {
|
||||
luamethod(MetaDataRef, contains),
|
||||
luamethod(MetaDataRef, get),
|
||||
luamethod(MetaDataRef, get_string),
|
||||
luamethod(MetaDataRef, get_int),
|
||||
luamethod(MetaDataRef, get_float),
|
||||
luamethod(MetaDataRef, to_table),
|
||||
{0,0}
|
||||
};
|
95
src/script/lua_api/l_nodemeta.h
Normal file
95
src/script/lua_api/l_nodemeta.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "lua_api/l_metadata.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "nodemetadata.h"
|
||||
|
||||
class ServerEnvironment;
|
||||
class NodeMetadata;
|
||||
|
||||
/*
|
||||
NodeMetaRef
|
||||
*/
|
||||
|
||||
class NodeMetaRef : public MetaDataRef {
|
||||
private:
|
||||
v3s16 m_p;
|
||||
ServerEnvironment *m_env = nullptr;
|
||||
Metadata *m_meta = nullptr;
|
||||
bool m_is_local = false;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methodsServer[];
|
||||
static const luaL_Reg methodsClient[];
|
||||
|
||||
static NodeMetaRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
/**
|
||||
* Retrieve metadata for a node.
|
||||
* If @p auto_create is set and the specified node has no metadata information
|
||||
* associated with it yet, the method attempts to attach a new metadata object
|
||||
* to the node and returns a pointer to the metadata when successful.
|
||||
*
|
||||
* However, it is NOT guaranteed that the method will return a pointer,
|
||||
* and @c NULL may be returned in case of an error regardless of @p auto_create.
|
||||
*
|
||||
* @param ref specifies the node for which the associated metadata is retrieved.
|
||||
* @param auto_create when true, try to create metadata information for the node if it has none.
|
||||
* @return pointer to a @c NodeMetadata object or @c NULL in case of error.
|
||||
*/
|
||||
virtual Metadata* getmeta(bool auto_create);
|
||||
virtual void clearMeta();
|
||||
|
||||
virtual void reportMetadataChange(const std::string *name = nullptr);
|
||||
|
||||
virtual void handleToTable(lua_State *L, Metadata *_meta);
|
||||
virtual bool handleFromTable(lua_State *L, int table, Metadata *_meta);
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// get_inventory(self)
|
||||
static int l_get_inventory(lua_State *L);
|
||||
|
||||
// mark_as_private(self, <string> or {<string>, <string>, ...})
|
||||
static int l_mark_as_private(lua_State *L);
|
||||
|
||||
public:
|
||||
NodeMetaRef(v3s16 p, ServerEnvironment *env);
|
||||
NodeMetaRef(Metadata *meta);
|
||||
|
||||
~NodeMetaRef() = default;
|
||||
|
||||
// Creates an NodeMetaRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
static void create(lua_State *L, v3s16 p, ServerEnvironment *env);
|
||||
|
||||
// Client-sided version of the above
|
||||
static void createClient(lua_State *L, Metadata *meta);
|
||||
|
||||
static void RegisterCommon(lua_State *L);
|
||||
static void Register(lua_State *L);
|
||||
static void RegisterClient(lua_State *L);
|
||||
};
|
141
src/script/lua_api/l_nodetimer.cpp
Normal file
141
src/script/lua_api/l_nodetimer.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_nodetimer.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "serverenvironment.h"
|
||||
#include "map.h"
|
||||
|
||||
|
||||
int NodeTimerRef::gc_object(lua_State *L) {
|
||||
NodeTimerRef *o = *(NodeTimerRef **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NodeTimerRef* NodeTimerRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if(!ud) luaL_typerror(L, narg, className);
|
||||
return *(NodeTimerRef**)ud; // unbox pointer
|
||||
}
|
||||
|
||||
int NodeTimerRef::l_set(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
NodeTimerRef *o = checkobject(L, 1);
|
||||
f32 t = readParam<float>(L,2);
|
||||
f32 e = readParam<float>(L,3);
|
||||
o->m_map->setNodeTimer(NodeTimer(t, e, o->m_p));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NodeTimerRef::l_start(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
NodeTimerRef *o = checkobject(L, 1);
|
||||
f32 t = readParam<float>(L,2);
|
||||
o->m_map->setNodeTimer(NodeTimer(t, 0, o->m_p));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NodeTimerRef::l_stop(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
NodeTimerRef *o = checkobject(L, 1);
|
||||
o->m_map->removeNodeTimer(o->m_p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NodeTimerRef::l_is_started(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
NodeTimerRef *o = checkobject(L, 1);
|
||||
NodeTimer t = o->m_map->getNodeTimer(o->m_p);
|
||||
lua_pushboolean(L,(t.timeout != 0));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NodeTimerRef::l_get_timeout(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
NodeTimerRef *o = checkobject(L, 1);
|
||||
NodeTimer t = o->m_map->getNodeTimer(o->m_p);
|
||||
lua_pushnumber(L,t.timeout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int NodeTimerRef::l_get_elapsed(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
NodeTimerRef *o = checkobject(L, 1);
|
||||
NodeTimer t = o->m_map->getNodeTimer(o->m_p);
|
||||
lua_pushnumber(L,t.elapsed);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Creates an NodeTimerRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
void NodeTimerRef::create(lua_State *L, v3s16 p, ServerMap *map)
|
||||
{
|
||||
NodeTimerRef *o = new NodeTimerRef(p, map);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
void NodeTimerRef::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
|
||||
// Cannot be created from Lua
|
||||
//lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char NodeTimerRef::className[] = "NodeTimerRef";
|
||||
const luaL_Reg NodeTimerRef::methods[] = {
|
||||
luamethod(NodeTimerRef, start),
|
||||
luamethod(NodeTimerRef, set),
|
||||
luamethod(NodeTimerRef, stop),
|
||||
luamethod(NodeTimerRef, is_started),
|
||||
luamethod(NodeTimerRef, get_timeout),
|
||||
luamethod(NodeTimerRef, get_elapsed),
|
||||
{0,0}
|
||||
};
|
61
src/script/lua_api/l_nodetimer.h
Normal file
61
src/script/lua_api/l_nodetimer.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irr_v3d.h"
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class ServerMap;
|
||||
|
||||
class NodeTimerRef : public ModApiBase
|
||||
{
|
||||
private:
|
||||
v3s16 m_p;
|
||||
ServerMap *m_map;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static NodeTimerRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
static int l_set(lua_State *L);
|
||||
|
||||
static int l_start(lua_State *L);
|
||||
|
||||
static int l_stop(lua_State *L);
|
||||
|
||||
static int l_is_started(lua_State *L);
|
||||
|
||||
static int l_get_timeout(lua_State *L);
|
||||
|
||||
static int l_get_elapsed(lua_State *L);
|
||||
|
||||
public:
|
||||
NodeTimerRef(v3s16 p, ServerMap *map) : m_p(p), m_map(map) {}
|
||||
~NodeTimerRef() = default;
|
||||
|
||||
// Creates an NodeTimerRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
static void create(lua_State *L, v3s16 p, ServerMap *map);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
712
src/script/lua_api/l_noise.cpp
Normal file
712
src/script/lua_api/l_noise.cpp
Normal file
@ -0,0 +1,712 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_noise.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "log.h"
|
||||
#include "porting.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
LuaPerlinNoise
|
||||
*/
|
||||
|
||||
LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
|
||||
np(*params)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoise::l_get_2d(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaPerlinNoise *o = checkobject(L, 1);
|
||||
v2f p = readParam<v2f>(L, 2);
|
||||
lua_Number val = NoisePerlin2D(&o->np, p.X, p.Y, 0);
|
||||
lua_pushnumber(L, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoise::l_get_3d(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaPerlinNoise *o = checkobject(L, 1);
|
||||
v3f p = check_v3f(L, 2);
|
||||
lua_Number val = NoisePerlin3D(&o->np, p.X, p.Y, p.Z, 0);
|
||||
lua_pushnumber(L, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoise::create_object(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
NoiseParams params;
|
||||
|
||||
if (lua_istable(L, 1)) {
|
||||
read_noiseparams(L, 1, ¶ms);
|
||||
} else {
|
||||
params.seed = luaL_checkint(L, 1);
|
||||
params.octaves = luaL_checkint(L, 2);
|
||||
params.persist = readParam<float>(L, 3);
|
||||
params.spread = v3f(1, 1, 1) * readParam<float>(L, 4);
|
||||
}
|
||||
|
||||
LuaPerlinNoise *o = new LuaPerlinNoise(¶ms);
|
||||
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoise::gc_object(lua_State *L)
|
||||
{
|
||||
LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
return *(LuaPerlinNoise **)ud;
|
||||
}
|
||||
|
||||
|
||||
void LuaPerlinNoise::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
|
||||
const char LuaPerlinNoise::className[] = "PerlinNoise";
|
||||
luaL_Reg LuaPerlinNoise::methods[] = {
|
||||
luamethod_aliased(LuaPerlinNoise, get_2d, get2d),
|
||||
luamethod_aliased(LuaPerlinNoise, get_3d, get3d),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
LuaPerlinNoiseMap
|
||||
*/
|
||||
|
||||
LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, s32 seed, v3s16 size)
|
||||
{
|
||||
m_is3d = size.Z > 1;
|
||||
np = *params;
|
||||
try {
|
||||
noise = new Noise(&np, seed, size.X, size.Y, size.Z);
|
||||
} catch (InvalidNoiseParamsException &e) {
|
||||
throw LuaError(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
|
||||
{
|
||||
delete noise;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::l_get_2d_map(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
size_t i = 0;
|
||||
|
||||
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||
v2f p = readParam<v2f>(L, 2);
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap2D(p.X, p.Y);
|
||||
|
||||
lua_createtable(L, n->sy, 0);
|
||||
for (u32 y = 0; y != n->sy; y++) {
|
||||
lua_createtable(L, n->sx, 0);
|
||||
for (u32 x = 0; x != n->sx; x++) {
|
||||
lua_pushnumber(L, n->result[i++]);
|
||||
lua_rawseti(L, -2, x + 1);
|
||||
}
|
||||
lua_rawseti(L, -2, y + 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::l_get_2d_map_flat(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||
v2f p = readParam<v2f>(L, 2);
|
||||
bool use_buffer = lua_istable(L, 3);
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap2D(p.X, p.Y);
|
||||
|
||||
size_t maplen = n->sx * n->sy;
|
||||
|
||||
if (use_buffer)
|
||||
lua_pushvalue(L, 3);
|
||||
else
|
||||
lua_createtable(L, maplen, 0);
|
||||
|
||||
for (size_t i = 0; i != maplen; i++) {
|
||||
lua_pushnumber(L, n->result[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::l_get_3d_map(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
size_t i = 0;
|
||||
|
||||
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||
v3f p = check_v3f(L, 2);
|
||||
|
||||
if (!o->m_is3d)
|
||||
return 0;
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap3D(p.X, p.Y, p.Z);
|
||||
|
||||
lua_createtable(L, n->sz, 0);
|
||||
for (u32 z = 0; z != n->sz; z++) {
|
||||
lua_createtable(L, n->sy, 0);
|
||||
for (u32 y = 0; y != n->sy; y++) {
|
||||
lua_createtable(L, n->sx, 0);
|
||||
for (u32 x = 0; x != n->sx; x++) {
|
||||
lua_pushnumber(L, n->result[i++]);
|
||||
lua_rawseti(L, -2, x + 1);
|
||||
}
|
||||
lua_rawseti(L, -2, y + 1);
|
||||
}
|
||||
lua_rawseti(L, -2, z + 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::l_get_3d_map_flat(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||
v3f p = check_v3f(L, 2);
|
||||
bool use_buffer = lua_istable(L, 3);
|
||||
|
||||
if (!o->m_is3d)
|
||||
return 0;
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap3D(p.X, p.Y, p.Z);
|
||||
|
||||
size_t maplen = n->sx * n->sy * n->sz;
|
||||
|
||||
if (use_buffer)
|
||||
lua_pushvalue(L, 3);
|
||||
else
|
||||
lua_createtable(L, maplen, 0);
|
||||
|
||||
for (size_t i = 0; i != maplen; i++) {
|
||||
lua_pushnumber(L, n->result[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::l_calc_2d_map(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||
v2f p = readParam<v2f>(L, 2);
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap2D(p.X, p.Y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaPerlinNoiseMap::l_calc_3d_map(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||
v3f p = check_v3f(L, 2);
|
||||
|
||||
if (!o->m_is3d)
|
||||
return 0;
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap3D(p.X, p.Y, p.Z);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::l_get_map_slice(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||
v3s16 slice_offset = read_v3s16(L, 2);
|
||||
v3s16 slice_size = read_v3s16(L, 3);
|
||||
bool use_buffer = lua_istable(L, 4);
|
||||
|
||||
Noise *n = o->noise;
|
||||
|
||||
if (use_buffer)
|
||||
lua_pushvalue(L, 4);
|
||||
else
|
||||
lua_newtable(L);
|
||||
|
||||
write_array_slice_float(L, lua_gettop(L), n->result,
|
||||
v3u16(n->sx, n->sy, n->sz),
|
||||
v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
|
||||
v3u16(slice_size.X, slice_size.Y, slice_size.Z));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::create_object(lua_State *L)
|
||||
{
|
||||
NoiseParams np;
|
||||
if (!read_noiseparams(L, 1, &np))
|
||||
return 0;
|
||||
v3s16 size = read_v3s16(L, 2);
|
||||
|
||||
LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(&np, 0, size);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPerlinNoiseMap::gc_object(lua_State *L)
|
||||
{
|
||||
LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(LuaPerlinNoiseMap **)ud;
|
||||
}
|
||||
|
||||
|
||||
void LuaPerlinNoiseMap::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
|
||||
const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
|
||||
luaL_Reg LuaPerlinNoiseMap::methods[] = {
|
||||
luamethod_aliased(LuaPerlinNoiseMap, get_2d_map, get2dMap),
|
||||
luamethod_aliased(LuaPerlinNoiseMap, get_2d_map_flat, get2dMap_flat),
|
||||
luamethod_aliased(LuaPerlinNoiseMap, calc_2d_map, calc2dMap),
|
||||
luamethod_aliased(LuaPerlinNoiseMap, get_3d_map, get3dMap),
|
||||
luamethod_aliased(LuaPerlinNoiseMap, get_3d_map_flat, get3dMap_flat),
|
||||
luamethod_aliased(LuaPerlinNoiseMap, calc_3d_map, calc3dMap),
|
||||
luamethod_aliased(LuaPerlinNoiseMap, get_map_slice, getMapSlice),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
LuaPseudoRandom
|
||||
*/
|
||||
|
||||
int LuaPseudoRandom::l_next(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPseudoRandom *o = checkobject(L, 1);
|
||||
int min = 0;
|
||||
int max = 32767;
|
||||
lua_settop(L, 3);
|
||||
if (lua_isnumber(L, 2))
|
||||
min = luaL_checkinteger(L, 2);
|
||||
if (lua_isnumber(L, 3))
|
||||
max = luaL_checkinteger(L, 3);
|
||||
if (max < min) {
|
||||
errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
|
||||
throw LuaError("PseudoRandom.next(): max < min");
|
||||
}
|
||||
if(max - min != 32767 && max - min > 32767/5)
|
||||
throw LuaError("PseudoRandom.next() max-min is not 32767"
|
||||
" and is > 32768/5. This is disallowed due to"
|
||||
" the bad random distribution the"
|
||||
" implementation would otherwise make.");
|
||||
PseudoRandom &pseudo = o->m_pseudo;
|
||||
int val = pseudo.next();
|
||||
val = (val % (max-min+1)) + min;
|
||||
lua_pushinteger(L, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPseudoRandom::create_object(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
u64 seed = luaL_checknumber(L, 1);
|
||||
LuaPseudoRandom *o = new LuaPseudoRandom(seed);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPseudoRandom::gc_object(lua_State *L)
|
||||
{
|
||||
LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
return *(LuaPseudoRandom **)ud;
|
||||
}
|
||||
|
||||
|
||||
void LuaPseudoRandom::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
|
||||
const char LuaPseudoRandom::className[] = "PseudoRandom";
|
||||
const luaL_Reg LuaPseudoRandom::methods[] = {
|
||||
luamethod(LuaPseudoRandom, next),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
LuaPcgRandom
|
||||
*/
|
||||
|
||||
int LuaPcgRandom::l_next(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPcgRandom *o = checkobject(L, 1);
|
||||
u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
|
||||
u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
|
||||
|
||||
lua_pushinteger(L, o->m_rnd.range(min, max));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaPcgRandom *o = checkobject(L, 1);
|
||||
u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
|
||||
u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
|
||||
int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
|
||||
|
||||
lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPcgRandom::create_object(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
u64 seed = luaL_checknumber(L, 1);
|
||||
LuaPcgRandom *o = lua_isnumber(L, 2) ?
|
||||
new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
|
||||
new LuaPcgRandom(seed);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaPcgRandom::gc_object(lua_State *L)
|
||||
{
|
||||
LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
return *(LuaPcgRandom **)ud;
|
||||
}
|
||||
|
||||
|
||||
void LuaPcgRandom::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
|
||||
const char LuaPcgRandom::className[] = "PcgRandom";
|
||||
const luaL_Reg LuaPcgRandom::methods[] = {
|
||||
luamethod(LuaPcgRandom, next),
|
||||
luamethod(LuaPcgRandom, rand_normal_dist),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
LuaSecureRandom
|
||||
*/
|
||||
|
||||
bool LuaSecureRandom::fillRandBuf()
|
||||
{
|
||||
return porting::secure_rand_fill_buf(m_rand_buf, RAND_BUF_SIZE);
|
||||
}
|
||||
|
||||
int LuaSecureRandom::l_next_bytes(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaSecureRandom *o = checkobject(L, 1);
|
||||
u32 count = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : 1;
|
||||
|
||||
// Limit count
|
||||
count = MYMIN(RAND_BUF_SIZE, count);
|
||||
|
||||
// Find out whether we can pass directly from our array, or have to do some gluing
|
||||
size_t count_remaining = RAND_BUF_SIZE - o->m_rand_idx;
|
||||
if (count_remaining >= count) {
|
||||
lua_pushlstring(L, o->m_rand_buf + o->m_rand_idx, count);
|
||||
o->m_rand_idx += count;
|
||||
} else {
|
||||
char output_buf[RAND_BUF_SIZE];
|
||||
|
||||
// Copy over with what we have left from our current buffer
|
||||
memcpy(output_buf, o->m_rand_buf + o->m_rand_idx, count_remaining);
|
||||
|
||||
// Refill buffer and copy over the remainder of what was requested
|
||||
o->fillRandBuf();
|
||||
memcpy(output_buf + count_remaining, o->m_rand_buf, count - count_remaining);
|
||||
|
||||
// Update index
|
||||
o->m_rand_idx = count - count_remaining;
|
||||
|
||||
lua_pushlstring(L, output_buf, count);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaSecureRandom::create_object(lua_State *L)
|
||||
{
|
||||
LuaSecureRandom *o = new LuaSecureRandom();
|
||||
|
||||
// Fail and return nil if we can't securely fill the buffer
|
||||
if (!o->fillRandBuf()) {
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LuaSecureRandom::gc_object(lua_State *L)
|
||||
{
|
||||
LuaSecureRandom *o = *(LuaSecureRandom **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LuaSecureRandom *LuaSecureRandom::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
return *(LuaSecureRandom **)ud;
|
||||
}
|
||||
|
||||
|
||||
void LuaSecureRandom::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char LuaSecureRandom::className[] = "SecureRandom";
|
||||
const luaL_Reg LuaSecureRandom::methods[] = {
|
||||
luamethod(LuaSecureRandom, next_bytes),
|
||||
{0,0}
|
||||
};
|
194
src/script/lua_api/l_noise.h
Normal file
194
src/script/lua_api/l_noise.h
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irr_v3d.h"
|
||||
#include "lua_api/l_base.h"
|
||||
#include "noise.h"
|
||||
|
||||
/*
|
||||
LuaPerlinNoise
|
||||
*/
|
||||
class LuaPerlinNoise : public ModApiBase
|
||||
{
|
||||
private:
|
||||
NoiseParams np;
|
||||
static const char className[];
|
||||
static luaL_Reg methods[];
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static int l_get_2d(lua_State *L);
|
||||
static int l_get_3d(lua_State *L);
|
||||
|
||||
public:
|
||||
LuaPerlinNoise(NoiseParams *params);
|
||||
~LuaPerlinNoise() = default;
|
||||
|
||||
// LuaPerlinNoise(seed, octaves, persistence, scale)
|
||||
// Creates an LuaPerlinNoise and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaPerlinNoise *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
||||
|
||||
/*
|
||||
LuaPerlinNoiseMap
|
||||
*/
|
||||
class LuaPerlinNoiseMap : public ModApiBase
|
||||
{
|
||||
NoiseParams np;
|
||||
Noise *noise;
|
||||
bool m_is3d;
|
||||
static const char className[];
|
||||
static luaL_Reg methods[];
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static int l_get_2d_map(lua_State *L);
|
||||
static int l_get_2d_map_flat(lua_State *L);
|
||||
static int l_get_3d_map(lua_State *L);
|
||||
static int l_get_3d_map_flat(lua_State *L);
|
||||
|
||||
static int l_calc_2d_map(lua_State *L);
|
||||
static int l_calc_3d_map(lua_State *L);
|
||||
static int l_get_map_slice(lua_State *L);
|
||||
|
||||
public:
|
||||
LuaPerlinNoiseMap(NoiseParams *np, s32 seed, v3s16 size);
|
||||
|
||||
~LuaPerlinNoiseMap();
|
||||
|
||||
// LuaPerlinNoiseMap(np, size)
|
||||
// Creates an LuaPerlinNoiseMap and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaPerlinNoiseMap *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
||||
|
||||
/*
|
||||
LuaPseudoRandom
|
||||
*/
|
||||
class LuaPseudoRandom : public ModApiBase
|
||||
{
|
||||
private:
|
||||
PseudoRandom m_pseudo;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// next(self, min=0, max=32767) -> get next value
|
||||
static int l_next(lua_State *L);
|
||||
|
||||
public:
|
||||
LuaPseudoRandom(s32 seed) : m_pseudo(seed) {}
|
||||
|
||||
// LuaPseudoRandom(seed)
|
||||
// Creates an LuaPseudoRandom and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaPseudoRandom *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
||||
|
||||
/*
|
||||
LuaPcgRandom
|
||||
*/
|
||||
class LuaPcgRandom : public ModApiBase
|
||||
{
|
||||
private:
|
||||
PcgRandom m_rnd;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// next(self, min=-2147483648, max=2147483647) -> get next value
|
||||
static int l_next(lua_State *L);
|
||||
|
||||
// rand_normal_dist(self, min=-2147483648, max=2147483647, num_trials=6) ->
|
||||
// get next normally distributed random value
|
||||
static int l_rand_normal_dist(lua_State *L);
|
||||
|
||||
public:
|
||||
LuaPcgRandom(u64 seed) : m_rnd(seed) {}
|
||||
LuaPcgRandom(u64 seed, u64 seq) : m_rnd(seed, seq) {}
|
||||
|
||||
// LuaPcgRandom(seed)
|
||||
// Creates an LuaPcgRandom and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaPcgRandom *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
||||
|
||||
/*
|
||||
LuaSecureRandom
|
||||
*/
|
||||
class LuaSecureRandom : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static const size_t RAND_BUF_SIZE = 2048;
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
u32 m_rand_idx;
|
||||
char m_rand_buf[RAND_BUF_SIZE];
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// next_bytes(self, count) -> get count many bytes
|
||||
static int l_next_bytes(lua_State *L);
|
||||
|
||||
public:
|
||||
bool fillRandBuf();
|
||||
|
||||
// LuaSecureRandom()
|
||||
// Creates an LuaSecureRandom and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaSecureRandom *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
2398
src/script/lua_api/l_object.cpp
Normal file
2398
src/script/lua_api/l_object.cpp
Normal file
File diff suppressed because it is too large
Load Diff
378
src/script/lua_api/l_object.h
Normal file
378
src/script/lua_api/l_object.h
Normal file
@ -0,0 +1,378 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "irrlichttypes.h"
|
||||
|
||||
class ServerActiveObject;
|
||||
class LuaEntitySAO;
|
||||
class PlayerSAO;
|
||||
class RemotePlayer;
|
||||
|
||||
/*
|
||||
ObjectRef
|
||||
*/
|
||||
|
||||
class ObjectRef : public ModApiBase {
|
||||
public:
|
||||
ObjectRef(ServerActiveObject *object);
|
||||
|
||||
~ObjectRef() = default;
|
||||
|
||||
// Creates an ObjectRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
static void create(lua_State *L, ServerActiveObject *object);
|
||||
|
||||
static void set_null(lua_State *L);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
|
||||
static ObjectRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
static ServerActiveObject* getobject(ObjectRef *ref);
|
||||
private:
|
||||
ServerActiveObject *m_object = nullptr;
|
||||
static const char className[];
|
||||
static luaL_Reg methods[];
|
||||
|
||||
|
||||
static LuaEntitySAO* getluaobject(ObjectRef *ref);
|
||||
|
||||
static PlayerSAO* getplayersao(ObjectRef *ref);
|
||||
|
||||
static RemotePlayer *getplayer(ObjectRef *ref);
|
||||
|
||||
// Exported functions
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// remove(self)
|
||||
static int l_remove(lua_State *L);
|
||||
|
||||
// get_pos(self)
|
||||
static int l_get_pos(lua_State *L);
|
||||
|
||||
// set_pos(self, pos)
|
||||
static int l_set_pos(lua_State *L);
|
||||
|
||||
// move_to(self, pos, continuous)
|
||||
static int l_move_to(lua_State *L);
|
||||
|
||||
// punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||
static int l_punch(lua_State *L);
|
||||
|
||||
// right_click(self, clicker)
|
||||
static int l_right_click(lua_State *L);
|
||||
|
||||
// set_hp(self, hp, reason)
|
||||
static int l_set_hp(lua_State *L);
|
||||
|
||||
// get_hp(self)
|
||||
static int l_get_hp(lua_State *L);
|
||||
|
||||
// get_inventory(self)
|
||||
static int l_get_inventory(lua_State *L);
|
||||
|
||||
// get_wield_list(self)
|
||||
static int l_get_wield_list(lua_State *L);
|
||||
|
||||
// get_wield_index(self)
|
||||
static int l_get_wield_index(lua_State *L);
|
||||
|
||||
// get_wielded_item(self)
|
||||
static int l_get_wielded_item(lua_State *L);
|
||||
|
||||
// set_wielded_item(self, item)
|
||||
static int l_set_wielded_item(lua_State *L);
|
||||
|
||||
// set_armor_groups(self, groups)
|
||||
static int l_set_armor_groups(lua_State *L);
|
||||
|
||||
// get_armor_groups(self)
|
||||
static int l_get_armor_groups(lua_State *L);
|
||||
|
||||
// set_physics_override(self, override_table)
|
||||
static int l_set_physics_override(lua_State *L);
|
||||
|
||||
// get_physics_override(self)
|
||||
static int l_get_physics_override(lua_State *L);
|
||||
|
||||
// set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
|
||||
static int l_set_animation(lua_State *L);
|
||||
|
||||
// set_animation_frame_speed(self, frame_speed)
|
||||
static int l_set_animation_frame_speed(lua_State *L);
|
||||
|
||||
// get_animation(self)
|
||||
static int l_get_animation(lua_State *L);
|
||||
|
||||
// set_bone_position(self, bone, position, rotation)
|
||||
static int l_set_bone_position(lua_State *L);
|
||||
|
||||
// get_bone_position(self, bone)
|
||||
static int l_get_bone_position(lua_State *L);
|
||||
|
||||
// set_attach(self, parent, bone, position, rotation)
|
||||
static int l_set_attach(lua_State *L);
|
||||
|
||||
// get_attach(self)
|
||||
static int l_get_attach(lua_State *L);
|
||||
|
||||
// get_children(self)
|
||||
static int l_get_children(lua_State *L);
|
||||
|
||||
// set_detach(self)
|
||||
static int l_set_detach(lua_State *L);
|
||||
|
||||
// set_properties(self, properties)
|
||||
static int l_set_properties(lua_State *L);
|
||||
|
||||
// get_properties(self)
|
||||
static int l_get_properties(lua_State *L);
|
||||
|
||||
// is_player(self)
|
||||
static int l_is_player(lua_State *L);
|
||||
|
||||
/* LuaEntitySAO-only */
|
||||
|
||||
// set_velocity(self, velocity)
|
||||
static int l_set_velocity(lua_State *L);
|
||||
|
||||
// add_velocity(self, velocity)
|
||||
static int l_add_velocity(lua_State *L);
|
||||
|
||||
// get_velocity(self)
|
||||
static int l_get_velocity(lua_State *L);
|
||||
|
||||
// set_acceleration(self, acceleration)
|
||||
static int l_set_acceleration(lua_State *L);
|
||||
|
||||
// get_acceleration(self)
|
||||
static int l_get_acceleration(lua_State *L);
|
||||
|
||||
// set_rotation(self, rotation)
|
||||
static int l_set_rotation(lua_State *L);
|
||||
|
||||
// get_rotation(self)
|
||||
static int l_get_rotation(lua_State *L);
|
||||
|
||||
// set_yaw(self, yaw)
|
||||
static int l_set_yaw(lua_State *L);
|
||||
|
||||
// get_yaw(self)
|
||||
static int l_get_yaw(lua_State *L);
|
||||
|
||||
// set_texture_mod(self, mod)
|
||||
static int l_set_texture_mod(lua_State *L);
|
||||
|
||||
// l_get_texture_mod(self)
|
||||
static int l_get_texture_mod(lua_State *L);
|
||||
|
||||
// set_sprite(self, start_frame, num_frames, framelength, select_x_by_camera)
|
||||
static int l_set_sprite(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// get_entity_name(self)
|
||||
static int l_get_entity_name(lua_State *L);
|
||||
|
||||
// get_luaentity(self)
|
||||
static int l_get_luaentity(lua_State *L);
|
||||
|
||||
/* Player-only */
|
||||
|
||||
// get_player_name(self)
|
||||
static int l_get_player_name(lua_State *L);
|
||||
|
||||
// get_fov(self)
|
||||
static int l_get_fov(lua_State *L);
|
||||
|
||||
// get_look_dir(self)
|
||||
static int l_get_look_dir(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// get_look_pitch(self)
|
||||
static int l_get_look_pitch(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// get_look_yaw(self)
|
||||
static int l_get_look_yaw(lua_State *L);
|
||||
|
||||
// get_look_pitch2(self)
|
||||
static int l_get_look_vertical(lua_State *L);
|
||||
|
||||
// get_look_yaw2(self)
|
||||
static int l_get_look_horizontal(lua_State *L);
|
||||
|
||||
// set_fov(self, degrees, is_multiplier, transition_time)
|
||||
static int l_set_fov(lua_State *L);
|
||||
|
||||
// set_look_vertical(self, radians)
|
||||
static int l_set_look_vertical(lua_State *L);
|
||||
|
||||
// set_look_horizontal(self, radians)
|
||||
static int l_set_look_horizontal(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// set_look_pitch(self, radians)
|
||||
static int l_set_look_pitch(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// set_look_yaw(self, radians)
|
||||
static int l_set_look_yaw(lua_State *L);
|
||||
|
||||
// set_breath(self, breath)
|
||||
static int l_set_breath(lua_State *L);
|
||||
|
||||
// get_breath(self, breath)
|
||||
static int l_get_breath(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// set_attribute(self, attribute, value)
|
||||
static int l_set_attribute(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// get_attribute(self, attribute)
|
||||
static int l_get_attribute(lua_State *L);
|
||||
|
||||
// get_meta(self)
|
||||
static int l_get_meta(lua_State *L);
|
||||
|
||||
// set_inventory_formspec(self, formspec)
|
||||
static int l_set_inventory_formspec(lua_State *L);
|
||||
|
||||
// get_inventory_formspec(self)
|
||||
static int l_get_inventory_formspec(lua_State *L);
|
||||
|
||||
// set_formspec_prepend(self, formspec)
|
||||
static int l_set_formspec_prepend(lua_State *L);
|
||||
|
||||
// get_formspec_prepend(self)
|
||||
static int l_get_formspec_prepend(lua_State *L);
|
||||
|
||||
// get_player_control(self)
|
||||
static int l_get_player_control(lua_State *L);
|
||||
|
||||
// get_player_control_bits(self)
|
||||
static int l_get_player_control_bits(lua_State *L);
|
||||
|
||||
// hud_add(self, id, form)
|
||||
static int l_hud_add(lua_State *L);
|
||||
|
||||
// hud_rm(self, id)
|
||||
static int l_hud_remove(lua_State *L);
|
||||
|
||||
// hud_change(self, id, stat, data)
|
||||
static int l_hud_change(lua_State *L);
|
||||
|
||||
// hud_get_next_id(self)
|
||||
static u32 hud_get_next_id(lua_State *L);
|
||||
|
||||
// hud_get(self, id)
|
||||
static int l_hud_get(lua_State *L);
|
||||
|
||||
// hud_set_flags(self, flags)
|
||||
static int l_hud_set_flags(lua_State *L);
|
||||
|
||||
// hud_get_flags()
|
||||
static int l_hud_get_flags(lua_State *L);
|
||||
|
||||
// hud_set_hotbar_itemcount(self, hotbar_itemcount)
|
||||
static int l_hud_set_hotbar_itemcount(lua_State *L);
|
||||
|
||||
// hud_get_hotbar_itemcount(self)
|
||||
static int l_hud_get_hotbar_itemcount(lua_State *L);
|
||||
|
||||
// hud_set_hotbar_image(self, name)
|
||||
static int l_hud_set_hotbar_image(lua_State *L);
|
||||
|
||||
// hud_get_hotbar_image(self)
|
||||
static int l_hud_get_hotbar_image(lua_State *L);
|
||||
|
||||
// hud_set_hotbar_selected_image(self, name)
|
||||
static int l_hud_set_hotbar_selected_image(lua_State *L);
|
||||
|
||||
// hud_get_hotbar_selected_image(self)
|
||||
static int l_hud_get_hotbar_selected_image(lua_State *L);
|
||||
|
||||
// set_sky(self, sky_parameters)
|
||||
static int l_set_sky(lua_State *L);
|
||||
|
||||
// get_sky(self)
|
||||
static int l_get_sky(lua_State *L);
|
||||
|
||||
// get_sky_color(self)
|
||||
static int l_get_sky_color(lua_State* L);
|
||||
|
||||
// set_sun(self, sun_parameters)
|
||||
static int l_set_sun(lua_State *L);
|
||||
|
||||
// get_sun(self)
|
||||
static int l_get_sun(lua_State *L);
|
||||
|
||||
// set_moon(self, moon_parameters)
|
||||
static int l_set_moon(lua_State *L);
|
||||
|
||||
// get_moon(self)
|
||||
static int l_get_moon(lua_State *L);
|
||||
|
||||
// set_stars(self, star_parameters)
|
||||
static int l_set_stars(lua_State *L);
|
||||
|
||||
// get_stars(self)
|
||||
static int l_get_stars(lua_State *L);
|
||||
|
||||
// set_clouds(self, cloud_parameters)
|
||||
static int l_set_clouds(lua_State *L);
|
||||
|
||||
// get_clouds(self)
|
||||
static int l_get_clouds(lua_State *L);
|
||||
|
||||
// override_day_night_ratio(self, type)
|
||||
static int l_override_day_night_ratio(lua_State *L);
|
||||
|
||||
// get_day_night_ratio(self)
|
||||
static int l_get_day_night_ratio(lua_State *L);
|
||||
|
||||
// set_local_animation(self, idle, walk, dig, walk_while_dig, frame_speed)
|
||||
static int l_set_local_animation(lua_State *L);
|
||||
|
||||
// get_local_animation(self)
|
||||
static int l_get_local_animation(lua_State *L);
|
||||
|
||||
// set_eye_offset(self, firstperson, thirdperson)
|
||||
static int l_set_eye_offset(lua_State *L);
|
||||
|
||||
// get_eye_offset(self)
|
||||
static int l_get_eye_offset(lua_State *L);
|
||||
|
||||
// set_nametag_attributes(self, attributes)
|
||||
static int l_set_nametag_attributes(lua_State *L);
|
||||
|
||||
// get_nametag_attributes(self)
|
||||
static int l_get_nametag_attributes(lua_State *L);
|
||||
|
||||
// send_mapblock(pos)
|
||||
static int l_send_mapblock(lua_State *L);
|
||||
|
||||
// set_minimap_modes(self, modes, wanted_mode)
|
||||
static int l_set_minimap_modes(lua_State *L);
|
||||
};
|
279
src/script/lua_api/l_particles.cpp
Normal file
279
src/script/lua_api/l_particles.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_particles.h"
|
||||
#include "lua_api/l_object.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "server.h"
|
||||
#include "particles.h"
|
||||
|
||||
// add_particle({pos=, velocity=, acceleration=, expirationtime=,
|
||||
// size=, collisiondetection=, collision_removal=, object_collision=,
|
||||
// vertical=, texture=, player=})
|
||||
// pos/velocity/acceleration = {x=num, y=num, z=num}
|
||||
// expirationtime = num (seconds)
|
||||
// size = num
|
||||
// collisiondetection = bool
|
||||
// collision_removal = bool
|
||||
// object_collision = bool
|
||||
// vertical = bool
|
||||
// texture = e.g."default_wood.png"
|
||||
// animation = TileAnimation definition
|
||||
// glow = num
|
||||
int ModApiParticles::l_add_particle(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
// Get parameters
|
||||
struct ParticleParameters p;
|
||||
std::string playername;
|
||||
|
||||
if (lua_gettop(L) > 1) // deprecated
|
||||
{
|
||||
log_deprecated(L, "Deprecated add_particle call with "
|
||||
"individual parameters instead of definition");
|
||||
p.pos = check_v3f(L, 1);
|
||||
p.vel = check_v3f(L, 2);
|
||||
p.acc = check_v3f(L, 3);
|
||||
p.expirationtime = luaL_checknumber(L, 4);
|
||||
p.size = luaL_checknumber(L, 5);
|
||||
p.collisiondetection = readParam<bool>(L, 6);
|
||||
p.texture = luaL_checkstring(L, 7);
|
||||
if (lua_gettop(L) == 8) // only spawn for a single player
|
||||
playername = luaL_checkstring(L, 8);
|
||||
}
|
||||
else if (lua_istable(L, 1))
|
||||
{
|
||||
lua_getfield(L, 1, "pos");
|
||||
if (lua_istable(L, -1))
|
||||
p.pos = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "vel");
|
||||
if (lua_istable(L, -1)) {
|
||||
p.vel = check_v3f(L, -1);
|
||||
log_deprecated(L, "The use of vel is deprecated. "
|
||||
"Use velocity instead");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "velocity");
|
||||
if (lua_istable(L, -1))
|
||||
p.vel = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "acc");
|
||||
if (lua_istable(L, -1)) {
|
||||
p.acc = check_v3f(L, -1);
|
||||
log_deprecated(L, "The use of acc is deprecated. "
|
||||
"Use acceleration instead");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "acceleration");
|
||||
if (lua_istable(L, -1))
|
||||
p.acc = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.expirationtime = getfloatfield_default(L, 1, "expirationtime",
|
||||
p.expirationtime);
|
||||
p.size = getfloatfield_default(L, 1, "size", p.size);
|
||||
p.collisiondetection = getboolfield_default(L, 1,
|
||||
"collisiondetection", p.collisiondetection);
|
||||
p.collision_removal = getboolfield_default(L, 1,
|
||||
"collision_removal", p.collision_removal);
|
||||
p.object_collision = getboolfield_default(L, 1,
|
||||
"object_collision", p.object_collision);
|
||||
p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
|
||||
|
||||
lua_getfield(L, 1, "animation");
|
||||
p.animation = read_animation_definition(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.texture = getstringfield_default(L, 1, "texture", p.texture);
|
||||
p.glow = getintfield_default(L, 1, "glow", p.glow);
|
||||
|
||||
lua_getfield(L, 1, "node");
|
||||
if (lua_istable(L, -1))
|
||||
p.node = readnode(L, -1, getGameDef(L)->ndef());
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
|
||||
|
||||
playername = getstringfield_default(L, 1, "playername", "");
|
||||
}
|
||||
|
||||
getServer(L)->spawnParticle(playername, p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// add_particlespawner({amount=, time=,
|
||||
// minpos=, maxpos=,
|
||||
// minvel=, maxvel=,
|
||||
// minacc=, maxacc=,
|
||||
// minexptime=, maxexptime=,
|
||||
// minsize=, maxsize=,
|
||||
// collisiondetection=,
|
||||
// collision_removal=,
|
||||
// object_collision=,
|
||||
// vertical=,
|
||||
// texture=,
|
||||
// player=})
|
||||
// minpos/maxpos/minvel/maxvel/minacc/maxacc = {x=num, y=num, z=num}
|
||||
// minexptime/maxexptime = num (seconds)
|
||||
// minsize/maxsize = num
|
||||
// collisiondetection = bool
|
||||
// collision_removal = bool
|
||||
// object_collision = bool
|
||||
// vertical = bool
|
||||
// texture = e.g."default_wood.png"
|
||||
// animation = TileAnimation definition
|
||||
// glow = num
|
||||
int ModApiParticles::l_add_particlespawner(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
// Get parameters
|
||||
ParticleSpawnerParameters p;
|
||||
ServerActiveObject *attached = NULL;
|
||||
std::string playername;
|
||||
|
||||
if (lua_gettop(L) > 1) //deprecated
|
||||
{
|
||||
log_deprecated(L, "Deprecated add_particlespawner call with "
|
||||
"individual parameters instead of definition");
|
||||
p.amount = luaL_checknumber(L, 1);
|
||||
p.time = luaL_checknumber(L, 2);
|
||||
p.minpos = check_v3f(L, 3);
|
||||
p.maxpos = check_v3f(L, 4);
|
||||
p.minvel = check_v3f(L, 5);
|
||||
p.maxvel = check_v3f(L, 6);
|
||||
p.minacc = check_v3f(L, 7);
|
||||
p.maxacc = check_v3f(L, 8);
|
||||
p.minexptime = luaL_checknumber(L, 9);
|
||||
p.maxexptime = luaL_checknumber(L, 10);
|
||||
p.minsize = luaL_checknumber(L, 11);
|
||||
p.maxsize = luaL_checknumber(L, 12);
|
||||
p.collisiondetection = readParam<bool>(L, 13);
|
||||
p.texture = luaL_checkstring(L, 14);
|
||||
if (lua_gettop(L) == 15) // only spawn for a single player
|
||||
playername = luaL_checkstring(L, 15);
|
||||
}
|
||||
else if (lua_istable(L, 1))
|
||||
{
|
||||
p.amount = getintfield_default(L, 1, "amount", p.amount);
|
||||
p.time = getfloatfield_default(L, 1, "time", p.time);
|
||||
|
||||
lua_getfield(L, 1, "minpos");
|
||||
if (lua_istable(L, -1))
|
||||
p.minpos = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxpos");
|
||||
if (lua_istable(L, -1))
|
||||
p.maxpos = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "minvel");
|
||||
if (lua_istable(L, -1))
|
||||
p.minvel = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxvel");
|
||||
if (lua_istable(L, -1))
|
||||
p.maxvel = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "minacc");
|
||||
if (lua_istable(L, -1))
|
||||
p.minacc = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxacc");
|
||||
if (lua_istable(L, -1))
|
||||
p.maxacc = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.minexptime = getfloatfield_default(L, 1, "minexptime", p.minexptime);
|
||||
p.maxexptime = getfloatfield_default(L, 1, "maxexptime", p.maxexptime);
|
||||
p.minsize = getfloatfield_default(L, 1, "minsize", p.minsize);
|
||||
p.maxsize = getfloatfield_default(L, 1, "maxsize", p.maxsize);
|
||||
p.collisiondetection = getboolfield_default(L, 1,
|
||||
"collisiondetection", p.collisiondetection);
|
||||
p.collision_removal = getboolfield_default(L, 1,
|
||||
"collision_removal", p.collision_removal);
|
||||
p.object_collision = getboolfield_default(L, 1,
|
||||
"object_collision", p.object_collision);
|
||||
|
||||
lua_getfield(L, 1, "animation");
|
||||
p.animation = read_animation_definition(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "attached");
|
||||
if (!lua_isnil(L, -1)) {
|
||||
ObjectRef *ref = ObjectRef::checkobject(L, -1);
|
||||
lua_pop(L, 1);
|
||||
attached = ObjectRef::getobject(ref);
|
||||
}
|
||||
|
||||
p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
|
||||
p.texture = getstringfield_default(L, 1, "texture", p.texture);
|
||||
playername = getstringfield_default(L, 1, "playername", "");
|
||||
p.glow = getintfield_default(L, 1, "glow", p.glow);
|
||||
|
||||
lua_getfield(L, 1, "node");
|
||||
if (lua_istable(L, -1))
|
||||
p.node = readnode(L, -1, getGameDef(L)->ndef());
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
|
||||
}
|
||||
|
||||
u32 id = getServer(L)->addParticleSpawner(p, attached, playername);
|
||||
lua_pushnumber(L, id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// delete_particlespawner(id, player)
|
||||
// player (string) is optional
|
||||
int ModApiParticles::l_delete_particlespawner(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
// Get parameters
|
||||
u32 id = luaL_checknumber(L, 1);
|
||||
std::string playername;
|
||||
if (lua_gettop(L) == 2) {
|
||||
playername = luaL_checkstring(L, 2);
|
||||
}
|
||||
|
||||
getServer(L)->deleteParticleSpawner(playername, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiParticles::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(add_particle);
|
||||
API_FCT(add_particlespawner);
|
||||
API_FCT(delete_particlespawner);
|
||||
}
|
||||
|
32
src/script/lua_api/l_particles.h
Normal file
32
src/script/lua_api/l_particles.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class ModApiParticles : public ModApiBase {
|
||||
private:
|
||||
static int l_add_particle(lua_State *L);
|
||||
static int l_add_particlespawner(lua_State *L);
|
||||
static int l_delete_particlespawner(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
183
src/script/lua_api/l_particles_local.cpp
Normal file
183
src/script/lua_api/l_particles_local.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 red-001 <red-001@outlook.ie>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_particles_local.h"
|
||||
#include "common/c_content.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "lua_api/l_object.h"
|
||||
#include "client/particles.h"
|
||||
#include "client/client.h"
|
||||
#include "client/clientevent.h"
|
||||
|
||||
int ModApiParticlesLocal::l_add_particle(lua_State *L)
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
// Get parameters
|
||||
ParticleParameters p;
|
||||
|
||||
lua_getfield(L, 1, "pos");
|
||||
if (lua_istable(L, -1))
|
||||
p.pos = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "velocity");
|
||||
if (lua_istable(L, -1))
|
||||
p.vel = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "acceleration");
|
||||
if (lua_istable(L, -1))
|
||||
p.acc = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.expirationtime = getfloatfield_default(L, 1, "expirationtime",
|
||||
p.expirationtime);
|
||||
p.size = getfloatfield_default(L, 1, "size", p.size);
|
||||
p.collisiondetection = getboolfield_default(L, 1,
|
||||
"collisiondetection", p.collisiondetection);
|
||||
p.collision_removal = getboolfield_default(L, 1,
|
||||
"collision_removal", p.collision_removal);
|
||||
p.object_collision = getboolfield_default(L, 1,
|
||||
"object_collision", p.object_collision);
|
||||
p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
|
||||
|
||||
lua_getfield(L, 1, "animation");
|
||||
p.animation = read_animation_definition(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.texture = getstringfield_default(L, 1, "texture", p.texture);
|
||||
p.glow = getintfield_default(L, 1, "glow", p.glow);
|
||||
|
||||
lua_getfield(L, 1, "node");
|
||||
if (lua_istable(L, -1))
|
||||
p.node = readnode(L, -1, getGameDef(L)->ndef());
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
|
||||
|
||||
ClientEvent *event = new ClientEvent();
|
||||
event->type = CE_SPAWN_PARTICLE;
|
||||
event->spawn_particle = new ParticleParameters(p);
|
||||
getClient(L)->pushToEventQueue(event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModApiParticlesLocal::l_add_particlespawner(lua_State *L)
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
// Get parameters
|
||||
ParticleSpawnerParameters p;
|
||||
|
||||
p.amount = getintfield_default(L, 1, "amount", p.amount);
|
||||
p.time = getfloatfield_default(L, 1, "time", p.time);
|
||||
|
||||
lua_getfield(L, 1, "minpos");
|
||||
if (lua_istable(L, -1))
|
||||
p.minpos = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxpos");
|
||||
if (lua_istable(L, -1))
|
||||
p.maxpos = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "minvel");
|
||||
if (lua_istable(L, -1))
|
||||
p.minvel = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxvel");
|
||||
if (lua_istable(L, -1))
|
||||
p.maxvel = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "minacc");
|
||||
if (lua_istable(L, -1))
|
||||
p.minacc = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxacc");
|
||||
if (lua_istable(L, -1))
|
||||
p.maxacc = check_v3f(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.minexptime = getfloatfield_default(L, 1, "minexptime", p.minexptime);
|
||||
p.maxexptime = getfloatfield_default(L, 1, "maxexptime", p.maxexptime);
|
||||
p.minsize = getfloatfield_default(L, 1, "minsize", p.minsize);
|
||||
p.maxsize = getfloatfield_default(L, 1, "maxsize", p.maxsize);
|
||||
p.collisiondetection = getboolfield_default(L, 1,
|
||||
"collisiondetection", p.collisiondetection);
|
||||
p.collision_removal = getboolfield_default(L, 1,
|
||||
"collision_removal", p.collision_removal);
|
||||
p.object_collision = getboolfield_default(L, 1,
|
||||
"object_collision", p.object_collision);
|
||||
|
||||
lua_getfield(L, 1, "animation");
|
||||
p.animation = read_animation_definition(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
|
||||
p.texture = getstringfield_default(L, 1, "texture", p.texture);
|
||||
p.glow = getintfield_default(L, 1, "glow", p.glow);
|
||||
|
||||
lua_getfield(L, 1, "node");
|
||||
if (lua_istable(L, -1))
|
||||
p.node = readnode(L, -1, getGameDef(L)->ndef());
|
||||
lua_pop(L, 1);
|
||||
|
||||
p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
|
||||
|
||||
u64 id = getClient(L)->getParticleManager()->generateSpawnerId();
|
||||
|
||||
auto event = new ClientEvent();
|
||||
event->type = CE_ADD_PARTICLESPAWNER;
|
||||
event->add_particlespawner.p = new ParticleSpawnerParameters(p);
|
||||
event->add_particlespawner.attached_id = 0;
|
||||
event->add_particlespawner.id = id;
|
||||
|
||||
getClient(L)->pushToEventQueue(event);
|
||||
lua_pushnumber(L, id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ModApiParticlesLocal::l_delete_particlespawner(lua_State *L)
|
||||
{
|
||||
// Get parameters
|
||||
u32 id = luaL_checknumber(L, 1);
|
||||
|
||||
ClientEvent *event = new ClientEvent();
|
||||
event->type = CE_DELETE_PARTICLESPAWNER;
|
||||
event->delete_particlespawner.id = id;
|
||||
|
||||
getClient(L)->pushToEventQueue(event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ModApiParticlesLocal::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(add_particle);
|
||||
API_FCT(add_particlespawner);
|
||||
API_FCT(delete_particlespawner);
|
||||
}
|
34
src/script/lua_api/l_particles_local.h
Normal file
34
src/script/lua_api/l_particles_local.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 red-001 <red-001@outlook.ie>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class ModApiParticlesLocal : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static int l_add_particle(lua_State *L);
|
||||
static int l_add_particlespawner(lua_State *L);
|
||||
static int l_delete_particlespawner(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
123
src/script/lua_api/l_playermeta.cpp
Normal file
123
src/script/lua_api/l_playermeta.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_playermeta.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_content.h"
|
||||
|
||||
/*
|
||||
PlayerMetaRef
|
||||
*/
|
||||
PlayerMetaRef *PlayerMetaRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(PlayerMetaRef **)ud; // unbox pointer
|
||||
}
|
||||
|
||||
Metadata *PlayerMetaRef::getmeta(bool auto_create)
|
||||
{
|
||||
return metadata;
|
||||
}
|
||||
|
||||
void PlayerMetaRef::clearMeta()
|
||||
{
|
||||
metadata->clear();
|
||||
}
|
||||
|
||||
void PlayerMetaRef::reportMetadataChange(const std::string *name)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// garbage collector
|
||||
int PlayerMetaRef::gc_object(lua_State *L)
|
||||
{
|
||||
PlayerMetaRef *o = *(PlayerMetaRef **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Creates an PlayerMetaRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
void PlayerMetaRef::create(lua_State *L, Metadata *metadata)
|
||||
{
|
||||
PlayerMetaRef *o = new PlayerMetaRef(metadata);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
void PlayerMetaRef::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "metadata_class");
|
||||
lua_pushlstring(L, className, strlen(className));
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__eq");
|
||||
lua_pushcfunction(L, l_equals);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Cannot be created from Lua
|
||||
// lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const char PlayerMetaRef::className[] = "PlayerMetaRef";
|
||||
const luaL_Reg PlayerMetaRef::methods[] = {
|
||||
luamethod(MetaDataRef, contains),
|
||||
luamethod(MetaDataRef, get),
|
||||
luamethod(MetaDataRef, get_string),
|
||||
luamethod(MetaDataRef, set_string),
|
||||
luamethod(MetaDataRef, get_int),
|
||||
luamethod(MetaDataRef, set_int),
|
||||
luamethod(MetaDataRef, get_float),
|
||||
luamethod(MetaDataRef, set_float),
|
||||
luamethod(MetaDataRef, to_table),
|
||||
luamethod(MetaDataRef, from_table),
|
||||
luamethod(MetaDataRef, equals),
|
||||
{0,0}
|
||||
};
|
||||
// clang-format on
|
57
src/script/lua_api/l_playermeta.h
Normal file
57
src/script/lua_api/l_playermeta.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017-8 rubenwardy <rw@rubenwardy.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
#include "lua_api/l_metadata.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "inventory.h"
|
||||
#include "metadata.h"
|
||||
|
||||
class PlayerMetaRef : public MetaDataRef
|
||||
{
|
||||
private:
|
||||
Metadata *metadata = nullptr;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
static PlayerMetaRef *checkobject(lua_State *L, int narg);
|
||||
|
||||
virtual Metadata *getmeta(bool auto_create);
|
||||
|
||||
virtual void clearMeta();
|
||||
|
||||
virtual void reportMetadataChange(const std::string *name = nullptr);
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
public:
|
||||
PlayerMetaRef(Metadata *metadata) : metadata(metadata) {}
|
||||
~PlayerMetaRef() = default;
|
||||
|
||||
// Creates an ItemStackMetaRef and leaves it on top of stack
|
||||
// Not callable from Lua; all references are created on the C side.
|
||||
static void create(lua_State *L, Metadata *metadata);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
117
src/script/lua_api/l_rollback.cpp
Normal file
117
src/script/lua_api/l_rollback.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_rollback.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "server.h"
|
||||
#include "rollback_interface.h"
|
||||
|
||||
|
||||
void push_RollbackNode(lua_State *L, RollbackNode &node)
|
||||
{
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushstring(L, node.name.c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
lua_pushnumber(L, node.param1);
|
||||
lua_setfield(L, -2, "param1");
|
||||
lua_pushnumber(L, node.param2);
|
||||
lua_setfield(L, -2, "param2");
|
||||
}
|
||||
|
||||
// rollback_get_node_actions(pos, range, seconds, limit) -> {{actor, pos, time, oldnode, newnode}, ...}
|
||||
int ModApiRollback::l_rollback_get_node_actions(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
v3s16 pos = read_v3s16(L, 1);
|
||||
int range = luaL_checknumber(L, 2);
|
||||
time_t seconds = (time_t) luaL_checknumber(L, 3);
|
||||
int limit = luaL_checknumber(L, 4);
|
||||
Server *server = getServer(L);
|
||||
IRollbackManager *rollback = server->getRollbackManager();
|
||||
if (rollback == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::list<RollbackAction> actions = rollback->getNodeActors(pos, range, seconds, limit);
|
||||
std::list<RollbackAction>::iterator iter = actions.begin();
|
||||
|
||||
lua_createtable(L, actions.size(), 0);
|
||||
for (unsigned int i = 1; iter != actions.end(); ++iter, ++i) {
|
||||
lua_createtable(L, 0, 5); // Make a table with enough space pre-allocated
|
||||
|
||||
lua_pushstring(L, iter->actor.c_str());
|
||||
lua_setfield(L, -2, "actor");
|
||||
|
||||
push_v3s16(L, iter->p);
|
||||
lua_setfield(L, -2, "pos");
|
||||
|
||||
lua_pushnumber(L, iter->unix_time);
|
||||
lua_setfield(L, -2, "time");
|
||||
|
||||
push_RollbackNode(L, iter->n_old);
|
||||
lua_setfield(L, -2, "oldnode");
|
||||
|
||||
push_RollbackNode(L, iter->n_new);
|
||||
lua_setfield(L, -2, "newnode");
|
||||
|
||||
lua_rawseti(L, -2, i); // Add action table to main table
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// rollback_revert_actions_by(actor, seconds) -> bool, log messages
|
||||
int ModApiRollback::l_rollback_revert_actions_by(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
std::string actor = luaL_checkstring(L, 1);
|
||||
int seconds = luaL_checknumber(L, 2);
|
||||
Server *server = getServer(L);
|
||||
IRollbackManager *rollback = server->getRollbackManager();
|
||||
|
||||
// If rollback is disabled, tell it's not a success.
|
||||
if (rollback == NULL) {
|
||||
lua_pushboolean(L, false);
|
||||
lua_newtable(L);
|
||||
return 2;
|
||||
}
|
||||
std::list<RollbackAction> actions = rollback->getRevertActions(actor, seconds);
|
||||
std::list<std::string> log;
|
||||
bool success = server->rollbackRevertActions(actions, &log);
|
||||
// Push boolean result
|
||||
lua_pushboolean(L, success);
|
||||
lua_createtable(L, log.size(), 0);
|
||||
unsigned long i = 0;
|
||||
for(std::list<std::string>::const_iterator iter = log.begin();
|
||||
iter != log.end(); ++i, ++iter) {
|
||||
lua_pushnumber(L, i);
|
||||
lua_pushstring(L, iter->c_str());
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
void ModApiRollback::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(rollback_get_node_actions);
|
||||
API_FCT(rollback_revert_actions_by);
|
||||
}
|
35
src/script/lua_api/l_rollback.h
Normal file
35
src/script/lua_api/l_rollback.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class ModApiRollback : public ModApiBase
|
||||
{
|
||||
private:
|
||||
// rollback_get_node_actions(pos, range, seconds) -> {{actor, pos, time, oldnode, newnode}, ...}
|
||||
static int l_rollback_get_node_actions(lua_State *L);
|
||||
|
||||
// rollback_revert_actions_by(actor, seconds) -> bool, log messages
|
||||
static int l_rollback_revert_actions_by(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
571
src/script/lua_api/l_server.cpp
Normal file
571
src/script/lua_api/l_server.cpp
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_server.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "cpp_api/s_base.h"
|
||||
#include "cpp_api/s_security.h"
|
||||
#include "server.h"
|
||||
#include "environment.h"
|
||||
#include "remoteplayer.h"
|
||||
#include "log.h"
|
||||
#include <algorithm>
|
||||
|
||||
// request_shutdown()
|
||||
int ModApiServer::l_request_shutdown(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *msg = lua_tolstring(L, 1, NULL);
|
||||
bool reconnect = readParam<bool>(L, 2);
|
||||
float seconds_before_shutdown = lua_tonumber(L, 3);
|
||||
getServer(L)->requestShutdown(msg ? msg : "", reconnect, seconds_before_shutdown);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_server_status()
|
||||
int ModApiServer::l_get_server_status(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_server_uptime()
|
||||
int ModApiServer::l_get_server_uptime(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
lua_pushnumber(L, getServer(L)->getUptime());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// print(text)
|
||||
int ModApiServer::l_print(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string text;
|
||||
text = luaL_checkstring(L, 1);
|
||||
getServer(L)->printToConsoleOnly(text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// chat_send_all(text)
|
||||
int ModApiServer::l_chat_send_all(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *text = luaL_checkstring(L, 1);
|
||||
// Get server from registry
|
||||
Server *server = getServer(L);
|
||||
// Send
|
||||
server->notifyPlayers(utf8_to_wide(text));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// chat_send_player(name, text)
|
||||
int ModApiServer::l_chat_send_player(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
const char *text = luaL_checkstring(L, 2);
|
||||
|
||||
// Get server from registry
|
||||
Server *server = getServer(L);
|
||||
// Send
|
||||
server->notifyPlayer(name, utf8_to_wide(text));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_player_privs(name, text)
|
||||
int ModApiServer::l_get_player_privs(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
// Get server from registry
|
||||
Server *server = getServer(L);
|
||||
// Do it
|
||||
lua_newtable(L);
|
||||
int table = lua_gettop(L);
|
||||
std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
|
||||
for (const std::string &privs_ : privs_s) {
|
||||
lua_pushboolean(L, true);
|
||||
lua_setfield(L, table, privs_.c_str());
|
||||
}
|
||||
lua_pushvalue(L, table);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_player_ip()
|
||||
int ModApiServer::l_get_player_ip(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char * name = luaL_checkstring(L, 1);
|
||||
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
|
||||
if(player == NULL)
|
||||
{
|
||||
lua_pushnil(L); // no such player
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
Address addr = getServer(L)->getPeerAddress(player->getPeerId());
|
||||
std::string ip_str = addr.serializeString();
|
||||
lua_pushstring(L, ip_str.c_str());
|
||||
return 1;
|
||||
} catch (const con::PeerNotFoundException &) {
|
||||
dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
|
||||
lua_pushnil(L); // error
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// get_player_information(name)
|
||||
int ModApiServer::l_get_player_information(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
Server *server = getServer(L);
|
||||
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
RemotePlayer *player = server->getEnv().getPlayer(name);
|
||||
if (!player) {
|
||||
lua_pushnil(L); // no such player
|
||||
return 1;
|
||||
}
|
||||
|
||||
Address addr;
|
||||
try {
|
||||
addr = server->getPeerAddress(player->getPeerId());
|
||||
} catch (const con::PeerNotFoundException &) {
|
||||
dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
|
||||
lua_pushnil(L); // error
|
||||
return 1;
|
||||
}
|
||||
|
||||
float min_rtt, max_rtt, avg_rtt, min_jitter, max_jitter, avg_jitter;
|
||||
ClientState state;
|
||||
u32 uptime;
|
||||
u16 prot_vers;
|
||||
u8 ser_vers, major, minor, patch;
|
||||
std::string vers_string, lang_code;
|
||||
|
||||
auto getConInfo = [&] (con::rtt_stat_type type, float *value) -> bool {
|
||||
return server->getClientConInfo(player->getPeerId(), type, value);
|
||||
};
|
||||
|
||||
bool have_con_info =
|
||||
getConInfo(con::MIN_RTT, &min_rtt) &&
|
||||
getConInfo(con::MAX_RTT, &max_rtt) &&
|
||||
getConInfo(con::AVG_RTT, &avg_rtt) &&
|
||||
getConInfo(con::MIN_JITTER, &min_jitter) &&
|
||||
getConInfo(con::MAX_JITTER, &max_jitter) &&
|
||||
getConInfo(con::AVG_JITTER, &avg_jitter);
|
||||
|
||||
bool r = server->getClientInfo(player->getPeerId(), &state, &uptime,
|
||||
&ser_vers, &prot_vers, &major, &minor, &patch, &vers_string,
|
||||
&lang_code);
|
||||
if (!r) {
|
||||
dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
|
||||
lua_pushnil(L); // error
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
int table = lua_gettop(L);
|
||||
|
||||
lua_pushstring(L,"address");
|
||||
lua_pushstring(L, addr.serializeString().c_str());
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L,"ip_version");
|
||||
if (addr.getFamily() == AF_INET) {
|
||||
lua_pushnumber(L, 4);
|
||||
} else if (addr.getFamily() == AF_INET6) {
|
||||
lua_pushnumber(L, 6);
|
||||
} else {
|
||||
lua_pushnumber(L, 0);
|
||||
}
|
||||
lua_settable(L, table);
|
||||
|
||||
if (have_con_info) { // may be missing
|
||||
lua_pushstring(L, "min_rtt");
|
||||
lua_pushnumber(L, min_rtt);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L, "max_rtt");
|
||||
lua_pushnumber(L, max_rtt);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L, "avg_rtt");
|
||||
lua_pushnumber(L, avg_rtt);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L, "min_jitter");
|
||||
lua_pushnumber(L, min_jitter);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L, "max_jitter");
|
||||
lua_pushnumber(L, max_jitter);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L, "avg_jitter");
|
||||
lua_pushnumber(L, avg_jitter);
|
||||
lua_settable(L, table);
|
||||
}
|
||||
|
||||
lua_pushstring(L,"connection_uptime");
|
||||
lua_pushnumber(L, uptime);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L,"protocol_version");
|
||||
lua_pushnumber(L, prot_vers);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L, "formspec_version");
|
||||
lua_pushnumber(L, player->formspec_version);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L, "lang_code");
|
||||
lua_pushstring(L, lang_code.c_str());
|
||||
lua_settable(L, table);
|
||||
|
||||
#ifndef NDEBUG
|
||||
lua_pushstring(L,"serialization_version");
|
||||
lua_pushnumber(L, ser_vers);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L,"major");
|
||||
lua_pushnumber(L, major);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L,"minor");
|
||||
lua_pushnumber(L, minor);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L,"patch");
|
||||
lua_pushnumber(L, patch);
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L,"version_string");
|
||||
lua_pushstring(L, vers_string.c_str());
|
||||
lua_settable(L, table);
|
||||
|
||||
lua_pushstring(L,"state");
|
||||
lua_pushstring(L,ClientInterface::state2Name(state).c_str());
|
||||
lua_settable(L, table);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_ban_list()
|
||||
int ModApiServer::l_get_ban_list(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
lua_pushstring(L, getServer(L)->getBanDescription("").c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_ban_description()
|
||||
int ModApiServer::l_get_ban_description(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char * ip_or_name = luaL_checkstring(L, 1);
|
||||
lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ban_player()
|
||||
int ModApiServer::l_ban_player(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char * name = luaL_checkstring(L, 1);
|
||||
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
|
||||
if (player == NULL) {
|
||||
lua_pushboolean(L, false); // no such player
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
Address addr = getServer(L)->getPeerAddress(
|
||||
dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name)->getPeerId());
|
||||
std::string ip_str = addr.serializeString();
|
||||
getServer(L)->setIpBanned(ip_str, name);
|
||||
} catch(const con::PeerNotFoundException &) {
|
||||
dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
|
||||
lua_pushboolean(L, false); // error
|
||||
return 1;
|
||||
}
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// kick_player(name, [reason]) -> success
|
||||
int ModApiServer::l_kick_player(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
std::string message("Kicked");
|
||||
if (lua_isstring(L, 2))
|
||||
message.append(": ").append(readParam<std::string>(L, 2));
|
||||
else
|
||||
message.append(".");
|
||||
|
||||
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
|
||||
if (player == NULL) {
|
||||
lua_pushboolean(L, false); // No such player
|
||||
return 1;
|
||||
}
|
||||
getServer(L)->DenyAccess_Legacy(player->getPeerId(), utf8_to_wide(message));
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remove_player(name)
|
||||
int ModApiServer::l_remove_player(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment *>(getEnv(L));
|
||||
assert(s_env);
|
||||
|
||||
RemotePlayer *player = s_env->getPlayer(name.c_str());
|
||||
if (!player)
|
||||
lua_pushinteger(L, s_env->removePlayerFromDatabase(name) ? 0 : 1);
|
||||
else
|
||||
lua_pushinteger(L, 2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// unban_player_or_ip()
|
||||
int ModApiServer::l_unban_player_or_ip(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char * ip_or_name = luaL_checkstring(L, 1);
|
||||
getServer(L)->unsetIpBanned(ip_or_name);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// show_formspec(playername,formname,formspec)
|
||||
int ModApiServer::l_show_formspec(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *playername = luaL_checkstring(L, 1);
|
||||
const char *formname = luaL_checkstring(L, 2);
|
||||
const char *formspec = luaL_checkstring(L, 3);
|
||||
|
||||
if(getServer(L)->showFormspec(playername,formspec,formname))
|
||||
{
|
||||
lua_pushboolean(L, true);
|
||||
}else{
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_current_modname()
|
||||
int ModApiServer::l_get_current_modname(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_modpath(modname)
|
||||
int ModApiServer::l_get_modpath(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string modname = luaL_checkstring(L, 1);
|
||||
const ModSpec *mod = getServer(L)->getModSpec(modname);
|
||||
if (!mod) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
lua_pushstring(L, mod->path.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_modnames()
|
||||
// the returned list is sorted alphabetically for you
|
||||
int ModApiServer::l_get_modnames(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
// Get a list of mods
|
||||
std::vector<std::string> modlist;
|
||||
getServer(L)->getModNames(modlist);
|
||||
|
||||
std::sort(modlist.begin(), modlist.end());
|
||||
|
||||
// Package them up for Lua
|
||||
lua_createtable(L, modlist.size(), 0);
|
||||
std::vector<std::string>::iterator iter = modlist.begin();
|
||||
for (u16 i = 0; iter != modlist.end(); ++iter) {
|
||||
lua_pushstring(L, iter->c_str());
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_worldpath()
|
||||
int ModApiServer::l_get_worldpath(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string worldpath = getServer(L)->getWorldPath();
|
||||
lua_pushstring(L, worldpath.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// sound_play(spec, parameters, [ephemeral])
|
||||
int ModApiServer::l_sound_play(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
SimpleSoundSpec spec;
|
||||
read_soundspec(L, 1, spec);
|
||||
ServerSoundParams params;
|
||||
read_server_sound_params(L, 2, params);
|
||||
bool ephemeral = lua_gettop(L) > 2 && readParam<bool>(L, 3);
|
||||
if (ephemeral) {
|
||||
getServer(L)->playSound(spec, params, true);
|
||||
lua_pushnil(L);
|
||||
} else {
|
||||
s32 handle = getServer(L)->playSound(spec, params);
|
||||
lua_pushinteger(L, handle);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// sound_stop(handle)
|
||||
int ModApiServer::l_sound_stop(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
s32 handle = luaL_checkinteger(L, 1);
|
||||
getServer(L)->stopSound(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModApiServer::l_sound_fade(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
s32 handle = luaL_checkinteger(L, 1);
|
||||
float step = readParam<float>(L, 2);
|
||||
float gain = readParam<float>(L, 3);
|
||||
getServer(L)->fadeSound(handle, step, gain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// dynamic_add_media(filepath)
|
||||
int ModApiServer::l_dynamic_add_media(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
// Reject adding media before the server has started up
|
||||
if (!getEnv(L))
|
||||
throw LuaError("Dynamic media cannot be added before server has started up");
|
||||
|
||||
std::string filepath = readParam<std::string>(L, 1);
|
||||
CHECK_SECURE_PATH(L, filepath.c_str(), false);
|
||||
|
||||
bool ok = getServer(L)->dynamicAddMedia(filepath);
|
||||
lua_pushboolean(L, ok);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_singleplayer()
|
||||
int ModApiServer::l_is_singleplayer(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
lua_pushboolean(L, getServer(L)->isSingleplayer());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// notify_authentication_modified(name)
|
||||
int ModApiServer::l_notify_authentication_modified(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string name;
|
||||
if(lua_isstring(L, 1))
|
||||
name = readParam<std::string>(L, 1);
|
||||
getServer(L)->reportPrivsModified(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_last_run_mod()
|
||||
int ModApiServer::l_get_last_run_mod(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
std::string current_mod = readParam<std::string>(L, -1, "");
|
||||
if (current_mod.empty()) {
|
||||
lua_pop(L, 1);
|
||||
lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_last_run_mod(modname)
|
||||
int ModApiServer::l_set_last_run_mod(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
#ifdef SCRIPTAPI_DEBUG
|
||||
const char *mod = lua_tostring(L, 1);
|
||||
getScriptApiBase(L)->setOriginDirect(mod);
|
||||
//printf(">>>> last mod set from Lua: %s\n", mod);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ModApiServer::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(request_shutdown);
|
||||
API_FCT(get_server_status);
|
||||
API_FCT(get_server_uptime);
|
||||
API_FCT(get_worldpath);
|
||||
API_FCT(is_singleplayer);
|
||||
|
||||
API_FCT(get_current_modname);
|
||||
API_FCT(get_modpath);
|
||||
API_FCT(get_modnames);
|
||||
|
||||
API_FCT(print);
|
||||
|
||||
API_FCT(chat_send_all);
|
||||
API_FCT(chat_send_player);
|
||||
API_FCT(show_formspec);
|
||||
API_FCT(sound_play);
|
||||
API_FCT(sound_stop);
|
||||
API_FCT(sound_fade);
|
||||
API_FCT(dynamic_add_media);
|
||||
|
||||
API_FCT(get_player_information);
|
||||
API_FCT(get_player_privs);
|
||||
API_FCT(get_player_ip);
|
||||
API_FCT(get_ban_list);
|
||||
API_FCT(get_ban_description);
|
||||
API_FCT(ban_player);
|
||||
API_FCT(kick_player);
|
||||
API_FCT(unban_player_or_ip);
|
||||
API_FCT(notify_authentication_modified);
|
||||
|
||||
API_FCT(get_last_run_mod);
|
||||
API_FCT(set_last_run_mod);
|
||||
}
|
114
src/script/lua_api/l_server.h
Normal file
114
src/script/lua_api/l_server.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class ModApiServer : public ModApiBase
|
||||
{
|
||||
private:
|
||||
// request_shutdown([message], [reconnect])
|
||||
static int l_request_shutdown(lua_State *L);
|
||||
|
||||
// get_server_status()
|
||||
static int l_get_server_status(lua_State *L);
|
||||
|
||||
// get_server_uptime()
|
||||
static int l_get_server_uptime(lua_State *L);
|
||||
|
||||
// get_worldpath()
|
||||
static int l_get_worldpath(lua_State *L);
|
||||
|
||||
// is_singleplayer()
|
||||
static int l_is_singleplayer(lua_State *L);
|
||||
|
||||
// get_current_modname()
|
||||
static int l_get_current_modname(lua_State *L);
|
||||
|
||||
// get_modpath(modname)
|
||||
static int l_get_modpath(lua_State *L);
|
||||
|
||||
// get_modnames()
|
||||
// the returned list is sorted alphabetically for you
|
||||
static int l_get_modnames(lua_State *L);
|
||||
|
||||
// print(text)
|
||||
static int l_print(lua_State *L);
|
||||
|
||||
// chat_send_all(text)
|
||||
static int l_chat_send_all(lua_State *L);
|
||||
|
||||
// chat_send_player(name, text)
|
||||
static int l_chat_send_player(lua_State *L);
|
||||
|
||||
// show_formspec(playername,formname,formspec)
|
||||
static int l_show_formspec(lua_State *L);
|
||||
|
||||
// sound_play(spec, parameters)
|
||||
static int l_sound_play(lua_State *L);
|
||||
|
||||
// sound_stop(handle)
|
||||
static int l_sound_stop(lua_State *L);
|
||||
|
||||
// sound_fade(handle, step, gain)
|
||||
static int l_sound_fade(lua_State *L);
|
||||
|
||||
// dynamic_add_media(filepath)
|
||||
static int l_dynamic_add_media(lua_State *L);
|
||||
|
||||
// get_player_privs(name, text)
|
||||
static int l_get_player_privs(lua_State *L);
|
||||
|
||||
// get_player_ip()
|
||||
static int l_get_player_ip(lua_State *L);
|
||||
|
||||
// get_player_information(name)
|
||||
static int l_get_player_information(lua_State *L);
|
||||
|
||||
// get_ban_list()
|
||||
static int l_get_ban_list(lua_State *L);
|
||||
|
||||
// get_ban_description()
|
||||
static int l_get_ban_description(lua_State *L);
|
||||
|
||||
// ban_player()
|
||||
static int l_ban_player(lua_State *L);
|
||||
|
||||
// unban_player_or_ip()
|
||||
static int l_unban_player_or_ip(lua_State *L);
|
||||
|
||||
// kick_player(name, [message]) -> success
|
||||
static int l_kick_player(lua_State *L);
|
||||
|
||||
// remove_player(name)
|
||||
static int l_remove_player(lua_State *L);
|
||||
|
||||
// notify_authentication_modified(name)
|
||||
static int l_notify_authentication_modified(lua_State *L);
|
||||
|
||||
// get_last_run_mod()
|
||||
static int l_get_last_run_mod(lua_State *L);
|
||||
|
||||
// set_last_run_mod(modname)
|
||||
static int l_set_last_run_mod(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
341
src/script/lua_api/l_settings.cpp
Normal file
341
src/script/lua_api/l_settings.cpp
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 PilzAdam <pilzadam@minetest.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_settings.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "cpp_api/s_security.h"
|
||||
#include "util/string.h" // FlagDesc
|
||||
#include "settings.h"
|
||||
#include "noise.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
#define SET_SECURITY_CHECK(L, name) \
|
||||
if (o->m_settings == g_settings && ScriptApiSecurity::isSecure(L) && \
|
||||
name.compare(0, 7, "secure.") == 0) { \
|
||||
throw LuaError("Attempt to set secure setting."); \
|
||||
}
|
||||
|
||||
LuaSettings::LuaSettings(Settings *settings, const std::string &filename) :
|
||||
m_settings(settings),
|
||||
m_filename(filename)
|
||||
{
|
||||
}
|
||||
|
||||
LuaSettings::LuaSettings(const std::string &filename, bool write_allowed) :
|
||||
m_filename(filename),
|
||||
m_is_own_settings(true),
|
||||
m_write_allowed(write_allowed)
|
||||
{
|
||||
m_settings = new Settings();
|
||||
m_settings->readConfigFile(filename.c_str());
|
||||
}
|
||||
|
||||
LuaSettings::~LuaSettings()
|
||||
{
|
||||
if (m_is_own_settings)
|
||||
delete m_settings;
|
||||
}
|
||||
|
||||
|
||||
void LuaSettings::create(lua_State *L, Settings *settings,
|
||||
const std::string &filename)
|
||||
{
|
||||
LuaSettings *o = new LuaSettings(settings, filename);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
|
||||
// garbage collector
|
||||
int LuaSettings::gc_object(lua_State* L)
|
||||
{
|
||||
LuaSettings* o = *(LuaSettings **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// get(self, key) -> value
|
||||
int LuaSettings::l_get(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
if (o->m_settings->exists(key)) {
|
||||
std::string value = o->m_settings->get(key);
|
||||
lua_pushstring(L, value.c_str());
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_bool(self, key) -> boolean
|
||||
int LuaSettings::l_get_bool(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
if (o->m_settings->exists(key)) {
|
||||
bool value = o->m_settings->getBool(key);
|
||||
lua_pushboolean(L, value);
|
||||
} else {
|
||||
// Push default value
|
||||
if (lua_isboolean(L, 3))
|
||||
lua_pushboolean(L, readParam<bool>(L, 3));
|
||||
else
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_np_group(self, key) -> value
|
||||
int LuaSettings::l_get_np_group(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings *o = checkobject(L, 1);
|
||||
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
if (o->m_settings->exists(key)) {
|
||||
NoiseParams np;
|
||||
o->m_settings->getNoiseParams(key, np);
|
||||
push_noiseparams(L, &np);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaSettings::l_get_flags(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings *o = checkobject(L, 1);
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
|
||||
u32 flags = 0;
|
||||
auto flagdesc = o->m_settings->getFlagDescFallback(key);
|
||||
if (o->m_settings->getFlagStrNoEx(key, flags, flagdesc)) {
|
||||
lua_newtable(L);
|
||||
int table = lua_gettop(L);
|
||||
for (size_t i = 0; flagdesc[i].name; ++i) {
|
||||
lua_pushboolean(L, flags & flagdesc[i].flag);
|
||||
lua_setfield(L, table, flagdesc[i].name);
|
||||
}
|
||||
lua_pushvalue(L, table);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set(self, key, value)
|
||||
int LuaSettings::l_set(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
const char* value = luaL_checkstring(L, 3);
|
||||
|
||||
SET_SECURITY_CHECK(L, key);
|
||||
|
||||
if (!o->m_settings->set(key, value))
|
||||
throw LuaError("Invalid sequence found in setting parameters");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// set_bool(self, key, value)
|
||||
int LuaSettings::l_set_bool(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
bool value = readParam<bool>(L, 3);
|
||||
|
||||
SET_SECURITY_CHECK(L, key);
|
||||
|
||||
o->m_settings->setBool(key, value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set(self, key, value)
|
||||
int LuaSettings::l_set_np_group(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings *o = checkobject(L, 1);
|
||||
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
NoiseParams value;
|
||||
read_noiseparams(L, 3, &value);
|
||||
|
||||
SET_SECURITY_CHECK(L, key);
|
||||
|
||||
o->m_settings->setNoiseParams(key, value, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// remove(self, key) -> success
|
||||
int LuaSettings::l_remove(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
std::string key = std::string(luaL_checkstring(L, 2));
|
||||
|
||||
SET_SECURITY_CHECK(L, key);
|
||||
|
||||
bool success = o->m_settings->remove(key);
|
||||
lua_pushboolean(L, success);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_names(self) -> {key1, ...}
|
||||
int LuaSettings::l_get_names(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
std::vector<std::string> keys = o->m_settings->getNames();
|
||||
|
||||
lua_newtable(L);
|
||||
for (unsigned int i=0; i < keys.size(); i++)
|
||||
{
|
||||
lua_pushstring(L, keys[i].c_str());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// write(self) -> success
|
||||
int LuaSettings::l_write(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
if (!o->m_write_allowed) {
|
||||
throw LuaError("Settings: writing " + o->m_filename +
|
||||
" not allowed with mod security on.");
|
||||
}
|
||||
|
||||
bool success = o->m_settings->updateConfigFile(o->m_filename.c_str());
|
||||
lua_pushboolean(L, success);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// to_table(self) -> {[key1]=value1,...}
|
||||
int LuaSettings::l_to_table(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
LuaSettings* o = checkobject(L, 1);
|
||||
|
||||
std::vector<std::string> keys = o->m_settings->getNames();
|
||||
|
||||
lua_newtable(L);
|
||||
for (const std::string &key : keys) {
|
||||
lua_pushstring(L, o->m_settings->get(key).c_str());
|
||||
lua_setfield(L, -2, key.c_str());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void LuaSettings::Register(lua_State* L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
|
||||
// Can be created from Lua (Settings(filename))
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
// LuaSettings(filename)
|
||||
// Creates a LuaSettings and leaves it on top of the stack
|
||||
int LuaSettings::create_object(lua_State* L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
bool write_allowed = true;
|
||||
const char* filename = luaL_checkstring(L, 1);
|
||||
CHECK_SECURE_PATH_POSSIBLE_WRITE(L, filename, &write_allowed);
|
||||
LuaSettings* o = new LuaSettings(filename, write_allowed);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaSettings* LuaSettings::checkobject(lua_State* L, int narg)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
return *(LuaSettings**) ud; // unbox pointer
|
||||
}
|
||||
|
||||
const char LuaSettings::className[] = "Settings";
|
||||
const luaL_Reg LuaSettings::methods[] = {
|
||||
luamethod(LuaSettings, get),
|
||||
luamethod(LuaSettings, get_bool),
|
||||
luamethod(LuaSettings, get_np_group),
|
||||
luamethod(LuaSettings, get_flags),
|
||||
luamethod(LuaSettings, set),
|
||||
luamethod(LuaSettings, set_bool),
|
||||
luamethod(LuaSettings, set_np_group),
|
||||
luamethod(LuaSettings, remove),
|
||||
luamethod(LuaSettings, get_names),
|
||||
luamethod(LuaSettings, write),
|
||||
luamethod(LuaSettings, to_table),
|
||||
{0,0}
|
||||
};
|
88
src/script/lua_api/l_settings.h
Normal file
88
src/script/lua_api/l_settings.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 PilzAdam <pilzadam@minetest.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/c_content.h"
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class Settings;
|
||||
|
||||
class LuaSettings : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
// get(self, key) -> value
|
||||
static int l_get(lua_State *L);
|
||||
|
||||
// get_bool(self, key) -> boolean
|
||||
static int l_get_bool(lua_State *L);
|
||||
|
||||
// get_np_group(self, key) -> noiseparam
|
||||
static int l_get_np_group(lua_State *L);
|
||||
|
||||
// get_flags(self, key) -> key/value table
|
||||
static int l_get_flags(lua_State *L);
|
||||
|
||||
// set(self, key, value)
|
||||
static int l_set(lua_State *L);
|
||||
|
||||
// set_bool(self, key, value)
|
||||
static int l_set_bool(lua_State *L);
|
||||
|
||||
// set_np_group(self, key, value)
|
||||
static int l_set_np_group(lua_State *L);
|
||||
|
||||
// remove(self, key) -> success
|
||||
static int l_remove(lua_State *L);
|
||||
|
||||
// get_names(self) -> {key1, ...}
|
||||
static int l_get_names(lua_State *L);
|
||||
|
||||
// write(self) -> success
|
||||
static int l_write(lua_State *L);
|
||||
|
||||
// to_table(self) -> {[key1]=value1,...}
|
||||
static int l_to_table(lua_State *L);
|
||||
|
||||
Settings *m_settings = nullptr;
|
||||
std::string m_filename;
|
||||
bool m_is_own_settings = false;
|
||||
bool m_write_allowed = true;
|
||||
|
||||
public:
|
||||
LuaSettings(Settings *settings, const std::string &filename);
|
||||
LuaSettings(const std::string &filename, bool write_allowed);
|
||||
~LuaSettings();
|
||||
|
||||
static void create(lua_State *L, Settings *settings, const std::string &filename);
|
||||
|
||||
// LuaSettings(filename)
|
||||
// Creates a LuaSettings and leaves it on top of the stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaSettings *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
53
src/script/lua_api/l_sound.cpp
Normal file
53
src/script/lua_api/l_sound.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "l_sound.h"
|
||||
#include "l_internal.h"
|
||||
#include "common/c_content.h"
|
||||
#include "gui/guiEngine.h"
|
||||
|
||||
|
||||
int ModApiSound::l_sound_play(lua_State *L)
|
||||
{
|
||||
SimpleSoundSpec spec;
|
||||
read_soundspec(L, 1, spec);
|
||||
bool looped = readParam<bool>(L, 2);
|
||||
|
||||
s32 handle = getGuiEngine(L)->playSound(spec, looped);
|
||||
|
||||
lua_pushinteger(L, handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ModApiSound::l_sound_stop(lua_State *L)
|
||||
{
|
||||
u32 handle = luaL_checkinteger(L, 1);
|
||||
|
||||
getGuiEngine(L)->stopSound(handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiSound::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(sound_play);
|
||||
API_FCT(sound_stop);
|
||||
}
|
33
src/script/lua_api/l_sound.h
Normal file
33
src/script/lua_api/l_sound.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class ModApiSound : public ModApiBase
|
||||
{
|
||||
private:
|
||||
static int l_sound_play(lua_State *L);
|
||||
static int l_sound_stop(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
155
src/script/lua_api/l_storage.cpp
Normal file
155
src/script/lua_api/l_storage.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_storage.h"
|
||||
#include "l_internal.h"
|
||||
#include "content/mods.h"
|
||||
#include "server.h"
|
||||
|
||||
int ModApiStorage::l_get_mod_storage(lua_State *L)
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
if (!lua_isstring(L, -1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string mod_name = readParam<std::string>(L, -1);
|
||||
|
||||
ModMetadata *store = new ModMetadata(mod_name);
|
||||
if (IGameDef *gamedef = getGameDef(L)) {
|
||||
store->load(gamedef->getModStoragePath());
|
||||
gamedef->registerModStorage(store);
|
||||
} else {
|
||||
delete store;
|
||||
assert(false); // this should not happen
|
||||
}
|
||||
|
||||
StorageRef::create(L, store);
|
||||
int object = lua_gettop(L);
|
||||
|
||||
lua_pushvalue(L, object);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiStorage::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(get_mod_storage);
|
||||
}
|
||||
|
||||
StorageRef::StorageRef(ModMetadata *object):
|
||||
m_object(object)
|
||||
{
|
||||
}
|
||||
|
||||
StorageRef::~StorageRef()
|
||||
{
|
||||
delete m_object;
|
||||
}
|
||||
|
||||
void StorageRef::create(lua_State *L, ModMetadata *object)
|
||||
{
|
||||
StorageRef *o = new StorageRef(object);
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
int StorageRef::gc_object(lua_State *L)
|
||||
{
|
||||
StorageRef *o = *(StorageRef **)(lua_touserdata(L, 1));
|
||||
// Server side
|
||||
if (IGameDef *gamedef = getGameDef(L))
|
||||
gamedef->unregisterModStorage(getobject(o)->getModName());
|
||||
delete o;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StorageRef::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "metadata_class");
|
||||
lua_pushlstring(L, className, strlen(className));
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__eq");
|
||||
lua_pushcfunction(L, l_equals);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
}
|
||||
|
||||
StorageRef* StorageRef::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud) luaL_typerror(L, narg, className);
|
||||
return *(StorageRef**)ud; // unbox pointer
|
||||
}
|
||||
|
||||
ModMetadata* StorageRef::getobject(StorageRef *ref)
|
||||
{
|
||||
ModMetadata *co = ref->m_object;
|
||||
return co;
|
||||
}
|
||||
|
||||
Metadata* StorageRef::getmeta(bool auto_create)
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
void StorageRef::clearMeta()
|
||||
{
|
||||
m_object->clear();
|
||||
}
|
||||
|
||||
const char StorageRef::className[] = "StorageRef";
|
||||
const luaL_Reg StorageRef::methods[] = {
|
||||
luamethod(MetaDataRef, contains),
|
||||
luamethod(MetaDataRef, get),
|
||||
luamethod(MetaDataRef, get_string),
|
||||
luamethod(MetaDataRef, set_string),
|
||||
luamethod(MetaDataRef, get_int),
|
||||
luamethod(MetaDataRef, set_int),
|
||||
luamethod(MetaDataRef, get_float),
|
||||
luamethod(MetaDataRef, set_float),
|
||||
luamethod(MetaDataRef, to_table),
|
||||
luamethod(MetaDataRef, from_table),
|
||||
luamethod(MetaDataRef, equals),
|
||||
{0,0}
|
||||
};
|
60
src/script/lua_api/l_storage.h
Normal file
60
src/script/lua_api/l_storage.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "l_metadata.h"
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class ModMetadata;
|
||||
|
||||
class ModApiStorage : public ModApiBase
|
||||
{
|
||||
protected:
|
||||
static int l_get_mod_storage(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
};
|
||||
|
||||
class StorageRef : public MetaDataRef
|
||||
{
|
||||
private:
|
||||
ModMetadata *m_object = nullptr;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
virtual Metadata *getmeta(bool auto_create);
|
||||
virtual void clearMeta();
|
||||
|
||||
// garbage collector
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
public:
|
||||
StorageRef(ModMetadata *object);
|
||||
~StorageRef();
|
||||
|
||||
static void Register(lua_State *L);
|
||||
static void create(lua_State *L, ModMetadata *object);
|
||||
|
||||
static StorageRef *checkobject(lua_State *L, int narg);
|
||||
static ModMetadata *getobject(StorageRef *ref);
|
||||
};
|
573
src/script/lua_api/l_util.cpp
Normal file
573
src/script/lua_api/l_util.cpp
Normal file
@ -0,0 +1,573 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "lua_api/l_util.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "lua_api/l_settings.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "common/c_content.h"
|
||||
#include "cpp_api/s_async.h"
|
||||
#include "serialization.h"
|
||||
#include <json/json.h>
|
||||
#include "cpp_api/s_security.h"
|
||||
#include "porting.h"
|
||||
#include "convert_json.h"
|
||||
#include "debug.h"
|
||||
#include "log.h"
|
||||
#include "tool.h"
|
||||
#include "filesys.h"
|
||||
#include "settings.h"
|
||||
#include "util/auth.h"
|
||||
#include "util/base64.h"
|
||||
#include "config.h"
|
||||
#include "version.h"
|
||||
#include "util/hex.h"
|
||||
#include "util/sha1.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
// log([level,] text)
|
||||
// Writes a line to the logger.
|
||||
// The one-argument version logs to LL_NONE.
|
||||
// The two-argument version accepts a log level.
|
||||
// Either the special case "deprecated" for deprecation notices, or any specified in
|
||||
// Logger::stringToLevel(name).
|
||||
int ModApiUtil::l_log(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string text;
|
||||
LogLevel level = LL_NONE;
|
||||
if (lua_isnone(L, 2)) {
|
||||
text = luaL_checkstring(L, 1);
|
||||
} else {
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
text = luaL_checkstring(L, 2);
|
||||
if (name == "deprecated") {
|
||||
log_deprecated(L, text, 2);
|
||||
return 0;
|
||||
}
|
||||
level = Logger::stringToLevel(name);
|
||||
if (level == LL_MAX) {
|
||||
warningstream << "Tried to log at unknown level '" << name
|
||||
<< "'. Defaulting to \"none\"." << std::endl;
|
||||
level = LL_NONE;
|
||||
}
|
||||
}
|
||||
g_logger.log(level, text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_us_time()
|
||||
int ModApiUtil::l_get_us_time(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
lua_pushnumber(L, porting::getTimeUs());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// parse_json(str[, nullvalue])
|
||||
int ModApiUtil::l_parse_json(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
const char *jsonstr = luaL_checkstring(L, 1);
|
||||
|
||||
// Use passed nullvalue or default to nil
|
||||
int nullindex = 2;
|
||||
if (lua_isnone(L, nullindex)) {
|
||||
lua_pushnil(L);
|
||||
nullindex = lua_gettop(L);
|
||||
}
|
||||
|
||||
Json::Value root;
|
||||
|
||||
{
|
||||
std::istringstream stream(jsonstr);
|
||||
|
||||
Json::CharReaderBuilder builder;
|
||||
builder.settings_["collectComments"] = false;
|
||||
std::string errs;
|
||||
|
||||
if (!Json::parseFromStream(builder, stream, &root, &errs)) {
|
||||
errorstream << "Failed to parse json data " << errs << std::endl;
|
||||
size_t jlen = strlen(jsonstr);
|
||||
if (jlen > 100) {
|
||||
errorstream << "Data (" << jlen
|
||||
<< " bytes) printed to warningstream." << std::endl;
|
||||
warningstream << "data: \"" << jsonstr << "\"" << std::endl;
|
||||
} else {
|
||||
errorstream << "data: \"" << jsonstr << "\"" << std::endl;
|
||||
}
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!push_json_value(L, root, nullindex)) {
|
||||
errorstream << "Failed to parse json data, "
|
||||
<< "depth exceeds lua stack limit" << std::endl;
|
||||
errorstream << "data: \"" << jsonstr << "\"" << std::endl;
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// write_json(data[, styled]) -> string or nil and error message
|
||||
int ModApiUtil::l_write_json(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
bool styled = false;
|
||||
if (!lua_isnone(L, 2)) {
|
||||
styled = readParam<bool>(L, 2);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
Json::Value root;
|
||||
try {
|
||||
read_json_value(L, root, 1);
|
||||
} catch (SerializationError &e) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, e.what());
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::string out;
|
||||
if (styled) {
|
||||
out = root.toStyledString();
|
||||
} else {
|
||||
out = fastWriteJson(root);
|
||||
}
|
||||
lua_pushlstring(L, out.c_str(), out.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_dig_params(groups, tool_capabilities)
|
||||
int ModApiUtil::l_get_dig_params(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
ItemGroupList groups;
|
||||
read_groups(L, 1, groups);
|
||||
ToolCapabilities tp = read_tool_capabilities(L, 2);
|
||||
push_dig_params(L, getDigParams(groups, &tp));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
|
||||
int ModApiUtil::l_get_hit_params(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::unordered_map<std::string, int> groups;
|
||||
read_groups(L, 1, groups);
|
||||
ToolCapabilities tp = read_tool_capabilities(L, 2);
|
||||
if(lua_isnoneornil(L, 3))
|
||||
push_hit_params(L, getHitParams(groups, &tp));
|
||||
else
|
||||
push_hit_params(L, getHitParams(groups, &tp, readParam<float>(L, 3)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check_password_entry(name, entry, password)
|
||||
int ModApiUtil::l_check_password_entry(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
std::string entry = luaL_checkstring(L, 2);
|
||||
std::string password = luaL_checkstring(L, 3);
|
||||
|
||||
if (base64_is_valid(entry)) {
|
||||
std::string hash = translate_password(name, password);
|
||||
lua_pushboolean(L, hash == entry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string salt;
|
||||
std::string verifier;
|
||||
|
||||
if (!decode_srp_verifier_and_salt(entry, &verifier, &salt)) {
|
||||
// invalid format
|
||||
warningstream << "Invalid password format for " << name << std::endl;
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
std::string gen_verifier = generate_srp_verifier(name, password, salt);
|
||||
|
||||
lua_pushboolean(L, gen_verifier == verifier);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_password_hash(name, raw_password)
|
||||
int ModApiUtil::l_get_password_hash(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
std::string name = luaL_checkstring(L, 1);
|
||||
std::string raw_password = luaL_checkstring(L, 2);
|
||||
std::string hash = translate_password(name, raw_password);
|
||||
lua_pushstring(L, hash.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_yes(arg)
|
||||
int ModApiUtil::l_is_yes(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
lua_getglobal(L, "tostring"); // function to be called
|
||||
lua_pushvalue(L, 1); // 1st argument
|
||||
lua_call(L, 1, 1); // execute function
|
||||
std::string str = readParam<std::string>(L, -1); // get result
|
||||
lua_pop(L, 1);
|
||||
|
||||
bool yes = is_yes(str);
|
||||
lua_pushboolean(L, yes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// is_nan(arg)
|
||||
int ModApiUtil::l_is_nan(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
lua_pushboolean(L, isNaN(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_builtin_path()
|
||||
int ModApiUtil::l_get_builtin_path(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
std::string path = porting::path_share + DIR_DELIM + "builtin" + DIR_DELIM;
|
||||
lua_pushstring(L, path.c_str());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compress(data, method, level)
|
||||
int ModApiUtil::l_compress(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
size_t size;
|
||||
const char *data = luaL_checklstring(L, 1, &size);
|
||||
|
||||
int level = -1;
|
||||
if (!lua_isnone(L, 3) && !lua_isnil(L, 3))
|
||||
level = readParam<float>(L, 3);
|
||||
|
||||
std::ostringstream os;
|
||||
compressZlib(std::string(data, size), os, level);
|
||||
|
||||
std::string out = os.str();
|
||||
|
||||
lua_pushlstring(L, out.data(), out.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// decompress(data, method)
|
||||
int ModApiUtil::l_decompress(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
size_t size;
|
||||
const char *data = luaL_checklstring(L, 1, &size);
|
||||
|
||||
std::istringstream is(std::string(data, size));
|
||||
std::ostringstream os;
|
||||
decompressZlib(is, os);
|
||||
|
||||
std::string out = os.str();
|
||||
|
||||
lua_pushlstring(L, out.data(), out.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// encode_base64(string)
|
||||
int ModApiUtil::l_encode_base64(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
size_t size;
|
||||
const char *data = luaL_checklstring(L, 1, &size);
|
||||
|
||||
std::string out = base64_encode((const unsigned char *)(data), size);
|
||||
|
||||
lua_pushlstring(L, out.data(), out.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// decode_base64(string)
|
||||
int ModApiUtil::l_decode_base64(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
size_t size;
|
||||
const char *d = luaL_checklstring(L, 1, &size);
|
||||
const std::string data = std::string(d, size);
|
||||
|
||||
if (!base64_is_valid(data))
|
||||
return 0;
|
||||
|
||||
std::string out = base64_decode(data);
|
||||
|
||||
lua_pushlstring(L, out.data(), out.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// mkdir(path)
|
||||
int ModApiUtil::l_mkdir(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
CHECK_SECURE_PATH(L, path, true);
|
||||
lua_pushboolean(L, fs::CreateAllDirs(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_dir_list(path, is_dir)
|
||||
int ModApiUtil::l_get_dir_list(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
bool list_all = !lua_isboolean(L, 2); // if its not a boolean list all
|
||||
bool list_dirs = readParam<bool>(L, 2); // true: list dirs, false: list files
|
||||
|
||||
CHECK_SECURE_PATH(L, path, false);
|
||||
|
||||
std::vector<fs::DirListNode> list = fs::GetDirListing(path);
|
||||
|
||||
int index = 0;
|
||||
lua_newtable(L);
|
||||
|
||||
for (const fs::DirListNode &dln : list) {
|
||||
if (list_all || list_dirs == dln.dir) {
|
||||
lua_pushstring(L, dln.name.c_str());
|
||||
lua_rawseti(L, -2, ++index);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// safe_file_write(path, content)
|
||||
int ModApiUtil::l_safe_file_write(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
size_t size;
|
||||
const char *content = luaL_checklstring(L, 2, &size);
|
||||
|
||||
CHECK_SECURE_PATH(L, path, true);
|
||||
|
||||
bool ret = fs::safeWriteToFile(path, std::string(content, size));
|
||||
lua_pushboolean(L, ret);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// request_insecure_environment()
|
||||
int ModApiUtil::l_request_insecure_environment(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
// Just return _G if security is disabled
|
||||
if (!ScriptApiSecurity::isSecure(L)) {
|
||||
lua_getglobal(L, "_G");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// We have to make sure that this function is being called directly by
|
||||
// a mod, otherwise a malicious mod could override this function and
|
||||
// steal its return value.
|
||||
lua_Debug info;
|
||||
// Make sure there's only one item below this function on the stack...
|
||||
if (lua_getstack(L, 2, &info)) {
|
||||
return 0;
|
||||
}
|
||||
FATAL_ERROR_IF(!lua_getstack(L, 1, &info), "lua_getstack() failed");
|
||||
FATAL_ERROR_IF(!lua_getinfo(L, "S", &info), "lua_getinfo() failed");
|
||||
// ...and that that item is the main file scope.
|
||||
if (strcmp(info.what, "main") != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get mod name
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
if (!lua_isstring(L, -1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check secure.trusted_mods
|
||||
std::string mod_name = readParam<std::string>(L, -1);
|
||||
std::string trusted_mods = g_settings->get("secure.trusted_mods");
|
||||
trusted_mods.erase(std::remove_if(trusted_mods.begin(),
|
||||
trusted_mods.end(), static_cast<int(*)(int)>(&std::isspace)),
|
||||
trusted_mods.end());
|
||||
std::vector<std::string> mod_list = str_split(trusted_mods, ',');
|
||||
if (std::find(mod_list.begin(), mod_list.end(), mod_name) ==
|
||||
mod_list.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Push insecure environment
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_version()
|
||||
int ModApiUtil::l_get_version(lua_State *L)
|
||||
{
|
||||
lua_createtable(L, 0, 3);
|
||||
int table = lua_gettop(L);
|
||||
|
||||
lua_pushstring(L, PROJECT_NAME_C);
|
||||
lua_setfield(L, table, "project");
|
||||
|
||||
lua_pushstring(L, g_version_string);
|
||||
lua_setfield(L, table, "string");
|
||||
|
||||
if (strcmp(g_version_string, g_version_hash) != 0) {
|
||||
lua_pushstring(L, g_version_hash);
|
||||
lua_setfield(L, table, "hash");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ModApiUtil::l_sha1(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
size_t size;
|
||||
const char *data = luaL_checklstring(L, 1, &size);
|
||||
bool hex = !lua_isboolean(L, 2) || !readParam<bool>(L, 2);
|
||||
|
||||
// Compute actual checksum of data
|
||||
std::string data_sha1;
|
||||
{
|
||||
SHA1 ctx;
|
||||
ctx.addBytes(data, size);
|
||||
unsigned char *data_tmpdigest = ctx.getDigest();
|
||||
data_sha1.assign((char*) data_tmpdigest, 20);
|
||||
free(data_tmpdigest);
|
||||
}
|
||||
|
||||
if (hex) {
|
||||
std::string sha1_hex = hex_encode(data_sha1);
|
||||
lua_pushstring(L, sha1_hex.c_str());
|
||||
} else {
|
||||
lua_pushlstring(L, data_sha1.data(), data_sha1.size());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ModApiUtil::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(log);
|
||||
|
||||
API_FCT(get_us_time);
|
||||
|
||||
API_FCT(parse_json);
|
||||
API_FCT(write_json);
|
||||
|
||||
API_FCT(get_dig_params);
|
||||
API_FCT(get_hit_params);
|
||||
|
||||
API_FCT(check_password_entry);
|
||||
API_FCT(get_password_hash);
|
||||
|
||||
API_FCT(is_yes);
|
||||
API_FCT(is_nan);
|
||||
|
||||
API_FCT(get_builtin_path);
|
||||
|
||||
API_FCT(compress);
|
||||
API_FCT(decompress);
|
||||
|
||||
API_FCT(mkdir);
|
||||
API_FCT(get_dir_list);
|
||||
API_FCT(safe_file_write);
|
||||
|
||||
API_FCT(request_insecure_environment);
|
||||
|
||||
API_FCT(encode_base64);
|
||||
API_FCT(decode_base64);
|
||||
|
||||
API_FCT(get_version);
|
||||
API_FCT(sha1);
|
||||
|
||||
LuaSettings::create(L, g_settings, g_settings_path);
|
||||
lua_setfield(L, top, "settings");
|
||||
}
|
||||
|
||||
void ModApiUtil::InitializeClient(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(log);
|
||||
|
||||
API_FCT(get_us_time);
|
||||
|
||||
API_FCT(parse_json);
|
||||
API_FCT(write_json);
|
||||
|
||||
API_FCT(is_yes);
|
||||
API_FCT(is_nan);
|
||||
|
||||
API_FCT(compress);
|
||||
API_FCT(decompress);
|
||||
|
||||
API_FCT(request_insecure_environment);
|
||||
|
||||
API_FCT(encode_base64);
|
||||
API_FCT(decode_base64);
|
||||
|
||||
API_FCT(get_version);
|
||||
API_FCT(sha1);
|
||||
|
||||
LuaSettings::create(L, g_settings, g_settings_path);
|
||||
lua_setfield(L, top, "settings");
|
||||
}
|
||||
|
||||
void ModApiUtil::InitializeAsync(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(log);
|
||||
|
||||
API_FCT(get_us_time);
|
||||
|
||||
API_FCT(parse_json);
|
||||
API_FCT(write_json);
|
||||
|
||||
API_FCT(is_yes);
|
||||
|
||||
API_FCT(get_builtin_path);
|
||||
|
||||
API_FCT(compress);
|
||||
API_FCT(decompress);
|
||||
|
||||
API_FCT(mkdir);
|
||||
API_FCT(get_dir_list);
|
||||
|
||||
API_FCT(encode_base64);
|
||||
API_FCT(decode_base64);
|
||||
|
||||
API_FCT(get_version);
|
||||
API_FCT(sha1);
|
||||
|
||||
LuaSettings::create(L, g_settings, g_settings_path);
|
||||
lua_setfield(L, top, "settings");
|
||||
}
|
110
src/script/lua_api/l_util.h
Normal file
110
src/script/lua_api/l_util.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class AsyncEngine;
|
||||
|
||||
class ModApiUtil : public ModApiBase
|
||||
{
|
||||
private:
|
||||
/*
|
||||
NOTE:
|
||||
The functions in this module are available in the in-game API
|
||||
as well as in the mainmenu API.
|
||||
|
||||
All functions that don't require either a Server or
|
||||
GUIEngine instance should be in here.
|
||||
*/
|
||||
|
||||
// log([level,] text)
|
||||
// Writes a line to the logger.
|
||||
// The one-argument version logs to LL_NONE.
|
||||
// The two-argument version accepts a log level.
|
||||
static int l_log(lua_State *L);
|
||||
|
||||
// get us precision time
|
||||
static int l_get_us_time(lua_State *L);
|
||||
|
||||
// parse_json(str[, nullvalue])
|
||||
static int l_parse_json(lua_State *L);
|
||||
|
||||
// write_json(data[, styled])
|
||||
static int l_write_json(lua_State *L);
|
||||
|
||||
// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
|
||||
static int l_get_dig_params(lua_State *L);
|
||||
|
||||
// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
|
||||
static int l_get_hit_params(lua_State *L);
|
||||
|
||||
// check_password_entry(name, entry, password)
|
||||
static int l_check_password_entry(lua_State *L);
|
||||
|
||||
// get_password_hash(name, raw_password)
|
||||
static int l_get_password_hash(lua_State *L);
|
||||
|
||||
// is_yes(arg)
|
||||
static int l_is_yes(lua_State *L);
|
||||
|
||||
// is_nan(arg)
|
||||
static int l_is_nan(lua_State *L);
|
||||
|
||||
// get_builtin_path()
|
||||
static int l_get_builtin_path(lua_State *L);
|
||||
|
||||
// compress(data, method, ...)
|
||||
static int l_compress(lua_State *L);
|
||||
|
||||
// decompress(data, method, ...)
|
||||
static int l_decompress(lua_State *L);
|
||||
|
||||
// mkdir(path)
|
||||
static int l_mkdir(lua_State *L);
|
||||
|
||||
// get_dir_list(path, is_dir)
|
||||
static int l_get_dir_list(lua_State *L);
|
||||
|
||||
// safe_file_write(path, content)
|
||||
static int l_safe_file_write(lua_State *L);
|
||||
|
||||
// request_insecure_environment()
|
||||
static int l_request_insecure_environment(lua_State *L);
|
||||
|
||||
// encode_base64(string)
|
||||
static int l_encode_base64(lua_State *L);
|
||||
|
||||
// decode_base64(string)
|
||||
static int l_decode_base64(lua_State *L);
|
||||
|
||||
// get_version()
|
||||
static int l_get_version(lua_State *L);
|
||||
|
||||
// sha1(string, raw)
|
||||
static int l_sha1(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
static void InitializeAsync(lua_State *L, int top);
|
||||
static void InitializeClient(lua_State *L, int top);
|
||||
|
||||
static void InitializeAsync(AsyncEngine &engine);
|
||||
};
|
479
src/script/lua_api/l_vmanip.cpp
Normal file
479
src/script/lua_api/l_vmanip.cpp
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "lua_api/l_vmanip.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_content.h"
|
||||
#include "common/c_converter.h"
|
||||
#include "emerge.h"
|
||||
#include "environment.h"
|
||||
#include "map.h"
|
||||
#include "mapblock.h"
|
||||
#include "server.h"
|
||||
#include "mapgen/mapgen.h"
|
||||
#include "voxelalgorithms.h"
|
||||
|
||||
// garbage collector
|
||||
int LuaVoxelManip::gc_object(lua_State *L)
|
||||
{
|
||||
LuaVoxelManip *o = *(LuaVoxelManip **)(lua_touserdata(L, 1));
|
||||
delete o;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_read_from_map(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
|
||||
v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
|
||||
sortBoxVerticies(bp1, bp2);
|
||||
|
||||
vm->initialEmerge(bp1, bp2);
|
||||
|
||||
push_v3s16(L, vm->m_area.MinEdge);
|
||||
push_v3s16(L, vm->m_area.MaxEdge);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_get_data(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
bool use_buffer = lua_istable(L, 2);
|
||||
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
u32 volume = vm->m_area.getVolume();
|
||||
|
||||
if (use_buffer)
|
||||
lua_pushvalue(L, 2);
|
||||
else
|
||||
lua_createtable(L, volume, 0);
|
||||
|
||||
for (u32 i = 0; i != volume; i++) {
|
||||
lua_Integer cid = vm->m_data[i].getContent();
|
||||
lua_pushinteger(L, cid);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_set_data(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
if (!lua_istable(L, 2))
|
||||
throw LuaError("VoxelManip:set_data called with missing parameter");
|
||||
|
||||
u32 volume = vm->m_area.getVolume();
|
||||
for (u32 i = 0; i != volume; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
content_t c = lua_tointeger(L, -1);
|
||||
|
||||
vm->m_data[i].setContent(c);
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_write_to_map(lua_State *L)
|
||||
{
|
||||
MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
bool update_light = !lua_isboolean(L, 2) || readParam<bool>(L, 2);
|
||||
GET_ENV_PTR;
|
||||
ServerMap *map = &(env->getServerMap());
|
||||
if (o->is_mapgen_vm || !update_light) {
|
||||
o->vm->blitBackAll(&(o->modified_blocks));
|
||||
} else {
|
||||
voxalgo::blit_back_with_light(map, o->vm,
|
||||
&(o->modified_blocks));
|
||||
}
|
||||
|
||||
MapEditEvent event;
|
||||
event.type = MEET_OTHER;
|
||||
for (const auto &modified_block : o->modified_blocks)
|
||||
event.modified_blocks.insert(modified_block.first);
|
||||
|
||||
map->dispatchEvent(event);
|
||||
|
||||
o->modified_blocks.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_get_node_at(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
v3s16 pos = check_v3s16(L, 2);
|
||||
|
||||
pushnode(L, o->vm->getNodeNoExNoEmerge(pos), ndef);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_set_node_at(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
v3s16 pos = check_v3s16(L, 2);
|
||||
MapNode n = readnode(L, 3, ndef);
|
||||
|
||||
o->vm->setNodeNoEmerge(pos, n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_update_liquids(lua_State *L)
|
||||
{
|
||||
GET_ENV_PTR;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
|
||||
Map *map = &(env->getMap());
|
||||
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
Mapgen mg;
|
||||
mg.vm = vm;
|
||||
mg.ndef = ndef;
|
||||
|
||||
mg.updateLiquid(&map->m_transforming_liquid,
|
||||
vm->m_area.MinEdge, vm->m_area.MaxEdge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_calc_lighting(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
if (!o->is_mapgen_vm) {
|
||||
warningstream << "VoxelManip:calc_lighting called for a non-mapgen "
|
||||
"VoxelManip object" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
|
||||
v3s16 fpmin = vm->m_area.MinEdge;
|
||||
v3s16 fpmax = vm->m_area.MaxEdge;
|
||||
v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : fpmin + yblock;
|
||||
v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : fpmax - yblock;
|
||||
bool propagate_shadow = !lua_isboolean(L, 4) || readParam<bool>(L, 4);
|
||||
|
||||
sortBoxVerticies(pmin, pmax);
|
||||
if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
|
||||
throw LuaError("Specified voxel area out of VoxelManipulator bounds");
|
||||
|
||||
Mapgen mg;
|
||||
mg.vm = vm;
|
||||
mg.ndef = ndef;
|
||||
mg.water_level = emerge->mgparams->water_level;
|
||||
|
||||
mg.calcLighting(pmin, pmax, fpmin, fpmax, propagate_shadow);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_set_lighting(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
if (!o->is_mapgen_vm) {
|
||||
warningstream << "VoxelManip:set_lighting called for a non-mapgen "
|
||||
"VoxelManip object" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lua_istable(L, 2))
|
||||
throw LuaError("VoxelManip:set_lighting called with missing parameter");
|
||||
|
||||
u8 light;
|
||||
light = (getintfield_default(L, 2, "day", 0) & 0x0F);
|
||||
light |= (getintfield_default(L, 2, "night", 0) & 0x0F) << 4;
|
||||
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
|
||||
v3s16 pmin = lua_istable(L, 3) ? check_v3s16(L, 3) : vm->m_area.MinEdge + yblock;
|
||||
v3s16 pmax = lua_istable(L, 4) ? check_v3s16(L, 4) : vm->m_area.MaxEdge - yblock;
|
||||
|
||||
sortBoxVerticies(pmin, pmax);
|
||||
if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
|
||||
throw LuaError("Specified voxel area out of VoxelManipulator bounds");
|
||||
|
||||
Mapgen mg;
|
||||
mg.vm = vm;
|
||||
|
||||
mg.setLighting(light, pmin, pmax);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_get_light_data(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
u32 volume = vm->m_area.getVolume();
|
||||
|
||||
lua_createtable(L, volume, 0);
|
||||
for (u32 i = 0; i != volume; i++) {
|
||||
lua_Integer light = vm->m_data[i].param1;
|
||||
lua_pushinteger(L, light);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_set_light_data(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
if (!lua_istable(L, 2))
|
||||
throw LuaError("VoxelManip:set_light_data called with missing "
|
||||
"parameter");
|
||||
|
||||
u32 volume = vm->m_area.getVolume();
|
||||
for (u32 i = 0; i != volume; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
u8 light = lua_tointeger(L, -1);
|
||||
|
||||
vm->m_data[i].param1 = light;
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_get_param2_data(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
bool use_buffer = lua_istable(L, 2);
|
||||
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
u32 volume = vm->m_area.getVolume();
|
||||
|
||||
if (use_buffer)
|
||||
lua_pushvalue(L, 2);
|
||||
else
|
||||
lua_createtable(L, volume, 0);
|
||||
|
||||
for (u32 i = 0; i != volume; i++) {
|
||||
lua_Integer param2 = vm->m_data[i].param2;
|
||||
lua_pushinteger(L, param2);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_set_param2_data(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
if (!lua_istable(L, 2))
|
||||
throw LuaError("VoxelManip:set_param2_data called with missing "
|
||||
"parameter");
|
||||
|
||||
u32 volume = vm->m_area.getVolume();
|
||||
for (u32 i = 0; i != volume; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
u8 param2 = lua_tointeger(L, -1);
|
||||
|
||||
vm->m_data[i].param2 = param2;
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_update_map(lua_State *L)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_was_modified(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
MMVManip *vm = o->vm;
|
||||
|
||||
lua_pushboolean(L, vm->m_is_dirty);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaVoxelManip::l_get_emerged_area(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
LuaVoxelManip *o = checkobject(L, 1);
|
||||
|
||||
push_v3s16(L, o->vm->m_area.MinEdge);
|
||||
push_v3s16(L, o->vm->m_area.MaxEdge);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
LuaVoxelManip::LuaVoxelManip(MMVManip *mmvm, bool is_mg_vm) :
|
||||
is_mapgen_vm(is_mg_vm),
|
||||
vm(mmvm)
|
||||
{
|
||||
}
|
||||
|
||||
LuaVoxelManip::LuaVoxelManip(Map *map) : vm(new MMVManip(map))
|
||||
{
|
||||
}
|
||||
|
||||
LuaVoxelManip::LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2)
|
||||
{
|
||||
vm = new MMVManip(map);
|
||||
|
||||
v3s16 bp1 = getNodeBlockPos(p1);
|
||||
v3s16 bp2 = getNodeBlockPos(p2);
|
||||
sortBoxVerticies(bp1, bp2);
|
||||
vm->initialEmerge(bp1, bp2);
|
||||
}
|
||||
|
||||
LuaVoxelManip::~LuaVoxelManip()
|
||||
{
|
||||
if (!is_mapgen_vm)
|
||||
delete vm;
|
||||
}
|
||||
|
||||
// LuaVoxelManip()
|
||||
// Creates an LuaVoxelManip and leaves it on top of stack
|
||||
int LuaVoxelManip::create_object(lua_State *L)
|
||||
{
|
||||
GET_ENV_PTR;
|
||||
|
||||
Map *map = &(env->getMap());
|
||||
LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
|
||||
new LuaVoxelManip(map, check_v3s16(L, 1), check_v3s16(L, 2)) :
|
||||
new LuaVoxelManip(map);
|
||||
|
||||
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
|
||||
luaL_getmetatable(L, className);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LuaVoxelManip *LuaVoxelManip::checkobject(lua_State *L, int narg)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
|
||||
void *ud = luaL_checkudata(L, narg, className);
|
||||
if (!ud)
|
||||
luaL_typerror(L, narg, className);
|
||||
|
||||
return *(LuaVoxelManip **)ud; // unbox pointer
|
||||
}
|
||||
|
||||
void LuaVoxelManip::Register(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
int methodtable = lua_gettop(L);
|
||||
luaL_newmetatable(L, className);
|
||||
int metatable = lua_gettop(L);
|
||||
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
|
||||
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, methodtable);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable);
|
||||
|
||||
lua_pop(L, 1); // drop metatable
|
||||
|
||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||
lua_pop(L, 1); // drop methodtable
|
||||
|
||||
// Can be created from Lua (VoxelManip())
|
||||
lua_register(L, className, create_object);
|
||||
}
|
||||
|
||||
const char LuaVoxelManip::className[] = "VoxelManip";
|
||||
const luaL_Reg LuaVoxelManip::methods[] = {
|
||||
luamethod(LuaVoxelManip, read_from_map),
|
||||
luamethod(LuaVoxelManip, get_data),
|
||||
luamethod(LuaVoxelManip, set_data),
|
||||
luamethod(LuaVoxelManip, get_node_at),
|
||||
luamethod(LuaVoxelManip, set_node_at),
|
||||
luamethod(LuaVoxelManip, write_to_map),
|
||||
luamethod(LuaVoxelManip, update_map),
|
||||
luamethod(LuaVoxelManip, update_liquids),
|
||||
luamethod(LuaVoxelManip, calc_lighting),
|
||||
luamethod(LuaVoxelManip, set_lighting),
|
||||
luamethod(LuaVoxelManip, get_light_data),
|
||||
luamethod(LuaVoxelManip, set_light_data),
|
||||
luamethod(LuaVoxelManip, get_param2_data),
|
||||
luamethod(LuaVoxelManip, set_param2_data),
|
||||
luamethod(LuaVoxelManip, was_modified),
|
||||
luamethod(LuaVoxelManip, get_emerged_area),
|
||||
{0,0}
|
||||
};
|
81
src/script/lua_api/l_vmanip.h
Normal file
81
src/script/lua_api/l_vmanip.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "irr_v3d.h"
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class Map;
|
||||
class MapBlock;
|
||||
class MMVManip;
|
||||
|
||||
/*
|
||||
VoxelManip
|
||||
*/
|
||||
class LuaVoxelManip : public ModApiBase
|
||||
{
|
||||
private:
|
||||
std::map<v3s16, MapBlock *> modified_blocks;
|
||||
bool is_mapgen_vm = false;
|
||||
|
||||
static const char className[];
|
||||
static const luaL_Reg methods[];
|
||||
|
||||
static int gc_object(lua_State *L);
|
||||
|
||||
static int l_read_from_map(lua_State *L);
|
||||
static int l_get_data(lua_State *L);
|
||||
static int l_set_data(lua_State *L);
|
||||
static int l_write_to_map(lua_State *L);
|
||||
|
||||
static int l_get_node_at(lua_State *L);
|
||||
static int l_set_node_at(lua_State *L);
|
||||
|
||||
static int l_update_map(lua_State *L);
|
||||
static int l_update_liquids(lua_State *L);
|
||||
|
||||
static int l_calc_lighting(lua_State *L);
|
||||
static int l_set_lighting(lua_State *L);
|
||||
static int l_get_light_data(lua_State *L);
|
||||
static int l_set_light_data(lua_State *L);
|
||||
|
||||
static int l_get_param2_data(lua_State *L);
|
||||
static int l_set_param2_data(lua_State *L);
|
||||
|
||||
static int l_was_modified(lua_State *L);
|
||||
static int l_get_emerged_area(lua_State *L);
|
||||
|
||||
public:
|
||||
MMVManip *vm = nullptr;
|
||||
|
||||
LuaVoxelManip(MMVManip *mmvm, bool is_mapgen_vm);
|
||||
LuaVoxelManip(Map *map, v3s16 p1, v3s16 p2);
|
||||
LuaVoxelManip(Map *map);
|
||||
~LuaVoxelManip();
|
||||
|
||||
// LuaVoxelManip()
|
||||
// Creates a LuaVoxelManip and leaves it on top of stack
|
||||
static int create_object(lua_State *L);
|
||||
|
||||
static LuaVoxelManip *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
};
|
111
src/script/scripting_client.cpp
Normal file
111
src/script/scripting_client.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "scripting_client.h"
|
||||
#include "client/client.h"
|
||||
#include "client/game.h"
|
||||
#include "cpp_api/s_internal.h"
|
||||
#include "lua_api/l_client.h"
|
||||
#include "lua_api/l_clientobject.h"
|
||||
#include "lua_api/l_env.h"
|
||||
#include "lua_api/l_inventoryaction.h"
|
||||
#include "lua_api/l_item.h"
|
||||
#include "lua_api/l_itemstackmeta.h"
|
||||
#include "lua_api/l_minimap.h"
|
||||
#include "lua_api/l_modchannels.h"
|
||||
#include "lua_api/l_particles_local.h"
|
||||
#include "lua_api/l_storage.h"
|
||||
#include "lua_api/l_sound.h"
|
||||
#include "lua_api/l_util.h"
|
||||
#include "lua_api/l_item.h"
|
||||
#include "lua_api/l_nodemeta.h"
|
||||
#include "lua_api/l_localplayer.h"
|
||||
#include "lua_api/l_camera.h"
|
||||
#include "lua_api/l_settings.h"
|
||||
#include "lua_api/l_http.h"
|
||||
#include "lua_api/l_clientobject.h"
|
||||
#include "lua_api/l_inventoryaction.h"
|
||||
|
||||
ClientScripting::ClientScripting(Client *client):
|
||||
ScriptApiBase(ScriptingType::Client)
|
||||
{
|
||||
setGameDef(client);
|
||||
setGame(g_game);
|
||||
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
// Security is mandatory client side
|
||||
initializeSecurityClient();
|
||||
|
||||
lua_getglobal(L, "core");
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "ui");
|
||||
|
||||
InitializeModApi(L, top);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Push builtin initialization type
|
||||
lua_pushstring(L, "client");
|
||||
lua_setglobal(L, "INIT");
|
||||
|
||||
infostream << "SCRIPTAPI: Initialized client game modules" << std::endl;
|
||||
}
|
||||
|
||||
void ClientScripting::InitializeModApi(lua_State *L, int top)
|
||||
{
|
||||
LuaItemStack::Register(L);
|
||||
ItemStackMetaRef::Register(L);
|
||||
LuaRaycast::Register(L);
|
||||
StorageRef::Register(L);
|
||||
LuaMinimap::Register(L);
|
||||
NodeMetaRef::RegisterClient(L);
|
||||
LuaLocalPlayer::Register(L);
|
||||
LuaCamera::Register(L);
|
||||
ModChannelRef::Register(L);
|
||||
LuaSettings::Register(L);
|
||||
ClientObjectRef::Register(L);
|
||||
LuaInventoryAction::Register(L);
|
||||
|
||||
ModApiItemMod::Initialize(L, top);
|
||||
ModApiUtil::InitializeClient(L, top);
|
||||
ModApiHttp::Initialize(L, top);
|
||||
ModApiClient::Initialize(L, top);
|
||||
ModApiStorage::Initialize(L, top);
|
||||
ModApiEnvMod::InitializeClient(L, top);
|
||||
ModApiChannels::Initialize(L, top);
|
||||
ModApiParticlesLocal::Initialize(L, top);
|
||||
}
|
||||
|
||||
void ClientScripting::on_client_ready(LocalPlayer *localplayer)
|
||||
{
|
||||
LuaLocalPlayer::create(getStack(), localplayer);
|
||||
}
|
||||
|
||||
void ClientScripting::on_camera_ready(Camera *camera)
|
||||
{
|
||||
LuaCamera::create(getStack(), camera);
|
||||
}
|
||||
|
||||
void ClientScripting::on_minimap_ready(Minimap *minimap)
|
||||
{
|
||||
LuaMinimap::create(getStack(), minimap);
|
||||
}
|
49
src/script/scripting_client.h
Normal file
49
src/script/scripting_client.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpp_api/s_base.h"
|
||||
#include "cpp_api/s_client.h"
|
||||
#include "cpp_api/s_cheats.h"
|
||||
#include "cpp_api/s_modchannels.h"
|
||||
#include "cpp_api/s_security.h"
|
||||
|
||||
class Client;
|
||||
class LocalPlayer;
|
||||
class Camera;
|
||||
class Minimap;
|
||||
|
||||
class ClientScripting:
|
||||
virtual public ScriptApiBase,
|
||||
public ScriptApiSecurity,
|
||||
public ScriptApiClient,
|
||||
public ScriptApiModChannels,
|
||||
public ScriptApiCheats
|
||||
{
|
||||
public:
|
||||
ClientScripting(Client *client);
|
||||
void on_client_ready(LocalPlayer *localplayer);
|
||||
void on_camera_ready(Camera *camera);
|
||||
void on_minimap_ready(Minimap *minimap);
|
||||
|
||||
private:
|
||||
virtual void InitializeModApi(lua_State *L, int top);
|
||||
};
|
101
src/script/scripting_mainmenu.cpp
Normal file
101
src/script/scripting_mainmenu.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "scripting_mainmenu.h"
|
||||
#include "content/mods.h"
|
||||
#include "cpp_api/s_internal.h"
|
||||
#include "lua_api/l_base.h"
|
||||
#include "lua_api/l_http.h"
|
||||
#include "lua_api/l_mainmenu.h"
|
||||
#include "lua_api/l_sound.h"
|
||||
#include "lua_api/l_util.h"
|
||||
#include "lua_api/l_settings.h"
|
||||
#include "log.h"
|
||||
|
||||
extern "C" {
|
||||
#include "lualib.h"
|
||||
}
|
||||
|
||||
#define MAINMENU_NUM_ASYNC_THREADS 4
|
||||
|
||||
|
||||
MainMenuScripting::MainMenuScripting(GUIEngine* guiengine):
|
||||
ScriptApiBase(ScriptingType::MainMenu)
|
||||
{
|
||||
setGuiEngine(guiengine);
|
||||
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
lua_getglobal(L, "core");
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "gamedata");
|
||||
|
||||
// Initialize our lua_api modules
|
||||
initializeModApi(L, top);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Push builtin initialization type
|
||||
lua_pushstring(L, "mainmenu");
|
||||
lua_setglobal(L, "INIT");
|
||||
|
||||
infostream << "SCRIPTAPI: Initialized main menu modules" << std::endl;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void MainMenuScripting::initializeModApi(lua_State *L, int top)
|
||||
{
|
||||
registerLuaClasses(L, top);
|
||||
|
||||
// Initialize mod API modules
|
||||
ModApiMainMenu::Initialize(L, top);
|
||||
ModApiUtil::Initialize(L, top);
|
||||
ModApiSound::Initialize(L, top);
|
||||
ModApiHttp::Initialize(L, top);
|
||||
|
||||
asyncEngine.registerStateInitializer(registerLuaClasses);
|
||||
asyncEngine.registerStateInitializer(ModApiMainMenu::InitializeAsync);
|
||||
asyncEngine.registerStateInitializer(ModApiUtil::InitializeAsync);
|
||||
asyncEngine.registerStateInitializer(ModApiHttp::InitializeAsync);
|
||||
|
||||
// Initialize async environment
|
||||
//TODO possibly make number of async threads configurable
|
||||
asyncEngine.initialize(MAINMENU_NUM_ASYNC_THREADS);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void MainMenuScripting::registerLuaClasses(lua_State *L, int top)
|
||||
{
|
||||
LuaSettings::Register(L);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void MainMenuScripting::step()
|
||||
{
|
||||
asyncEngine.step(getStack());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
unsigned int MainMenuScripting::queueAsync(const std::string &serialized_func,
|
||||
const std::string &serialized_param)
|
||||
{
|
||||
return asyncEngine.queueAsyncJob(serialized_func, serialized_param);
|
||||
}
|
||||
|
48
src/script/scripting_mainmenu.h
Normal file
48
src/script/scripting_mainmenu.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpp_api/s_base.h"
|
||||
#include "cpp_api/s_mainmenu.h"
|
||||
#include "cpp_api/s_async.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Scripting <-> Main Menu Interface */
|
||||
/*****************************************************************************/
|
||||
|
||||
class MainMenuScripting
|
||||
: virtual public ScriptApiBase,
|
||||
public ScriptApiMainMenu
|
||||
{
|
||||
public:
|
||||
MainMenuScripting(GUIEngine* guiengine);
|
||||
|
||||
// Global step handler to pass back async events
|
||||
void step();
|
||||
|
||||
// Pass async events from engine to async threads
|
||||
unsigned int queueAsync(const std::string &serialized_func,
|
||||
const std::string &serialized_params);
|
||||
private:
|
||||
void initializeModApi(lua_State *L, int top);
|
||||
static void registerLuaClasses(lua_State *L, int top);
|
||||
|
||||
AsyncEngine asyncEngine;
|
||||
};
|
127
src/script/scripting_server.cpp
Normal file
127
src/script/scripting_server.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "scripting_server.h"
|
||||
#include "server.h"
|
||||
#include "log.h"
|
||||
#include "settings.h"
|
||||
#include "cpp_api/s_internal.h"
|
||||
#include "lua_api/l_areastore.h"
|
||||
#include "lua_api/l_auth.h"
|
||||
#include "lua_api/l_base.h"
|
||||
#include "lua_api/l_craft.h"
|
||||
#include "lua_api/l_env.h"
|
||||
#include "lua_api/l_inventory.h"
|
||||
#include "lua_api/l_item.h"
|
||||
#include "lua_api/l_itemstackmeta.h"
|
||||
#include "lua_api/l_mapgen.h"
|
||||
#include "lua_api/l_modchannels.h"
|
||||
#include "lua_api/l_nodemeta.h"
|
||||
#include "lua_api/l_nodetimer.h"
|
||||
#include "lua_api/l_noise.h"
|
||||
#include "lua_api/l_object.h"
|
||||
#include "lua_api/l_playermeta.h"
|
||||
#include "lua_api/l_particles.h"
|
||||
#include "lua_api/l_rollback.h"
|
||||
#include "lua_api/l_server.h"
|
||||
#include "lua_api/l_util.h"
|
||||
#include "lua_api/l_vmanip.h"
|
||||
#include "lua_api/l_settings.h"
|
||||
#include "lua_api/l_http.h"
|
||||
#include "lua_api/l_storage.h"
|
||||
|
||||
extern "C" {
|
||||
#include "lualib.h"
|
||||
}
|
||||
|
||||
ServerScripting::ServerScripting(Server* server):
|
||||
ScriptApiBase(ScriptingType::Server)
|
||||
{
|
||||
setGameDef(server);
|
||||
|
||||
// setEnv(env) is called by ScriptApiEnv::initializeEnvironment()
|
||||
// once the environment has been created
|
||||
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
if (g_settings->getBool("secure.enable_security")) {
|
||||
initializeSecurity();
|
||||
} else {
|
||||
warningstream << "\\!/ Mod security should never be disabled, as it allows any mod to "
|
||||
<< "access the host machine."
|
||||
<< "Mods should use minetest.request_insecure_environment() instead \\!/" << std::endl;
|
||||
}
|
||||
|
||||
lua_getglobal(L, "core");
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "object_refs");
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "luaentities");
|
||||
|
||||
// Initialize our lua_api modules
|
||||
InitializeModApi(L, top);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Push builtin initialization type
|
||||
lua_pushstring(L, "game");
|
||||
lua_setglobal(L, "INIT");
|
||||
|
||||
infostream << "SCRIPTAPI: Initialized game modules" << std::endl;
|
||||
}
|
||||
|
||||
void ServerScripting::InitializeModApi(lua_State *L, int top)
|
||||
{
|
||||
// Register reference classes (userdata)
|
||||
InvRef::Register(L);
|
||||
ItemStackMetaRef::Register(L);
|
||||
LuaAreaStore::Register(L);
|
||||
LuaItemStack::Register(L);
|
||||
LuaPerlinNoise::Register(L);
|
||||
LuaPerlinNoiseMap::Register(L);
|
||||
LuaPseudoRandom::Register(L);
|
||||
LuaPcgRandom::Register(L);
|
||||
LuaRaycast::Register(L);
|
||||
LuaSecureRandom::Register(L);
|
||||
LuaVoxelManip::Register(L);
|
||||
NodeMetaRef::Register(L);
|
||||
NodeTimerRef::Register(L);
|
||||
ObjectRef::Register(L);
|
||||
PlayerMetaRef::Register(L);
|
||||
LuaSettings::Register(L);
|
||||
StorageRef::Register(L);
|
||||
ModChannelRef::Register(L);
|
||||
|
||||
// Initialize mod api modules
|
||||
ModApiAuth::Initialize(L, top);
|
||||
ModApiCraft::Initialize(L, top);
|
||||
ModApiEnvMod::Initialize(L, top);
|
||||
ModApiInventory::Initialize(L, top);
|
||||
ModApiItemMod::Initialize(L, top);
|
||||
ModApiMapgen::Initialize(L, top);
|
||||
ModApiParticles::Initialize(L, top);
|
||||
ModApiRollback::Initialize(L, top);
|
||||
ModApiServer::Initialize(L, top);
|
||||
ModApiUtil::Initialize(L, top);
|
||||
ModApiHttp::Initialize(L, top);
|
||||
ModApiStorage::Initialize(L, top);
|
||||
ModApiChannels::Initialize(L, top);
|
||||
}
|
53
src/script/scripting_server.h
Normal file
53
src/script/scripting_server.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "cpp_api/s_base.h"
|
||||
#include "cpp_api/s_entity.h"
|
||||
#include "cpp_api/s_env.h"
|
||||
#include "cpp_api/s_inventory.h"
|
||||
#include "cpp_api/s_modchannels.h"
|
||||
#include "cpp_api/s_node.h"
|
||||
#include "cpp_api/s_player.h"
|
||||
#include "cpp_api/s_server.h"
|
||||
#include "cpp_api/s_security.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Scripting <-> Server Game Interface */
|
||||
/*****************************************************************************/
|
||||
|
||||
class ServerScripting:
|
||||
virtual public ScriptApiBase,
|
||||
public ScriptApiDetached,
|
||||
public ScriptApiEntity,
|
||||
public ScriptApiEnv,
|
||||
public ScriptApiModChannels,
|
||||
public ScriptApiNode,
|
||||
public ScriptApiPlayer,
|
||||
public ScriptApiServer,
|
||||
public ScriptApiSecurity
|
||||
{
|
||||
public:
|
||||
ServerScripting(Server* server);
|
||||
|
||||
// use ScriptApiBase::loadMod() to load mods
|
||||
|
||||
private:
|
||||
void InitializeModApi(lua_State *L, int top);
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user