Raised This Month: $ Target: $400
 0% 

getting dependent plugins to add info to a menu in core plugin?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
nergal
Veteran Member
Join Date: Apr 2012
Old 12-31-2015 , 22:11   getting dependent plugins to add info to a menu in core plugin?
Reply With Quote #1

basically in the Title....

I'm trying to make a core-module plugin system where the modules add info to a Menu handle which the core plugin then utilizes but my attempts have failed.

One attempt was to use a global forward and push a reference of the menu handle. This worked when only one module-plugin was utilizing it but it didn't work when I had multiple plugins trying to do this.

Here's exactly what I want it to do.

I want the core plugin to send a single menu handle for the module plugins to edit and have the core plugin then use the modified menu handle for whatever.

How can I do this without multiple module-plugins overriding the menu handle like using a Global Forward did?
__________________

Last edited by nergal; 12-31-2015 at 22:11.
nergal is offline
Godis
Senior Member
Join Date: Jan 2014
Old 01-01-2016 , 06:53   Re: getting dependent plugins to add info to a menu in core plugin?
Reply With Quote #2

EDIT: After reading your question again, i'm not so sure this is what you wanted, i'm sorry if that's the case.

This is how i do it, i'm not sure if i should be posting it here or in the snippets/tutorials section but whatever.
I think it is safer and less error prone to create an interface rather than giving out the handle to other plugins.

This code will enable plugins to add new items to another plugins menu.
First we need some way of storing our menu items information, i am going to use a multidimensional array for this.

PHP Code:
enum MenuItem
{
    
String:DisplayName[32],
    
String:Info[32],
    
Handle:PluginHandle
};

int g_menu_item[32][MenuItem]; // Each of the 32 slots available can hold two strings and one handle 
In this array, we will be able to store up to 32 different items, we'll come back here later.

Adding the item to the menu is the easy part, but we need some way of sending information back to the plugin that created the item.
First create an include file, myplugin.inc;

PHP Code:
#if defined MYPLUGIN_INC
 #endinput
#endif
#define MYPLUGIN_INC

typeset MyPlugin_MenuCallback // This function will be used as a callback to send the info string back to the module
{
    function 
void(int client, const char[] info);

And while we're here, let's define our native too.

PHP Code:
/**
 * Add an item to the MyPlugin main menu.
 *
 * @param display        What the item will appear as in the menu (obviously).
 * @param info            Information string, used to know what item was selected if multiple have been created by the same plugin.
 *
 * @return                Slot in the array/menu, may be useful for other purposes (removing, finding the item etc).
 */
native int MyPlugin_AddMenuItem(const char[] display, const char[] infoMyPlugin_MenuCallback callback);

public 
SharedPlugin __pl_myplugin =
{
    
name "myplugin",
    
file "myplugin.smx",
#if defined REQUIRED_PLUGIN
    
required 1,
#else
    
required 0,
#endif
};

#if !defined REQUIRED_PLUGIN
public __pl_myplugin_SetNTVOptional()
{
    
MarkNativeAsOptional("MyPlugin_AddMenuItem");

Now let's go back and update our MenuItem enum;

PHP Code:
enum MenuItem
{
    
String:DisplayName[32],
    
String:Info[32],
    
Handle:PluginHandle,
    
MyPlugin_MenuCallback:Callback
};

int g_menu_item[32][MenuItem];
int g_menu_item_count// We use this for iterating through the array later 
We haven't created our native function yet so let's do that.

PHP Code:
public APLRes AskPluginLoad2(Handle myselfbool latechar[] errorint err_max)
{
    
CreateNative("MyPlugin_AddMenuItem"Native_AddMenuItem);
    
RegPluginLibrary("myplugin");
    return 
APLRes_Success;
}

public 
int Native_AddMenuItem(Handle pluginint params)
{
    
char display[32];
    
GetNativeString(1displaysizeof(display));
    
    
char info[32];
    
GetNativeString(2infosizeof(info));
    
    
int item;

    for(
int i 0g_menu_item_counti++) // Iterate through every available item slot until the condition below are met
    
{
        if(
g_menu_item[i][PluginHandle] != null// Here we just make sure the slot is not occupied
        
{
            
Format(g_menu_item[i][DisplayName], 32display);
            
Format(g_menu_item[i][Info], 32info);
            
g_menu_item[i][PluginHandle] = plugin// We need to know where to go when the item is selected
            
g_menu_item[i][Callback] = GetNativeCell(3);
            
            
g_menu_item_count++;
            
item i;

            break; 
// The item was added to the first empty slot in the array, we're done here
        
}
    }

    return 
item// Return the item slot, again this can be used later.

Let's actually create the menu now.

PHP Code:
void ShowMyMenu(int client)
{
    
Menu menu = new Menu(MenuHandler);
    
menu.SetTitle("MyPlugin Amazing Menu");
    
    
int err_count;
    for(
int i 0g_menu_item_counti++)
    {
        if(
GetPluginStatus(g_menu_item[i][PluginHandle]) != Plugin_Running// Make sure the plugin is loaded before proceeding
        
{
            
g_menu_item[i][PluginHandle] = null// Something did not work out, remember we checked the plugin handle for null in our native?
            
err_count++;
            
            break;
        }

        
char buffer[32];
        
IntToString(ibuffersizeof(buffer)); // Passed to the handler, we need the array slot to be able to do anything
        
menu.AddItem(bufferg_menu_item[i][DisplayName]);
    }
    
    
g_menu_item_count -= err_count;

    
menu.ExitButton true;
    
menu.Display(client20);
}

public 
int MenuHandler(Menu menuMenuAction actionint param1int param2)
{
    if(
action == MenuAction_Select)
    {
        
char info[32];
        
menu.GetItem(param2infosizeof(info));
        
        
int item StringToInt(info); // Transform our array slot back into an integer
        
        
Call_StartFunction(g_menu_item[item][PluginHandle], view_as<Function>(g_menu_item[item][Callback])); // Pass the plugin handle and the callback we stored for this specific item.
        
Call_PushCell(param1); // Client who selected the item
        
Call_PushString(g_menu_item[item][Info]); // Item string used by the module
        
Call_Finish();
    }
    else if(
action == MenuAction_End)
    {
        
delete menu;
    }

We still need some way to tell our modules it's okay to start adding items, for this we will use a global forward.

PHP Code:
Handle g_fwd_ready null;

public 
void OnPluginStart()
{
    
g_fwd_ready CreateGlobalForward("OnMyPluginReady"ET_Ignore);
}

public 
void OnAllPluginsLoaded() // Called once, if it loaded late it will be called right after OnPluginStart
{
    
Call_StartForward(g_fwd_ready);
    
Call_Finish();

And in our include file

PHP Code:
forward void OnMyPluginReady(); 
Now if all is well, we should be able to do this:
PHP Code:
#include <sourcemod>
#include <myplugin>

public void OnPluginStart()
{
    
OnMyPluginReady(); // Account for late-loading
}

public 
void OnMyPluginReady()
{
    
MyPlugin_AddMenuItem("My Item #1""item1"view_as<MyPlugin_MenuCallback>(MyCallback));
    
MyPlugin_AddMenuItem("My Item #2""item2"view_as<MyPlugin_MenuCallback>(MyCallback));
}

public 
void MyPlugin_MenuCallback MyCallback(int client, const char[] info)
{
    
PrintToChat(client"%s"info); // either "item1" or "item2"

I hope this will help you! It is quite an extensive post so forgive me for any mistakes, i just woke up so i'm still quite tired.

Last edited by Godis; 01-01-2016 at 15:14.
Godis 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 17:41.


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