Esempio n. 1
0
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);
}
Esempio n. 2
0
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());
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);	
}
Esempio n. 6
0
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();
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
	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);
	}
Esempio n. 11
0
	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;
	}
Esempio n. 12
0
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;
}
Esempio n. 13
0
	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;
	}
Esempio n. 14
0
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);
		}
	}
}
Esempio n. 15
0
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();
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
	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);
	}
Esempio n. 18
0
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;
}
Esempio n. 19
0
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())
}
Esempio n. 20
0
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();
}
Esempio n. 21
0
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());
}
Esempio n. 22
0
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());
}
Esempio n. 23
0
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;
}