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

[TUT] Better Methodmaps tut


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
nergal
Veteran Member
Join Date: Apr 2012
Old 03-29-2015 , 14:50   [TUT] Better Methodmaps tut
Reply With Quote #1

the sourcepawn transitional syntax wiki [ https://wiki.alliedmods.net/SourcePa...itional_Syntax ] horribly explains methodmaps.

This tutorial will aim to give a better understanding, especially to beginners...

In a nutshell, Methodmaps are basically class-like functions for enums

According to Bailopan, "Methodmaps are syntactic transformations only. That is, x.y() on methodmap Z is transformed into a function call that looks like Z_y(x)." - https://forums.alliedmods.net/showpo...&postcount=365

As you can see, methodmaps can help make life a bit easier. Let's begin!

It should be known that methodmaps do not need to be attached to a enum to work. You can have a solo methodmap work by itself, but if you want custom types/tags, then you will be needing an enum.

Because methodmaps are similar to classes, the first part of a methodmap you need is a constructor!

Through messing around with the compiler and such, I've found that Constructors must always have the same name as the Methodmap they're operating from as well as having no identified return type! Constructors can also just do nothing lol! As long as you have a constructor at least.
PHP Code:
methodmap MapMethod
{
    public 
MapMethodint index //this is the constructor!
    
{
        return 
view_as<MapMethod>( index ); /*you must return the data as the methodmap. The data also cannot be an array
or the enum tag you're making the methodmap for or make the constructor do absolutely nothing.*/
    
}

Methodmaps can also have regular, normal functions be used inside them, like so!
PHP Code:
methodmap EntityWithHealth
{
    public 
void SetHealth(int value//normal function
    
{
        
SetEntProp(thisProp_Send"m_iHealth"value);
    }

Adding properties/accessors to your methodmap can make it that much simpler to accessing data. Properties have getters and setters so you can easily set their data and utilize it as soon as possible! properties do not have to have both getters and setters but it should definitely have getters.
PHP Code:
int iMoney 0;
/*
remember that methodmaps are not classes/structs so you need to create globals.
The purpose of the methodmap is to be the only modifier of these global variables
so that the code is more structured and controlled.
*/

methodmap Bank
{
    
property int Money //property!
    
{
        public 
get() { return iMoney; }
        public 
setint value ) { iMoney value; } //property is an int, so the data must be set with an int!
    
}

Then there's inheritance! You can make other methodmaps get the same data and handling as your initial methodmap!

Here's a good example. The parent methodmap has the money property while the child mtm has toys! Since the child mtm inherits from the parent mtm, that means you can use the "Money" accessor from the child mtm!
PHP Code:
int iMoney;
int iToys;
methodmap Parent
{
    
property int Money //has money!
    
{
        public 
get() { return iMoney; }
        public 
setint value ) { iMoney value; }
    }
}
methodmap Child Parent
{
    
property int Toys //has toys AND money :D
    
{
        public 
get() { return iToys; }
        public 
setint value ) { iToys value; }
    }

There's also stuff about inline methods but I've never used them but I just wanted to cover the beginner stuff.

The most important concept of methodmaps is the "this" name. The "this" name basically refers to whatever instance of the methodmap uses the available functions inside it. look at the final code below to see what I mean.

Here's the final product of what most realistic (custom) methodmaps would look like and how they are used!

PHP Code:

int iHealth
[MAXPLAYERS+1];
int iAmmo[MAXPLAYERS+1];
float flSpeed[MAXPLAYERS+1];

methodmap Playur
{
    public 
Playur(int playerindex//constructor
    
{
        return 
view_as<Playur>(playerindex); //make sure you do validity check on players
    
}
     
property int index 
    

        public 
get()                { return view_as<int>(this); } 
    }
    
property int Health
    
{
        public 
get() { return iHealth[this.index]; }
        public 
setint value ) { iHealth[this.index] = value; }
    }
    
property int Ammo
    
{
        public 
get() { return iAmmo[this.index]; }
        public 
setint value ) { iAmmo[this.index] = value; }
    }
    
property float Speed
    
{
        public 
get() { return flSpeed[this.index]; }
        public 
setfloat value ) { flSpeed[this.index] = value; }
    }
    public 
void GiveAmmo(int amount)
    {
        
this.Ammo += amount;
    }
    public 
void RemoveAmmo(int amount)
    {
        
this.Ammo -= amount;
    }
}

public 
void OnClientPutInServer(int client)
{
    
Playur player Playur(client);
    if (
player.Health 1player.Health 100;
    if (
player.Ammo 1player.Ammo 50;
    if (
player.Speed 1.0player.Speed 300.0;

EDIT #1

another thing to introduce to the Methodmaps is the concept of "objectifying" them

Here's an example!
PHP Code:
methodmap MapMethod __nullable__
{
    ........

the methodmap is now nullable! Nullable methodmaps actually create objects compared to normal, non-nullable methodmaps!

with a nullable methodmap, you have to use "new" with its constructor!

like so!
PHP Code:
methodmap MapMethod __nullable__
{
    public 
MapMethod() //constructor
    
{
        
//code here
    
}
}

MapMethod Data = new MapMethod(); 
Here's a better full example from one of my own plugins, the Arm Chair General plugin that allows spectators to be more interactive with red or blue team....

PHP Code:
enum {
    
IsGen 0,
    
LeadingTeam
};

#define int(%1)            view_as<int>(%1)

int General[MAX][2];

methodmap Commander
{
    public 
Commander(int userid//constructor: It's less of a headache to use userids
    
{
        if ( 
IsValidClientuserid ) ) {
            return 
view_asCommander >( GetClientUserIduserid ) );
        }
        return 
view_asCommander >(-1);
    }

    
property int index
    
{
        public 
get()            { return GetClientOfUserIdint(this) ); }
    }
    
property int bIsGeneral
    
{
        public 
get()            { return Generalthis.index ][ IsGen ]; }
        public 
setint val )        { Generalthis.index ][ IsGen ] = val; }
    }
    
property int iLeadingTeam
    
{
        public 
get()            { return Generalthis.index ][ LeadingTeam ]; }
        public 
setint val )        { Generalthis.index ][ LeadingTeam ] = val; }
    }
}; 
Creating a methodmap out of natives!

.inc file
PHP Code:
methodmap NativeMap
{
    public 
native NativeMap();

    
property int MyIntProperty {
        public 
native get();
        public 
native set(const int val);
    }

    public 
native void MyMethodFunc();

implementation in the plugin that's exporting the native-based methodmap
PHP Code:
public APLRes AskPluginLoad2(Handle myselfbool latechar[] errorint err_max)
{  
    
CreateNative("NativeMap.NativeMap"Native_NativeMapInstance);

    
CreateNative("NativeMap.MyIntProperty.get"Native_GetMyIntProperty);
    
CreateNative("NativeMap.MyIntProperty.set"Native_SetMyIntProperty);
    
CreateNative("NativeMap.MyMethodFunc"Native_MyMethodFunc);
    
    return 
APLRes_Success;
}

public 
int Native_NativeMapInstance(Handle pluginint numParams)
{
    return 
GetNativeCell(1);
}
public 
int Native_GetMyIntProperty(Handle pluginint numParams)
{
    return 
Health[GetNativeCell(1)];    /* GetNativeCell(1) IS ALWAYS THE "this" parameter */
}
public 
int Native_SetMyIntProperty(Handle pluginint numParams)
{
    
Health[GetNativeCell(1)] = GetNativeCell(2);
}
public 
int Native_MyMethodFunc(Handle pluginint numParams)
{
    
CallBackFunc(GetNativeCell(1), GetNativeCell(2));
    
// Remember that GetNativeCell(1) is always the "this" parameter aka the first argument

__________________

Last edited by nergal; 12-13-2016 at 03:24.
nergal is offline
Chdata
Veteran Member
Join Date: Aug 2012
Location: Computer Chair, Illinois
Old 03-29-2015 , 15:00   Re: [TUT] Better Methodmaps tut
Reply With Quote #2

(int i = 0; i < 9; i++)

(int i = 0; i < 10; i++)
__________________
Chdata is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 03-29-2015 , 15:28   Re: [TUT] Better Methodmaps tut
Reply With Quote #3

Quote:
Originally Posted by chdata View Post
(int i = 0; i < 9; i++)

(int i = 0; i < 10; i++)
(╯ ͡° ͜ʖ ͡°)╯︵ /(.□ . \)
__________________
nergal is offline
psychonic

BAFFLED
Join Date: May 2008
Old 03-29-2015 , 16:03   Re: [TUT] Better Methodmaps tut
Reply With Quote #4

Quote:
Originally Posted by nergal View Post
the sourcepawn transitional syntax wiki [ https://wiki.alliedmods.net/SourcePa...itional_Syntax ] horribly explains methodmaps.
It's a wiki. Feel free to edit or add to it.

(You can use your forum username and password to log in).
psychonic is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 03-29-2015 , 17:31   Re: [TUT] Better Methodmaps tut
Reply With Quote #5

Quote:
Originally Posted by psychonic View Post
It's a wiki. Feel free to edit or add to it.

(You can use your forum username and password to log in).
my gut says I shouldn't touch the wiki and accept whatever the wiki tells me as God.
__________________
nergal is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 03-29-2015 , 18:03   Re: [TUT] Better Methodmaps tut
Reply With Quote #6

A huge focus of this is on properties... but none of your properties have anything backing them.
__________________
asherkin is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 03-29-2015 , 18:50   Re: [TUT] Better Methodmaps tut
Reply With Quote #7

Quote:
Originally Posted by asherkin View Post
A huge focus of this is on properties... but none of your properties have anything backing them.
not quite understanding what you mean.

I'm assuming you're saying that there's no real variables? They're just examples.

Plus we should talk about this more so others can understand more where I'm making a mistake
__________________
nergal is offline
TnTSCS
AlliedModders Donor
Join Date: Oct 2010
Location: Undisclosed...
Old 03-30-2015 , 03:32   Re: [TUT] Better Methodmaps tut
Reply With Quote #8

I will be watching this thread - Methodmaps is a completely foreign concept for me atm.
__________________
View my Plugins | Donate
TnTSCS is offline
Nerus
Senior Member
Join Date: Aug 2010
Location: Poland
Old 12-26-2015 , 09:59   Re: [TUT] Better Methodmaps tut
Reply With Quote #9

Quote:
Originally Posted by TnTSCS View Post
I will be watching this thread - Methodmaps is a completely foreign concept for me atm.
OK, there is other method to create something similar to class ?

Regards,
Nerus
Nerus is offline
nosoop
Veteran Member
Join Date: Aug 2014
Old 12-26-2015 , 11:15   Re: [TUT] Better Methodmaps tut
Reply With Quote #10

Quote:
Originally Posted by nergal View Post
I'm assuming you're saying that there's no real variables? They're just examples.
Here's what I (very sleepily) think might throw people off:
  • First example: The variable name index is vague. I'm assuming entity index based on context, but there's also array indices. MethodMap is also vague and I'd recommend replacing it with a more descriptive name for that particular example, like DamageableEntity.
  • Second example: I'd say add the constructor from the previous constructor to this snippet for completeness' sake, and explain that this basically just refers to the value passed into the constructor (which is why it was only returned with a different view; syntactic transformation only, remember!).
  • Third through fifth: Methodmaps have no member variables; just having iMoney, etc. show up out of nowhere leaves questions of implementation (which I can't think of a simple answer to except by saying "just pretend methodmaps don't exist and use some kind of array / data structure like you would've instead"). I'd point to the SourceMod transitional helpers for some examples of the "pass a variable and use 'wrapper' functions to manipulate them in a readable fashion", as well as the new API documentation for DataPacks (note: the x() = y binding was removed), StringMaps, etc. to show how they're used when you're working with Handles.
  • Eighth: int(x) doesn't exist in stock SourceMod?
Can't comment on __nullable__ as I'm not familiar with the specifics of that, but I'm sure they don't actually create objects (i.e., they won't magically have member variables).

Quote:
Originally Posted by Nerus View Post
OK, there is other method to create something similar to class?
Not quite natively. As mentioned, you have to store those "member" variables somewhere. The built-in StringMaps or Dynamic would work, but you'll be working with Handles at that point.
__________________
I do TF2, TF2 servers, and TF2 plugins.
I don't do DMs over Discord -- PM me on the forums regarding inquiries.
AlliedModders Releases / Github / TF2 Server / Donate (BTC / BCH / coffee)

Last edited by nosoop; 12-26-2015 at 11:38. Reason: 8:30am? time for beeeeed
nosoop is offline
Reply


Thread Tools
Display Modes

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 02:57.


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