1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Lua on each mapgen thread (#13092)

This commit is contained in:
sfan5 2024-02-13 22:47:30 +01:00 committed by GitHub
parent d4b107e2e8
commit 3cac17d23e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 1329 additions and 193 deletions

View file

@ -75,6 +75,11 @@ GUIEngine *ModApiBase::getGuiEngine(lua_State *L)
}
#endif
EmergeThread *ModApiBase::getEmergeThread(lua_State *L)
{
return getScriptApiBase(L)->getEmergeThread();
}
std::string ModApiBase::getCurrentModPath(lua_State *L)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);

View file

@ -34,7 +34,7 @@ extern "C" {
class Client;
class GUIEngine;
#endif
class EmergeThread;
class ScriptApiBase;
class Server;
class Environment;
@ -49,6 +49,7 @@ public:
static Client* getClient(lua_State *L);
static GUIEngine* getGuiEngine(lua_State *L);
#endif // !SERVER
static EmergeThread* getEmergeThread(lua_State *L);
static IGameDef* getGameDef(lua_State *L);

View file

@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "daynightratio.h"
#include "util/pointedthing.h"
#include "mapgen/treegen.h"
#include "emerge.h"
#include "emerge_internal.h"
#include "pathfinder.h"
#include "face_position_cache.h"
#include "remoteplayer.h"
@ -241,7 +241,7 @@ void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
delete state;
}
// Exported functions
/* Exported functions */
// set_node(pos, node)
// pos = {x=num, y=num, z=num}
@ -1538,3 +1538,189 @@ void ModApiEnv::InitializeClient(lua_State *L, int top)
API_FCT(line_of_sight);
API_FCT(raycast);
}
#define GET_VM_PTR \
MMVManip *vm = getVManip(L); \
if (!vm) \
return 0
// get_node_max_level(pos)
int ModApiEnvVM::l_get_node_max_level(lua_State *L)
{
GET_VM_PTR;
v3s16 pos = read_v3s16(L, 1);
MapNode n = vm->getNodeNoExNoEmerge(pos);
lua_pushnumber(L, n.getMaxLevel(getGameDef(L)->ndef()));
return 1;
}
// get_node_level(pos)
int ModApiEnvVM::l_get_node_level(lua_State *L)
{
GET_VM_PTR;
v3s16 pos = read_v3s16(L, 1);
MapNode n = vm->getNodeNoExNoEmerge(pos);
lua_pushnumber(L, n.getLevel(getGameDef(L)->ndef()));
return 1;
}
// set_node_level(pos, level)
int ModApiEnvVM::l_set_node_level(lua_State *L)
{
GET_VM_PTR;
v3s16 pos = read_v3s16(L, 1);
u8 level = 1;
if (lua_isnumber(L, 2))
level = lua_tonumber(L, 2);
MapNode n = vm->getNodeNoExNoEmerge(pos);
lua_pushnumber(L, n.setLevel(getGameDef(L)->ndef(), level));
vm->setNodeNoEmerge(pos, n);
return 1;
}
// add_node_level(pos, level)
int ModApiEnvVM::l_add_node_level(lua_State *L)
{
GET_VM_PTR;
v3s16 pos = read_v3s16(L, 1);
u8 level = 1;
if (lua_isnumber(L, 2))
level = lua_tonumber(L, 2);
MapNode n = vm->getNodeNoExNoEmerge(pos);
lua_pushnumber(L, n.addLevel(getGameDef(L)->ndef(), level));
vm->setNodeNoEmerge(pos, n);
return 1;
}
// find_node_near(pos, radius, nodenames, [search_center])
int ModApiEnvVM::l_find_node_near(lua_State *L)
{
GET_VM_PTR;
const NodeDefManager *ndef = getGameDef(L)->ndef();
v3s16 pos = read_v3s16(L, 1);
int radius = luaL_checkinteger(L, 2);
std::vector<content_t> filter;
collectNodeIds(L, 3, ndef, filter);
int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1;
auto getNode = [&vm] (v3s16 p) -> MapNode {
return vm->getNodeNoExNoEmerge(p);
};
return findNodeNear(L, pos, radius, filter, start_radius, getNode);
}
// find_nodes_in_area(minp, maxp, nodenames, [grouped])
int ModApiEnvVM::l_find_nodes_in_area(lua_State *L)
{
GET_VM_PTR;
const NodeDefManager *ndef = getGameDef(L)->ndef();
v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp);
checkArea(minp, maxp);
// avoid the loop going out-of-bounds
{
VoxelArea cropped = VoxelArea(minp, maxp).intersect(vm->m_area);
minp = cropped.MinEdge;
maxp = cropped.MaxEdge;
}
std::vector<content_t> filter;
collectNodeIds(L, 3, ndef, filter);
bool grouped = lua_isboolean(L, 4) && readParam<bool>(L, 4);
auto iterate = [&] (auto callback) {
for (s16 z = minp.Z; z <= maxp.Z; z++)
for (s16 y = minp.Y; y <= maxp.Y; y++) {
u32 vi = vm->m_area.index(minp.X, y, z);
for (s16 x = minp.X; x <= maxp.X; x++) {
v3s16 pos(x, y, z);
MapNode n = vm->m_data[vi];
if (!callback(pos, n))
return;
++vi;
}
}
};
return findNodesInArea(L, ndef, filter, grouped, iterate);
}
// find_nodes_in_area_under_air(minp, maxp, nodenames)
int ModApiEnvVM::l_find_nodes_in_area_under_air(lua_State *L)
{
GET_VM_PTR;
const NodeDefManager *ndef = getGameDef(L)->ndef();
v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp);
checkArea(minp, maxp);
std::vector<content_t> filter;
collectNodeIds(L, 3, ndef, filter);
auto getNode = [&vm] (v3s16 p) -> MapNode {
return vm->getNodeNoExNoEmerge(p);
};
return findNodesInAreaUnderAir(L, minp, maxp, filter, getNode);
}
// spawn_tree(pos, treedef)
int ModApiEnvVM::l_spawn_tree(lua_State *L)
{
GET_VM_PTR;
const NodeDefManager *ndef = getGameDef(L)->ndef();
v3s16 p0 = read_v3s16(L, 1);
treegen::TreeDef tree_def;
if (!read_tree_def(L, 2, ndef, tree_def))
return 0;
treegen::error e;
if ((e = treegen::make_ltree(*vm, p0, ndef, tree_def)) != treegen::SUCCESS) {
if (e == treegen::UNBALANCED_BRACKETS) {
throw LuaError("spawn_tree(): closing ']' has no matching opening bracket");
} else {
throw LuaError("spawn_tree(): unknown error");
}
}
lua_pushboolean(L, true);
return 1;
}
MMVManip *ModApiEnvVM::getVManip(lua_State *L)
{
auto emerge = getEmergeThread(L);
if (emerge)
return emerge->getMapgen()->vm;
return nullptr;
}
void ModApiEnvVM::InitializeEmerge(lua_State *L, int top)
{
// other, more trivial functions are in builtin/emerge/env.lua
API_FCT(get_node_max_level);
API_FCT(get_node_level);
API_FCT(set_node_level);
API_FCT(add_node_level);
API_FCT(find_node_near);
API_FCT(find_nodes_in_area);
API_FCT(find_nodes_in_area_under_air);
API_FCT(spawn_tree);
}
#undef GET_VM_PTR

View file

@ -243,6 +243,44 @@ public:
static void InitializeClient(lua_State *L, int top);
};
/*
* Duplicates of certain env APIs that operate not on the global
* map but on a VoxelManipulator. This is for emerge scripting.
*/
class ModApiEnvVM : public ModApiEnvBase {
private:
// get_node_max_level(pos)
static int l_get_node_max_level(lua_State *L);
// get_node_level(pos)
static int l_get_node_level(lua_State *L);
// set_node_level(pos)
static int l_set_node_level(lua_State *L);
// add_node_level(pos)
static int l_add_node_level(lua_State *L);
// find_node_near(pos, radius, nodenames, [search_center])
static int l_find_node_near(lua_State *L);
// find_nodes_in_area(minp, maxp, nodenames, [grouped])
static int l_find_nodes_in_area(lua_State *L);
// find_surface_nodes_in_area(minp, maxp, nodenames)
static int l_find_nodes_in_area_under_air(lua_State *L);
// spawn_tree(pos, treedef)
static int l_spawn_tree(lua_State *L);
// Helper: get the vmanip we're operating on
static MMVManip *getVManip(lua_State *L);
public:
static void InitializeEmerge(lua_State *L, int top);
};
class LuaABM : public ActiveBlockModifier {
private:
int m_id;

View file

@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/serialize.h"
#include "server.h"
#include "environment.h"
#include "emerge.h"
#include "emerge_internal.h"
#include "mapgen/mg_biome.h"
#include "mapgen/mg_ore.h"
#include "mapgen/mg_decoration.h"
@ -482,7 +482,7 @@ int ModApiMapgen::l_get_biome_id(lua_State *L)
const char *biome_str = luaL_checkstring(L, 1);
const BiomeManager *bmgr = getServer(L)->getEmergeManager()->getBiomeManager();
const BiomeManager *bmgr = getEmergeManager(L)->getBiomeManager();
if (!bmgr)
return 0;
@ -504,7 +504,7 @@ int ModApiMapgen::l_get_biome_name(lua_State *L)
int biome_id = luaL_checkinteger(L, 1);
const BiomeManager *bmgr = getServer(L)->getEmergeManager()->getBiomeManager();
const BiomeManager *bmgr = getEmergeManager(L)->getBiomeManager();
if (!bmgr)
return 0;
@ -523,8 +523,7 @@ int ModApiMapgen::l_get_heat(lua_State *L)
v3s16 pos = read_v3s16(L, 1);
const BiomeGen *biomegen = getServer(L)->getEmergeManager()->getBiomeGen();
const BiomeGen *biomegen = getBiomeGen(L);
if (!biomegen || biomegen->getType() != BIOMEGEN_ORIGINAL)
return 0;
@ -544,8 +543,7 @@ int ModApiMapgen::l_get_humidity(lua_State *L)
v3s16 pos = read_v3s16(L, 1);
const BiomeGen *biomegen = getServer(L)->getEmergeManager()->getBiomeGen();
const BiomeGen *biomegen = getBiomeGen(L);
if (!biomegen || biomegen->getType() != BIOMEGEN_ORIGINAL)
return 0;
@ -565,7 +563,7 @@ int ModApiMapgen::l_get_biome_data(lua_State *L)
v3s16 pos = read_v3s16(L, 1);
const BiomeGen *biomegen = getServer(L)->getEmergeManager()->getBiomeGen();
const BiomeGen *biomegen = getBiomeGen(L);
if (!biomegen)
return 0;
@ -607,8 +605,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
enum MapgenObject mgobj = (MapgenObject)mgobjint;
EmergeManager *emerge = getServer(L)->getEmergeManager();
Mapgen *mg = emerge->getCurrentMapgen();
Mapgen *mg = getMapgen(L);
if (!mg)
throw LuaError("Must only be called in a mapgen thread!");
@ -683,8 +680,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
return 1;
}
case MGOBJ_GENNOTIFY: {
std::map<std::string, std::vector<v3s16> >event_map;
std::map<std::string, std::vector<v3s16>> event_map;
mg->gennotify.getEvents(event_map);
lua_createtable(L, 0, event_map.size());
@ -699,6 +695,24 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
lua_setfield(L, -2, it->first.c_str());
}
// push user-defined data
auto &custom_map = mg->gennotify.getCustomData();
lua_createtable(L, 0, custom_map.size());
lua_getglobal(L, "core");
lua_getfield(L, -1, "deserialize");
lua_remove(L, -2); // remove 'core'
for (const auto &it : custom_map) {
lua_pushvalue(L, -1); // deserialize func
lua_pushlstring(L, it.second.c_str(), it.second.size());
lua_pushboolean(L, true);
lua_call(L, 2, 1);
lua_setfield(L, -3, it.first.c_str()); // put into table
}
lua_pop(L, 1); // remove func
lua_setfield(L, -2, "custom"); // put into top-level table
return 1;
}
}
@ -728,6 +742,31 @@ int ModApiMapgen::l_get_spawn_level(lua_State *L)
}
// get_seed([add])
int ModApiMapgen::l_get_seed(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
// This exists to
// 1. not duplicate the truncation logic from Mapgen::Mapgen() once more
// 2. because I don't trust myself to do it correctly in Lua
auto *emerge = getEmergeManager(L);
if (!emerge || !emerge->mgparams)
return 0;
int add = 0;
if (lua_isnumber(L, 1))
add = luaL_checkint(L, 1);
s32 seed = (s32)emerge->mgparams->seed;
seed += add;
lua_pushinteger(L, seed);
return 1;
}
int ModApiMapgen::l_get_mapgen_params(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@ -737,8 +776,8 @@ int ModApiMapgen::l_get_mapgen_params(lua_State *L)
std::string value;
MapSettingsManager *settingsmgr =
getServer(L)->getEmergeManager()->map_settings_mgr;
const MapSettingsManager *settingsmgr =
getEmergeManager(L)->map_settings_mgr;
lua_newtable(L);
@ -810,7 +849,8 @@ int ModApiMapgen::l_get_mapgen_edges(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
MapSettingsManager *settingsmgr = getServer(L)->getEmergeManager()->map_settings_mgr;
const MapSettingsManager *settingsmgr =
getEmergeManager(L)->map_settings_mgr;
// MapSettingsManager::makeMapgenParams cannot be used here because it would
// make mapgen settings immutable from then on. Mapgen settings should stay
@ -846,8 +886,8 @@ int ModApiMapgen::l_get_mapgen_setting(lua_State *L)
NO_MAP_LOCK_REQUIRED;
std::string value;
MapSettingsManager *settingsmgr =
getServer(L)->getEmergeManager()->map_settings_mgr;
const MapSettingsManager *settingsmgr =
getEmergeManager(L)->map_settings_mgr;
const char *name = luaL_checkstring(L, 1);
if (!settingsmgr->getMapSetting(name, &value))
@ -863,8 +903,8 @@ int ModApiMapgen::l_get_mapgen_setting_noiseparams(lua_State *L)
NO_MAP_LOCK_REQUIRED;
NoiseParams np;
MapSettingsManager *settingsmgr =
getServer(L)->getEmergeManager()->map_settings_mgr;
const MapSettingsManager *settingsmgr =
getEmergeManager(L)->map_settings_mgr;
const char *name = luaL_checkstring(L, 1);
if (!settingsmgr->getMapSettingNoiseParams(name, &np))
@ -964,7 +1004,7 @@ int ModApiMapgen::l_get_noiseparams(lua_State *L)
}
// set_gen_notify(flags, {deco_id_table})
// set_gen_notify(flags, {deco_ids}, {custom_ids})
int ModApiMapgen::l_set_gen_notify(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@ -986,11 +1026,26 @@ int ModApiMapgen::l_set_gen_notify(lua_State *L)
}
}
if (lua_istable(L, 3)) {
lua_pushnil(L);
while (lua_next(L, 3)) {
emerge->gen_notify_on_custom.insert(readParam<std::string>(L, -1));
lua_pop(L, 1);
}
}
// Clear sets if relevant flag disabled
if ((emerge->gen_notify_on & (1 << GENNOTIFY_DECORATION)) == 0)
emerge->gen_notify_on_deco_ids.clear();
if ((emerge->gen_notify_on & (1 << GENNOTIFY_CUSTOM)) == 0)
emerge->gen_notify_on_custom.clear();
return 0;
}
// get_gen_notify()
// returns flagstring, {deco_ids}, {custom_ids})
int ModApiMapgen::l_get_gen_notify(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@ -999,13 +1054,43 @@ int ModApiMapgen::l_get_gen_notify(lua_State *L)
push_flags_string(L, flagdesc_gennotify, emerge->gen_notify_on,
emerge->gen_notify_on);
lua_newtable(L);
lua_createtable(L, emerge->gen_notify_on_deco_ids.size(), 0);
int i = 1;
for (u32 gen_notify_on_deco_id : emerge->gen_notify_on_deco_ids) {
lua_pushnumber(L, gen_notify_on_deco_id);
for (u32 id : emerge->gen_notify_on_deco_ids) {
lua_pushnumber(L, id);
lua_rawseti(L, -2, i++);
}
return 2;
lua_createtable(L, emerge->gen_notify_on_custom.size(), 0);
int j = 1;
for (const auto &id : emerge->gen_notify_on_custom) {
lua_pushstring(L, id.c_str());
lua_rawseti(L, -2, j++);
}
return 3;
}
// save_gen_notify(custom_id, data) [in emerge thread]
int ModApiMapgen::l_save_gen_notify(lua_State *L)
{
auto *emerge = getEmergeThread(L);
std::string key = readParam<std::string>(L, 1);
lua_getglobal(L, "core");
lua_getfield(L, -1, "serialize");
lua_remove(L, -2); // remove 'core'
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
std::string val = readParam<std::string>(L, -1);
lua_pop(L, 1);
bool set = emerge->getMapgen()->gennotify.setCustom(key, val);
lua_pushboolean(L, set);
return 1;
}
@ -1020,8 +1105,7 @@ int ModApiMapgen::l_get_decoration_id(lua_State *L)
return 0;
const DecorationManager *dmgr =
getServer(L)->getEmergeManager()->getDecorationManager();
getEmergeManager(L)->getDecorationManager();
if (!dmgr)
return 0;
@ -1452,20 +1536,26 @@ int ModApiMapgen::l_clear_registered_schematics(lua_State *L)
}
// generate_ores(vm, p1, p2, [ore_id])
// generate_ores(vm, p1, p2)
int ModApiMapgen::l_generate_ores(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
EmergeManager *emerge = getServer(L)->getEmergeManager();
auto *emerge = getEmergeManager(L);
if (!emerge || !emerge->mgparams)
return 0;
OreManager *oremgr;
if (auto mg = getMapgen(L))
oremgr = mg->m_emerge->oremgr;
else
oremgr = emerge->oremgr;
Mapgen mg;
// Intentionally truncates to s32, see Mapgen::Mapgen()
mg.seed = (s32)emerge->mgparams->seed;
mg.vm = checkObject<LuaVoxelManip>(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
mg.ndef = emerge->ndef;
v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) :
mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
@ -1475,26 +1565,32 @@ int ModApiMapgen::l_generate_ores(lua_State *L)
u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
emerge->oremgr->placeAllOres(&mg, blockseed, pmin, pmax);
oremgr->placeAllOres(&mg, blockseed, pmin, pmax);
return 0;
}
// generate_decorations(vm, p1, p2, [deco_id])
// generate_decorations(vm, p1, p2)
int ModApiMapgen::l_generate_decorations(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
EmergeManager *emerge = getServer(L)->getEmergeManager();
auto *emerge = getEmergeManager(L);
if (!emerge || !emerge->mgparams)
return 0;
DecorationManager *decomgr;
if (auto mg = getMapgen(L))
decomgr = mg->m_emerge->decomgr;
else
decomgr = emerge->decomgr;
Mapgen mg;
// Intentionally truncates to s32, see Mapgen::Mapgen()
mg.seed = (s32)emerge->mgparams->seed;
mg.vm = checkObject<LuaVoxelManip>(L, 1)->vm;
mg.ndef = getServer(L)->getNodeDefManager();
mg.ndef = emerge->ndef;
v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) :
mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
@ -1504,7 +1600,7 @@ int ModApiMapgen::l_generate_decorations(lua_State *L)
u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
return 0;
}
@ -1629,7 +1725,11 @@ int ModApiMapgen::l_place_schematic_on_vmanip(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
SchematicManager *schemmgr;
if (auto mg = getMapgen(L))
schemmgr = mg->m_emerge->schemmgr;
else
schemmgr = getServer(L)->getEmergeManager()->schemmgr;
//// Read VoxelManip object
MMVManip *vm = checkObject<LuaVoxelManip>(L, 1)->vm;
@ -1677,7 +1777,7 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const SchematicManager *schemmgr = getServer(L)->getEmergeManager()->getSchematicManager();
const SchematicManager *schemmgr = getEmergeManager(L)->getSchematicManager();
//// Read options
bool use_comments = getboolfield_default(L, 3, "lua_use_comments", false);
@ -1727,8 +1827,7 @@ int ModApiMapgen::l_read_schematic(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const SchematicManager *schemmgr =
getServer(L)->getEmergeManager()->getSchematicManager();
const SchematicManager *schemmgr = getEmergeManager(L)->getSchematicManager();
const NodeDefManager *ndef = getGameDef(L)->ndef();
//// Read options
@ -1806,17 +1905,22 @@ int ModApiMapgen::l_read_schematic(lua_State *L)
int ModApiMapgen::update_liquids(lua_State *L, MMVManip *vm)
{
GET_ENV_PTR;
UniqueQueue<v3s16> *trans_liquid;
if (auto emerge = getEmergeThread(L)) {
trans_liquid = emerge->m_trans_liquid;
} else {
GET_ENV_PTR;
trans_liquid = &env->getServerMap().m_transforming_liquid;
}
assert(trans_liquid);
ServerMap *map = &(env->getServerMap());
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
const NodeDefManager *ndef = getGameDef(L)->ndef();
Mapgen mg;
mg.vm = vm;
mg.ndef = ndef;
mg.updateLiquid(&map->m_transforming_liquid,
vm->m_area.MinEdge, vm->m_area.MaxEdge);
mg.updateLiquid(trans_liquid, vm->m_area.MinEdge, vm->m_area.MaxEdge);
return 0;
}
@ -1824,7 +1928,7 @@ int ModApiMapgen::calc_lighting(lua_State *L, MMVManip *vm,
v3s16 pmin, v3s16 pmax, bool propagate_shadow)
{
const NodeDefManager *ndef = getGameDef(L)->ndef();
EmergeManager *emerge = getServer(L)->getEmergeManager();
auto emerge = getEmergeManager(L);
assert(vm->m_area.contains(VoxelArea(pmin, pmax)));
@ -1850,6 +1954,35 @@ int ModApiMapgen::set_lighting(lua_State *L, MMVManip *vm,
return 0;
}
const EmergeManager *ModApiMapgen::getEmergeManager(lua_State *L)
{
auto emerge = getEmergeThread(L);
if (emerge)
return emerge->getEmergeManager();
return getServer(L)->getEmergeManager();
}
const BiomeGen *ModApiMapgen::getBiomeGen(lua_State *L)
{
// path 1: we're in the emerge environment
auto emerge = getEmergeThread(L);
if (emerge)
return emerge->getMapgen()->m_emerge->biomegen;
// path 2: we're in the server environment
auto manager = getServer(L)->getEmergeManager();
return manager->getBiomeGen();
}
Mapgen *ModApiMapgen::getMapgen(lua_State *L)
{
// path 1
auto emerge = getEmergeThread(L);
if (emerge)
return emerge->getMapgen();
// path 2
return getServer(L)->getEmergeManager()->getCurrentMapgen();
}
void ModApiMapgen::Initialize(lua_State *L, int top)
{
API_FCT(get_biome_id);
@ -1891,3 +2024,28 @@ void ModApiMapgen::Initialize(lua_State *L, int top)
API_FCT(serialize_schematic);
API_FCT(read_schematic);
}
void ModApiMapgen::InitializeEmerge(lua_State *L, int top)
{
API_FCT(get_biome_id);
API_FCT(get_biome_name);
API_FCT(get_heat);
API_FCT(get_humidity);
API_FCT(get_biome_data);
API_FCT(get_mapgen_object);
API_FCT(get_seed);
API_FCT(get_mapgen_params);
API_FCT(get_mapgen_edges);
API_FCT(get_mapgen_setting);
API_FCT(get_mapgen_setting_noiseparams);
API_FCT(get_noiseparams);
API_FCT(get_decoration_id);
API_FCT(save_gen_notify);
API_FCT(generate_ores);
API_FCT(generate_decorations);
API_FCT(place_schematic_on_vmanip);
API_FCT(serialize_schematic);
API_FCT(read_schematic);
}

View file

@ -25,6 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include
class MMVManip;
class BiomeManager;
class BiomeGen;
class Mapgen;
class ModApiMapgen : public ModApiBase
{
@ -68,6 +71,9 @@ private:
// get_mapgen_edges([mapgen_limit[, chunksize]])
static int l_get_mapgen_edges(lua_State *L);
// get_seed([add])
static int l_get_seed(lua_State *L);
// get_mapgen_setting(name)
static int l_get_mapgen_setting(lua_State *L);
@ -86,12 +92,15 @@ private:
// get_noiseparam_defaults(name)
static int l_get_noiseparams(lua_State *L);
// set_gen_notify(flags, {deco_id_table})
// set_gen_notify(flags, {deco_ids}, {ud_ids})
static int l_set_gen_notify(lua_State *L);
// get_gen_notify()
static int l_get_gen_notify(lua_State *L);
// save_gen_notify(ud_id, data)
static int l_save_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);
@ -158,8 +167,18 @@ private:
static int set_lighting(lua_State *L, MMVManip *vm,
v3s16 pmin, v3s16 pmax, u8 light);
// Helpers
// get a read-only(!) EmergeManager
static const EmergeManager *getEmergeManager(lua_State *L);
// get the thread-local or global BiomeGen (still read-only)
static const BiomeGen *getBiomeGen(lua_State *L);
// get the thread-local mapgen
static Mapgen *getMapgen(lua_State *L);
public:
static void Initialize(lua_State *L, int top);
static void InitializeEmerge(lua_State *L, int top);
static struct EnumString es_BiomeTerrainType[];
static struct EnumString es_DecorationType[];

View file

@ -667,6 +667,25 @@ int ModApiServer::l_register_async_dofile(lua_State *L)
return 1;
}
// register_mapgen_script(path)
int ModApiServer::l_register_mapgen_script(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
std::string path = readParam<std::string>(L, 1);
CHECK_SECURE_PATH(L, path.c_str(), false);
// Find currently running mod name (only at init time)
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
if (!lua_isstring(L, -1))
return 0;
std::string modname = readParam<std::string>(L, -1);
getServer(L)->m_mapgen_init_files.emplace_back(modname, path);
lua_pushboolean(L, true);
return 1;
}
// serialize_roundtrip(value)
// Meant for unit testing the packer from Lua
int ModApiServer::l_serialize_roundtrip(lua_State *L)
@ -730,6 +749,8 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(do_async_callback);
API_FCT(register_async_dofile);
API_FCT(serialize_roundtrip);
API_FCT(register_mapgen_script);
}
void ModApiServer::InitializeAsync(lua_State *L, int top)

View file

@ -118,6 +118,9 @@ private:
// register_async_dofile(path)
static int l_register_async_dofile(lua_State *L);
// register_mapgen_script(path)
static int l_register_mapgen_script(lua_State *L);
// serialize_roundtrip(obj)
static int l_serialize_roundtrip(lua_State *L);

View file

@ -48,6 +48,9 @@ int LuaVoxelManip::l_read_from_map(lua_State *L)
if (vm->isOrphan())
return 0;
if (getEmergeThread(L))
throw LuaError("VoxelManip:read_from_map called in mapgen environment");
v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
sortBoxVerticies(bp1, bp2);
@ -110,14 +113,18 @@ int LuaVoxelManip::l_set_data(lua_State *L)
int LuaVoxelManip::l_write_to_map(lua_State *L)
{
GET_ENV_PTR;
LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
bool update_light = !lua_isboolean(L, 2) || readParam<bool>(L, 2);
if (o->vm->isOrphan())
return 0;
// This wouldn't work anyway as we have no env ptr, but it's still unsafe.
if (getEmergeThread(L))
throw LuaError("VoxelManip:write_to_map called in mapgen environment");
GET_ENV_PTR;
ServerMap *map = &(env->getServerMap());
std::map<v3s16, MapBlock*> modified_blocks;
@ -154,9 +161,8 @@ int LuaVoxelManip::l_set_node_at(lua_State *L)
v3s16 pos = check_v3s16(L, 2);
MapNode n = readnode(L, 3);
o->vm->setNodeNoEmerge(pos, n);
return 0;
lua_pushboolean(L, o->vm->setNodeNoEmerge(pos, n));
return 1;
}
int LuaVoxelManip::l_update_liquids(lua_State *L)
@ -193,8 +199,8 @@ int LuaVoxelManip::l_set_lighting(lua_State *L)
{
LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
if (!o->is_mapgen_vm) {
warningstream << "VoxelManip:set_lighting called for a non-mapgen "
"VoxelManip object" << std::endl;
log_deprecated(L, "set_lighting called for a non-mapgen "
"VoxelManip object");
return 0;
}