Add files via upload

This commit is contained in:
VoidCosmos 2021-09-19 16:07:25 +05:30 committed by GitHub
parent 2e17095765
commit 37b8dd27e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 20847 additions and 0 deletions

21
src/script/CMakeLists.txt Normal file
View 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)

View 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)

View 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}
};

View 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);
};

View 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");
}

View 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);
};

View 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);
}

View 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);
};

View 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

View 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);
};

View 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);
}

View 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);
};

View 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}
};

View 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);
};

View 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);
}

View 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

File diff suppressed because it is too large Load Diff

333
src/script/lua_api/l_env.h Normal file
View 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;
};

View 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
}

View 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);
};

View 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

View 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);
}

View 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);
};

View 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}
};

View 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);
};

View 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
View 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);
};

View 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}
};

View 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);
};

View 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}
};

View 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);
};

File diff suppressed because it is too large Load Diff

View 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);
};

File diff suppressed because it is too large Load Diff

View 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[];
};

View 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;
}

View 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);
};

View 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}
};

View 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);
};

View 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

View 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[];
};

View 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}
};

View 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);
};

View 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}
};

View 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);
};

View 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, &params);
} 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(&params);
*(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}
};

View 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);
};

File diff suppressed because it is too large Load Diff

View 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);
};

View 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);
}

View 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);
};

View 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);
}

View 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);
};

View 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

View 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);
};

View 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);
}

View 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);
};

View 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);
}

View 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);
};

View 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}
};

View 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);
};

View 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);
}

View 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);
};

View 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}
};

View 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);
};

View 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
View 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);
};

View 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}
};

View 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);
};

View 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);
}

View 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);
};

View 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);
}

View 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;
};

View 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);
}

View 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);
};