EXPORT(void) lpClose() { rootTable = LuaTable(); currTable = LuaTable(); luaTables.clear(); intKeys.clear(); strKeys.clear(); delete luaParser; luaParser = NULL; return; }
int main() { Lua lua; auto global = lua.GetGlobalEnvironment(); auto newCar = lua.CreateFunction<LuaTable()>( [&]() -> LuaTable { LuaTable table = lua.CreateTable(); table.Set("type", "renault"); return table; } ); global.Set("newCar", newCar); // Run the script that chooses a function to return lua.RunScript( "x = newCar()['type']" ); auto type = global.Get<std::string>("x"); return type.compare("renault"); }
Lua::Lua(std::tr1::shared_ptr<lua_State> state) : state(state), registry(LuaTable(state, LUA_REGISTRYINDEX)), globals(registry.Get<LuaTable>(LUA_RIDX_GLOBALS)) { }
LuaTable Lua::CreateTable() { lua_newtable(state.get()); LuaTable table = LuaTable(state, -1); lua_pop(state.get(), 1); return table; }
LuaTable LuaReference::GetMetaTable() const { PushToStack(state.get()); int res = lua_getmetatable(state.get(), -1); assert(res != 0); LuaTable table = LuaTable(state, -1); lua_pop(state.get(), 2); return table; }
LuaTable GetTable(const char* name) { lua_getglobal(m_luaState, name); if (!lua_istable(m_luaState, -1)) { lua_newtable(m_luaState); lua_setglobal(m_luaState, name); } const auto index = lua_gettop(m_luaState); return LuaTable(m_luaState, index); }
LuaTable MapParser::GetRoot() { if (parser) { errorLog.clear(); return parser->GetRoot(); } else { errorLog = "Map-Parser: Failed to get parser root node, reason: parser not ready || file not found."; return LuaTable(); } }
/* * Method: IsCommodityLegal * * Determine if a given cargo item is legal for trade in this system * * > is_legal = system:IsCommodityLegal(cargo) * * Parameters: * * cargo - the wanted commodity (for instance, Equipment.cargo.hydrogen) * * Return: * * is_legal - true if the commodity is legal, otherwise false * * Availability: * * alpha 10 * * Status: * * experimental */ static int l_starsystem_is_commodity_legal(lua_State *l) { PROFILE_SCOPED() StarSystem *s = LuaObject<StarSystem>::CheckFromLua(1); // XXX: Don't use the l10n_key hack, this is just UGLY!! luaL_checktype(l, 2, LUA_TTABLE); LuaTable(l, 2).PushValueToStack("l10n_key"); GalacticEconomy::Commodity e = static_cast<GalacticEconomy::Commodity>( LuaConstants::GetConstantFromArg(l, "CommodityType", -1)); lua_pushboolean(l, Polit::IsCommodityLegal(s, e)); return 1; }
LuaTable LuaTable::SubTableExpr(const string& expr) const { if (expr.empty()) { return LuaTable(*this); } if (!isValid) { return LuaTable(); } string::size_type endPos; LuaTable nextTable; if (expr[0] == '[') { // numeric key endPos = expr.find(']'); if (endPos == string::npos) { return LuaTable(); // missing brace } const char* startPtr = expr.c_str() + 1; // skip the '[' char* endPtr; const int index = strtol(startPtr, &endPtr, 10); if (endPtr == startPtr) { return LuaTable(); // invalid index } endPos++; // eat the ']' nextTable = SubTable(index); } else { // string key endPos = expr.find_first_of(".["); if (endPos == string::npos) { return SubTable(expr); } nextTable = SubTable(expr.substr(0, endPos)); } if (expr[endPos] == '.') { endPos++; // eat the dot } return nextTable.SubTableExpr(expr.substr(endPos)); }
LuaTable createMatatable(lua_State* state)const { util::ScopedSavedStack save(state); if (!class_userdata::newmetatable<class_type>(state)) { except::OtherError(state, typeid(class_type*).name() + std::string(" is already registered")); return LuaTable(); } int metatable_index = lua_gettop(state); Metatable::setMembers(state, metatable_index,member_map_,property_map_); if (!traits::is_same<base_class_type, void>::value || !property_map_.empty())//if base class has property and derived class hasnt property. need property access metamethod { if (member_map_.count("__index") == 0) { Metatable::setPropertyIndexMetamethod(state, metatable_index); } if (member_map_.count("__newindex") == 0) { Metatable::setPropertyNewIndexMetamethod(state, metatable_index); } } else { if (member_map_.count("__index") == 0) { lua_pushstring(state, "__index"); lua_pushvalue(state, metatable_index); lua_rawset(state, metatable_index); } } set_base_metatable(state, metatable_index, types::typetag<base_class_type>()); if (lua_getmetatable(state, metatable_index))//get base_metatable { lua_pushstring(state, "__call"); lua_pushcfunction(state, &Metatable::call_constructor_function); lua_rawset(state,-3);//base_metatable["__call"] = Metatable::call_constructor_function } else { Metatable::get_call_constructor_metatable(state); lua_setmetatable(state, metatable_index); } return LuaStackRef(state, metatable_index); }
static int _get_stage_durations(lua_State *L, const char *key, int &outNumStages, double **outDurationArray) { LUA_DEBUG_START(L); LuaTable stages = LuaTable(L, -1).Sub(key); if (stages.GetLua() == 0) { luaL_error(L, "Not a proper table (%s)", key); } if (stages.Size() < 1) return luaL_error(L, "Station must have at least 1 stage in %s", key); outNumStages = stages.Size(); *outDurationArray = new double[stages.Size()]; std::copy(stages.Begin<double>(), stages.End<double>(), *outDurationArray); lua_pop(L, 1); // Popping t LUA_DEBUG_END(L, 0); return 0; }
LuaTable createMatatable(lua_State* state)const { util::ScopedSavedStack save(state); if (class_userdata::newmetatable<class_type>(state)) { LuaStackRef metatable(state, -1); registerMember(state); if (!traits::is_same<base_class_type, void>::value || !property_map_.empty())//if base class has property and derived class hasnt property. need property access metamethod { LuaFunction indexfun = kaguya::LuaFunction::loadstring(state, "local arg = {...};local metatable = arg[1];" "return function(table, index)" // " if type(table) == 'userdata' then " " local propfun = metatable['_prop_'..index];" " if propfun then return propfun(table) end " // " end " " return metatable[index]" " end")(metatable); metatable.setField("__index", indexfun); LuaFunction newindexfn = LuaFunction::loadstring(state, "local arg = {...};local metatable = arg[1];" " return function(table, index, value) " " if type(table) == 'userdata' then " " local propfun = metatable['_prop_'..index];" " if propfun then return propfun(table,value) end " " end " " rawset(table,index,value) " " end")(metatable); metatable.setField("__newindex", newindexfn); } else { metatable.setField("__index", metatable); } set_base_metatable(state, metatable, types::typetag<base_class_type>()); return metatable; } else { except::OtherError(state, typeid(class_type*).name() + std::string(" is already registered")); } return LuaTable(); }
// Data format example: // bay_groups = { // {0, 500, {1}}, // }, static int _get_bay_ids(lua_State *L, const char *key, SpaceStationType::TBayGroups &outBayGroups, unsigned int &outNumDockingPorts) { LUA_DEBUG_START(L); LuaTable t = LuaTable(L, -1).Sub(key); if (t.GetLua() == 0) { luaL_error(L, "The bay group isn't a proper table (%s)", key); } if (t.Size() < 1) { return luaL_error(L, "Station must have at least 1 group of bays in %s", key); } LuaTable::VecIter<LuaTable> it_end = t.End<LuaTable>(); for (LuaTable::VecIter<LuaTable> it = t.Begin<LuaTable>(); it != it_end; ++it) { SpaceStationType::SBayGroup newBay; newBay.minShipSize = it->Get<int>(1); newBay.maxShipSize = it->Get<int>(2); LuaTable group = it->Sub(3); if (group.GetLua() == 0) { luaL_error(L, "A group is of the form {int, int, table} (%s)", key); } if (group.Size() == 0) { return luaL_error(L, "Group must have at least 1 bay %s", key); } newBay.bayIDs.reserve(group.Size()); LuaTable::VecIter<int> jt_end = group.End<int>(); for (LuaTable::VecIter<int> jt = group.Begin<int>(); jt != jt_end; ++jt) { if ((*jt) < 1) { return luaL_error(L, "Valid bay ID ranges start from 1 %s", key); } newBay.bayIDs.push_back((*jt)-1); ++outNumDockingPorts; } lua_pop(L, 1); // Popping group outBayGroups.push_back(newBay); } lua_pop(L, 1); // Popping t LUA_DEBUG_END(L, 0); return 0; }
void Ship::InitEquipSet() { lua_State * l = Lua::manager->GetLuaState(); PropertyMap & p = Properties(); LUA_DEBUG_START(l); pi_lua_import(l, "EquipSet"); LuaTable es_class(l, -1); LuaTable slots = LuaTable(l).LoadMap(GetShipType()->slots.begin(), GetShipType()->slots.end()); m_equipSet = es_class.Call<LuaRef>("New", slots); p.Set("equipSet", ScopedTable(m_equipSet)); UpdateEquipStats(); { ScopedTable es(m_equipSet); int usedCargo = es.CallMethod<int>("OccupiedSpace", "cargo"); int totalCargo = std::min(m_stats.free_capacity + usedCargo, es.CallMethod<int>("SlotSize", "cargo")); p.Set("usedCargo", usedCargo); p.Set("totalCargo", totalCargo); } lua_pop(l, 2); LUA_DEBUG_END(l, 0); }
unsigned int CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag) { unsigned int explosionID = -1U; if (tag.empty()) { return explosionID; } const std::map<std::string, unsigned int>::const_iterator it = explosionIDs.find(tag); if (it == explosionIDs.end()) { CEGData cegData; const LuaTable* root = h->GetExplosionTableRoot(); const LuaTable& expTable = (root != NULL)? root->SubTable(tag): LuaTable(); if (!expTable.IsValid()) { // not a fatal error: any calls to ::Explosion will just return early logOutput.Print("[CCEG::Load] WARNING: table for CEG \"" + tag + "\" invalid (parse errors?)"); return explosionID; } vector<string> spawns; expTable.GetKeys(spawns); for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) { ProjectileSpawnInfo psi; const string& spawnName = *si; const LuaTable spawnTable = expTable.SubTable(spawnName); if (!spawnTable.IsValid() || spawnName == "groundflash") { continue; } const string className = spawnTable.GetString("class", spawnName); psi.projectileClass = h->projectileClasses.GetClass(className); psi.flags = GetFlagsFromTable(spawnTable); psi.count = spawnTable.GetInt("count", 1); if (psi.projectileClass->binder->flags & creg::CF_Synced) { psi.flags |= SPW_SYNCED; } string code; map<string, string> props; map<string, string>::const_iterator propIt; spawnTable.SubTable("properties").GetMap(props); for (propIt = props.begin(); propIt != props.end(); ++propIt) { creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str()); if (m && (m->flags & creg::CM_Config)) { ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code); } } code += (char)OP_END; psi.code.resize(code.size()); copy(code.begin(), code.end(), psi.code.begin()); cegData.projectileSpawn.push_back(psi); } const LuaTable gndTable = expTable.SubTable("groundflash"); const int ttl = gndTable.GetInt("ttl", 0); if (ttl > 0) { cegData.groundFlash.circleAlpha = gndTable.GetFloat("circleAlpha", 0.0f); cegData.groundFlash.flashSize = gndTable.GetFloat("flashSize", 0.0f); cegData.groundFlash.flashAlpha = gndTable.GetFloat("flashAlpha", 0.0f); cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f); cegData.groundFlash.color = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f)); cegData.groundFlash.flags = SPW_GROUND | GetFlagsFromTable(gndTable); cegData.groundFlash.ttl = ttl; } cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false); explosionID = explosionData.size(); explosionData.push_back(cegData); explosionIDs[tag] = explosionID; } else { explosionID = it->second; } return explosionID; }
Widget *Context::CallTemplate(const char *name) { return CallTemplate(name, LuaTable(m_lua->GetLuaState())); }
void Ship::StaticUpdate(const float timeStep) { // do player sounds before dead check, so they also turn off if (IsType(Object::PLAYER)) DoThrusterSounds(); if (IsDead()) return; if (m_controller) m_controller->StaticUpdate(timeStep); if (GetHullTemperature() > 1.0) Explode(); UpdateAlertState(); /* FUEL SCOOPING!!!!!!!!! */ int capacity = 0; Properties().Get("fuel_scoop_cap", capacity); if (m_flightState == FLYING && capacity > 0) { Body *astro = GetFrame()->GetBody(); if (astro && astro->IsType(Object::PLANET)) { Planet *p = static_cast<Planet*>(astro); if (p->GetSystemBody()->IsScoopable()) { double dist = GetPosition().Length(); double pressure, density; p->GetAtmosphericState(dist, &pressure, &density); double speed = GetVelocity().Length(); vector3d vdir = GetVelocity().Normalized(); vector3d pdir = -GetOrient().VectorZ(); double dot = vdir.Dot(pdir); if ((m_stats.free_capacity) && (dot > 0.95) && (speed > 2000.0) && (density > 1.0)) { double rate = speed*density*0.00000333f*double(capacity); if (Pi::rng.Double() < rate) { lua_State *l = Lua::manager->GetLuaState(); pi_lua_import(l, "Equipment"); LuaTable hydrogen = LuaTable(l, -1).Sub("cargo").Sub("hydrogen"); LuaObject<Ship>::CallMethod(this, "AddEquip", hydrogen); UpdateEquipStats(); if (this->IsType(Object::PLAYER)) { Pi::game->log->Add(stringf(Lang::FUEL_SCOOP_ACTIVE_N_TONNES_H_COLLECTED, formatarg("quantity", LuaObject<Ship>::CallMethod<int>(this, "CountEquip", hydrogen)))); } lua_pop(l, 3); } } } } } // Cargo bay life support capacity = 0; Properties().Get("cargo_life_support_cap", capacity); if (!capacity) { // Hull is pressure-sealed, it just doesn't provide // temperature regulation and breathable atmosphere // kill stuff roughly every 5 seconds if ((!m_dockedWith) && (5.0*Pi::rng.Double() < timeStep)) { std::string t(Pi::rng.Int32(2) ? "live_animals" : "slaves"); lua_State *l = Lua::manager->GetLuaState(); pi_lua_import(l, "Equipment"); LuaTable cargo = LuaTable(l, -1).Sub("cargo"); if (LuaObject<Ship>::CallMethod<int>(this, "RemoveEquip", cargo.Sub(t))) { LuaObject<Ship>::CallMethod<int>(this, "AddEquip", cargo.Sub("fertilizer")); if (this->IsType(Object::PLAYER)) { Pi::game->log->Add(Lang::CARGO_BAY_LIFE_SUPPORT_LOST); } lua_pop(l, 4); } else lua_pop(l, 3); } } if (m_flightState == FLYING) m_launchLockTimeout -= timeStep; if (m_launchLockTimeout < 0) m_launchLockTimeout = 0; if (m_flightState == JUMPING || m_flightState == HYPERSPACE) m_launchLockTimeout = 0; // lasers for (int i=0; i<ShipType::GUNMOUNT_MAX; i++) { m_gun[i].recharge -= timeStep; float rateCooling = 0.01f; float cooler = 1.0f; Properties().Get("laser_cooler_cap", cooler); rateCooling *= cooler; m_gun[i].temperature -= rateCooling*timeStep; if (m_gun[i].temperature < 0.0f) m_gun[i].temperature = 0; if (m_gun[i].recharge < 0.0f) m_gun[i].recharge = 0; if (!m_gun[i].state) continue; if (m_gun[i].recharge > 0.0f) continue; if (m_gun[i].temperature > 1.0) continue; FireWeapon(i); } if (m_ecmRecharge > 0.0f) { m_ecmRecharge = std::max(0.0f, m_ecmRecharge - timeStep); } if (m_shieldCooldown > 0.0f) { m_shieldCooldown = std::max(0.0f, m_shieldCooldown - timeStep); } if (m_stats.shield_mass_left < m_stats.shield_mass) { // 250 second recharge float recharge_rate = 0.004f; float booster = 1.0f; Properties().Get("shield_energy_booster_cap", booster); recharge_rate *= booster; m_stats.shield_mass_left = Clamp(m_stats.shield_mass_left + m_stats.shield_mass * recharge_rate * timeStep, 0.0f, m_stats.shield_mass); Properties().Set("shieldMassLeft", m_stats.shield_mass_left); } if (m_wheelTransition) { m_wheelState += m_wheelTransition*0.3f*timeStep; m_wheelState = Clamp(m_wheelState, 0.0f, 1.0f); if (is_equal_exact(m_wheelState, 0.0f) || is_equal_exact(m_wheelState, 1.0f)) m_wheelTransition = 0; } if (m_testLanded) TestLanded(); capacity = 0; Properties().Get("hull_autorepair_cap", capacity); if (capacity) { m_stats.hull_mass_left = std::min(m_stats.hull_mass_left + 0.1f*timeStep, float(m_type->hullMass)); Properties().Set("hullMassLeft", m_stats.hull_mass_left); Properties().Set("hullPercent", 100.0f * (m_stats.hull_mass_left / float(m_type->hullMass))); } // After calling StartHyperspaceTo this Ship must not spawn objects // holding references to it (eg missiles), as StartHyperspaceTo // removes the ship from Space::bodies and so the missile will not // have references to this cleared by NotifyRemoved() if (m_hyperspace.now) { m_hyperspace.now = false; EnterHyperspace(); } if (m_hyperspace.countdown > 0.0f) { // Check the Lua function bool abort = false; lua_State * l = m_hyperspace.checks.GetLua(); if (l) { m_hyperspace.checks.PushCopyToStack(); if (lua_isfunction(l, -1)) { lua_call(l, 0, 1); abort = !lua_toboolean(l, -1); lua_pop(l, 1); } } if (abort) { AbortHyperjump(); } else { m_hyperspace.countdown = m_hyperspace.countdown - timeStep; if (!abort && m_hyperspace.countdown <= 0.0f) { m_hyperspace.countdown = 0; m_hyperspace.now = true; SetFlightState(JUMPING); // We have to fire it here, because the event isn't actually fired until // after the whole physics update, which means the flight state on next // step would be HYPERSPACE, thus breaking quite a few things. LuaEvent::Queue("onLeaveSystem", this); } } } //Add smoke trails for missiles on thruster state static double s_timeAccum = 0.0; s_timeAccum += timeStep; if (m_type->tag == ShipType::TAG_MISSILE && !is_equal_exact(m_thrusters.LengthSqr(), 0.0) && (s_timeAccum > 4 || 0.1*Pi::rng.Double() < timeStep)) { s_timeAccum = 0.0; const vector3d pos = GetOrient() * vector3d(0, 0 , 5); const float speed = std::min(10.0*GetVelocity().Length()*std::max(1.0,fabs(m_thrusters.z)),100.0); SfxManager::AddThrustSmoke(this, speed, pos); } }
Lua::Lua() : state(luaL_newstate(), lua_close), registry(LuaTable(state, LUA_REGISTRYINDEX)), globals(registry.Get<LuaTable>(LUA_RIDX_GLOBALS)) { }
LuaTable LuaParser::GetRoot() { return LuaTable(this); }