Advanced RCON: Command output is sent to the RCON client.
RCON authentication is now required before executing commands. Console command handlers now return two values, bool (IsHandled) and string (CommandOutput). API change: removed cRoot:ExecuteConsoleCommand(), added cRoot:QueueExecuteConsoleCommand(). API change: removed cPluginManager:ExecuteConsoleCommand(), use cRoot:QueueExecuteConsoleCommand() instead git-svn-id: http://mc-server.googlecode.com/svn/trunk@1631 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
cff6ff2223
commit
7b75aaea7c
@ -18,23 +18,27 @@ function HandleBanCommand( Split, Player )
|
||||
return true
|
||||
end
|
||||
|
||||
function BanPlayer( PlayerName, Reason )
|
||||
if( Reason == nil ) then
|
||||
|
||||
|
||||
|
||||
|
||||
function BanPlayer(PlayerName, Reason)
|
||||
-- Ban the player in the banned.ini:
|
||||
BannedPlayersIni:SetValueB("Banned", PlayerName, true)
|
||||
BannedPlayersIni:WriteFile()
|
||||
|
||||
-- Kick the player:
|
||||
if (Reason == nil) then
|
||||
Reason = "You have been banned"
|
||||
end
|
||||
|
||||
local Success, RealName = KickPlayer( PlayerName, Reason )
|
||||
if( Success == false ) then
|
||||
return false
|
||||
local Success = KickPlayer(PlayerName, Reason)
|
||||
if (not(Success)) then
|
||||
return false;
|
||||
end
|
||||
|
||||
LOGINFO( "'" .. RealName .. "' is being banned for ( "..Reason..") " )
|
||||
|
||||
local Server = cRoot:Get():GetServer()
|
||||
Server:SendMessage( "Banning " .. RealName )
|
||||
|
||||
BannedPlayersIni:SetValueB("Banned", RealName, true)
|
||||
BannedPlayersIni:WriteFile()
|
||||
LOGINFO("'" .. PlayerName .. "' has been banned (\"" .. Reason .. "\") ");
|
||||
local Server = cRoot:Get():GetServer();
|
||||
Server:SendMessage("Banned " .. PlayerName);
|
||||
|
||||
return true
|
||||
end
|
@ -9,16 +9,60 @@
|
||||
|
||||
function InitConsoleCommands()
|
||||
local PluginMgr = cPluginManager:Get();
|
||||
|
||||
-- Please keep the list alpha-sorted
|
||||
PluginMgr:BindConsoleCommand("ban", HandleConsoleBan, "Bans a player by name");
|
||||
PluginMgr:BindConsoleCommand("banlist", HandleConsoleBanList, "Lists all players banned by name");
|
||||
PluginMgr:BindConsoleCommand("banlist ips", HandleConsoleBanList, "Lists all players banned by IP");
|
||||
PluginMgr:BindConsoleCommand("help", HandleConsoleHelp, "Lists all commands");
|
||||
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("primaryserverversion", HandleConsolePrimaryServerVersion, "Gets or sets server version reported to 1.4+ clients");
|
||||
PluginMgr:BindConsoleCommand("rank", HandleConsoleRank, " [Player] [Group] - 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("unload", HandleConsoleUnload, "Unloads all unused chunks");
|
||||
PluginMgr:BindConsoleCommand("rank", HandleConsoleRank, " [Player] [Rank] - to add someone to a group");
|
||||
PluginMgr:BindConsoleCommand("listgroups", HandleConsoleListGroups, "Shows a list of all the groups");
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function HandleConsoleBan(Split)
|
||||
if (#Split < 2) then
|
||||
return true, cChatColor.Green .. "Usage: /ban [Player] <Reason>";
|
||||
end
|
||||
|
||||
local Reason = "You have been banned"
|
||||
if (#Split > 2) then
|
||||
Reason = table.concat(Split, " ", 3);
|
||||
end
|
||||
|
||||
|
||||
if (not(BanPlayer(Split[2], Reason))) then
|
||||
return true, cChatColor.Green .. "Could not find player " .. Split[2];
|
||||
end
|
||||
|
||||
return true, "Player " .. Split[2] .. " has been banned.";
|
||||
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
|
||||
|
||||
|
||||
@ -44,11 +88,55 @@ function HandleConsoleHelp(Split)
|
||||
end
|
||||
table.sort(Commands, CompareCommands);
|
||||
|
||||
local Out = "";
|
||||
for i, Command in ipairs(Commands) do
|
||||
local Cmd = Command[1] .. string.rep(" ", MaxLength - Command[1]:len()); -- Align to a table
|
||||
LOG(Cmd .. " - " .. Command[2]);
|
||||
Out = Out .. Command[1] .. string.rep(" ", MaxLength - Command[1]:len()); -- Align to a table
|
||||
Out = Out .. " - " .. Command[2] .. "\n";
|
||||
end
|
||||
return true;
|
||||
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
|
||||
|
||||
|
||||
@ -64,13 +152,14 @@ function HandleConsoleNumChunks(Split)
|
||||
cRoot:Get():ForEachWorld(AddNumChunks);
|
||||
|
||||
local Total = 0;
|
||||
local Out = "";
|
||||
for name, num in pairs(Output) do
|
||||
LOG(" " .. name .. ": " .. num .. " chunks");
|
||||
Out = Out .. " " .. name .. ": " .. num .. " chunks\n";
|
||||
Total = Total + num;
|
||||
end
|
||||
LOG("Total: " .. Total .. " chunks");
|
||||
Out = Out .. "Total: " .. Total .. " chunks\n";
|
||||
|
||||
return true;
|
||||
return true, Out;
|
||||
end
|
||||
|
||||
|
||||
@ -89,14 +178,15 @@ function HandleConsolePlayers(Split)
|
||||
|
||||
cRoot:Get():ForEachPlayer(AddToTable);
|
||||
|
||||
local Out = "";
|
||||
for WorldName, Players in pairs(PlayersInWorlds) do
|
||||
LOG("World " .. WorldName .. ":");
|
||||
Out = Out .. "World " .. WorldName .. ":\n";
|
||||
for i, PlayerName in ipairs(Players) do
|
||||
LOG(" " .. PlayerName);
|
||||
Out = Out .. " " .. PlayerName .. "\n";
|
||||
end
|
||||
end
|
||||
|
||||
return true;
|
||||
return true, Out;
|
||||
end
|
||||
|
||||
|
||||
@ -107,15 +197,62 @@ function HandleConsolePrimaryServerVersion(Split)
|
||||
if (#Split == 1) then
|
||||
-- Display current version:
|
||||
local Version = cRoot:Get():GetPrimaryServerVersion();
|
||||
LOG("Primary server version: #" .. Version .. ", " .. cRoot:GetProtocolVersionTextFromInt(Version));
|
||||
return true;
|
||||
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();
|
||||
LOG("Primary server version is now #" .. Version .. ", " .. cRoot:GetProtocolVersionTextFromInt(Version));
|
||||
return true;
|
||||
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
|
||||
Player:SendMessage(cChatColor.Green .. "You were moved to group " .. Split[3]);
|
||||
Player:LoadPermissionsFromDisk();
|
||||
end
|
||||
end
|
||||
);
|
||||
end
|
||||
)
|
||||
|
||||
return true, Out .. "Player " .. Split[2] .. " was moved to " .. Split[3];
|
||||
end
|
||||
|
||||
|
||||
@ -162,10 +299,10 @@ function HandleConsoleUnload(Split)
|
||||
World:UnloadUnusedChunks();
|
||||
end
|
||||
|
||||
LOGINFO("Num loaded chunks before: " .. cRoot:Get():GetTotalChunkCount());
|
||||
local Out = "Num loaded chunks before: " .. cRoot:Get():GetTotalChunkCount() .. "\n";
|
||||
cRoot:Get():ForEachWorld(UnloadChunks);
|
||||
LOGINFO("Num loaded chunks after: " .. cRoot:Get():GetTotalChunkCount());
|
||||
return true;
|
||||
Out = Out .. "Num loaded chunks after: " .. cRoot:Get():GetTotalChunkCount();
|
||||
return true, Out;
|
||||
end
|
||||
|
||||
|
||||
@ -173,75 +310,34 @@ end
|
||||
|
||||
|
||||
|
||||
function HandleConsoleRank(Split)
|
||||
if Split[2] == nil or Split[3] == nil then
|
||||
LOG("Usage: /rank [Player] [Group]")
|
||||
return true
|
||||
end
|
||||
local GroupsIni = cIniFile("groups.ini")
|
||||
if( GroupsIni:ReadFile() == false ) then
|
||||
LOG("Could not read groups.ini!")
|
||||
end
|
||||
if GroupsIni:FindKey(Split[3]) == -1 then
|
||||
LOG("Group does not exist")
|
||||
return true
|
||||
end
|
||||
local UsersIni = cIniFile("users.ini")
|
||||
if( UsersIni:ReadFile() == false ) then
|
||||
LOG("Could not read users.ini!")
|
||||
end
|
||||
UsersIni:DeleteKey(Split[2])
|
||||
UsersIni:GetValueSet(Split[2], "Groups", Split[3])
|
||||
UsersIni:WriteFile()
|
||||
local loopPlayers = function( Player )
|
||||
if Player:GetName() == Split[2] then
|
||||
Player:SendMessage( cChatColor.Green .. "You were moved to group " .. Split[3] )
|
||||
Player:LoadPermissionsFromDisk()
|
||||
-------------------------------------------------------------------------------------------
|
||||
-- Helper functions:
|
||||
|
||||
--- Returns the list of players banned by name, separated by ", "
|
||||
function BanListByName()
|
||||
local NumValues = BannedPlayersIni:NumValues("Banned");
|
||||
local Banned = {};
|
||||
local KeyID = BannedPlayersIni:FindKey("Banned");
|
||||
for i = 1, NumValues do
|
||||
local PlayerName = BannedPlayersIni:ValueName(KeyID, i - 1);
|
||||
if (BannedPlayersIni:GetValueB("Banned", PlayerName)) then
|
||||
-- Player listed AND banned
|
||||
table.insert(Banned, PlayerName);
|
||||
end
|
||||
end
|
||||
local loopWorlds = function ( World )
|
||||
World:ForEachPlayer( loopPlayers )
|
||||
end
|
||||
cRoot:Get():ForEachWorld( loopWorlds )
|
||||
LOG("Player " .. Split[2] .. " Was moved to " .. Split[3])
|
||||
return true
|
||||
return table.concat(Banned, ", ");
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function HandleConsoleListGroups(Split)
|
||||
local GroupsIni = cIniFile("groups.ini")
|
||||
if GroupsIni:ReadFile() == false then
|
||||
LOG( "No groups found" )
|
||||
end
|
||||
Number = GroupsIni:NumKeys()
|
||||
Groups = {}
|
||||
for i=0, Number do
|
||||
table.insert( Groups, GroupsIni:KeyName(i) )
|
||||
end
|
||||
LOGINFO( "Groups:" )
|
||||
LOGINFO( table.concat( Groups, ", " ) )
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
function HandleConsole(Split)
|
||||
return true;
|
||||
--- Returns the list of players banned by IP, separated by ", "
|
||||
function BanListByIPs()
|
||||
-- TODO: No IP ban implemented yet
|
||||
return "";
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function HandleConsole(Split)
|
||||
return true;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -17,26 +17,30 @@ function HandleKickCommand( Split, Player )
|
||||
end
|
||||
|
||||
|
||||
function KickPlayer( PlayerName, Reason )
|
||||
local RealName = ""
|
||||
local FoundPlayerCallback = function( OtherPlayer )
|
||||
if( Reason == nil ) then
|
||||
Reason = "You have been kicked"
|
||||
end
|
||||
|
||||
RealName = OtherPlayer:GetName()
|
||||
|
||||
|
||||
|
||||
--- Kicks a player by name, with the specified reason; returns bool whether found and player's real name
|
||||
function KickPlayer(PlayerName, Reason)
|
||||
local RealName = "";
|
||||
if (Reason == nil) then
|
||||
Reason = "You have been kicked";
|
||||
end
|
||||
|
||||
local FoundPlayerCallback = function(a_Player)
|
||||
RealName = a_Player:GetName()
|
||||
|
||||
local Server = cRoot:Get():GetServer()
|
||||
LOGINFO( "'" .. RealName .. "' is being kicked for ( "..Reason..") " )
|
||||
Server:SendMessage( "Kicking " .. RealName )
|
||||
Server:SendMessage("Kicking " .. RealName)
|
||||
|
||||
local ClientHandle = OtherPlayer:GetClientHandle()
|
||||
ClientHandle:Kick( Reason )
|
||||
a_Player:GetClientHandle():Kick(Reason);
|
||||
end
|
||||
|
||||
if( cRoot:Get():FindAndDoWithPlayer( PlayerName, FoundPlayerCallback ) == false ) then
|
||||
return false -- could not find player
|
||||
if (not(cRoot:Get():FindAndDoWithPlayer( PlayerName, FoundPlayerCallback))) then
|
||||
-- Could not find player
|
||||
return false;
|
||||
end
|
||||
|
||||
return true, RealName -- player should be kicked now
|
||||
return true, RealName; -- Player has been kicked
|
||||
end
|
@ -1,13 +1,13 @@
|
||||
function HandleRequest_ManageServer( Request )
|
||||
local Content = ""
|
||||
if( Request.PostParams["RestartServer"] ~= nil ) then
|
||||
cRoot:Get():ExecuteConsoleCommand("restart")
|
||||
elseif( Request.PostParams["ReloadServer"] ~= nil ) then
|
||||
cRoot:Get():GetPluginManager():ReloadPlugins()
|
||||
elseif( Request.PostParams["StopServer"] ~= nil ) then
|
||||
cRoot:Get():ExecuteConsoleCommand("stop")
|
||||
elseif( Request.PostParams["WorldSaveAllChunks"] ~= nil ) then
|
||||
cRoot:Get():GetWorld(Request.PostParams["WorldSaveAllChunks"]):SaveAllChunks()
|
||||
if (Request.PostParams["RestartServer"] ~= nil) then
|
||||
cRoot:Get():QueueExecuteConsoleCommand("restart");
|
||||
elseif (Request.PostParams["ReloadServer"] ~= nil) then
|
||||
cRoot:Get():GetPluginManager():ReloadPlugins();
|
||||
elseif (Request.PostParams["StopServer"] ~= nil) then
|
||||
cRoot:Get():QueueExecuteConsoleCommand("stop");
|
||||
elseif (Request.PostParams["WorldSaveAllChunks"] ~= nil) then
|
||||
cRoot:Get():GetWorld(Request.PostParams["WorldSaveAllChunks"]):SaveAllChunks();
|
||||
end
|
||||
Content = Content .. [[
|
||||
<form method="POST">
|
||||
|
@ -362,6 +362,14 @@
|
||||
RelativePath="..\source\ClientHandle.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\CommandOutput.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\CommandOutput.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\CraftingRecipes.cpp"
|
||||
>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 06/22/13 19:31:23.
|
||||
** Generated automatically by tolua++-1.0.92 on 06/29/13 17:21:35.
|
||||
*/
|
||||
|
||||
#ifndef __cplusplus
|
||||
@ -195,7 +195,7 @@ static void tolua_reg_types (lua_State* tolua_S)
|
||||
{
|
||||
tolua_usertype(tolua_S,"TakeDamageInfo");
|
||||
tolua_usertype(tolua_S,"cCraftingRecipe");
|
||||
tolua_usertype(tolua_S,"cEntity");
|
||||
tolua_usertype(tolua_S,"cPlugin_NewLua");
|
||||
tolua_usertype(tolua_S,"cStringMap");
|
||||
tolua_usertype(tolua_S,"cItemGrid");
|
||||
tolua_usertype(tolua_S,"cBlockArea");
|
||||
@ -205,48 +205,47 @@ static void tolua_reg_types (lua_State* tolua_S)
|
||||
tolua_usertype(tolua_S,"cRoot");
|
||||
tolua_usertype(tolua_S,"cWindow");
|
||||
tolua_usertype(tolua_S,"cCraftingGrid");
|
||||
tolua_usertype(tolua_S,"cTracer");
|
||||
tolua_usertype(tolua_S,"cPickup");
|
||||
tolua_usertype(tolua_S,"cItems");
|
||||
tolua_usertype(tolua_S,"cGroup");
|
||||
tolua_usertype(tolua_S,"cClientHandle");
|
||||
tolua_usertype(tolua_S,"cChunkDesc");
|
||||
tolua_usertype(tolua_S,"cFurnaceRecipe");
|
||||
tolua_usertype(tolua_S,"cCuboid");
|
||||
tolua_usertype(tolua_S,"cTracer");
|
||||
tolua_usertype(tolua_S,"cChatColor");
|
||||
tolua_usertype(tolua_S,"cCuboid");
|
||||
tolua_usertype(tolua_S,"Vector3i");
|
||||
tolua_usertype(tolua_S,"cPlugin_NewLua");
|
||||
tolua_usertype(tolua_S,"Lua__cWebPlugin");
|
||||
tolua_usertype(tolua_S,"Lua__cPawn");
|
||||
tolua_usertype(tolua_S,"cWebAdmin");
|
||||
tolua_usertype(tolua_S,"cEntity");
|
||||
tolua_usertype(tolua_S,"cItem");
|
||||
tolua_usertype(tolua_S,"Vector3f");
|
||||
tolua_usertype(tolua_S,"cCraftingRecipes");
|
||||
tolua_usertype(tolua_S,"cWebAdmin");
|
||||
tolua_usertype(tolua_S,"cDropSpenserEntity");
|
||||
tolua_usertype(tolua_S,"Lua__cPlayer");
|
||||
tolua_usertype(tolua_S,"cItemGrid::cListener");
|
||||
tolua_usertype(tolua_S,"cCraftingRecipes");
|
||||
tolua_usertype(tolua_S,"cChestEntity");
|
||||
tolua_usertype(tolua_S,"cDispenserEntity");
|
||||
tolua_usertype(tolua_S,"Lua__cPickup");
|
||||
tolua_usertype(tolua_S,"cPlugin");
|
||||
tolua_usertype(tolua_S,"cBlockEntity");
|
||||
tolua_usertype(tolua_S,"cCriticalSection");
|
||||
tolua_usertype(tolua_S,"Lua__cPickup");
|
||||
tolua_usertype(tolua_S,"cWebPlugin");
|
||||
tolua_usertype(tolua_S,"HTTPRequest");
|
||||
tolua_usertype(tolua_S,"HTTPFormData");
|
||||
tolua_usertype(tolua_S,"cFurnaceEntity");
|
||||
tolua_usertype(tolua_S,"cDropperEntity");
|
||||
tolua_usertype(tolua_S,"cPluginManager");
|
||||
tolua_usertype(tolua_S,"cWorld");
|
||||
tolua_usertype(tolua_S,"cDropperEntity");
|
||||
tolua_usertype(tolua_S,"cIniFile");
|
||||
tolua_usertype(tolua_S,"cPlugin");
|
||||
tolua_usertype(tolua_S,"AStringVector");
|
||||
tolua_usertype(tolua_S,"cWorld");
|
||||
tolua_usertype(tolua_S,"cListeners");
|
||||
tolua_usertype(tolua_S,"cPawn");
|
||||
tolua_usertype(tolua_S,"cPlayer");
|
||||
tolua_usertype(tolua_S,"cGroupManager");
|
||||
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
|
||||
tolua_usertype(tolua_S,"cBlockEntityWithItems");
|
||||
tolua_usertype(tolua_S,"cItemGrid::cListener");
|
||||
tolua_usertype(tolua_S,"cServer");
|
||||
tolua_usertype(tolua_S,"cListeners");
|
||||
tolua_usertype(tolua_S,"cBlockEntityWithItems");
|
||||
tolua_usertype(tolua_S,"Lua__cEntity");
|
||||
tolua_usertype(tolua_S,"Vector3d");
|
||||
}
|
||||
@ -5878,18 +5877,20 @@ static int tolua_AllToLua_cEntity_Destroy00(lua_State* tolua_S)
|
||||
tolua_Error tolua_err;
|
||||
if (
|
||||
!tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
|
||||
!tolua_isnoobj(tolua_S,2,&tolua_err)
|
||||
!tolua_isboolean(tolua_S,2,1,&tolua_err) ||
|
||||
!tolua_isnoobj(tolua_S,3,&tolua_err)
|
||||
)
|
||||
goto tolua_lerror;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
|
||||
bool a_ShouldBroadcast = ((bool) tolua_toboolean(tolua_S,2,true));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Destroy'", NULL);
|
||||
#endif
|
||||
{
|
||||
self->Destroy();
|
||||
self->Destroy(a_ShouldBroadcast);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -10169,40 +10170,6 @@ static int tolua_AllToLua_cPluginManager_IsConsoleCommandBound00(lua_State* tolu
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: ExecuteConsoleCommand of class cPluginManager */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPluginManager_ExecuteConsoleCommand00
|
||||
static int tolua_AllToLua_cPluginManager_ExecuteConsoleCommand00(lua_State* tolua_S)
|
||||
{
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_Error tolua_err;
|
||||
if (
|
||||
!tolua_isusertype(tolua_S,1,"cPluginManager",0,&tolua_err) ||
|
||||
(tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const AStringVector",0,&tolua_err)) ||
|
||||
!tolua_isnoobj(tolua_S,3,&tolua_err)
|
||||
)
|
||||
goto tolua_lerror;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
|
||||
const AStringVector* a_Split = ((const AStringVector*) tolua_tousertype(tolua_S,2,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'ExecuteConsoleCommand'", NULL);
|
||||
#endif
|
||||
{
|
||||
bool tolua_ret = (bool) self->ExecuteConsoleCommand(*a_Split);
|
||||
tolua_pushboolean(tolua_S,(bool)tolua_ret);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_lerror:
|
||||
tolua_error(tolua_S,"#ferror in function 'ExecuteConsoleCommand'.",&tolua_err);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: GetName of class cPlugin */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlugin_GetName00
|
||||
static int tolua_AllToLua_cPlugin_GetName00(lua_State* tolua_S)
|
||||
@ -18771,9 +18738,9 @@ static int tolua_AllToLua_cRoot_GetPluginManager00(lua_State* tolua_S)
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: ExecuteConsoleCommand of class cRoot */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cRoot_ExecuteConsoleCommand00
|
||||
static int tolua_AllToLua_cRoot_ExecuteConsoleCommand00(lua_State* tolua_S)
|
||||
/* method: QueueExecuteConsoleCommand of class cRoot */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cRoot_QueueExecuteConsoleCommand00
|
||||
static int tolua_AllToLua_cRoot_QueueExecuteConsoleCommand00(lua_State* tolua_S)
|
||||
{
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_Error tolua_err;
|
||||
@ -18789,17 +18756,17 @@ static int tolua_AllToLua_cRoot_ExecuteConsoleCommand00(lua_State* tolua_S)
|
||||
cRoot* self = (cRoot*) tolua_tousertype(tolua_S,1,0);
|
||||
const AString a_Cmd = ((const AString) tolua_tocppstring(tolua_S,2,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'ExecuteConsoleCommand'", NULL);
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'QueueExecuteConsoleCommand'", NULL);
|
||||
#endif
|
||||
{
|
||||
self->ExecuteConsoleCommand(a_Cmd);
|
||||
self->QueueExecuteConsoleCommand(a_Cmd);
|
||||
tolua_pushcppstring(tolua_S,(const char*)a_Cmd);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_lerror:
|
||||
tolua_error(tolua_S,"#ferror in function 'ExecuteConsoleCommand'.",&tolua_err);
|
||||
tolua_error(tolua_S,"#ferror in function 'QueueExecuteConsoleCommand'.",&tolua_err);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@ -28187,7 +28154,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
||||
tolua_function(tolua_S,"ExecuteCommand",tolua_AllToLua_cPluginManager_ExecuteCommand00);
|
||||
tolua_function(tolua_S,"ForceExecuteCommand",tolua_AllToLua_cPluginManager_ForceExecuteCommand00);
|
||||
tolua_function(tolua_S,"IsConsoleCommandBound",tolua_AllToLua_cPluginManager_IsConsoleCommandBound00);
|
||||
tolua_function(tolua_S,"ExecuteConsoleCommand",tolua_AllToLua_cPluginManager_ExecuteConsoleCommand00);
|
||||
tolua_endmodule(tolua_S);
|
||||
tolua_cclass(tolua_S,"cPlugin","cPlugin","",NULL);
|
||||
tolua_beginmodule(tolua_S,"cPlugin");
|
||||
@ -28599,7 +28565,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
||||
tolua_function(tolua_S,"GetFurnaceRecipe",tolua_AllToLua_cRoot_GetFurnaceRecipe00);
|
||||
tolua_function(tolua_S,"GetWebAdmin",tolua_AllToLua_cRoot_GetWebAdmin00);
|
||||
tolua_function(tolua_S,"GetPluginManager",tolua_AllToLua_cRoot_GetPluginManager00);
|
||||
tolua_function(tolua_S,"ExecuteConsoleCommand",tolua_AllToLua_cRoot_ExecuteConsoleCommand00);
|
||||
tolua_function(tolua_S,"QueueExecuteConsoleCommand",tolua_AllToLua_cRoot_QueueExecuteConsoleCommand00);
|
||||
tolua_function(tolua_S,"GetTotalChunkCount",tolua_AllToLua_cRoot_GetTotalChunkCount00);
|
||||
tolua_function(tolua_S,"SaveAllChunks",tolua_AllToLua_cRoot_SaveAllChunks00);
|
||||
tolua_function(tolua_S,"GetProtocolVersionTextFromInt",tolua_AllToLua_cRoot_GetProtocolVersionTextFromInt00);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 06/22/13 19:31:24.
|
||||
** Generated automatically by tolua++-1.0.92 on 06/29/13 17:21:36.
|
||||
*/
|
||||
|
||||
/* Exported function */
|
||||
|
71
source/CommandOutput.cpp
Normal file
71
source/CommandOutput.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
// CommandOutput.cpp
|
||||
|
||||
// Implements the various classes that process command output
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CommandOutput.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cCommandOutputCallback:
|
||||
|
||||
void cCommandOutputCallback::Out(const char * a_Fmt, ...)
|
||||
{
|
||||
AString Output;
|
||||
va_list args;
|
||||
va_start(args, a_Fmt);
|
||||
AppendVPrintf(Output, a_Fmt, args);
|
||||
va_end(args);
|
||||
Output.append("\n");
|
||||
Out(Output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cLogCommandOutputCallback:
|
||||
|
||||
void cLogCommandOutputCallback::Out(const AString & a_Text)
|
||||
{
|
||||
m_Buffer.append(a_Text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cLogCommandOutputCallback::Finished(void)
|
||||
{
|
||||
// Log each line separately:
|
||||
size_t len = m_Buffer.length();
|
||||
size_t last = 0;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
switch (m_Buffer[i])
|
||||
{
|
||||
case '\n':
|
||||
{
|
||||
LOG(m_Buffer.substr(last, i - last).c_str());
|
||||
last = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // for i - m_Buffer[]
|
||||
if (last < len)
|
||||
{
|
||||
LOG(m_Buffer.substr(last).c_str());
|
||||
}
|
||||
|
||||
// Clear the buffer for the next command output:
|
||||
m_Buffer.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
82
source/CommandOutput.h
Normal file
82
source/CommandOutput.h
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
// CommandOutput.h
|
||||
|
||||
// Declares various classes that process command output
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Interface for a callback that receives command output
|
||||
The Out() function is called for any output the command has produced.
|
||||
Descendants override that function to provide specific processing of the output.
|
||||
*/
|
||||
class cCommandOutputCallback
|
||||
{
|
||||
public:
|
||||
virtual ~cCommandOutputCallback() {}; // Force a virtual destructor in subclasses
|
||||
|
||||
/// Syntax sugar function, calls Out() with Printf()-ed parameters; appends a "\n"
|
||||
void Out(const char * a_Fmt, ...);
|
||||
|
||||
/// Called when the command wants to output anything; may be called multiple times
|
||||
virtual void Out(const AString & a_Text) = 0;
|
||||
|
||||
/// Called when the command processing has been finished
|
||||
virtual void Finished(void) {};
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Class that discards all command output
|
||||
class cNullCommandOutputCallback :
|
||||
public cCommandOutputCallback
|
||||
{
|
||||
// cCommandOutputCallback overrides:
|
||||
virtual void Out(const AString & a_Text) override
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Sends all command output to a log, line by line, when the command finishes processing
|
||||
class cLogCommandOutputCallback :
|
||||
public cCommandOutputCallback
|
||||
{
|
||||
public:
|
||||
// cCommandOutputCallback overrides:
|
||||
virtual void Out(const AString & a_Text) override;
|
||||
virtual void Finished(void) override;
|
||||
|
||||
protected:
|
||||
/// Output is stored here until the command finishes processing
|
||||
AString m_Buffer;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Sends all command output to a log, line by line; deletes self when command finishes processing
|
||||
class cLogCommandDeleteSelfOutputCallback :
|
||||
public cLogCommandOutputCallback
|
||||
{
|
||||
typedef cLogCommandOutputCallback super;
|
||||
|
||||
virtual void Finished(void) override
|
||||
{
|
||||
super::Finished();
|
||||
delete this;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Pawn.h"
|
||||
#include "Player.h"
|
||||
#include "World.h"
|
||||
#include "CommandOutput.h"
|
||||
|
||||
|
||||
|
||||
@ -546,9 +547,10 @@ bool cPlugin::HandleCommand(const AStringVector & a_Split, cPlayer * a_Player)
|
||||
|
||||
|
||||
|
||||
bool cPlugin::HandleConsoleCommand(const AStringVector & a_Split)
|
||||
bool cPlugin::HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output)
|
||||
{
|
||||
UNUSED(a_Split);
|
||||
UNUSED(a_Output);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,10 @@ public:
|
||||
*/
|
||||
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer * a_Player);
|
||||
|
||||
/// Handles the console command split into a_Split. Returns true if command handled successfully.
|
||||
virtual bool HandleConsoleCommand(const AStringVector & a_Split);
|
||||
/** Handles the console command split into a_Split.
|
||||
Returns true if command handled successfully. Output is to be sent to the a_Output callback.
|
||||
*/
|
||||
virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output);
|
||||
|
||||
/// All bound commands are to be removed, do any language-dependent cleanup here
|
||||
virtual void ClearCommands(void) {} ;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "Item.h"
|
||||
#include "Root.h"
|
||||
#include "Server.h"
|
||||
#include "CommandOutput.h"
|
||||
|
||||
#include "../iniFile/iniFile.h"
|
||||
#include "tolua++.h"
|
||||
@ -1300,7 +1301,7 @@ bool cPluginManager::IsConsoleCommandBound(const AString & a_Command)
|
||||
|
||||
|
||||
|
||||
bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split)
|
||||
bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output)
|
||||
{
|
||||
if (a_Split.empty())
|
||||
{
|
||||
@ -1323,11 +1324,11 @@ bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split)
|
||||
// Ask plugins first if a command is okay to execute the console command:
|
||||
if (CallHookExecuteCommand(NULL, a_Split))
|
||||
{
|
||||
LOGINFO("Command \"%s\" was stopped by the HOOK_EXECUTE_COMMAND hook", a_Split[0].c_str());
|
||||
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);
|
||||
return cmd->second.m_Plugin->HandleConsoleCommand(a_Split, a_Output);
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,6 +29,9 @@ class cPickup;
|
||||
struct TakeDamageInfo;
|
||||
class cPawn;
|
||||
|
||||
// fwd: CommandOutput.h
|
||||
class cCommandOutputCallback;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -191,8 +194,8 @@ public: // tolua_export
|
||||
/// Returns true if the console command is in the command map
|
||||
bool IsConsoleCommandBound(const AString & a_Command); // tolua_export
|
||||
|
||||
/// Executes the command split into a_Split, as if it was given on the console. Returns true if executed.
|
||||
bool ExecuteConsoleCommand(const AStringVector & a_Split); // tolua_export
|
||||
/// Executes the command split into a_Split, as if it was given on the console. Returns true if executed. Output is sent to the a_Output callback
|
||||
bool ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output);
|
||||
|
||||
private:
|
||||
friend class cRoot;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#define LUA_USE_POSIX
|
||||
#include "Plugin_NewLua.h"
|
||||
#include "MCLogger.h"
|
||||
#include "CommandOutput.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -1378,13 +1378,15 @@ bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Pl
|
||||
|
||||
|
||||
|
||||
bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split)
|
||||
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\".", a_Split[0].c_str());
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1407,16 +1409,21 @@ bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split)
|
||||
}
|
||||
|
||||
// Call function:
|
||||
int s = lua_pcall(m_LuaState, 1, 1, 0);
|
||||
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 value:
|
||||
bool RetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
|
||||
lua_pop(m_LuaState, 1); // Pop return value
|
||||
// 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;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public:
|
||||
|
||||
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer * a_Player) override;
|
||||
|
||||
virtual bool HandleConsoleCommand(const AStringVector & a_Split) override;
|
||||
virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output) override;
|
||||
|
||||
virtual void ClearCommands(void) override;
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "RCONServer.h"
|
||||
#include "Server.h"
|
||||
#include "Root.h"
|
||||
#include "CommandOutput.h"
|
||||
|
||||
|
||||
|
||||
@ -37,6 +38,41 @@ enum
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cRCONCommandOutput:
|
||||
|
||||
class cRCONCommandOutput :
|
||||
public cCommandOutputCallback
|
||||
{
|
||||
public:
|
||||
cRCONCommandOutput(cRCONServer::cConnection & a_Connection, int a_RequestID) :
|
||||
m_Connection(a_Connection),
|
||||
m_RequestID(a_RequestID)
|
||||
{
|
||||
}
|
||||
|
||||
// cCommandOutputCallback overrides:
|
||||
virtual void Out(const AString & a_Text) override
|
||||
{
|
||||
m_Buffer.append(a_Text);
|
||||
}
|
||||
|
||||
virtual void Finished(void) override
|
||||
{
|
||||
m_Connection.SendResponse(m_RequestID, RCON_PACKET_RESPONSE, m_Buffer.size(), m_Buffer.c_str());
|
||||
delete this;
|
||||
}
|
||||
|
||||
protected:
|
||||
cRCONServer::cConnection & m_Connection;
|
||||
int m_RequestID;
|
||||
AString m_Buffer;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cRCONServer:
|
||||
|
||||
@ -218,9 +254,16 @@ bool cRCONServer::cConnection::ProcessPacket(int a_RequestID, int a_PacketType,
|
||||
|
||||
case RCON_PACKET_COMMAND:
|
||||
{
|
||||
if (!m_IsAuthenticated)
|
||||
{
|
||||
char AuthNeeded[] = "You need to authenticate first!";
|
||||
SendResponse(a_RequestID, RCON_PACKET_RESPONSE, sizeof(AuthNeeded), AuthNeeded);
|
||||
return false;
|
||||
}
|
||||
|
||||
AString cmd(a_Payload, a_PayloadLength);
|
||||
LOGD("RCON command from %s: \"%s\"", m_IPAddress.c_str(), cmd.c_str());
|
||||
cRoot::Get()->ExecuteConsoleCommand(cmd);
|
||||
cRoot::Get()->ExecuteConsoleCommand(cmd, *(new cRCONCommandOutput(*this, a_RequestID)));
|
||||
|
||||
// Send an empty response:
|
||||
SendResponse(a_RequestID, RCON_PACKET_RESPONSE, 0, NULL);
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
void Initialize(cIniFile & a_IniFile);
|
||||
|
||||
protected:
|
||||
friend class cRCONCommandOutput;
|
||||
|
||||
class cConnection :
|
||||
public cSocketThreads::cCallback
|
||||
{
|
||||
@ -41,6 +43,7 @@ protected:
|
||||
cConnection(cRCONServer & a_RCONServer, cSocket & a_Socket);
|
||||
|
||||
protected:
|
||||
friend class cRCONCommandOutput;
|
||||
|
||||
/// Set to true if the client has successfully authenticated
|
||||
bool m_IsAuthenticated;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "Items/ItemHandler.h"
|
||||
#include "Chunk.h"
|
||||
#include "Protocol/ProtocolRecognizer.h" // for protocol version constants
|
||||
#include "CommandOutput.h"
|
||||
|
||||
#ifdef USE_SQUIRREL
|
||||
#include "squirrelbindings/SquirrelFunctions.h"
|
||||
@ -69,11 +70,13 @@ void cRoot::InputThread(void * a_Params)
|
||||
{
|
||||
cRoot & self = *(cRoot*)a_Params;
|
||||
|
||||
cLogCommandOutputCallback Output;
|
||||
|
||||
while (!(self.m_bStop || self.m_bRestart))
|
||||
{
|
||||
std::string Command;
|
||||
std::getline(std::cin, Command);
|
||||
self.ExecuteConsoleCommand(Command);
|
||||
self.ExecuteConsoleCommand(Command, Output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,14 +353,14 @@ bool cRoot::ForEachWorld(cWorldListCallback & a_Callback)
|
||||
void cRoot::TickWorlds(float a_Dt)
|
||||
{
|
||||
// Execute any pending commands:
|
||||
AStringVector PendingCommands;
|
||||
cCommandQueue PendingCommands;
|
||||
{
|
||||
cCSLock Lock(m_CSPendingCommands);
|
||||
std::swap(PendingCommands, m_PendingCommands);
|
||||
}
|
||||
for (AStringVector::iterator itr = PendingCommands.begin(), end = PendingCommands.end(); itr != end; ++itr)
|
||||
for (cCommandQueue::iterator itr = PendingCommands.begin(), end = PendingCommands.end(); itr != end; ++itr)
|
||||
{
|
||||
DoExecuteConsoleCommand(*itr);
|
||||
ExecuteConsoleCommand(itr->m_Command, *(itr->m_Output));
|
||||
}
|
||||
|
||||
// Tick the worlds:
|
||||
@ -371,7 +374,7 @@ void cRoot::TickWorlds(float a_Dt)
|
||||
|
||||
|
||||
|
||||
void cRoot::ExecuteConsoleCommand(const AString & a_Cmd)
|
||||
void cRoot::QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output)
|
||||
{
|
||||
// Some commands are built-in:
|
||||
if (a_Cmd == "stop")
|
||||
@ -385,17 +388,48 @@ void cRoot::ExecuteConsoleCommand(const AString & a_Cmd)
|
||||
|
||||
// Put the command into a queue (Alleviates FS #363):
|
||||
cCSLock Lock(m_CSPendingCommands);
|
||||
m_PendingCommands.push_back(a_Cmd);
|
||||
m_PendingCommands.push_back(cCommand(a_Cmd, &a_Output));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cRoot::DoExecuteConsoleCommand(const AString & a_Cmd)
|
||||
void cRoot::QueueExecuteConsoleCommand(const AString & a_Cmd)
|
||||
{
|
||||
// Some commands are built-in:
|
||||
if (a_Cmd == "stop")
|
||||
{
|
||||
m_bStop = true;
|
||||
}
|
||||
else if (a_Cmd == "restart")
|
||||
{
|
||||
m_bRestart = true;
|
||||
}
|
||||
|
||||
// Put the command into a queue (Alleviates FS #363):
|
||||
cCSLock Lock(m_CSPendingCommands);
|
||||
m_PendingCommands.push_back(cCommand(a_Cmd, new cLogCommandDeleteSelfOutputCallback));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cRoot::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output)
|
||||
{
|
||||
// Some commands are built-in:
|
||||
if (a_Cmd == "stop")
|
||||
{
|
||||
m_bStop = true;
|
||||
}
|
||||
else if (a_Cmd == "restart")
|
||||
{
|
||||
m_bRestart = true;
|
||||
}
|
||||
|
||||
LOG("Executing console command: \"%s\"", a_Cmd.c_str());
|
||||
m_Server->ExecuteConsoleCommand(a_Cmd);
|
||||
m_Server->ExecuteConsoleCommand(a_Cmd, a_Output);
|
||||
}
|
||||
|
||||
|
||||
@ -524,7 +558,7 @@ AString cRoot::GetProtocolVersionTextFromInt(int a_ProtocolVersion)
|
||||
|
||||
|
||||
|
||||
void cRoot::LogChunkStats(void)
|
||||
void cRoot::LogChunkStats(cCommandOutputCallback & a_Output)
|
||||
{
|
||||
int SumNumValid = 0;
|
||||
int SumNumDirty = 0;
|
||||
@ -541,35 +575,35 @@ void cRoot::LogChunkStats(void)
|
||||
int NumDirty = 0;
|
||||
int NumInLighting = 0;
|
||||
World->GetChunkStats(NumValid, NumDirty, NumInLighting);
|
||||
LOG("World %s:", World->GetName().c_str());
|
||||
LOG(" Num loaded chunks: %d", NumValid);
|
||||
LOG(" Num dirty chunks: %d", NumDirty);
|
||||
LOG(" Num chunks in lighting queue: %d", NumInLighting);
|
||||
LOG(" Num chunks in generator queue: %d", NumInGenerator);
|
||||
LOG(" Num chunks in storage load queue: %d", NumInLoadQueue);
|
||||
LOG(" Num chunks in storage save queue: %d", NumInSaveQueue);
|
||||
a_Output.Out("World %s:", World->GetName().c_str());
|
||||
a_Output.Out(" Num loaded chunks: %d", NumValid);
|
||||
a_Output.Out(" Num dirty chunks: %d", NumDirty);
|
||||
a_Output.Out(" Num chunks in lighting queue: %d", NumInLighting);
|
||||
a_Output.Out(" Num chunks in generator queue: %d", NumInGenerator);
|
||||
a_Output.Out(" Num chunks in storage load queue: %d", NumInLoadQueue);
|
||||
a_Output.Out(" Num chunks in storage save queue: %d", NumInSaveQueue);
|
||||
int Mem = NumValid * sizeof(cChunk);
|
||||
LOG(" Memory used by chunks: %d KiB (%d MiB)", (Mem + 1023) / 1024, (Mem + 1024 * 1024 - 1) / (1024 * 1024));
|
||||
LOG(" Per-chunk memory size breakdown:");
|
||||
LOG(" block types: %6d bytes (%3d KiB)", sizeof(cChunkDef::BlockTypes), (sizeof(cChunkDef::BlockTypes) + 1023) / 1024);
|
||||
LOG(" block metadata: %6d bytes (%3d KiB)", sizeof(cChunkDef::BlockNibbles), (sizeof(cChunkDef::BlockNibbles) + 1023) / 1024);
|
||||
LOG(" block lighting: %6d bytes (%3d KiB)", 2 * sizeof(cChunkDef::BlockNibbles), (2 * sizeof(cChunkDef::BlockNibbles) + 1023) / 1024);
|
||||
LOG(" heightmap: %6d bytes (%3d KiB)", sizeof(cChunkDef::HeightMap), (sizeof(cChunkDef::HeightMap) + 1023) / 1024);
|
||||
LOG(" biomemap: %6d bytes (%3d KiB)", sizeof(cChunkDef::BiomeMap), (sizeof(cChunkDef::BiomeMap) + 1023) / 1024);
|
||||
a_Output.Out(" Memory used by chunks: %d KiB (%d MiB)", (Mem + 1023) / 1024, (Mem + 1024 * 1024 - 1) / (1024 * 1024));
|
||||
a_Output.Out(" Per-chunk memory size breakdown:");
|
||||
a_Output.Out(" block types: %6d bytes (%3d KiB)", sizeof(cChunkDef::BlockTypes), (sizeof(cChunkDef::BlockTypes) + 1023) / 1024);
|
||||
a_Output.Out(" block metadata: %6d bytes (%3d KiB)", sizeof(cChunkDef::BlockNibbles), (sizeof(cChunkDef::BlockNibbles) + 1023) / 1024);
|
||||
a_Output.Out(" block lighting: %6d bytes (%3d KiB)", 2 * sizeof(cChunkDef::BlockNibbles), (2 * sizeof(cChunkDef::BlockNibbles) + 1023) / 1024);
|
||||
a_Output.Out(" heightmap: %6d bytes (%3d KiB)", sizeof(cChunkDef::HeightMap), (sizeof(cChunkDef::HeightMap) + 1023) / 1024);
|
||||
a_Output.Out(" biomemap: %6d bytes (%3d KiB)", sizeof(cChunkDef::BiomeMap), (sizeof(cChunkDef::BiomeMap) + 1023) / 1024);
|
||||
int Rest = sizeof(cChunk) - sizeof(cChunkDef::BlockTypes) - 3 * sizeof(cChunkDef::BlockNibbles) - sizeof(cChunkDef::HeightMap) - sizeof(cChunkDef::BiomeMap);
|
||||
LOG(" other: %6d bytes (%3d KiB)", Rest, (Rest + 1023) / 1024);
|
||||
a_Output.Out(" other: %6d bytes (%3d KiB)", Rest, (Rest + 1023) / 1024);
|
||||
SumNumValid += NumValid;
|
||||
SumNumDirty += NumDirty;
|
||||
SumNumInLighting += NumInLighting;
|
||||
SumNumInGenerator += NumInGenerator;
|
||||
SumMem += Mem;
|
||||
}
|
||||
LOG("Totals:");
|
||||
LOG(" Num loaded chunks: %d", SumNumValid);
|
||||
LOG(" Num dirty chunks: %d", SumNumDirty);
|
||||
LOG(" Num chunks in lighting queue: %d", SumNumInLighting);
|
||||
LOG(" Num chunks in generator queue: %d", SumNumInGenerator);
|
||||
LOG(" Memory used by chunks: %d KiB (%d MiB)", (SumMem + 1023) / 1024, (SumMem + 1024 * 1024 - 1) / (1024 * 1024));
|
||||
a_Output.Out("Totals:");
|
||||
a_Output.Out(" Num loaded chunks: %d", SumNumValid);
|
||||
a_Output.Out(" Num dirty chunks: %d", SumNumDirty);
|
||||
a_Output.Out(" Num chunks in lighting queue: %d", SumNumInLighting);
|
||||
a_Output.Out(" Num chunks in generator queue: %d", SumNumInGenerator);
|
||||
a_Output.Out(" Memory used by chunks: %d KiB (%d MiB)", (SumMem + 1023) / 1024, (SumMem + 1024 * 1024 - 1) / (1024 * 1024));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,15 +1,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
|
||||
#include "Authenticator.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// fwd:
|
||||
class cThread;
|
||||
class cMonsterConfig;
|
||||
class cGroupManager;
|
||||
@ -20,6 +18,8 @@ class cPluginManager;
|
||||
class cServer;
|
||||
class cWorld;
|
||||
class cPlayer;
|
||||
class cCommandOutputCallback ;
|
||||
|
||||
typedef cItemCallback<cPlayer> cPlayerListCallback;
|
||||
typedef cItemCallback<cWorld> cWorldListCallback;
|
||||
|
||||
@ -27,6 +27,7 @@ typedef cItemCallback<cWorld> cWorldListCallback;
|
||||
|
||||
|
||||
|
||||
/// The root of the object hierarchy
|
||||
class cRoot // tolua_export
|
||||
{ // tolua_export
|
||||
public:
|
||||
@ -47,8 +48,8 @@ public:
|
||||
/// Calls the callback for each world; returns true if the callback didn't abort (return true)
|
||||
bool ForEachWorld(cWorldListCallback & a_Callback); // >> Exported in ManualBindings <<
|
||||
|
||||
/// Logs chunkstats for each world and totals
|
||||
void LogChunkStats(void);
|
||||
/// Writes chunkstats, for each world and totals, to the output callback
|
||||
void LogChunkStats(cCommandOutputCallback & a_Output);
|
||||
|
||||
int GetPrimaryServerVersion(void) const { return m_PrimaryServerVersion; } // tolua_export
|
||||
void SetPrimaryServerVersion(int a_Version) { m_PrimaryServerVersion = a_Version; } // tolua_export
|
||||
@ -62,8 +63,22 @@ public:
|
||||
cPluginManager * GetPluginManager (void) { return m_PluginManager; } // tolua_export
|
||||
cAuthenticator & GetAuthenticator (void) { return m_Authenticator; }
|
||||
|
||||
/// Queues a console command for execution through the cServer class; does special handling for "stop" and "restart".
|
||||
void ExecuteConsoleCommand(const AString & a_Cmd); // tolua_export
|
||||
/** Queues a console command for execution through the cServer class.
|
||||
The command will be executed in the tick thread
|
||||
The command's output will be written to the a_Output callback
|
||||
"stop" and "restart" commands have special handling.
|
||||
*/
|
||||
void QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output);
|
||||
|
||||
/** Queues a console command for execution through the cServer class.
|
||||
The command will be executed in the tick thread
|
||||
The command's output will be sent to console
|
||||
"stop" and "restart" commands have special handling.
|
||||
*/
|
||||
void QueueExecuteConsoleCommand(const AString & a_Cmd); // tolua_export
|
||||
|
||||
/// Executes a console command through the cServer class; does special handling for "stop" and "restart".
|
||||
void ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output);
|
||||
|
||||
/// Kicks the user, no matter in what world they are. Used from cAuthenticator
|
||||
void KickUser(int a_ClientID, const AString & a_Reason);
|
||||
@ -89,12 +104,27 @@ public:
|
||||
static AString GetProtocolVersionTextFromInt(int a_ProtocolVersionNum); // tolua_export
|
||||
|
||||
private:
|
||||
typedef std::map< AString, cWorld* > WorldMap;
|
||||
cWorld* m_pDefaultWorld;
|
||||
class cCommand
|
||||
{
|
||||
public:
|
||||
cCommand(const AString & a_Command, cCommandOutputCallback * a_Output) :
|
||||
m_Command(a_Command),
|
||||
m_Output(a_Output)
|
||||
{
|
||||
}
|
||||
|
||||
AString m_Command;
|
||||
cCommandOutputCallback * m_Output;
|
||||
} ;
|
||||
|
||||
typedef std::map<AString, cWorld *> WorldMap;
|
||||
typedef std::vector<cCommand> cCommandQueue;
|
||||
|
||||
cWorld * m_pDefaultWorld;
|
||||
WorldMap m_WorldsByName;
|
||||
|
||||
cCriticalSection m_CSPendingCommands;
|
||||
AStringVector m_PendingCommands;
|
||||
cCommandQueue m_PendingCommands;
|
||||
|
||||
cThread * m_InputThread;
|
||||
|
||||
@ -131,7 +161,7 @@ private:
|
||||
void DoExecuteConsoleCommand(const AString & a_Cmd);
|
||||
|
||||
static void InputThread(void* a_Params);
|
||||
|
||||
|
||||
static cRoot* s_Root;
|
||||
}; // tolua_export
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "Tracer.h"
|
||||
#include "WebAdmin.h"
|
||||
#include "Protocol/ProtocolRecognizer.h"
|
||||
#include "CommandOutput.h"
|
||||
|
||||
#include "MersenneTwister.h"
|
||||
|
||||
@ -425,7 +426,7 @@ bool cServer::Command(cClientHandle & a_Client, AString & a_Cmd)
|
||||
|
||||
|
||||
|
||||
void cServer::ExecuteConsoleCommand(const AString & a_Cmd)
|
||||
void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output)
|
||||
{
|
||||
AStringVector split = StringSplit(a_Cmd, " ");
|
||||
if (split.empty())
|
||||
@ -442,7 +443,8 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd)
|
||||
// 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();
|
||||
cRoot::Get()->LogChunkStats(a_Output);
|
||||
a_Output.Finished();
|
||||
return;
|
||||
}
|
||||
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
|
||||
@ -462,12 +464,14 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cPluginManager::Get()->ExecuteConsoleCommand(split))
|
||||
if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output))
|
||||
{
|
||||
a_Output.Finished();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("Unknown command, type 'help' for all commands.\n");
|
||||
a_Output.Out("Unknown command, type 'help' for all commands.");
|
||||
a_Output.Finished();
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,9 +19,11 @@
|
||||
|
||||
|
||||
|
||||
// fwd:
|
||||
class cPlayer;
|
||||
class cClientHandle;
|
||||
class cIniFile;
|
||||
class cCommandOutputCallback ;
|
||||
|
||||
typedef std::list<cClientHandle *> cClientHandleList;
|
||||
|
||||
@ -44,7 +46,9 @@ public: // tolua_export
|
||||
bool Start(void);
|
||||
|
||||
bool Command(cClientHandle & a_Client, AString & a_Cmd);
|
||||
void ExecuteConsoleCommand(const AString & a_Cmd);
|
||||
|
||||
/// Executes the console command, sends output through the specified callback
|
||||
void ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output);
|
||||
|
||||
/// Binds the built-in console commands with the plugin manager
|
||||
static void BindBuiltInConsoleCommands(void);
|
||||
|
@ -569,26 +569,3 @@ AString & CreateHexDump(AString & a_Out, const void * a_Data, int a_Size, int a_
|
||||
|
||||
|
||||
|
||||
|
||||
AString Trim(const AString & a_Text)
|
||||
{
|
||||
if (a_Text.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
size_t Beginning = a_Text.find_first_not_of(" \r\n\t");
|
||||
if (Beginning == AString::npos)
|
||||
{
|
||||
Beginning = 0;
|
||||
}
|
||||
size_t End = a_Text.find_last_not_of(" \r\n\t");
|
||||
if (End == AString::npos)
|
||||
{
|
||||
End = a_Text.length();
|
||||
}
|
||||
return a_Text.substr(Beginning, End - Beginning + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user