/** ** Get province data. ** ** @param l Lua state. */ static int CclGetProvinceData(lua_State *l) { if (lua_gettop(l) < 2) { LuaError(l, "incorrect argument"); } std::string province_name = LuaToString(l, 1); CProvince *province = GetProvince(province_name); if (!province) { LuaError(l, "Province \"%s\" doesn't exist." _C_ province_name.c_str()); } const char *data = LuaToString(l, 2); if (!strcmp(data, "Name")) { lua_pushstring(l, province->Name.c_str()); return 1; } else if (!strcmp(data, "World")) { if (province->World != NULL) { lua_pushstring(l, province->World->Name.c_str()); } else { lua_pushstring(l, ""); } return 1; } else if (!strcmp(data, "Water")) { lua_pushboolean(l, province->Water); return 1; } else if (!strcmp(data, "Coastal")) { lua_pushboolean(l, province->Coastal); return 1; } else if (!strcmp(data, "Map")) { lua_pushstring(l, province->Map.c_str()); return 1; } else if (!strcmp(data, "SettlementTerrain")) { lua_pushstring(l, province->SettlementTerrain.c_str()); return 1; } else if (!strcmp(data, "SettlementLocationX")) { lua_pushnumber(l, province->SettlementLocation.x); return 1; } else if (!strcmp(data, "SettlementLocationY")) { lua_pushnumber(l, province->SettlementLocation.y); return 1; } else if (!strcmp(data, "Tiles")) { lua_createtable(l, province->Tiles.size() * 2, 0); for (size_t i = 1; i <= province->Tiles.size() * 2; ++i) { lua_pushnumber(l, province->Tiles[(i-1) / 2].x); lua_rawseti(l, -2, i); ++i; lua_pushnumber(l, province->Tiles[(i-1) / 2].y); lua_rawseti(l, -2, i); } return 1; } else { LuaError(l, "Invalid field: %s" _C_ data); } return 0; }
// 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 = getServer(L)->getWritableItemDefManager(); IWritableNodeDefManager *ndef = getServer(L)->getWritableNodeDefManager(); // Check if name is defined std::string name; lua_getfield(L, table, "name"); if(lua_isstring(L, -1)){ name = lua_tostring(L, -1); verbosestream<<"register_item_raw: "<<name<<std::endl; } 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 def = read_item_definition(L, table, 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){ const ContentFeatures &f = read_content_features(L, table); 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 */ }
/** ** Parse the Condition for spell. ** ** @param l Lua state. ** @param autocast pointer to autocast to fill with data. ** ** @note: autocast must be allocated. All data already in is LOST. */ static void CclSpellAutocast(lua_State *l, AutoCastInfo *autocast) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int args = lua_rawlen(l, -1); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, -1, j + 1); ++j; if (!strcmp(value, "range")) { autocast->Range = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "min-range")) { autocast->MinRange = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "position-autocast")) { lua_rawgeti(l, -1, j + 1); autocast->PositionAutoCast = new LuaCallback(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "combat")) { autocast->Combat = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "attacker")) { autocast->Attacker = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "corpse")) { autocast->Corpse = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "priority")) { lua_rawgeti(l, -1, j + 1); if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 2) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, -1, 1); std::string var = LuaToString(l, -1); int index = UnitTypeVar.VariableNameLookup[var.c_str()];// User variables if (index == -1) { if (!strcmp(var.c_str(), "Distance")) { index = ACP_DISTANCE; } else { fprintf(stderr, "Bad variable name '%s'\n", var.c_str()); Exit(1); } } autocast->PriorytyVar = index; lua_pop(l, 1); autocast->ReverseSort = LuaToBoolean(l, -1, 2); lua_pop(l, 1); } else if (!strcmp(value, "condition")) { if (!autocast->Condition) { autocast->Condition = new ConditionInfo; } lua_rawgeti(l, -1, j + 1); CclSpellCondition(l, autocast->Condition); lua_pop(l, 1); } else { LuaError(l, "Unsupported autocast tag: %s" _C_ value); } } }
/** ** Get world data. ** ** @param l Lua state. */ static int CclGetWorldData(lua_State *l) { if (lua_gettop(l) < 2) { LuaError(l, "incorrect argument"); } std::string world_ident = LuaToString(l, 1); CWorld *world = CWorld::GetWorld(world_ident); if (!world) { LuaError(l, "World \"%s\" doesn't exist." _C_ world_ident.c_str()); } const char *data = LuaToString(l, 2); if (!strcmp(data, "Name")) { lua_pushstring(l, world->Name.c_str()); return 1; } else if (!strcmp(data, "ID")) { lua_pushnumber(l, world->ID); return 1; } else if (!strcmp(data, "Description")) { lua_pushstring(l, world->Description.c_str()); return 1; } else if (!strcmp(data, "Background")) { lua_pushstring(l, world->Background.c_str()); return 1; } else if (!strcmp(data, "Quote")) { lua_pushstring(l, world->Quote.c_str()); return 1; } else if (!strcmp(data, "Plane")) { if (world->Plane) { lua_pushstring(l, world->Plane->Ident.c_str()); } else { lua_pushstring(l, ""); } return 1; } else if (!strcmp(data, "Provinces")) { lua_createtable(l, world->Provinces.size(), 0); for (size_t i = 1; i <= world->Provinces.size(); ++i) { lua_pushstring(l, world->Provinces[i-1]->Name.c_str()); lua_rawseti(l, -2, i); } return 1; } else if (!strcmp(data, "Species")) { lua_createtable(l, world->Species.size(), 0); for (size_t i = 1; i <= world->Species.size(); ++i) { lua_pushstring(l, world->Species[i-1]->Ident.c_str()); lua_rawseti(l, -2, i); } return 1; } else { LuaError(l, "Invalid field: %s" _C_ data); } return 0; }
/** ** Define a force, a groups of units. ** ** @param l Lua state. */ static int CclAiForce(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument"); } int force = LuaToNumber(l, 1); if (force < 0 || force >= AI_MAX_FORCES) { LuaError(l, "Force out of range: %d" _C_ force); } AiForce &aiforce = AiPlayer->Force[AiPlayer->Force.getScriptForce(force)]; int args = lua_rawlen(l, 2); for (int j = 0; j < args; ++j) { lua_rawgeti(l, 2, j + 1); CUnitType *type = CclGetUnitType(l); lua_pop(l, 1); ++j; lua_rawgeti(l, 2, j + 1); int count = LuaToNumber(l, -1); lua_pop(l, 1); if (!type) { // bulletproof continue; } // Use the equivalent unittype. type = UnitTypes[UnitTypeEquivs[type->Slot]]; // Look if already in force. size_t i; for (i = 0; i < aiforce.UnitTypes.size(); ++i) { AiUnitType *aiut = &aiforce.UnitTypes[i]; if (aiut->Type->Slot == type->Slot) { // found if (count) { aiut->Want = count; } else { aiforce.UnitTypes.erase(aiforce.UnitTypes.begin() + i); } break; } } // New type append it. if (i == aiforce.UnitTypes.size()) { AiUnitType newaiut; newaiut.Want = count; newaiut.Type = type; aiforce.UnitTypes.push_back(newaiut); } } AiAssignFreeUnitsToForce(); lua_pushboolean(l, 0); return 1; }
/** ** Create a missile on the map ** ** @param l Lua state. ** */ static int CclCreateMissile(lua_State *l) { LuaCheckArgs(l, 6); const std::string name = LuaToString(l, 1); const MissileType *mtype = MissileTypeByIdent(name); if (!mtype) { LuaError(l, "Bad missile"); } PixelPos startpos, endpos; if (!lua_istable(l, 2) || lua_rawlen(l, 2) != 2) { LuaError(l, "incorrect argument !!"); } lua_rawgeti(l, 2, 1); startpos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 2, 2); startpos.y = LuaToNumber(l, -1); lua_pop(l, 1); if (!lua_istable(l, 3) || lua_rawlen(l, 3) != 2) { LuaError(l, "incorrect argument !!"); } lua_rawgeti(l, 3, 1); endpos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 3, 2); endpos.y = LuaToNumber(l, -1); lua_pop(l, 1); const int sourceUnitId = LuaToNumber(l, 4); const int destUnitId = LuaToNumber(l, 5); const bool dealDamage = LuaToBoolean(l, 6); CUnit *sourceUnit = sourceUnitId != -1 ? &UnitManager.GetSlotUnit(sourceUnitId) : NULL; CUnit *destUnit = destUnitId != -1 ? &UnitManager.GetSlotUnit(destUnitId) : NULL; if (sourceUnit != NULL) { startpos += sourceUnit->GetMapPixelPosTopLeft(); } if (destUnit != NULL) { endpos += destUnit->GetMapPixelPosTopLeft(); } Missile *missile = MakeMissile(*mtype, startpos, endpos); if (!missile) { return 0; } if (dealDamage) { missile->SourceUnit = sourceUnit; } missile->TargetUnit = destUnit; return 0; }
void CMapField::parse(lua_State *l) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int len = lua_rawlen(l, -1); if (len < 4) { LuaError(l, "incorrect argument"); } this->tile = LuaToNumber(l, -1, 1); this->playerInfo.SeenTile = LuaToNumber(l, -1, 2); this->Value = LuaToNumber(l, -1, 3); this->cost = LuaToNumber(l, -1, 4); for (int j = 4; j < len; ++j) { const char *value = LuaToString(l, -1, j + 1); if (!strcmp(value, "explored")) { ++j; this->playerInfo.Visible[LuaToNumber(l, -1, j + 1)] = 1; } else if (!strcmp(value, "human")) { this->Flags |= MapFieldHuman; } else if (!strcmp(value, "land")) { this->Flags |= MapFieldLandAllowed; } else if (!strcmp(value, "coast")) { this->Flags |= MapFieldCoastAllowed; } else if (!strcmp(value, "water")) { this->Flags |= MapFieldWaterAllowed; } else if (!strcmp(value, "mud")) { this->Flags |= MapFieldNoBuilding; } else if (!strcmp(value, "block")) { this->Flags |= MapFieldUnpassable; } else if (!strcmp(value, "wall")) { this->Flags |= MapFieldWall; } else if (!strcmp(value, "rock")) { this->Flags |= MapFieldRocks; } else if (!strcmp(value, "wood")) { this->Flags |= MapFieldForest; } else if (!strcmp(value, "ground")) { this->Flags |= MapFieldLandUnit; } else if (!strcmp(value, "air")) { this->Flags |= MapFieldAirUnit; } else if (!strcmp(value, "sea")) { this->Flags |= MapFieldSeaUnit; } else if (!strcmp(value, "building")) { this->Flags |= MapFieldBuilding; } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } }
void LuaWear_Event(const LLUUID& assetid) { LLWearable *wear=LuaLoadWearable(assetid); if(!wear) LuaError("No Wearable found"); else if((wear=gWearableList.createCopy(wear))==NULL) LuaError("Failed creation of new wearable"); else { wear->saveNewAsset(); wear->writeToAvatar(false); } }
/** ** Parse the missile location description for a spell action. ** ** @param l Lua state. ** @param location Pointer to missile location description. ** ** @note This is only here to avoid code duplication. You don't have ** any reason to USE this:) */ static void CclSpellMissileLocation(lua_State *l, SpellActionMissileLocation *location) { const char *value; int args; int j; Assert(location != NULL); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } args = lua_objlen(l, -1); j = 0; for (j = 0; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "base")) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); if (!strcmp(value, "caster")) { location->Base = LocBaseCaster; } else if (!strcmp(value, "target")) { location->Base = LocBaseTarget; } else { LuaError(l, "Unsupported missile location base flag: %s" _C_ value); } } else if (!strcmp(value, "add-x")) { lua_rawgeti(l, -1, j + 1); location->AddX = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "add-y")) { lua_rawgeti(l, -1, j + 1); location->AddY = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "add-rand-x")) { lua_rawgeti(l, -1, j + 1); location->AddRandX = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "add-rand-y")) { lua_rawgeti(l, -1, j + 1); location->AddRandY = LuaToNumber(l, -1); lua_pop(l, 1); } else { LuaError(l, "Unsupported missile location description flag: %s" _C_ value); } } }
/** ** Define race names ** ** @param l Lua state. */ static int CclDefineRaceNames(lua_State *l) { int i; int j; int k; int args; int subargs; const char *value; PlayerRaces.Count = 0; args = lua_gettop(l); for (j = 0; j < args; ++j) { value = LuaToString(l, j + 1); if (!strcmp(value, "race")) { ++j; if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } subargs = luaL_getn(l, j + 1); i = PlayerRaces.Count++; PlayerRaces.Name[i] = NULL; PlayerRaces.Display[i] = NULL; PlayerRaces.Visible[i] = 0; for (k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); value = LuaToString(l, -1); lua_pop(l, 1); if (!strcmp(value, "name")) { ++k; lua_rawgeti(l, j + 1, k + 1); PlayerRaces.Name[i] = new_strdup(LuaToString(l, -1)); lua_pop(l, 1); } else if (!strcmp(value, "display")) { ++k; lua_rawgeti(l, j + 1, k + 1); PlayerRaces.Display[i] = new_strdup(LuaToString(l, -1)); lua_pop(l, 1); } else if (!strcmp(value, "visible")) { PlayerRaces.Visible[i] = 1; } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
// Return number of accepted items to be taken int ScriptApiDetached::detached_inventory_AllowTake( const std::string &name, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "allow_take")) return stack.count; // All will be accepted // Call function(inv, listname, index, stack, player) InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); // inv 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_take should return a number. name=" + name); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; }
/** ** Create a sound. ** ** Glue between c and scheme. This function asks the sound system to ** register a sound under a given name, wiht an associated list of files ** (the list can be replaced by only one file). ** ** @param l Lua state. ** ** @return the sound id of the created sound */ static int CclMakeSound(lua_State *l) { LuaCheckArgs(l, 2); std::string c_name = LuaToString(l, 1); std::vector<std::string> files; CSound *id; if (lua_isstring(l, 2)) { // only one file files.push_back(LuaToString(l, 2)); id = MakeSound(c_name, files); } else if (lua_istable(l, 2)) { // several files const int args = lua_rawlen(l, 2); files.reserve(args); for (int j = 0; j < args; ++j) { lua_rawgeti(l, 2, j + 1); files.push_back(LuaToString(l, -1)); lua_pop(l, 1); } id = MakeSound(c_name, files); } else { LuaError(l, "string or table expected"); return 0; } LuaUserData *data = (LuaUserData *)lua_newuserdata(l, sizeof(LuaUserData)); data->Type = LuaSoundType; data->Data = id; return 1; }
/** ** Get a player's units in rectangle box specified with 2 coordinates ** ** @param l Lua state. ** ** @return Array of units. */ static int CclGetUnitsAroundUnit(lua_State *l) { const int nargs = lua_gettop(l); if (nargs != 2 && nargs != 3) { LuaError(l, "incorrect argument\n"); } const int slot = LuaToNumber(l, 1); const CUnit &unit = UnitManager.GetSlotUnit(slot); const int range = LuaToNumber(l, 2); bool allUnits = false; if (nargs == 3) { allUnits = LuaToBoolean(l, 3); } lua_newtable(l); std::vector<CUnit *> table; if (allUnits) { SelectAroundUnit(unit, range, table, HasNotSamePlayerAs(Players[PlayerNumNeutral])); } else { SelectAroundUnit(unit, range, table, HasSamePlayerAs(*unit.Player)); } size_t n = 0; for (size_t i = 0; i < table.size(); ++i) { if (table[i]->IsAliveOnMap()) { lua_pushnumber(l, UnitNumber(*table[i])); lua_rawseti(l, -2, ++n); } } return 1; }
// 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 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")) 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 if (lua_pcall(L, 5, 1, m_errorhandler)) scriptError(); 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, 1); // Pop integer return num; }
/** ** Parse an animation */ static CAnimation *ParseAnimation(lua_State *l, int idx) { if (!lua_istable(l, idx)) { LuaError(l, "incorrect argument"); } const int args = lua_rawlen(l, idx); if (args == 0) { return NULL; } Labels.clear(); LabelsLater.clear(); const char *str = LuaToString(l, idx, 1); CAnimation *firstAnim = ParseAnimationFrame(l, str); CAnimation *prev = firstAnim; for (int j = 1; j < args; ++j) { const char *str = LuaToString(l, idx, j + 1); CAnimation *anim = ParseAnimationFrame(l, str); prev->Next = anim; prev = anim; } prev->Next = firstAnim; FixLabels(l); return firstAnim; }
int LuaVoxelManip::l_set_lighting(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaVoxelManip *o = checkobject(L, 1); if (!o->is_mapgen_vm) return 0; if (!lua_istable(L, 2)) return 0; 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_calc_lighting(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaVoxelManip *o = checkobject(L, 1); if (!o->is_mapgen_vm) return 0; INodeDefManager *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) || lua_toboolean(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; }
/** ** Define burning building missiles. ** ** @param l Lua state. */ static int CclDefineBurningBuilding(lua_State *l) { for (std::vector<BurningBuildingFrame *>::iterator i = BurningBuildingFrames.begin(); i != BurningBuildingFrames.end(); ++i) { delete *i; } BurningBuildingFrames.clear(); const int args = lua_gettop(l); for (int j = 0; j < args; ++j) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } BurningBuildingFrame *ptr = new BurningBuildingFrame; const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { const char *value = LuaToString(l, j + 1, k + 1); ++k; if (!strcmp(value, "percent")) { ptr->Percent = LuaToNumber(l, j + 1, k + 1); } else if (!strcmp(value, "missile")) { ptr->Missile = MissileTypeByIdent(LuaToString(l, j + 1, k + 1)); } } BurningBuildingFrames.insert(BurningBuildingFrames.begin(), ptr); } return 0; }
// Return number of accepted items to be moved int ScriptApiDetached::detached_inventory_AllowMove( const std::string &name, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "allow_move")) return count; // function(inv, from_list, from_index, to_list, to_index, count, player) // inv InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); 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(L, player); // player PCALL_RES(lua_pcall(L, 7, 1, error_handler)); if(!lua_isnumber(L, -1)) throw LuaError("allow_move should return a number. name=" + name); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; }
//------------------------------------------------------------------------------ // Function: LuaReadBytes // // Description: // // Read 'count' bytes from 'addr' // // Returns: // // Pushes result on stack and returns number of results. // // Notes: // // Lua strings, like Ruby, can carry arbitrary payloads. // int LuaReadBytes( _In_ lua_State* L, _In_ UINT64 addr, _In_ ULONG count) { char* buf = new char[count]; if (!buf) { return luaL_error(L, "Couldn't allocate buffer."); } ULONG cbActual = 0; HRESULT hr = UtilReadBytes( GetLuaProvGlobals()->HostCtxt, addr, buf, count, &cbActual); if (FAILED(hr)) { delete [] buf; // Don't leak. return LuaError(L, "UtilReadBytes failed. Error 0x%08x.", hr); } // Push result on the stack. // lua_pushlstring(L, buf, cbActual); // Lua makes an internal copy of the input buffer. // delete [] buf; return 1; }
/** ** Parse the slot part of a tileset definition ** ** @param l Lua state. ** @param t FIXME: docu */ void CTileset::parseSlots(lua_State *l, int t) { tiles.clear(); // Parse the list: (still everything could be changed!) const int args = lua_rawlen(l, t); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, t, j + 1); ++j; if (!strcmp(value, "special")) { lua_rawgeti(l, t, j + 1); parseSpecial(l); lua_pop(l, 1); } else if (!strcmp(value, "solid")) { lua_rawgeti(l, t, j + 1); parseSolid(l); lua_pop(l, 1); } else if (!strcmp(value, "mixed")) { lua_rawgeti(l, t, j + 1); parseMixed(l); lua_pop(l, 1); } else { LuaError(l, "slots: unsupported tag: %s" _C_ value); } } }
bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user, const InventoryList *old_craft_grid, const InventoryLocation &craft_inv) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); lua_getglobal(L, "core"); lua_getfield(L, -1, "craft_predict"); LuaItemStack::create(L, item); objectrefGetOrCreate(L, user); //Push inventory list std::vector<ItemStack> items; for (u32 i = 0; i < old_craft_grid->getSize(); i++) { items.push_back(old_craft_grid->getItem(i)); } push_items(L, items); InvRef::create(L, craft_inv); PCALL_RES(lua_pcall(L, 4, 1, error_handler)); if (!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
//------------------------------------------------------------------------------ // Function: LuaReadWideString // // Description: // // Read a wide string from the target process as a Lua string up to 'count' // chars. // // Returns: // // Pushes new string on stack and returns 1 result. // // Notes: // int LuaReadWideString( _In_ lua_State* L, _In_ UINT64 addr, _In_ int count) { WCHAR buf[MAX_READ_STRING_LEN] = {}; char utf8buf[MAX_READ_STRING_LEN * sizeof(WCHAR)] = {}; if (!count || count > MAX_READ_STRING_LEN - 1) { return luaL_error(L, "count supports at most %d and can't be 0", MAX_READ_STRING_LEN - 1); } HRESULT hr = UtilReadWideString( GetLuaProvGlobals()->HostCtxt, addr, STRING_AND_CCH(buf), count); if (FAILED(hr)) { return LuaError(L, "UtilReadWideString failed. Error 0x%08x.", hr); } // Convert to UTF8. // const int cbWritten = WideCharToMultiByte( CP_UTF8, 0, buf, -1, utf8buf, sizeof utf8buf, nullptr, nullptr); if (!cbWritten) { DWORD err = GetLastError(); luaL_error(L, "WideCharToMultiByte failed. Error %d.", err); } lua_pushstring(L, utf8buf); return 1; }
bool ScriptApiItem::item_OnUse(ItemStack &item, ServerActiveObject *user, const PointedThing &pointed) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getItemCallback(item.name.c_str(), "on_use")) return false; // Call function LuaItemStack::create(L, item); objectrefGetOrCreate(L, user); pushPointedThing(pointed); PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if(!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
bool ScriptApiItem::item_OnDrop(ItemStack &item, ServerActiveObject *dropper, v3f pos) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); // Push callback function on stack if(!getItemCallback(item.name.c_str(), "on_drop")) return false; // Call function LuaItemStack::create(L, item); objectrefGetOrCreate(dropper); pushFloatPos(L, pos); if(lua_pcall(L, 3, 1, errorhandler)) scriptError(); if(!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user, const InventoryList *old_craft_grid, const InventoryLocation &craft_inv) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); lua_getglobal(L, "minetest"); lua_getfield(L, -1, "on_craft"); LuaItemStack::create(L, item); objectrefGetOrCreate(user); //Push inventory list std::vector<ItemStack> items; for(u32 i=0; i<old_craft_grid->getSize(); i++) items.push_back(old_craft_grid->getItem(i)); push_items(L, items); InvRef::create(L, craft_inv); if(lua_pcall(L, 4, 1, errorhandler)) scriptError(); if(!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
/** ** Change unit owner ** ** @param l Lua state. */ static int CclChangeUnitsOwner(lua_State *l) { CUnit *table[UnitMax]; int n; int oldp; int newp; int x1; int y1; int x2; int y2; LuaCheckArgs(l, 4); if (!lua_istable(l, 1) || !lua_istable(l, 2)) { LuaError(l, "incorrect argument"); } if (luaL_getn(l, 1) != 2) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, 1, 1); x1 = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 1, 1); y1 = LuaToNumber(l, -1); lua_pop(l, 1); if (luaL_getn(l, 2) != 2) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, 2, 1); x2 = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 2, 1); y2 = LuaToNumber(l, -1); lua_pop(l, 1); n = UnitCacheSelect(x1, y1, x2 + 1, y2 + 1, table); oldp = LuaToNumber(l, 3); newp = LuaToNumber(l, 4); while (n) { if (table[n - 1]->Player->Index == oldp) { table[n - 1]->ChangeOwner(&Players[newp]); } --n; } return 0; }
/** ** Parse an animation frame ** ** @param str string formated as "animationType extraArgs" */ static CAnimation *ParseAnimationFrame(lua_State *l, const char *str) { const std::string all(str); const size_t len = all.size(); size_t end = all.find(' '); const std::string op1(all, 0, end); size_t begin = std::min(len, all.find_first_not_of(' ', end)); const std::string extraArg(all, begin); CAnimation *anim = NULL; if (op1 == "frame") { anim = new CAnimation_Frame; } else if (op1 == "exact-frame") { anim = new CAnimation_ExactFrame; } else if (op1 == "wait") { anim = new CAnimation_Wait; } else if (op1 == "random-wait") { anim = new CAnimation_RandomWait; } else if (op1 == "sound") { anim = new CAnimation_Sound; } else if (op1 == "random-sound") { anim = new CAnimation_RandomSound; } else if (op1 == "attack") { anim = new CAnimation_Attack; } else if (op1 == "spawn-missile") { anim = new CAnimation_SpawnMissile; } else if (op1 == "spawn-unit") { anim = new CAnimation_SpawnUnit; } else if (op1 == "if-var") { anim = new CAnimation_IfVar; } else if (op1 == "set-var") { anim = new CAnimation_SetVar; } else if (op1 == "set-player-var") { anim = new CAnimation_SetPlayerVar; } else if (op1 == "die") { anim = new CAnimation_Die(); } else if (op1 == "rotate") { anim = new CAnimation_Rotate; } else if (op1 == "random-rotate") { anim = new CAnimation_RandomRotate; } else if (op1 == "move") { anim = new CAnimation_Move; } else if (op1 == "unbreakable") { anim = new CAnimation_Unbreakable; } else if (op1 == "label") { anim = new CAnimation_Label; AddLabel(anim, extraArg); } else if (op1 == "goto") { anim = new CAnimation_Goto; } else if (op1 == "random-goto") { anim = new CAnimation_RandomGoto; } else if (op1 == "lua-callback") { anim = new CAnimation_LuaCallback; } else { LuaError(l, "Unknown animation: %s" _C_ op1.c_str()); } anim->Init(extraArg.c_str(), l); return anim; }
int GetResourceIdByName(lua_State *l, const char *resourceName) { const int res = GetResourceIdByName(resourceName); if (res == -1) { LuaError(l, "Resource not found: %s" _C_ resourceName); } return res; }
/** ** Set the flags like "water" for a tile of a tileset ** ** @param l Lua state. */ static int CclSetTileFlags(lua_State *l) { if (lua_gettop(l) < 2) { LuaError(l, "No flags defined"); } const unsigned int tilenumber = LuaToNumber(l, 1); if (tilenumber >= Map.Tileset->tiles.size()) { LuaError(l, "Accessed a tile that's not defined"); } int j = 0; int flags = 0; ParseTilesetTileFlags(l, &flags, &j); Map.Tileset->tiles[tilenumber].flag = flags; return 0; }