Console output to string

Another newbquestion by me:

Is it possible to get the output of RunConsoleCommand and convert it to a string/int? How should I do it?
I have been messing around with tostring, but no result.

What context are you needing this for?

The console-output can only be retrieved using a binary-module.
I once wrote one:

Download

Usage:
[lua]require(“luaconsole”);
function myconsoletexthook(message,color)
–do stuff
end
hook.Add(“ConsolePrint”,“myconsoletexthook”,myconsoletexthook);[/lua]

Pay attention: Once your hook above does error and therefore print stuff to the console, it will be called again and so on. This will freeze gmod. Also don’t use print() in there.

Sourcecode:

[cpp]#define _RETAIL
#define GAME_DLL
#include <windows.h>
#define WIN32_LEAN_AND_MEAN

#include <string>
using std::string;

#include “common/GMLuaModule.h” //Lua Module base

//Necessary for Sys_GetFactory() to work
#include <eiface.h>
#include <interface.h>
#include <cdll_int.h>

//Necessary classes for g_pCVar to work
#include <icvar.h>
#include <convar.h>
#include <Color.h>

// memdbgon must be the last include file in a .cpp file!!!
#include “tier0/memdbgon.h”

GMOD_MODULE(Init,Shutdown);

//Lua-Objects
static ILuaInterface* gLua = NULL;
static ICvar* g_pCVar = NULL;

//################ Logs a console message @aVoN
void LogConMessage(const char* msg,int r = 255,int g = 255,int b = 255,int a = 255){
if(!gLua) return;

//Create a Lua-Color table
ILuaObject* LuaColor = gLua-&gt;GetGlobal("Color");

gLua-&gt;Push(LuaColor); //Push function we want to call onto the stack
gLua-&gt;Push((float) r);
gLua-&gt;Push((float) g);
gLua-&gt;Push((float) b);
gLua-&gt;Push((float) a);
gLua-&gt;Call(4,1); //Call the function, telling lua it uses 4 elements (the one on the stack) and returning one element
ILuaObject* col = gLua-&gt;GetReturn(0); //Get the return (from stack 0)

LuaColor-&gt;UnReference();

//Call a hook
ILuaObject* hook = gLua-&gt;GetGlobal("hook");
ILuaObject* hookCall = hook-&gt;GetMember("Call");

gLua-&gt;Push(hookCall);
gLua-&gt;Push("ConsolePrint");
gLua-&gt;PushNil();
gLua-&gt;Push(msg);
gLua-&gt;Push(col);
gLua-&gt;Call(4,0);

hook-&gt;UnReference();
hookCall-&gt;UnReference();

col-&gt;UnReference();

}

//################ Hook-Class to ConsolePrint @aVoN
class CLuaConsoleDisplayFunc : public IConsoleDisplayFunc
{
public:
virtual void ColorPrint(const Color& col,const char* msg){
LogConMessage(msg,col.r(),col.g(),col.b(),col.a());
}
virtual void Print(const char* msg){
LogConMessage(msg);
}
virtual void DPrint(const char* msg){
LogConMessage(msg);
}
};

//################ Get all ConCommands and cvars @aVoN
LUA_FUNCTION(GetConcommands){
ILuaObject* Commands = gLua->GetNewTable(); //This table will be returned

//Get first argument of this function. If set, we will do a search for commands/cvars staring with this value
ILuaObject* needle_ = gLua-&gt;GetObject(1);
bool search = false;
const char* needle;
if(needle_-&gt;isString()){
	search = true;
	needle = needle_-&gt;GetString();
}

//Cycle through every single ConCommand or ConVar
ConCommandBase* CMD = g_pCVar-&gt;GetCommands();
int i = 2;
while(CMD){
	const char* name = CMD-&gt;GetName(); //Name of this concommand or cvar
	
	//Search, if this cvar or concommand begins with the supplied string
	if(search){
		string haystack(name);
		if(haystack.find(needle) != 0){
			CMD = CMD-&gt;GetNext();
			continue; //The cvar does not begin with this string -&gt; Go to next cvar!
		}
	}
	
	ILuaObject* value = gLua-&gt;GetNewTable();
	value-&gt;SetMember("Name",name);
	//If it's a convar, push it's value into the table
	if(!CMD-&gt;IsCommand()){
		ConVar* var = g_pCVar-&gt;FindVar(name);
		value-&gt;SetMember("Value",var-&gt;GetString());
	}
	
	//Push keys and values of this convar or command into the commands-table
	Commands-&gt;SetMember(i++,value);
	
	//value-&gt;UnReference(); // I have no clue why, but running this will cause massive failures. I just can hope, this does not leak memory
	
	CMD = CMD-&gt;GetNext();
}

gLua-&gt;Push(Commands); //Return commands

Commands-&gt;UnReference();

return 1;

}

//################ Init @aVoN
CLuaConsoleDisplayFunc* CONSOLE_HOOK;
int Init(lua_State* L){
if(gLua) return 0; //Do not run this shit again, when we already loaded it
gLua = Lua();

//Extract g_pCVar
CreateInterfaceFn vstdFactory = Sys_GetFactory("vstdlib.dll");
if(!vstdFactory) return 0;
g_pCVar = (ICvar*)vstdFactory(CVAR_INTERFACE_VERSION, NULL);

//Install console-hook
CONSOLE_HOOK = new CLuaConsoleDisplayFunc();
g_pCVar-&gt;InstallConsoleDisplayFunc(CONSOLE_HOOK);

//##### Lua
gLua-&gt;SetGlobal("GetConcommands",GetConcommands);

return 0;

}

//################ Shutdown @aVoN
int Shutdown(lua_State* L){
if((lua_State*) gLua->GetLuaState() != L) return 0; //If any other state tries to unload the module, disallow it

//Remove hook and delete allocated memory
g_pCVar-&gt;RemoveConsoleDisplayFunc(CONSOLE_HOOK);
delete CONSOLE_HOOK;

return 0;

}
[/cpp]

Thought using console would be the easiest way lol.
I’ll explain what I’m trying to do.
I’m using the big_timespent addon to count and save the players’ platime. Now I am making some DarkRP jobs that require a certain ammount of playtime.
I made it so when I enter “thetime” in console, it shows my playtime on seconds. I wanted to use that to restrict some jobs (compare to a predefined value when choosing the job).
Guess using the return value of the Gettime function in the addon would be easier, any notes on that? (like how i can include tha addon in the sh_commands.lua file and then use that function directly?)

Show us your “thetime” function and I’ll tell you exactly how to do what you want.


function BTS.GetTime( ply, calculated ) // calculated == true then return FullTime, SessionTime else return join, start [ALL IN SECONDS, USE BTS.FormatTime( seconds ) to get Weeks, Days, Hours, Minutes, Seconds]
	local id = BTS.GetID( ply )
	if IsValid( ply ) and BTS.PlayerTimes[id] then
		if calculated then
			local text = BTS.PlayerTimes[id].start + BTS.GlobalTimer - BTS.PlayerTimes[id].join, BTS.GlobalTimer - BTS.PlayerTimes[id].join
                                else
			local text = BTS.PlayerTimes[id].join, BTS.PlayerTimes[id].start
		end
                print(text)
	end
	return 0, 0
end
concommand.Add("thetime", BTS.GetTime)

Like i stated before, this is not mine, i just made it print it in console.
this is the original:


function BTS.GetTime( ply, calculated ) // calculated == true then return FullTime, SessionTime else return join, start [ALL IN SECONDS, USE BTS.FormatTime( seconds ) to get Weeks, Days, Hours, Minutes, Seconds]
	local id = BTS.GetID( ply )
	if IsValid( ply ) and BTS.PlayerTimes[id] then
		if calculated then
			return BTS.PlayerTimes[id].start + BTS.GlobalTimer - BTS.PlayerTimes[id].join, BTS.GlobalTimer - BTS.PlayerTimes[id].join
                                else
			return BTS.PlayerTimes[id].join, BTS.PlayerTimes[id].start
		end
	end
	return 0, 0
end


Anyone, and alos, yay for the dumb rating, I don’t get why people do that .IT’s two pieces of code that i didn’t even write and a small sentence, cmon people.

But seriously, anyone who could help?

you not just make your function call BTS.GetTime instead of running the console command and trying to read the output?

[editline]10:32AM[/editline]

remember to use the original to do that

That’s what I want to do, but how do I include the addon that has this function into the darkrp sh_commands.lua file?

not sure but it may be possible that the functions is global and can be called from anywhere. give me a second to check that

[editline]10:41AM[/editline]

checked, they are global i would suggest making a table that contains the job’s team index and the amount of seconds you have to play to get it

[editline]10:42AM[/editline]

then checking if the job is in the table and if the player’s playtime is bigger or equal that time

I already have all that set up, I just needed that function to work, Thanks, I’ll look at it.

i did a test and came up with something like this inside the ChangeJob functions in the player.lua file
i defined a table something like this at the top of the file:



TimeSpentForJob = {}
TimeSpentForJob[TEAM_MOB]=1440


and inside the ChangeTeam function in the player.lua file i added:



			if TimeSpentForJob[t] then
				if TimeSpentForJob[t]<BTS.GetTime(self,false) then
					Notify(self, 1, 4, string.format(LANGUAGE.unable, team.GetName(t), ""))
					return
				end
			end


it’s untested so i’m not sure if it works, or if it works for your version etc.

[editline]10:53AM[/editline]

oh damn
-Rate me late-

Thnx man, also, above works, but you need to change the ‘string.format(LANGUAGE.unable, team.GetName(t), “”)’.
I used this:
“You can not become “…v.name…” As you need atleast “…TimeSpentForJob[t]…” seconds of playtime!”
Will be setting the correct timeformat for that output later as it is in seconds right now.