Raised This Month: $51 Target: $400
 12% 

Class problem ?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Cr3V3TT3
Senior Member
Join Date: Jul 2004
Location: V'dauban
Old 04-04-2005 , 18:24   Class problem ?
Reply With Quote #1

Hi,

Thats the first time i create a class ( plz dont smile )

This is what i done
Code:
class Delayed {
public:
	int used;
	float runtime;
	const char* command;
};
Delayed Delayeds[40];
void CEventScriptsPlugin::CheckDelayed( void ){ // CALLED IN GameFrame() !.
	for (int x = 0; x <= 40; x++){
		if (Delayeds[x].used == 1){ // If the Delayed is waiting
			Msg("debug : delayed slot %d is waiting to put \"%s\"\n", x, Delayeds[x].command);
			if (engine->Time() >= Delayeds[x].runtime){
				Msg("debug : delayed slot %d runing the command %s!\n", x, Delayeds[x].command);
				engine->ServerCommand(Delayeds[x].command);
				Delayeds[x].used = 0; // Free the delayed
			}
		}
	}
}
CON_COMMAND( es_delayed, "Syntax : es_delayed <seconds> <commandstring>\n    Will run <commandstring>, after <seconds> seconds." ){
	for (int x = 0; x <= 40; x++){ //  \Searching for the nearest free slot of 0
		if (Delayeds[x].used == 0){ // /
			Delayeds[x].used = 1;
			Delayeds[x].runtime = (engine->Time() + atof(engine->Cmd_Argv(1)));
			Delayeds[x].command = engine->Cmd_Argv(2); // Set the command to run
	//		Msg("debug : a delayed get slot %d, it will run the command : %s in %f seconds\n", x, Delayeds[x].command, atof(engine->Cmd_Argv(1)));
			break;
		}
	}
}
When i type es_delayed 10 "echo test" i get that :

Quote:
] es_delayed 5 "echo test"
debug : delayed slot 0 is waiting to put "8~ test"
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
[...]
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 is waiting to put "8~ "
debug : delayed slot 0 runing the command 8~ !
Error, bad server command 8~ 
echo test -> 8~ test" -> 8d~ "

i' m only changing command in the con_command :/
Cab some one explain me please because i lost 2 hours to made trys

Hope you can help me
Bye,

Cr3V3TT3
Cr3V3TT3 is offline
Send a message via MSN to Cr3V3TT3
Cr3V3TT3
Senior Member
Join Date: Jul 2004
Location: V'dauban
Old 04-05-2005 , 14:18  
Reply With Quote #2

using std resolv the problem but still dont understand why it dont work with chars :/

Code:
class Delayed {
public:
	bool used;
	float time;
	std::string cmd;
public:
	const char* GetCmd();
};
const char* Delayed::GetCmd( void ) {return cmd.c_str();}

Delayed Delayeds[40];

void CEventScriptsPlugin::ResetDelayed( void ){ // CALLED IN LevelInit() !
/*	for (int x = 0; x <= 40; x++)
		Delayeds[x].used = 0; // Delete all unterminated*/
	// Crashs the server :|
}
void CEventScriptsPlugin::CheckDelayed( void ){ // CALLED IN GameFrame() !.
	for (int x = 0; x <= 40; x++){
		if (Delayeds[x].used == true){ // If the Delayed is waiting
			Msg("debug : delayed slot %d is waiting to put \"%s\" in the ass of this server\n", x, Delayeds[x].GetCmd());
			if (engine->Time() >= Delayeds[x].time){
				Msg("debug : delayed slot %d runing the command \"%s\" !\n", x, Delayeds[x].GetCmd());
				engine->ServerCommand(Delayeds[x].GetCmd());
				Delayeds[x].used = false; // Free the delayed
			}
		}
	}
}
CON_COMMAND( es_delayed, "Syntax : es_delayed <seconds> <commandstring>\n    Will run <commandstring>, after <seconds> seconds." ){
	for (int x = 0; x <= 40; x++){ //  \Searching for the nearest free slot of 0
		if (Delayeds[x].used == false){ // /
			Delayeds[x].used = true;
			Delayeds[x].time = (engine->Time() + atof(engine->Cmd_Argv(1)));
			Delayeds[x].cmd = engine->Cmd_Argv(2); // Set the command to run
			Msg("Arg 2: \"%s\", setted value: \"%s\"\n",engine->Cmd_Argv(2),Delayeds[x].GetCmd());
			Msg("debug : a delayed get slot %d, it will run the command : \"%s\" in %f seconds\n", x, Delayeds[x].GetCmd(), atof(engine->Cmd_Argv(1)));
			break;
		}
	}
}
Quote:
] es_delayed 5 "echo test"
Arg 2: "echo test", setted value: "echo test"
debug : a delayed get slot 0, it will run the command : "echo test" in 5.000000 seconds
debug : delayed slot 0 is waiting to put "echo test" in the ass of this server
debug : delayed slot 0 is waiting to put "echo test" in the ass of this server
debug : delayed slot 0 is waiting to put "echo test" in the ass of this server
[...]
debug : delayed slot 0 is waiting to put "echo test" in the ass of this server
debug : delayed slot 0 is waiting to put "echo test" in the ass of this server
debug : delayed slot 0 runing the command "echo test" !
Error, bad server command echo test
Cr3V3TT3 is offline
Send a message via MSN to Cr3V3TT3
vancelorgin
Senior Member
Join Date: Dec 2004
Location: san frandisco
Old 04-05-2005 , 14:42  
Reply With Quote #3

std::string is wrapped to hell, so when you call operator= (mystring = somecharptr), it's actually copying what's at that pointer to it's own buffer.

Anything with * by it is a pointer, meaning that the variable holds nothing but an address, so a char* is just the address of a single character. A null-terminated string is a sequence of characters terminated by a null (char = to 0), but since you can't hold a whole string in a handy little 32 bit package, you put it somewhere in memory and reference it [the beginning of it] by it's address through a pointer.

When you have char* shit = engine->Cmd_Argv(2), you are retrieving the address of a string in the engine's memory containing the second argument. After your command is executed, lord only knows wtf the engine will do with the memory at that address. You need to copy what's there, when it's good, into something you control (your std::string, or a char array of your own).

As for

Code:
Delayed Delayeds[40];
/*   for (int x = 0; x <= 40; x++) 
      Delayeds[x].used = 0; // Delete all unterminated*/ 
   // Crashs the server :|
That's because Delayeds has 40 elements, indexed 0 - 39. C[++] has no bounds checking (thank God), so Delayeds[40] will reference the memory just after the last Delayed, which in this case is bad mojo. Change <= to <.

For this, however, I recommend you learn std::vector. It kicks ass:

Code:
typedef struct {
 std::string strCmd;
 float flTime;
} DelayedCmd_s;

std::vector<DelayedCmd_s*> g_vDelayedCmds;

void AddDelayedCmd(const char* lpcCmd, float flTime){
 DelayedCmd_s* Cmd = new DelayedCmd_s;
 Cmd->strCmd = lpcCmd;
 Cmd->flTime = flTime;
 g_vDelayedCmds.push_back(Cmd);
}

void UpdateCmds(){
 float flNow = engine->Time();
 
 for(unsigned int i = 0; i < g_vDelayedCmds.size(); i++){
  if(g_vDelayedCmds[i]->flTime <= flNow){
   engine->ServerCommand(g_vDelayedCmds[i]->strCmd.c_str());
   delete g_vDelayedCmds[i];
   g_vDelayedCmds.erase(g_vDelayedCmds.begin() + i);
   i--;
  }
 }
}
or some shit

purists will say use std::list and iterators. they can go fuck themselves
__________________
Avoid like the plague.
vancelorgin is offline
Cr3V3TT3
Senior Member
Join Date: Jul 2004
Location: V'dauban
Old 04-05-2005 , 15:22  
Reply With Quote #4

wOw

Thx for explained all that

Your sample with std::verctor rocks!
I will take a look at this ;)
Cr3V3TT3 is offline
Send a message via MSN to Cr3V3TT3
Mattie
Veteran Member
Join Date: Jan 2005
Old 04-05-2005 , 16:34  
Reply With Quote #5

There's no reason you can't use the Valve supplied classes/functions for CUtlVector (I think) and/or even their KeyValues class for storing the times.

Since the std classes have slightly different implementations on different platforms, Valve's SDK generic functions are sometimes a better fit for plugins that don't require anything too fancy (iterators, etc).

-Mattie
Mattie is offline
vancelorgin
Senior Member
Join Date: Dec 2004
Location: san frandisco
Old 04-05-2005 , 17:05  
Reply With Quote #6

Or you could get to know stl, something portable across anything you'll code on and rock solid, instead of using the known to be buggy and horribly implimentation specific valve templates :/ Why use an inferior clone when you can use the original

As for KeyValues, I used to use that, but wound up writing my own data storage / serialization system that transparently supports mysql. Valve's stuff has so much shit done on initialization that should be straightened out compile time it sorta makes me sick. I dunno what it is about valve utilities I just avoid
__________________
Avoid like the plague.
vancelorgin is offline
Mattie
Veteran Member
Join Date: Jan 2005
Old 04-05-2005 , 17:18  
Reply With Quote #7

Quote:
Originally Posted by vancelorgin
Or you could get to know stl, something portable across anything you'll code on and rock solid, instead of using the known to be buggy and horribly implimentation specific valve templates :/ Why use an inferior clone when you can use the original
Well, I, personally, need to compile for different platforms and don't have time to test for corner cases in implementations across gcc/stl versions on Linux platforms. I don't disagree with you that STL is more powerful, yet if we're already linking against Valve's libraries, why increase my dependencies when some of the Valve implementations aren't really all that terrible at times?

I often use stl in my job, yet really haven't seen a need for it when working with the Source SDK. I'm probably not doing as many fun things as you are, though, so it could just be a matter of time.

Quote:
As for KeyValues, I used to use that, but wound up writing my own data storage / serialization system that transparently supports mysql. I dunno what it is about valve utilities I just avoid
That sounds rather spiffy-- you oughta post it (if ya haven't already). I assume it's cross-platform?

Thanks,
-Mattie
Mattie is offline
vancelorgin
Senior Member
Join Date: Dec 2004
Location: san frandisco
Old 04-05-2005 , 17:25  
Reply With Quote #8

Muh - I just trust stl alot. And it's not really dependency once compiled

Yeah, it works pretty well, but it's sorta nasty - too many type specifics to be considered pretty. Rock solid though. Cross platform afaik - I'm sure there's some nitty gritty crap I'll need to change for the switch. I still plan on and have still yet to switch over to linux, but mark my words it'll happen
__________________
Avoid like the plague.
vancelorgin is offline
theqizmo
Member
Join Date: Oct 2004
Old 04-06-2005 , 01:49  
Reply With Quote #9

Quote:
Originally Posted by Mattie
Well, I, personally, need to compile for different platforms and don't have time to test for corner cases in implementations across gcc/stl versions on Linux platforms.
In the context of source SDK, CUtlVector seems to be better, since it's been coded (apparently anyway) for source development, and it's apparently cross compatible.

However, most programmers won't be using templates from the STL that will cause significant breakage when cross compiling, even if the versions of gcc/stl are different.

For example, Lance gave me his source to his player class, from which I adapted and used. He is still using win32, I am using linux.

What did I have to adapt? I had to copy and paste his class into my class, change the class names so they matched, then recompiled.

Although this example does not mean every distro of linux with libstdc++ will support his code, his code is using such a widely used standard that it would be just plain stupid not to use the standard. (i'll have to go look for my version of libstdc++ anyway)

In other words, USE STD::VECTOR. If your version of gcc can use CUtlVector, then it can definitely use std::vector.

Code:
std::vector< std::string* > g_somevec;

std::string *pBob = new std::string( "Hi bob" );
std::string *pJoe = new std::string( "Joe" );

g_somevec.push_back( pJoe );
g_somevec.push_back( pBob );

for ( unsigned int i = 0; i < g_somevec.size( ); i++ )
{
	std::string *pTemp = g_somevec[ i ];

	if ( pTemp )
	{
		engine->ServerCommand( "echo \"command: %s\", pTemp->c_str( )  );

		delete pTemp;
		pTemp = NULL;

		g_somevec.erase( pTemp );
		continue;
	}

	g_somevec.erase( pTemp );
}

g_somevec.clear( );
P.S. iterators are too much of a pain =x
theqizmo is offline
Send a message via ICQ to theqizmo Send a message via AIM to theqizmo Send a message via MSN to theqizmo
Mattie
Veteran Member
Join Date: Jan 2005
Old 04-06-2005 , 09:35  
Reply With Quote #10

Quote:
Originally Posted by theqizmo
In other words, USE STD::VECTOR.
But ... why? Do you know of bugs in CUtlVector (etc) that cause you to say this? Or is it just a preference? I see no real reason why people should be reluctant to use std::vector (etc), yet I also haven't seen any reason why people should be reluctant to use the Valve container classes.

While I've been paid to code for nearly a decade now, Source is my first experience using one of Valve's SDKs. If there are pitfalls that their development teams commonly fall back into, I'd love to hear about those problems.

Quote:
If your version of gcc can use CUtlVector, then it can definitely use std::vector.
Absolute statements were meant to be broken. ;) I'm probably the only case where this isn't true: my old Linux box has an older gcc which has a linker bug when I try to statically link libstdc++.a.

I could spend hours grabbing a new GCC without the problem, rebuilding it all on the slow machine, and then rebuilding and testing my plugins. Instead, at the moment I'm just happy that I used Valve's slightly-clunky classes so I'm not forced to do so.


-Mattie
Mattie is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 03:58.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode