int ServerMap::getSurface(v3s16 basepos, int searchup, bool walkable_only) { s16 max = MYMIN(searchup + basepos.Y, 0x7FFF); MapNode last_node = getNodeNoEx(basepos); MapNode node = last_node; v3s16 runpos = basepos; INodeDefManager *nodemgr = m_gamedef->ndef(); bool last_was_walkable = nodemgr->get(node).walkable; while ((runpos.Y < max) && (node.param0 != CONTENT_AIR)) { runpos.Y += 1; last_node = node; node = getNodeNoEx(runpos); if (!walkable_only) { if ((last_node.param0 != CONTENT_AIR) && (last_node.param0 != CONTENT_IGNORE) && (node.param0 == CONTENT_AIR)) { return runpos.Y; } } else { bool is_walkable = nodemgr->get(node).walkable; if (last_was_walkable && (!is_walkable)) { return runpos.Y; } last_was_walkable = is_walkable; } } return basepos.Y - 1; }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); int cold = ((ItemGroupList) ndef->get(neighbor).groups)["cold"]; int freeze = ((ItemGroupList) ndef->get(n).groups)["freeze"]; if (cold < freeze) { n.freeze_melt(ndef, -1); map->setNode(p, n); } }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); int hot = ((ItemGroupList) ndef->get(neighbor).groups)["hot"]; int melt = ((ItemGroupList) ndef->get(n).groups)["melt"]; if (hot > melt) { n.freeze_melt(ndef, +1); map->setNode(p, n); env->nodeUpdate(p, 2); } }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); if(!ndef->get(n_top).light_propagates || ndef->get(n_top).isLiquid()) { n.setContent(ndef->getId("dirt")); map->addNodeWithEvent(p, n); } }
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { INodeDefManager *ndef = env->getGameDef()->ndef(); ServerMap *map = &env->getServerMap(); MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); if(ndef->get(n_top).light_propagates && !ndef->get(n_top).isLiquid() && n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13) { n.setContent(ndef->getId("dirt_with_grass")); map->addNodeWithEvent(p, n); } }
void GridNodeContainer::initNode(v3s16 ipos, PathGridnode *p_node) { INodeDefManager *ndef = m_pathf->m_env->getGameDef()->ndef(); PathGridnode &elem = *p_node; v3s16 realpos = m_pathf->getRealPos(ipos); MapNode current = m_pathf->m_env->getMap().getNodeNoEx(realpos); MapNode below = m_pathf->m_env->getMap().getNodeNoEx(realpos + v3s16(0, -1, 0)); if ((current.param0 == CONTENT_IGNORE) || (below.param0 == CONTENT_IGNORE)) { DEBUG_OUT("Pathfinder: " << PP(realpos) << " current or below is invalid element" << std::endl); if (current.param0 == CONTENT_IGNORE) { elem.type = 'i'; DEBUG_OUT(PP(ipos) << ": " << 'i' << std::endl); } return; } //don't add anything if it isn't an air node if (ndef->get(current).walkable || !ndef->get(below).walkable) { DEBUG_OUT("Pathfinder: " << PP(realpos) << " not on surface" << std::endl); if (ndef->get(current).walkable) { elem.type = 's'; DEBUG_OUT(PP(ipos) << ": " << 's' << std::endl); } else { elem.type = '-'; DEBUG_OUT(PP(ipos) << ": " << '-' << std::endl); } return; } elem.valid = true; elem.pos = realpos; elem.type = 'g'; DEBUG_OUT(PP(ipos) << ": " << 'a' << std::endl); if (m_pathf->m_prefetch) { elem.directions[DIR_XP] = m_pathf->calcCost(realpos, v3s16( 1, 0, 0)); elem.directions[DIR_XM] = m_pathf->calcCost(realpos, v3s16(-1, 0, 0)); elem.directions[DIR_ZP] = m_pathf->calcCost(realpos, v3s16( 0, 0, 1)); elem.directions[DIR_ZM] = m_pathf->calcCost(realpos, v3s16( 0, 0,-1)); } }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); float heat = map->updateBlockHeat(env, p); //heater = rare content_t c = map->getNodeTry(p - v3POS(0, -1, 0 )).getContent(); // top //more chance to freeze if air at top static int water_level = g_settings->getS16("water_level"); bool top_liquid = ndef->get(n).liquid_type > LIQUID_NONE && p.Y > water_level; int freeze = ((ItemGroupList) ndef->get(n).groups)["freeze"]; if (heat <= freeze - 1 && ((!top_liquid && (activate || (heat <= freeze - 50))) || heat <= freeze - 50 || (myrand_range(freeze - 50, heat) <= (freeze + (top_liquid ? -42 : c == CONTENT_AIR ? -10 : -40))))) { content_t c_self = n.getContent(); // making freeze not annoying, do not freeze random blocks in center of ocean // todo: any block not water (dont freeze _source near _flowing) bool allow = activate || heat < freeze - 40; // todo: make for(...) if (!allow) { c = map->getNodeTry(p - v3POS(0, 1, 0 )).getContent(); // below if (c == CONTENT_AIR || c == CONTENT_IGNORE) if (ndef->get(n.getContent()).liquid_type == LIQUID_FLOWING || ndef->get(n.getContent()).liquid_type == LIQUID_SOURCE) return; // do not freeze when falling if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(1, 0, 0 )).getContent(); // right if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(-1, 0, 0 )).getContent(); // left if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(0, 0, 1 )).getContent(); // back if (c != c_self && c != CONTENT_IGNORE) allow = 1; if (!allow) { c = map->getNodeTry(p - v3POS(0, 0, -1)).getContent(); // front if (c != c_self && c != CONTENT_IGNORE) allow = 1; } } } } } if (allow) { n.freeze_melt(ndef, -1); map->setNode(p, n); } } }
void ClientMap::renderPostFx() { INodeDefManager *nodemgr = m_gamedef->ndef(); // Sadly ISceneManager has no "post effects" render pass, in that case we // could just register for that and handle it in renderMap(). m_camera_mutex.Lock(); v3f camera_position = m_camera_position; m_camera_mutex.Unlock(); MapNode n = getNodeNoEx(floatToInt(camera_position, BS)); // - If the player is in a solid node, make everything black. // - If the player is in liquid, draw a semi-transparent overlay. const ContentFeatures& features = nodemgr->get(n); video::SColor post_effect_color = features.post_effect_color; if(features.solidness == 2 && !(g_settings->getBool("noclip") && m_gamedef->checkLocalPrivilege("noclip"))) { post_effect_color = video::SColor(255, 0, 0, 0); } if (post_effect_color.getAlpha() != 0) { // Draw a full-screen rectangle video::IVideoDriver* driver = SceneManager->getVideoDriver(); v2u32 ss = driver->getScreenSize(); core::rect<s32> rect(0,0, ss.X, ss.Y); driver->draw2DRectangle(post_effect_color, rect); } }
// Return number of accepted items to be put int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return 0; // Push callback function on stack std::string nodename = ndef->get(node).name; if (!getItemCallback(nodename.c_str(), "allow_metadata_inventory_put", &p)) return stack.count; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 5, 1, error_handler)); if(!lua_isnumber(L, -1)) throw LuaError("allow_metadata_inventory_put should" " return a number, guilty node: " + nodename); int num = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return num; }
// Report moved items void ScriptApiNodemeta::nodemeta_inventory_OnMove(v3s16 p, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_metadata_inventory_move")) return; // function(pos, from_list, from_index, to_list, to_index, count, player) push_v3s16(L, p); // pos lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(player); // player if(lua_pcall(L, 7, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }
// Report taken items void ScriptApiNodemeta::nodemeta_inventory_OnTake(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_metadata_inventory_take")) return; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(player); // player if(lua_pcall(L, 5, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }
// place_node(pos, node) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_place_node(lua_State *L) { GET_ENV_PTR; ScriptApiItem *scriptIfaceItem = getScriptApi<ScriptApiItem>(L); Server *server = getServer(L); INodeDefManager *ndef = server->ndef(); IItemDefManager *idef = server->idef(); v3s16 pos = read_v3s16(L, 1); MapNode n = readnode(L, 2, ndef); // Don't attempt to load non-loaded area as of now MapNode n_old = env->getMap().getNodeNoEx(pos); if(n_old.getContent() == CONTENT_IGNORE){ lua_pushboolean(L, false); return 1; } // Create item to place ItemStack item(ndef->get(n).name, 1, 0, "", idef); // Make pointed position PointedThing pointed; pointed.type = POINTEDTHING_NODE; pointed.node_abovesurface = pos; pointed.node_undersurface = pos + v3s16(0,-1,0); // Place it with a NULL placer (appears in Lua as a non-functional // ObjectRef) bool success = scriptIfaceItem->item_OnPlace(item, NULL, pointed); lua_pushboolean(L, success); return 1; }
void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef) { ITextureSource *tsrc = gamedef->getTextureSource(); IItemDefManager *idef = gamedef->getItemDefManager(); const ItemDefinition &def = item.getDefinition(idef); // If wield_image is defined, it overrides everything else if (def.wield_image != "") { setExtruded(def.wield_image, def.wield_scale, tsrc); return; } // Handle nodes // See also CItemDefManager::createClientCached() if (def.type == ITEM_NODE) { INodeDefManager *ndef = gamedef->getNodeDefManager(); const ContentFeatures &f = ndef->get(def.name); if (f.mesh_ptr[0]) { // e.g. mesh nodes and nodeboxes changeToMesh(f.mesh_ptr[0]); // mesh_ptr[0] is pre-scaled by BS * f->visual_scale m_meshnode->setScale( def.wield_scale * WIELD_SCALE_FACTOR / (BS * f.visual_scale)); // Customize materials for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) { assert(i < 6); video::SMaterial &material = m_meshnode->getMaterial(i); material.setTexture(0, f.tiles[i].texture); f.tiles[i].applyMaterialOptions(material); } return; } else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) { setCube(f.tiles, def.wield_scale, tsrc); return; } else if (f.drawtype == NDT_AIRLIKE) { changeToMesh(NULL); return; } // If none of the above standard cases worked, use the wield mesh from ClientCached scene::IMesh *mesh = idef->getWieldMesh(item.name, gamedef); if (mesh) { changeToMesh(mesh); m_meshnode->setScale(def.wield_scale * WIELD_SCALE_FACTOR); return; } } // default to inventory_image if (def.inventory_image != "") { setExtruded(def.inventory_image, def.wield_scale, tsrc); return; } // no wield mesh found changeToMesh(NULL); }
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) { GET_ENV_PTR; INodeDefManager *ndef = getServer(L)->ndef(); v3s16 minp = read_v3s16(L, 1); v3s16 maxp = read_v3s16(L, 2); sortBoxVerticies(minp, maxp); v3s16 cube = maxp - minp + 1; /* Limit for too large areas, assume default values * and give tolerances of 1 node on each side * (chunksize * MAP_BLOCKSIZE + 2)^3 = 551368 */ if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 551368) { luaL_error(L, "find_nodes_in_area(): area volume" " exceeds allowed value of 551368"); return 0; } std::set<content_t> filter; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, 3) != 0) { // key at index -2 and value at index -1 luaL_checktype(L, -1, LUA_TSTRING); ndef->getIds(lua_tostring(L, -1), filter); // removes value, keeps key for next iteration lua_pop(L, 1); } } else if (lua_isstring(L, 3)) { ndef->getIds(lua_tostring(L, 3), filter); } std::unordered_map<content_t, u32> individual_count; lua_newtable(L); u64 i = 0; for (s16 x = minp.X; x <= maxp.X; x++) for (s16 y = minp.Y; y <= maxp.Y; y++) for (s16 z = minp.Z; z <= maxp.Z; z++) { v3s16 p(x, y, z); content_t c = env->getMap().getNodeNoEx(p).getContent(); if (filter.count(c) != 0) { push_v3s16(L, p); lua_rawseti(L, -2, ++i); individual_count[c]++; } } lua_newtable(L); for (std::set<content_t>::const_iterator it = filter.begin(); it != filter.end(); ++it) { lua_pushnumber(L, individual_count[*it]); lua_setfield(L, -2, ndef->get(*it).name.c_str()); } return 2; }
/* Gets nth node tile (0 <= n <= 5). */ TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data) { INodeDefManager *ndef = data->m_gamedef->ndef(); TileSpec spec = ndef->get(mn).tiles[tileindex]; // Apply temporary crack if (p == data->m_crack_pos_relative) spec.material_flags |= MATERIAL_FLAG_CRACK; return spec; }
/* Calculate smooth lighting at the XYZ- corner of p. Single light bank. */ static u8 getSmoothLight(enum LightBank bank, v3s16 p, MeshMakeData *data) { static v3s16 dirs8[8] = { v3s16(0,0,0), v3s16(0,0,1), v3s16(0,1,0), v3s16(0,1,1), v3s16(1,0,0), v3s16(1,1,0), v3s16(1,0,1), v3s16(1,1,1), }; INodeDefManager *ndef = data->m_gamedef->ndef(); u16 ambient_occlusion = 0; u16 light = 0; u16 light_count = 0; u8 light_source_max = 0; for(u32 i=0; i<8; i++) { MapNode n = data->m_vmanip.getNodeNoEx(p - dirs8[i]); const ContentFeatures &f = ndef->get(n); if(f.light_source > light_source_max) light_source_max = f.light_source; // Check f.solidness because fast-style leaves look // better this way if(f.param_type == CPT_LIGHT && f.solidness != 2) { light += decode_light(n.getLight(bank, ndef)); light_count++; } else if(n.getContent() != CONTENT_IGNORE) { ambient_occlusion++; } } if(light_count == 0) return 255; light /= light_count; // Boost brightness around light sources if(decode_light(light_source_max) >= light) //return decode_light(undiminish_light(light_source_max)); return decode_light(light_source_max); if(ambient_occlusion > 4) { ambient_occlusion -= 4; light = (float)light / ((float)ambient_occlusion * 0.5 + 1.0); } return light; }
virtual void trigger(ServerEnvironment *env, v3POS p, MapNode n, u32 active_object_count, u32 active_object_count_wider, MapNode neighbor, bool activate) { ServerMap *map = &env->getServerMap(); INodeDefManager *ndef = env->getGameDef()->ndef(); float heat = map->updateBlockHeat(env, p); content_t c = map->getNodeTry(p - v3POS(0, -1, 0 )).getContent(); // top int melt = ((ItemGroupList) ndef->get(n).groups)["melt"]; if (heat >= melt + 1 && (activate || heat >= melt + 40 || ((myrand_range(heat, melt + 40)) >= (c == CONTENT_AIR ? melt + 10 : melt + 20)))) { if (ndef->get(n.getContent()).liquid_type == LIQUID_FLOWING || ndef->get(n.getContent()).liquid_type == LIQUID_SOURCE) { c = map->getNodeTry(p - v3POS(0, 1, 0 )).getContent(); // below if (c == CONTENT_AIR || c == CONTENT_IGNORE) return; // do not melt when falling (dirt->dirt_with_grass on air) } n.freeze_melt(ndef, +1); map->setNode(p, n); env->nodeUpdate(p, 2); //enable after making FAST nodeupdate } }
// 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); INodeDefManager *ndef = getServer(L)->getNodeDefManager(); const char *name = ndef->get(c).name.c_str(); lua_pushstring(L, name); return 1; /* number of results */ }
/* Calculate non-smooth lighting at face of node. Single light bank. */ static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2, v3s16 face_dir, MeshMakeData *data) { INodeDefManager *ndef = data->m_gamedef->ndef(); u8 light; u8 l1 = n.getLight(bank, ndef); u8 l2 = n2.getLight(bank, ndef); if(l1 > l2) light = l1; else light = l2; // Boost light level for light sources u8 light_source = MYMAX(ndef->get(n).light_source, ndef->get(n2).light_source); //if(light_source >= light) //return decode_light(undiminish_light(light_source)); if(light_source > light) //return decode_light(light_source); light = light_source; // Make some nice difference to different sides // This makes light come from a corner /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1) light = diminish_light(diminish_light(light)); else if(face_dir.X == -1 || face_dir.Z == -1) light = diminish_light(light);*/ // All neighboring faces have different shade (like in minecraft) if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1) light = diminish_light(diminish_light(light)); else if(face_dir.Z == 1 || face_dir.Z == -1) light = diminish_light(light); return decode_light(light); }
RollbackNode::RollbackNode(Map *map, v3s16 p, IGameDef *gamedef) { INodeDefManager *ndef = gamedef->ndef(); MapNode n = map->getNodeNoEx(p); name = ndef->get(n).name; param1 = n.param1; param2 = n.param2; NodeMetadata *metap = map->getNodeMetadata(p); if (metap) { std::ostringstream os(std::ios::binary); metap->serialize(os); meta = os.str(); } }
MapgenSinglenode::MapgenSinglenode(int mapgenid, MapgenParams *params, EmergeManager *emerge) : Mapgen(mapgenid, params, emerge) { flags = params->flags; INodeDefManager *ndef = emerge->ndef; c_node = ndef->getId("mapgen_singlenode"); if (c_node == CONTENT_IGNORE) c_node = CONTENT_AIR; MapNode n_node(c_node); set_light = (ndef->get(n_node).sunlight_propagates) ? LIGHT_SUN : 0x00; }
/* Gets nth node tile (0 <= n <= 5). */ TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data) { INodeDefManager *ndef = data->m_gamedef->ndef(); TileSpec spec = ndef->get(mn).tiles[tileindex]; // Apply temporary crack if(p == data->m_crack_pos_relative) { spec.material_flags |= MATERIAL_FLAG_CRACK; spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture); } // If animated, replace tile texture with one without texture atlas if(spec.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture); } return spec; }
void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node) { realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); INodeDefManager *ndef = get_server(L)->ndef(); // Push callback function on stack if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_destruct")) return; // Call function push_v3s16(L, p); if(lua_pcall(L, 1, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); }
void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_destruct")) return; // Call function push_v3s16(L, p); PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) { GET_ENV_PTR; INodeDefManager *ndef = getServer(L)->ndef(); v3s16 minp = read_v3s16(L, 1); v3s16 maxp = read_v3s16(L, 2); std::set<content_t> filter; if(lua_istable(L, 3)) { int table = 3; lua_pushnil(L); while(lua_next(L, table) != 0) { // key at index -2 and value at index -1 luaL_checktype(L, -1, LUA_TSTRING); ndef->getIds(lua_tostring(L, -1), filter); // removes value, keeps key for next iteration lua_pop(L, 1); } } else if(lua_isstring(L, 3)) { ndef->getIds(lua_tostring(L, 3), filter); } std::map<content_t, u16> individual_count; lua_newtable(L); u64 i = 0; for (s16 x = minp.X; x <= maxp.X; x++) for (s16 y = minp.Y; y <= maxp.Y; y++) for (s16 z = minp.Z; z <= maxp.Z; z++) { v3s16 p(x, y, z); content_t c = env->getMap().getNodeNoEx(p).getContent(); if (filter.count(c) != 0) { push_v3s16(L, p); lua_rawseti(L, -2, ++i); individual_count[c]++; } } lua_newtable(L); for (std::set<content_t>::iterator it = filter.begin(); it != filter.end(); ++it) { lua_pushnumber(L, individual_count[*it]); lua_setfield(L, -2, ndef->get(*it).name.c_str()); } return 2; }
void ScriptApiNode::node_on_deactivate(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_deactivate")) return; // Call function push_v3s16(L, p); PCALL_RES(lua_pcall(L, 1, 0, errorhandler)); lua_pop(L, 1); // Pop error handler }
bool ScriptApiNode::node_on_timer(v3s16 p, MapNode node, f32 dtime) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_timer")) return false; // Call function push_v3s16(L, p); lua_pushnumber(L,dtime); PCALL_RES(lua_pcall(L, 2, 1, error_handler)); lua_remove(L, error_handler); return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true; }
bool RollbackAction::isImportant(IGameDef *gamedef) const { if (type != TYPE_SET_NODE) return true; // If names differ, action is always important if(n_old.name != n_new.name) return true; // If metadata differs, action is always important if(n_old.meta != n_new.meta) return true; INodeDefManager *ndef = gamedef->ndef(); // Both are of the same name, so a single definition is needed const ContentFeatures &def = ndef->get(n_old.name); // If the type is flowing liquid, action is not important if (def.liquid_type == LIQUID_FLOWING) return false; // Otherwise action is important return true; }
// get_node_def(nodename) int ModApiClient::l_get_node_def(lua_State *L) { IGameDef *gdef = getGameDef(L); assert(gdef); INodeDefManager *ndef = gdef->ndef(); assert(ndef); if (!lua_isstring(L, 1)) return 0; const std::string &name = lua_tostring(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; }
void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "after_destruct")) return; // Call function push_v3s16(L, p); pushnode(L, node, ndef); if(lua_pcall(L, 2, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }