bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_Command) { if (a_Split.empty()) { return false; } CommandMap::iterator cmd = m_ConsoleCommands.find(a_Split[0]); if (cmd == m_ConsoleCommands.end()) { // Command not found // Still notify the plugins (so that plugins such as Aliases can intercept unknown commands). CommandResult res = crBlocked; CallHookExecuteCommand(nullptr, a_Split, a_Command, res); return (res == crExecuted); } if (cmd->second.m_Plugin == nullptr) { // This is a built-in command return false; } // Ask plugins first if a command is okay to execute the console command: CommandResult res = crBlocked; if (CallHookExecuteCommand(nullptr, a_Split, a_Command, res)) { return (res == crExecuted); } return cmd->second.m_Handler->ExecuteCommand(a_Split, nullptr, a_Command, &a_Output); }
std::pair<AString, AString> cWebPlugin::GetTabNameForRequest(const HTTPRequest & a_Request) { AStringVector Split = StringSplit(a_Request.Path, "/"); if (Split.empty()) { return std::make_pair(AString(), AString()); } cCSLock Lock(m_CSTabs); cTabPtr Tab; if (Split.size() > 2) // If we got the tab name, show that page { for (auto itr = m_Tabs.cbegin(), end = m_Tabs.cend(); itr != end; ++itr) { if ((*itr)->m_SafeTitle.compare(Split[2]) == 0) // This is the one! { return std::make_pair((*itr)->m_Title, (*itr)->m_SafeTitle); } } // Tab name not found, display an "empty" page: return std::make_pair(AString(), AString()); } // Show the first tab: if (!m_Tabs.empty()) { return std::make_pair(m_Tabs.front()->m_SafeTitle, m_Tabs.front()->m_SafeTitle); } // No tabs at all: return std::make_pair(AString(), AString()); }
bool cCraftingRecipes::ParseItem(const AString & a_String, cItem & a_Item) { // The caller provides error logging AStringVector Split = StringSplit(a_String, "^"); if (Split.empty()) { return false; } if (!StringToItem(Split[0], a_Item)) { return false; } if (Split.size() > 1) { AString Damage = TrimString(Split[1]); if (!StringToInteger<short>(Damage.c_str(), a_Item.m_ItemDamage)) { // Parsing the number failed return false; } } // Success return true; }
bool cProbabDistrib::SetDefString(const AString & a_DefString) { AStringVector Points = StringSplitAndTrim(a_DefString, ";"); if (Points.empty()) { return false; } cPoints Pts; for (AStringVector::const_iterator itr = Points.begin(), end = Points.end(); itr != end; ++itr) { AStringVector Split = StringSplitAndTrim(*itr, ","); if (Split.size() != 2) { // Bad format return false; } int Value = atoi(Split[0].c_str()); int Prob = atoi(Split[1].c_str()); if ( ((Value == 0) && (Split[0] != "0")) || ((Prob == 0) && (Split[1] != "0")) ) { // Number parse error return false; } Pts.push_back(cPoint(Value, Prob)); } // for itr - Points[] SetPoints(Pts); return true; }
bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output) { if (a_Split.empty()) { return false; } CommandMap::iterator cmd = m_ConsoleCommands.find(a_Split[0]); if (cmd == m_ConsoleCommands.end()) { // Command not found return false; } if (cmd->second.m_Plugin == NULL) { // This is a built-in command return false; } // Ask plugins first if a command is okay to execute the console command: if (CallHookExecuteCommand(NULL, a_Split)) { a_Output.Out("Command \"%s\" was stopped by the HOOK_EXECUTE_COMMAND hook", a_Split[0].c_str()); return false; } return cmd->second.m_Plugin->HandleConsoleCommand(a_Split, a_Output); }
void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output) { AStringVector split = StringSplit(a_Cmd, " "); if (split.empty()) { return; } // Special handling: "stop" and "restart" are built in if ((split[0].compare("stop") == 0) || (split[0].compare("restart") == 0)) { return; } // "help" and "reload" are to be handled by MCS, so that they work no matter what if (split[0] == "help") { PrintHelp(split, a_Output); return; } if (split[0] == "reload") { cPluginManager::Get()->ReloadPlugins(); return; } // There is currently no way a plugin can do these (and probably won't ever be): if (split[0].compare("chunkstats") == 0) { cRoot::Get()->LogChunkStats(a_Output); a_Output.Finished(); return; } #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) if (split[0].compare("dumpmem") == 0) { LeakFinderXmlOutput Output("memdump.xml"); DumpUsedMemory(&Output); return; } if (split[0].compare("killmem") == 0) { while (true) { new char[100 * 1024 * 1024]; // Allocate and leak 100 MiB in a loop -> fill memory and kill MCS } } #endif if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output)) { a_Output.Finished(); return; } a_Output.Out("Unknown command, type 'help' for all commands."); a_Output.Finished(); }
AStringVector ReadUpgradeIniPorts( cSettingsRepositoryInterface & a_Settings, const AString & a_KeyName, const AString & a_PortsValueName, const AString & a_OldIPv4ValueName, const AString & a_OldIPv6ValueName, const AString & a_DefaultValue ) { // Read the regular value, but don't use the default (in order to detect missing value for upgrade): AStringVector Ports; for (auto pair : a_Settings.GetValues(a_KeyName)) { if (pair.first != a_PortsValueName) { continue; } AStringVector temp = StringSplitAndTrim(pair.second, ";,"); Ports.insert(Ports.end(), temp.begin(), temp.end()); } if (Ports.empty()) { // Historically there were two separate entries for IPv4 and IPv6, merge them and migrate: AString Ports4 = a_Settings.GetValue(a_KeyName, a_OldIPv4ValueName, a_DefaultValue); AString Ports6 = a_Settings.GetValue(a_KeyName, a_OldIPv6ValueName); Ports = MergeStringVectors(StringSplitAndTrim(Ports4, ";,"), StringSplitAndTrim(Ports6, ";,")); a_Settings.DeleteValue(a_KeyName, a_OldIPv4ValueName); a_Settings.DeleteValue(a_KeyName, a_OldIPv6ValueName); // If those weren't present or were empty, use the default:" if (Ports.empty()) { Ports = StringSplitAndTrim(a_DefaultValue, ";,"); } a_Settings.SetValue(a_KeyName, a_PortsValueName, StringsConcat(Ports, ',')); } return Ports; }
bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output) { ASSERT(!a_Split.empty()); CommandMap::iterator cmd = m_ConsoleCommands.find(a_Split[0]); if (cmd == m_ConsoleCommands.end()) { LOGWARNING("Console command handler is registered in cPluginManager but not in cPlugin, wtf? Console command \"%s\", plugin \"%s\".", a_Split[0].c_str(), GetName().c_str() ); return false; } cCSLock Lock(m_CriticalSection); // Push the function to be called: lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref() // Push the split: lua_createtable(m_LuaState, a_Split.size(), 0); int newTable = lua_gettop(m_LuaState); int index = 1; std::vector<std::string>::const_iterator iter = a_Split.begin(), end = a_Split.end(); while(iter != end) { tolua_pushstring(m_LuaState, (*iter).c_str()); lua_rawseti(m_LuaState, newTable, index); ++iter; ++index; } // Call function: int s = lua_pcall(m_LuaState, 1, 2, 0); if (report_errors(m_LuaState, s)) { LOGERROR("Lua error. Stack size: %i", lua_gettop(m_LuaState)); return false; } // Handle return values: if (lua_isstring(m_LuaState, -1)) { AString str = tolua_tocppstring(m_LuaState, -1, ""); a_Output.Out(str); } bool RetVal = (tolua_toboolean(m_LuaState, -2, 0) > 0); lua_pop(m_LuaState, 2); // Pop return values return RetVal; }
bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer & a_Player, const AString & a_FullCommand) { ASSERT(!a_Split.empty()); CommandMap::iterator cmd = m_Commands.find(a_Split[0]); if (cmd == m_Commands.end()) { LOGWARNING("Command handler is registered in cPluginManager but not in cPlugin, wtf? Command \"%s\".", a_Split[0].c_str()); return false; } cCSLock Lock(m_CriticalSection); bool res = false; m_LuaState.Call(cmd->second, a_Split, &a_Player, a_FullCommand, cLuaState::Return, res); return res; }
void AddToMap(const AString & a_Name, const AString & a_Value) { AStringVector Split = StringSplit(a_Value, ":"); if (Split.size() == 1) { Split = StringSplit(a_Value, "^"); } if (Split.empty()) { return; } short ItemType = (short)atoi(Split[0].c_str()); short ItemDamage = (Split.size() > 1) ? (short)atoi(Split[1].c_str()) : -1; m_Map[a_Name] = std::make_pair(ItemType, ItemDamage); }
bool ResolveItem(const AString & a_ItemName, cItem & a_Item) { // Split into parts divided by either ':' or '^' AStringVector Split = StringSplitAndTrim(a_ItemName, ":^"); if (Split.empty()) { return false; } ItemMap::iterator itr = m_Map.find(Split[0]); if (itr != m_Map.end()) { // Resolved as a string, assign the type and the default damage / count a_Item.m_ItemType = itr->second.first; a_Item.m_ItemDamage = itr->second.second; if (a_Item.m_ItemDamage == -1) { a_Item.m_ItemDamage = 0; } } else { // Not a resolvable string, try pure numbers: "45:6", "45^6" etc. a_Item.m_ItemType = (short)atoi(Split[0].c_str()); if ((a_Item.m_ItemType == 0) && (Split[0] != "0")) { // Parsing the number failed return false; } } // Parse the damage, if present: if (Split.size() < 2) { // Not present, set the item as valid and return success: a_Item.m_ItemCount = 1; return true; } a_Item.m_ItemDamage = (short)atoi(Split[1].c_str()); if ((a_Item.m_ItemDamage == 0) && (Split[1] != "0")) { // Parsing the number failed return false; } a_Item.m_ItemCount = 1; return true; }
bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Player) { ASSERT(!a_Split.empty()); CommandMap::iterator cmd = m_Commands.find(a_Split[0]); if (cmd == m_Commands.end()) { LOGWARNING("Command handler is registered in cPluginManager but not in cPlugin, wtf? Command \"%s\".", a_Split[0].c_str()); return false; } cCSLock Lock(m_CriticalSection); // Push the function to be called: lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref() // Push the split: lua_createtable(m_LuaState, a_Split.size(), 0); int newTable = lua_gettop(m_LuaState); int index = 1; std::vector<std::string>::const_iterator iter = a_Split.begin(), end = a_Split.end(); while(iter != end) { tolua_pushstring(m_LuaState, (*iter).c_str()); lua_rawseti(m_LuaState, newTable, index); ++iter; ++index; } // Push player: tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); // Call function: int s = lua_pcall(m_LuaState, 2, 1, 0); if (report_errors(m_LuaState, s)) { LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState)); return false; } // Handle return value: bool RetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0); lua_pop(m_LuaState, 1); // Pop return value return RetVal; }
bool ResolveItem(const AString & a_ItemName, cItem & a_Item) { ItemMap::iterator itr = m_Map.find(a_ItemName); if (itr != m_Map.end()) { a_Item.m_ItemType = itr->second.first; a_Item.m_ItemDamage = itr->second.second; if (a_Item.m_ItemDamage == -1) { a_Item.m_ItemDamage = 0; } a_Item.m_ItemCount = 1; return true; } // Not a resolvable string, try pure numbers: "45:6", "45^6" etc. AStringVector Split = StringSplit(a_ItemName, ":"); if (Split.size() == 1) { Split = StringSplit(a_ItemName, "^"); } if (Split.empty()) { return false; } a_Item.m_ItemType = (short)atoi(Split[0].c_str()); if ((a_Item.m_ItemType == 0) && (Split[0] != "0")) { // Parsing the number failed return false; } if (Split.size() < 2) { a_Item.m_ItemCount = 1; return true; } a_Item.m_ItemDamage = atoi(Split[1].c_str()); if ((a_Item.m_ItemDamage == 0) && (Split[1] != "0")) { // Parsing the number failed return false; } a_Item.m_ItemCount = 1; return true; }
void cMojangAPI::Update(void) { Int64 LimitDateTime = time(nullptr) - MAX_AGE; // Re-query all playernames that are stale: AStringVector PlayerNames; { cCSLock Lock(m_CSNameToUUID); for (const auto & NameToUUID : m_NameToUUID) { if (NameToUUID.second.m_DateTime < LimitDateTime) { PlayerNames.push_back(NameToUUID.first); } } // for itr - m_NameToUUID[] } if (!PlayerNames.empty()) { LOG("cMojangAPI: Updating name-to-uuid cache for %u names", static_cast<unsigned>(PlayerNames.size())); QueryNamesToUUIDs(PlayerNames); } // Re-query all profiles that are stale: std::vector<cUUID> ProfileUUIDs; { cCSLock Lock(m_CSUUIDToProfile); for (auto & UUIDToProfile : m_UUIDToProfile) { if (UUIDToProfile.second.m_DateTime < LimitDateTime) { ProfileUUIDs.push_back(UUIDToProfile.first); } } // for itr - m_UUIDToProfile[] } if (!ProfileUUIDs.empty()) { LOG("cMojangAPI: Updating uuid-to-profile cache for %u uuids", static_cast<unsigned>(ProfileUUIDs.size())); for (const auto & UUID : ProfileUUIDs) { QueryUUIDToProfile(UUID); } } }
void cProtocol132::SendTabCompletionResults(const AStringVector & a_Results) { if (a_Results.empty()) { // No results to send return; } AString Serialized(a_Results[0]); for (AStringVector::const_iterator itr = a_Results.begin() + 1, end = a_Results.end(); itr != end; ++itr) { Serialized.push_back(0); Serialized.append(*itr); } // for itr - a_Results[] cCSLock Lock(m_CSPacket); WriteByte(PACKET_TAB_COMPLETION); WriteString(Serialized); Flush(); }
bool cPluginLua::HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_FullCommand) { ASSERT(!a_Split.empty()); CommandMap::iterator cmd = m_ConsoleCommands.find(a_Split[0]); if (cmd == m_ConsoleCommands.end()) { LOGWARNING("Console command handler is registered in cPluginManager but not in cPlugin, wtf? Console command \"%s\", plugin \"%s\".", a_Split[0].c_str(), GetName().c_str() ); return false; } cCSLock Lock(m_CriticalSection); bool res = false; AString str; m_LuaState.Call(cmd->second, a_Split, a_FullCommand, cLuaState::Return, res, str); if (res && !str.empty()) { a_Output.Out(str); } return res; }
void AddToMap(const AString & a_Name, const AString & a_Value) { AStringVector Split = StringSplit(a_Value, ":"); if (Split.size() == 1) { Split = StringSplit(a_Value, "^"); } if (Split.empty()) { return; } short ItemType; if (!StringToInteger(Split[0], ItemType)) { ASSERT(!"Invalid item type"); } short ItemDamage = -1; if (Split.size() > 1 && !StringToInteger(Split[1], ItemDamage)) { ASSERT(!"Invalid item damage"); } m_Map[a_Name] = std::make_pair(ItemType, ItemDamage); }
int cProtocol125::ParseHandshake(void) { HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username); AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565" if (UserData.empty()) { m_Client->Kick("Did not receive username"); return PARSE_OK; } m_Username = UserData[0]; LOGD("HANDSHAKE %s", Username.c_str()); if (!m_Client->HandleHandshake( m_Username )) { return PARSE_OK; // Player is not allowed into the server } SendHandshake(cRoot::Get()->GetServer()->GetServerID()); LOGD("User \"%s\" was sent a handshake response", m_Username.c_str()); return PARSE_OK; }
void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames) { // Create a list of names to query, by removing those that are already cached: AStringVector NamesToQuery; NamesToQuery.reserve(a_PlayerNames.size()); { cCSLock Lock(m_CSNameToUUID); for (AStringVector::const_iterator itr = a_PlayerNames.begin(), end = a_PlayerNames.end(); itr != end; ++itr) { if (m_NameToUUID.find(*itr) == m_NameToUUID.end()) { NamesToQuery.push_back(*itr); } } // for itr - a_PlayerNames[] } // Lock(m_CSNameToUUID) while (!NamesToQuery.empty()) { // Create the request body - a JSON containing up to MAX_PER_QUERY playernames: Json::Value root; int Count = 0; AStringVector::iterator itr = NamesToQuery.begin(), end = NamesToQuery.end(); for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count) { Json::Value req(*itr); root.append(req); } // for itr - a_PlayerNames[] NamesToQuery.erase(NamesToQuery.begin(), itr); Json::FastWriter Writer; AString RequestBody = Writer.write(root); // Create the HTTP request: AString Request; Request += "POST " + m_NameToUUIDAddress + " HTTP/1.0\r\n"; // We need to use HTTP 1.0 because we don't handle Chunked transfer encoding Request += "Host: " + m_NameToUUIDServer + "\r\n"; Request += "User-Agent: MCServer\r\n"; Request += "Connection: close\r\n"; Request += "Content-Type: application/json\r\n"; Request += Printf("Content-Length: %u\r\n", (unsigned)RequestBody.length()); Request += "\r\n"; Request += RequestBody; // Get the response from the server: AString Response; if (!SecureRequest(m_NameToUUIDServer, Request, Response)) { continue; } // Check the HTTP status line: const AString Prefix("HTTP/1.1 200 OK"); AString HexDump; if (Response.compare(0, Prefix.size(), Prefix)) { LOGINFO("%s failed: bad HTTP status line received", __FUNCTION__); LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); continue; } // Erase the HTTP headers from the response: size_t idxHeadersEnd = Response.find("\r\n\r\n"); if (idxHeadersEnd == AString::npos) { LOGINFO("%s failed: bad HTTP response header received", __FUNCTION__); LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); continue; } Response.erase(0, idxHeadersEnd + 4); // Parse the returned string into Json: Json::Reader reader; if (!reader.parse(Response, root, false) || !root.isArray()) { LOGWARNING("%s failed: Cannot parse received data (NameToUUID) to JSON!", __FUNCTION__); LOGD("Response body:\n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); continue; } // Store the returned results into cache: size_t JsonCount = root.size(); Int64 Now = time(NULL); { cCSLock Lock(m_CSNameToUUID); for (size_t idx = 0; idx < JsonCount; ++idx) { Json::Value & Val = root[idx]; AString JsonName = Val.get("name", "").asString(); AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString()); if (JsonUUID.empty()) { continue; } m_NameToUUID[StrToLower(JsonName)] = sProfile(JsonName, JsonUUID, "", "", Now); } // for idx - root[] } // cCSLock (m_CSNameToUUID) // Also cache the UUIDToName: { cCSLock Lock(m_CSUUIDToName); for (size_t idx = 0; idx < JsonCount; ++idx) { Json::Value & Val = root[idx]; AString JsonName = Val.get("name", "").asString(); AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString()); if (JsonUUID.empty()) { continue; } m_UUIDToName[JsonUUID] = sProfile(JsonName, JsonUUID, "", "", Now); } // for idx - root[] } } // while (!NamesToQuery.empty()) }
void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output) { AStringVector split = StringSplit(a_Cmd, " "); if (split.empty()) { return; } // "stop" and "restart" are handled in cRoot::ExecuteConsoleCommand, our caller, due to its access to controlling variables // "help" and "reload" are to be handled by MCS, so that they work no matter what if (split[0] == "help") { PrintHelp(split, a_Output); a_Output.Finished(); return; } else if (split[0] == "reload") { cPluginManager::Get()->ReloadPlugins(); a_Output.Finished(); return; } else if (split[0] == "reloadplugins") { cPluginManager::Get()->ReloadPlugins(); a_Output.Out("Plugins reloaded"); a_Output.Finished(); return; } else if (split[0] == "load") { if (split.size() > 1) { cPluginManager::Get()->RefreshPluginList(); // Refresh the plugin list, so that if the plugin was added just now, it is loadable a_Output.Out(cPluginManager::Get()->LoadPlugin(split[1]) ? "Plugin loaded" : "Error occurred loading plugin"); } else { a_Output.Out("Usage: load <PluginFolder>"); } a_Output.Finished(); return; } else if (split[0] == "unload") { if (split.size() > 1) { cPluginManager::Get()->UnloadPlugin(split[1]); a_Output.Out("Plugin unload scheduled"); } else { a_Output.Out("Usage: unload <PluginFolder>"); } a_Output.Finished(); return; } if (split[0] == "destroyentities") { class WorldCallback : public cWorldListCallback { virtual bool Item(cWorld * a_World) override { class EntityCallback : public cEntityCallback { virtual bool Item(cEntity * a_Entity) override { if (!a_Entity->IsPlayer()) { a_Entity->Destroy(); } return false; } } EC; a_World->ForEachEntity(EC); return false; } } WC; cRoot::Get()->ForEachWorld(WC); a_Output.Out("Destroyed all entities"); a_Output.Finished(); return; } // There is currently no way a plugin can do these (and probably won't ever be): else if (split[0].compare("chunkstats") == 0) { cRoot::Get()->LogChunkStats(a_Output); a_Output.Finished(); return; } #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) else if (split[0].compare("dumpmem") == 0) { LeakFinderXmlOutput Output("memdump.xml"); DumpUsedMemory(&Output); return; } else if (split[0].compare("killmem") == 0) { for (;;) { new char[100 * 1024 * 1024]; // Allocate and leak 100 MiB in a loop -> fill memory and kill MCS } } #endif else if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output, a_Cmd)) { a_Output.Finished(); return; } a_Output.Out("Unknown command, type 'help' for all commands."); a_Output.Finished(); }
void cCraftingRecipes::AddRecipeLine(int a_LineNum, const AString & a_RecipeLine) { // Remove any spaces within the line: AString RecipeLine(a_RecipeLine); RecipeLine.erase(std::remove_if(RecipeLine.begin(), RecipeLine.end(), isspace), RecipeLine.end()); AStringVector Sides = StringSplit(RecipeLine, "="); if (Sides.size() != 2) { LOGWARNING("crafting.txt: line %d: A single '=' was expected, got %d", a_LineNum, (int)Sides.size() - 1); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } std::unique_ptr<cCraftingRecipes::cRecipe> Recipe(new cCraftingRecipes::cRecipe); // Parse the result: AStringVector ResultSplit = StringSplit(Sides[0], ","); if (ResultSplit.empty()) { LOGWARNING("crafting.txt: line %d: Result is empty, ignoring the recipe.", a_LineNum); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } if (!ParseItem(ResultSplit[0], Recipe->m_Result)) { LOGWARNING("crafting.txt: line %d: Cannot parse result item, ignoring the recipe.", a_LineNum); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } if (ResultSplit.size() > 1) { if (!StringToInteger<char>(ResultSplit[1].c_str(), Recipe->m_Result.m_ItemCount)) { LOGWARNING("crafting.txt: line %d: Cannot parse result count, ignoring the recipe.", a_LineNum); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } } else { Recipe->m_Result.m_ItemCount = 1; } // Parse each ingredient: AStringVector Ingredients = StringSplit(Sides[1], "|"); int Num = 1; for (AStringVector::const_iterator itr = Ingredients.begin(); itr != Ingredients.end(); ++itr, ++Num) { if (!ParseIngredient(*itr, Recipe.get())) { LOGWARNING("crafting.txt: line %d: Cannot parse ingredient #%d, ignoring the recipe.", a_LineNum, Num); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } } // for itr - Ingredients[] NormalizeIngredients(Recipe.get()); m_Recipes.push_back(Recipe.release()); }
bool cListenThread::CreateSockets(const AString & a_PortsString) { AStringVector Ports = StringSplitAndTrim(a_PortsString, ","); if (Ports.empty()) { return false; } AString FamilyStr = m_ServiceName; switch (m_Family) { case cSocket::IPv4: FamilyStr.append(" IPv4"); break; case cSocket::IPv6: FamilyStr.append(" IPv6"); break; default: { ASSERT(!"Unknown address family"); break; } } for (AStringVector::const_iterator itr = Ports.begin(), end = Ports.end(); itr != end; ++itr) { int Port = atoi(itr->c_str()); if ((Port <= 0) || (Port > 65535)) { LOGWARNING("%s: Invalid port specified: \"%s\".", FamilyStr.c_str(), itr->c_str()); continue; } m_Sockets.push_back(cSocket::CreateSocket(m_Family)); if (!m_Sockets.back().IsValid()) { LOGWARNING("%s: Cannot create listening socket for port %d: \"%s\"", FamilyStr.c_str(), Port, cSocket::GetLastErrorString().c_str()); m_Sockets.pop_back(); continue; } if (m_ShouldReuseAddr) { if (!m_Sockets.back().SetReuseAddress()) { LOG("%s: Port %d cannot reuse addr, syscall failed: \"%s\".", FamilyStr.c_str(), Port, cSocket::GetLastErrorString().c_str()); } } // Bind to port: bool res = false; switch (m_Family) { case cSocket::IPv4: res = m_Sockets.back().BindToAnyIPv4(Port); break; case cSocket::IPv6: res = m_Sockets.back().BindToAnyIPv6(Port); break; default: { ASSERT(!"Unknown address family"); res = false; } } if (!res) { LOGWARNING("%s: Cannot bind port %d: \"%s\".", FamilyStr.c_str(), Port, cSocket::GetLastErrorString().c_str()); m_Sockets.pop_back(); continue; } if (!m_Sockets.back().Listen()) { LOGWARNING("%s: Cannot listen on port %d: \"%s\".", FamilyStr.c_str(), Port, cSocket::GetLastErrorString().c_str()); m_Sockets.pop_back(); continue; } LOGINFO("%s: Port %d is open for connections", FamilyStr.c_str(), Port); } // for itr - Ports[] return !(m_Sockets.empty()); }
bool cPluginLua::Load(void) { cCSLock Lock(m_CriticalSection); if (!m_LuaState.IsValid()) { m_LuaState.Create(); m_LuaState.RegisterAPILibs(); // Inject the identification global variables into the state: lua_pushlightuserdata(m_LuaState, this); lua_setglobal(m_LuaState, LUA_PLUGIN_INSTANCE_VAR_NAME); lua_pushstring(m_LuaState, GetName().c_str()); lua_setglobal(m_LuaState, LUA_PLUGIN_NAME_VAR_NAME); // Add the plugin's folder to the package.path and package.cpath variables (#693): m_LuaState.AddPackagePath("path", FILE_IO_PREFIX + GetLocalFolder() + "/?.lua"); #ifdef _WIN32 m_LuaState.AddPackagePath("cpath", GetLocalFolder() + "\\?.dll"); #else m_LuaState.AddPackagePath("cpath", FILE_IO_PREFIX + GetLocalFolder() + "/?.so"); #endif tolua_pushusertype(m_LuaState, this, "cPluginLua"); lua_setglobal(m_LuaState, "g_Plugin"); } std::string PluginPath = FILE_IO_PREFIX + GetLocalFolder() + "/"; // List all Lua files for this plugin. Info.lua has a special handling - make it the last to load: AStringVector Files = cFile::GetFolderContents(PluginPath.c_str()); AStringVector LuaFiles; bool HasInfoLua = false; for (AStringVector::const_iterator itr = Files.begin(), end = Files.end(); itr != end; ++itr) { if (itr->rfind(".lua") != AString::npos) { if (*itr == "Info.lua") { HasInfoLua = true; } else { LuaFiles.push_back(*itr); } } } std::sort(LuaFiles.begin(), LuaFiles.end()); // Warn if there are no Lua files in the plugin folder: if (LuaFiles.empty()) { SetLoadError("No lua files found, plugin is probably missing."); LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str()); Close(); return false; } // Load all files in the list, including the Info.lua as last, if it exists: for (AStringVector::const_iterator itr = LuaFiles.begin(), end = LuaFiles.end(); itr != end; ++itr) { AString Path = PluginPath + *itr; if (!m_LuaState.LoadFile(Path)) { SetLoadError(Printf("Failed to load file %s.", itr->c_str())); Close(); return false; } } // for itr - Files[] if (HasInfoLua) { AString Path = PluginPath + "Info.lua"; if (!m_LuaState.LoadFile(Path)) { SetLoadError("Failed to load file Info.lua."); m_Status = cPluginManager::psError; Close(); return false; } } // Call the Initialize function: bool res = false; if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res)) { SetLoadError("Cannot call the Initialize() function."); LOGWARNING("Error in plugin %s: Cannot call the Initialize() function. Plugin is temporarily disabled.", GetName().c_str()); Close(); return false; } if (!res) { SetLoadError("The Initialize() function failed."); LOGINFO("Plugin %s: Initialize() call failed, plugin is temporarily disabled.", GetName().c_str()); Close(); return false; } m_Status = cPluginManager::psLoaded; return true; }