PDA

View Full Version : Need help with text menu



Quazm
13-02-2016, 12:10 AM
I am trying to figure out how to make text menu, but it always crash my server. Is something wrong with this code?



CTextMenu@ menu;


void PluginInit()
{
g_Module.ScriptInfo.SetAuthor( "123" );
g_Module.ScriptInfo.SetContactInfo( "123" );
g_Hooks.RegisterHook( Hooks::Player::ClientSay, @ClientSay );
}


void MenuCallback(CTextMenu@ menu, CBasePlayer@ plr, int page, const CTextMenuItem@ item)
{
g_Game.AlertMessage( at_console, "Menu callback debug\n");
}


HookReturnCode ClientSay( SayParameters@ pParams )
{
const CCommand@ args = pParams.GetArguments();
CBasePlayer@ plr = pParams.GetPlayer();
if ( args.ArgC() > 0 )
{
if ( args[0] == "!m" )
{
@menu = CTextMenu(@MenuCallback);
menu.SetTitle( "title" );
menu.AddItem( "item1", "item1" );
menu.AddItem( "item2", "item2" );
menu.Register();
g_Game.AlertMessage( at_console, "Opening menu\n");
menu.Open(2, 0, plr);
}
}
return HOOK_HANDLED;
}


How to reproduce crash:
1. Start server.
2. Open menu with "say !m".
3. Changelevel.
4. Open menu with "say !m".
5. Changelevel. - CRASH.

No amxx and metamod.

http://forums.svencoop.com/attachment.php?attachmentid=16896&stc=1

w00tguy123
13-02-2016, 12:57 AM
I don't see anything wrong there. I tried reproducing your crashes using your code and steps but it all worked fine.

Quazm
13-02-2016, 08:06 AM
Tried on just installed server with same effect. My system is win 7 x64.


https://www.youtube.com/watch?v=cNCAgn22V0A&feature=youtu.be

w00tguy123
13-02-2016, 01:11 PM
I followed along with your video and still no crash (even used the same maps). I'm also using a SteamCMD dedicated server, but I've tried this on a listen server also. I can say !m and changelevel 12 times and it never crashes.

Looking at your script, the only thing I think might possibly be a problem is that the "menu" var is never unregistered or cleared (I guess setting to null would clear it). While that hasn't been a problem for me (and I actually get errors when trying to unregister menus), it might be worth a try to unregister your menu after the callback, or even right after you've registered it, for testing. Or, try just creating the menu but don't open it and see if it still crashes.

You might be able to pinpoint the problem a bit further and discover a bug in the game or something.

Quazm
13-02-2016, 02:53 PM
and I actually get errors when trying to unregister menus
Same for me. But seems it is not necessary to prevent crashing my server. @menu = null in mapchange hook do the trick. So, I currently running this code without crashes:



CTextMenu@ menu;

void PluginInit()
{
g_Module.ScriptInfo.SetAuthor( "123" );
g_Module.ScriptInfo.SetContactInfo( "123" );
g_Hooks.RegisterHook( Hooks::Player::ClientSay, @ClientSay );
g_Hooks.RegisterHook( Hooks::Game::MapChange, @MapChange );
}
void MapInit()
{
MenuInit();
}

void MenuCallback(CTextMenu@ menu, CBasePlayer@ plr, int page, const CTextMenuItem@ item)
{
g_Game.AlertMessage( at_console, "Menu callback debug\n");
}

void MenuInit()
{
@menu = CTextMenu(@MenuCallback);
menu.SetTitle( "title" );
menu.AddItem( "item1", "item1" );
menu.AddItem( "item2", "item2" );
menu.Register();
}

HookReturnCode MapChange( )
{
if(@menu !is null)
@menu = null;
return HOOK_HANDLED;
}

HookReturnCode ClientSay( SayParameters@ pParams )
{
const CCommand@ args = pParams.GetArguments();
CBasePlayer@ plr = pParams.GetPlayer();
if ( args.ArgC() > 0 )
{
if ( args[0] == "!m" )
{
g_Game.AlertMessage( at_console, "Opening menu \n");
g_PlayerFuncs.ClientPrintAll( HUD_PRINTTALK, "Opening menu %s\n", string(menu.get_Id()));
menu.Open(5, 0, plr);

}
}
return HOOK_HANDLED;
}


Thanks for helping me.

w00tguy123
13-02-2016, 06:30 PM
@menu = null in mapchange hook do the trick.

Interesting. This might be why people are crashing when they use my plugin...

It's strange that it doesn't affect me.

Solokiller
15-02-2016, 03:15 AM
I've debugged this, what happens is that every time the map changes, all text menus are removed. The menu handle still points to a menu that has been removed, so when you assign a new one, it tries to release the old one, which points to freed memory. I've changed it so that menus are no longer removed on map change. Note that you should release menus when you no longer use them, otherwise you'll end up using up all of the menu IDs (which is unlikely, but still).

As to why it doesn't happen to everyone, i've noticed differences between Windows 8 and other versions regarding bugs like this. W8 tends to initialize all memory to 0, preventing dangling pointer bugs from occurring quite as often. It makes debugging harder than it should be.

w00tguy123
15-02-2016, 03:27 AM
I've debugged this, what happens is that every time the map changes, all text menus are removed. The menu handle still points to a menu that has been removed, so when you assign a new one, it tries to release the old one, which points to freed memory. I've changed it so that menus are no longer removed on map change. Note that you should release menus when you no longer use them, otherwise you'll end up using up all of the menu IDs (which is unlikely, but still).

As to why it doesn't happen to everyone, i've noticed differences between Windows 8 and other versions regarding bugs like this. W8 tends to initialize all memory to 0, preventing dangling pointer bugs from occurring quite as often. It makes debugging harder than it should be.

Thank you for the fix and especially for the additional info! That explains my problem. I guess I'll be doing all my testing on Windows 7 from now on, unless there is some way to prevent Windows 8 being too nice.

Quazm
15-02-2016, 03:43 AM
Note that you should release menus when you no longer use them
You mean Unregister() function?

Solokiller
15-02-2016, 03:58 AM
No, do @menu = null;
You have to release the handle itself.