diff options
Diffstat (limited to 'MCServer/Plugins/Core/console.lua')
-rw-r--r-- | MCServer/Plugins/Core/console.lua | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/MCServer/Plugins/Core/console.lua b/MCServer/Plugins/Core/console.lua new file mode 100644 index 000000000..669d7c9cb --- /dev/null +++ b/MCServer/Plugins/Core/console.lua @@ -0,0 +1,338 @@ +-- Implements things related to console commands + +function InitConsoleCommands() + local PluginMgr = cPluginManager:Get(); + + -- Please keep the list alpha-sorted + PluginMgr:BindConsoleCommand("ban", HandleConsoleBan, " ~ Bans a player by name"); + PluginMgr:BindConsoleCommand("banlist ips", HandleConsoleBanList, " - Lists all players banned by IP"); + PluginMgr:BindConsoleCommand("banlist", HandleConsoleBanList, " - Lists all players banned by name"); + PluginMgr:BindConsoleCommand("getversion", HandleConsoleVersion, " - Gets server version reported to 1.4+ clients"); + PluginMgr:BindConsoleCommand("help", HandleConsoleHelp, " - Lists all commands"); + PluginMgr:BindConsoleCommand("give", HandleConsoleGive, " - Gives items to the specified player.") + PluginMgr:BindConsoleCommand("list", HandleConsoleList, " - Lists all players in a machine-readable format"); + PluginMgr:BindConsoleCommand("listgroups", HandleConsoleListGroups, " - Shows a list of all the groups"); + PluginMgr:BindConsoleCommand("numchunks", HandleConsoleNumChunks, " - Shows number of chunks currently loaded"); + PluginMgr:BindConsoleCommand("players", HandleConsolePlayers, " - Lists all connected players"); + PluginMgr:BindConsoleCommand("rank", HandleConsoleRank, " ~ Add a player to a group"); + PluginMgr:BindConsoleCommand("reload", HandleConsoleReload, " - Reloads all plugins"); + PluginMgr:BindConsoleCommand("save-all", HandleConsoleSaveAll, " - Saves all chunks"); + PluginMgr:BindConsoleCommand("say", HandleConsoleSay, " - Sends a chat message to all players"); + PluginMgr:BindConsoleCommand("setversion", HandleConsoleVersion, " ~ Sets server version reported to 1.4+ clients"); + PluginMgr:BindConsoleCommand("unban", HandleConsoleUnban, " ~ Unbans a player by name"); + PluginMgr:BindConsoleCommand("unload", HandleConsoleUnload, " - Unloads all unused chunks"); + +end + +function HandleConsoleGive(Split) + + -- Make sure there are a correct number of arguments. + if #Split ~= 3 and #Split ~= 4 and #Split ~= 5 then + return true, "Usage: give <player> <item> [amount] [meta]" + end + + -- Get the item from the arguments and check it's valid. + local Item = cItem() + if #Split == 5 then + local FoundItem = StringToItem(Split[3] .. ":" .. Split[5], Item) + else + local FoundItem = StringToItem(Split[3], Item) + end + if not IsValidItem(Item.m_ItemType) then -- StringToItem does not check if item is valid + FoundItem = false + end + + if not FoundItem then + return true, "Invalid item id or name!" + end + + -- Work out how many items the user wants. + local ItemAmount = 1 + if #Split > 3 then + ItemAmount = tonumber(Split[4]) + if ItemAmount == nil or ItemAmount < 1 or ItemAmount > 512 then + return true, "Invalid amount!" + end + end + + Item.m_ItemCount = ItemAmount + + -- Get the playername from the split. + local playerName = Split[2] + + local function giveItems(newPlayer) + local ItemsGiven = newPlayer:GetInventory():AddItem(Item) + if ItemsGiven == ItemAmount then + SendMessageSuccess( newPlayer, "There you go!" ) + LOG("Gave " .. newPlayer:GetName() .. " " .. Item.m_ItemCount .. " times " .. Item.m_ItemType .. ":" .. Item.m_ItemDamage) + else + SendMessageFailure( Player, "Not enough space in inventory, only gave " .. ItemsGiven) + return true, "Only " .. Item.m_ItemCount .. " out of " .. ItemsGiven .. "items could be delivered." + end + end + + -- Finally give the items to the player. + itemStatus = cRoot:Get():FindAndDoWithPlayer(playerName, giveItems) + + -- Check to make sure that giving items was successful. + if not itemStatus then + return true, "There was no player that matched your query." + end + + return true + +end + +function HandleConsoleBan(Split) + if (#Split < 2) then + return true, "Usage: ban [Player] <Reason>"; + end + + local Reason = cChatColor.Red .. "You have been banned." .. cChatColor.White .. " Did you do something illegal?" + if( #Split > 2 ) then + Reason = table.concat(Split, " ", 3) + end + + if KickPlayer(Split[2], Reason) == false then + BannedPlayersIni:DeleteValue("Banned", Split[2]) + BannedPlayersIni:SetValueB("Banned", Split[2], true) + BannedPlayersIni:WriteFile() + LOGINFO("Could not find player, but banned anyway" ) + else + BannedPlayersIni:DeleteValue("Banned", Split[2]) + BannedPlayersIni:SetValueB("Banned", Split[2], true) + BannedPlayersIni:WriteFile() + LOGINFO("Successfully kicked and banned player" ) + end + + return true +end + +function HandleConsoleUnban(Split) + + if #Split < 2 then + return true, "Usage: /unban [Player]" + end + + if( BannedPlayersIni:GetValueB("Banned", Split[2], false) == false ) then + return true, Split[2] .. " is not banned!" + end + + BannedPlayersIni:SetValueB("Banned", Split[2], false, false) + BannedPlayersIni:WriteFile() + + local Server = cRoot:Get():GetServer() + return true, "Unbanned " .. Split[2] + +end + +function HandleConsoleBanList(Split) + if (#Split == 1) then + return true, BanListByName(); + end + + if (string.lower(Split[2]) == "ips") then + return true, BanListByIPs(); + end + + return true, "Unknown banlist subcommand"; +end + +function HandleConsoleHelp(Split) + local Commands = {}; -- {index => {"Command", "HelpString"} } + local MaxLength = 0; + local AddToTable = function(Command, HelpString) + table.insert(Commands, { Command, HelpString }); + local CmdLen = Command:len(); + if (CmdLen > MaxLength) then + MaxLength = CmdLen; + end + end + + cPluginManager:Get():ForEachConsoleCommand(AddToTable); + + -- Sort the table: + local CompareCommands = function(a, b) + return a[1] < b[1]; -- compare command strings + end + table.sort(Commands, CompareCommands); + + local Out = ""; + Out = "'-' denotes no prefix, '~' denotes that a value is required.\n" + for i, Command in ipairs(Commands) do + Out = Out .. Command[1] .. string.rep(" ", MaxLength - Command[1]:len()); -- Align to a table + Out = Out .. Command[2] .. "\n"; + end + return true, Out; +end + +function HandleConsoleList(Split) + -- Get a list of all players, one playername per line + local Out = ""; + cRoot:Get():ForEachWorld( + function (a_World) + a_World:ForEachPlayer( + function (a_Player) + Out = Out .. a_Player:GetName() .. "\n"; + end + ); + end + ); + return true, Out; +end + +function HandleConsoleListGroups(Split) + -- Read the groups.ini file: + local GroupsIni = cIniFile("groups.ini"); + if (not(GroupsIni:ReadFile())) then + return true, "No groups found"; + end + + -- Read the groups: + Number = GroupsIni:NumKeys(); + Groups = {}; + for i = 0, Number do + table.insert(Groups, GroupsIni:KeyName(i)) + end + + -- Output the groups, concatenated to a string: + local Out = "Groups:\n" + Out = Out .. table.concat(Groups, ", "); + return true, Out; +end + +function HandleConsoleNumChunks(Split) + local Output = {}; + local AddNumChunks = function(World) + Output[World:GetName()] = World:GetNumChunks(); + end; + + cRoot:Get():ForEachWorld(AddNumChunks); + + local Total = 0; + local Out = ""; + for name, num in pairs(Output) do + Out = Out .. " " .. name .. ": " .. num .. " chunks\n"; + Total = Total + num; + end + Out = Out .. "Total: " .. Total .. " chunks\n"; + + return true, Out; +end + +function HandleConsolePlayers(Split) + local PlayersInWorlds = {}; -- "WorldName" => [players array] + local AddToTable = function(Player) + local WorldName = Player:GetWorld():GetName(); + if (PlayersInWorlds[WorldName] == nil) then + PlayersInWorlds[WorldName] = {}; + end + table.insert(PlayersInWorlds[WorldName], Player:GetName() .. " @ " .. Player:GetIP()); + end + + cRoot:Get():ForEachPlayer(AddToTable); + + local Out = ""; + for WorldName, Players in pairs(PlayersInWorlds) do + Out = Out .. "World " .. WorldName .. ":\n"; + for i, PlayerName in ipairs(Players) do + Out = Out .. " " .. PlayerName .. "\n"; + end + end + + return true, Out; +end + +function HandleConsoleVersion(Split) + if (#Split == 1) then + -- Display current version: + local Version = cRoot:Get():GetPrimaryServerVersion(); + return true, "Primary server version: #" .. Version .. ", " .. cRoot:GetProtocolVersionTextFromInt(Version); + end + + -- Set new value as the version: + cRoot:Get():SetPrimaryServerVersion(tonumber(Split[2])); + local Version = cRoot:Get():GetPrimaryServerVersion(); + return true, "Primary server version is now #" .. Version .. ", " .. cRoot:GetProtocolVersionTextFromInt(Version); +end + +function HandleConsoleRank(Split) + if (Split[2] == nil) or (Split[3] == nil) then + return true, "Usage: /rank [Player] [Group]"; + end + local Out = ""; + + -- Read the groups.ini file: + local GroupsIni = cIniFile("groups.ini") + if (not(GroupsIni:ReadFile())) then + Out = "Could not read groups.ini, creating anew!\n" + end + + -- Find the group: + if (GroupsIni:FindKey(Split[3]) == -1) then + return true, Out .. "Group does not exist"; + end + + -- Read the users.ini file: + local UsersIni = cIniFile("users.ini"); + if (not(UsersIni:ReadFile())) then + Out = Out .. "Could not read users.ini, creating anew!\n"; + end + + -- Write the new group value to users.ini: + UsersIni:DeleteKey(Split[2]); + UsersIni:GetValueSet(Split[2], "Groups", Split[3]); + UsersIni:WriteFile(); + + -- Reload the player's permissions: + cRoot:Get():ForEachWorld( + function (World) + World:ForEachPlayer( + function (Player) + if (Player:GetName() == Split[2]) then + SendMessage( Player, "You were moved to group " .. Split[3] ) + Player:LoadPermissionsFromDisk(); + end + end + ); + end + ) + + return true, Out .. "Player " .. Split[2] .. " was moved to " .. Split[3]; +end + +function HandleConsoleReload(Split) + Server = cRoot:Get():GetServer(); + Server:SendMessage(cChatColor.Rose .. "[WARNING] " .. cChatColor.White .. "Reloading all plugins!"); + cPluginManager:Get():ReloadPlugins(); + return true; +end + +function HandleConsoleSaveAll(Split) + Server = cRoot:Get():GetServer(); + Server:SendMessage(cChatColor.Rose .. "[WARNING] " .. cChatColor.White .. "Saving all chunks!"); + cRoot:Get():SaveAllChunks(); + return true; +end + +function HandleConsoleSay(Split) + table.remove(Split, 1); + local Message = ""; + for i, Text in ipairs(Split) do + Message = Message .. " " .. Text; + end + Message = Message:sub(2); -- Cut off the first space + cRoot:Get():GetServer():BroadcastChat(cChatColor.Gold .. "[SERVER] " .. cChatColor.Yellow .. Message); + return true; +end + +function HandleConsoleUnload(Split) + local UnloadChunks = function(World) + World:UnloadUnusedChunks(); + end + + local Out = "Num loaded chunks before: " .. cRoot:Get():GetTotalChunkCount() .. "\n"; + cRoot:Get():ForEachWorld(UnloadChunks); + Out = Out .. "Num loaded chunks after: " .. cRoot:Get():GetTotalChunkCount(); + return true, Out; +end |