AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   Enum Structs Available This Holiday Season (https://forums.alliedmods.net/showthread.php?t=312822)

BAILOPAN 12-17-2018 02:50

Enum Structs Available This Holiday Season
 
Hi Folks,

As of PR #934, SourceMod 1.10 has support for enum structs. This is some long-overdue syntactic sugar that makes SourcePawn feel more like a real language. Enum Structs are internally implemented as arrays, but the syntax is a lot nicer than before and we've fixed a lot of the corner cases and rough edges around using them. You can also have enum struct methods now.

You can read more about enum structs either in the Transitional Syntax Docs, or in the commit message.

If you're too impatient to read that, I'll just copy and paste the sample code from the doc:

PHP Code:

enum struct Rectangle {
  
int x;
  
int y;
  
int width;
  
int height;
 
  
int Area() {
    return 
this.width this.height;
  }
}
 
void DoStuff(const Rectangle r) {
  
PrintToServer("%d, %d, %d, %d"r.xr.yr.widthr.height);



Maxximou5 12-17-2018 03:37

Re: Enum Structs Available This Holiday Season
 
Like a breath of fresh air. Well done!

Starbish 12-19-2018 04:33

Re: Enum Structs Available This Holiday Season
 
I really appreciate this!

but looks like latest mac compiler can't compile this expression...?

Powerlord 12-19-2018 22:06

Re: Enum Structs Available This Holiday Season
 
If I ever get around to working on it again, this will greatly simplify some the code to a plugin I was working on to replace the aging UMC plugin.

Timocop 12-22-2018 14:52

Re: Enum Structs Available This Holiday Season
 
All this sugar is pretty epic. Already added support to BasicPawn.
Lets hope we dont get diabetes :lol:

ofir753 12-22-2018 15:00

Re: Enum Structs Available This Holiday Season
 
Looks great but why 'enum' is needed its seems like c struct

KliPPy 12-22-2018 15:21

Re: Enum Structs Available This Holiday Season
 
Because it's still just syntactic sugar over arrays, just like old enum structs, but with nicer syntax.

Powerlord 12-23-2018 01:34

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by KliPPy (Post 2630549)
Because it's still just syntactic sugar over arrays, just like old enum structs, but with nicer syntax.

Exactly. I don't know about you, but one plugin I was writing literally has a text document to remind me of what the object graph is supposed to look like because they're not easily expressed through old-style enum structs.

Edit: Also text document because I'm too lazy to use a UML diagram maker to do it.

LeToucan 12-24-2018 04:19

Re: Enum Structs Available This Holiday Season
 
Is there a way we can push enum structs with array fields in them into an ArrayList? For example,

PHP Code:

#include <sourcemod>

enum struct Foo {
    
int x;
    
int y;
    
char strTest[32];
    
int iTest[16];
}

public 
void OnPluginStart() {
    
PrintToChatAll("Start");
    
    
Foo f;
    
strcopy(f.strTestsizeof(f.strTest), "Bar");
    
f.iTest[0] = 123;
    
    
ArrayList arr = new ArrayList();
    
    
PrintToChatAll("f.strTest = \"%s\", f.iTest[0] = %d"f.strTestf.iTest[0]);
    
    
arr.PushArray(fsizeof(f));
    
Foo copy;
    
arr.GetArray(0copysizeof(copy));
    
    
PrintToChatAll("copy.strTest = \"%s\", copy.iTest[0] = %d"copy.strTestcopy.iTest[0]);
    
PrintToChatAll("End");


has the following output

Code:

Start
f.strTest = "Bar", f.iTest[0] = 123
copy.strTest = "", copy.iTest[0] = 0
End


hmmmmm 12-25-2018 07:25

Re: Enum Structs Available This Holiday Season
 
Seems like a bug to me. You should open an issue on the github page: https://github.com/alliedmodders/sourcepawn/issues

Bacardi 12-25-2018 07:30

Re: Enum Structs Available This Holiday Season
 

LeToucan 12-26-2018 16:33

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by Bacardi (Post 2630883)

So since enum structs are treated as an array, when using array fields they are treated as 2 dimensional arrays, and thus wouldn't correctly work with ArrayLists? The section outlining using them with ArrayLists could be updated, as this part makes it seem like my snippet should work.
Quote:

The exception is when interacting with opaque data structures like ArrayList. For example, this is considered valid:

KliPPy 12-26-2018 17:10

Re: Enum Structs Available This Holiday Season
 
You never gave blocksize to the ArrayList constructor.

Powerlord 12-26-2018 17:20

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by LeToucan (Post 2631124)
So since enum structs are treated as an array, when using array fields they are treated as 2 dimensional arrays, and thus wouldn't correctly work with ArrayLists? The section outlining using them with ArrayLists could be updated, as this part makes it seem like my snippet should work.

While I can't say I know how Pawn internally treats 2-dimensional arrays, in this case you're storing an array reference nside another array.

It helps if you know arrays are a reference type. When I say that, I mean when you do this:

PHP Code:

int players[MAXPLAYERS+1]; 

you're actually creating an array with a length of MAXPLAYERS+1, then storing the memory address of the start of that array in players

LeToucan 12-26-2018 17:23

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by KliPPy (Post 2631130)
You never gave blocksize to the ArrayList constructor.

Thank you, after setting the blocksize to sizeof(f), it worked perfectly.

gubka 01-05-2019 22:52

Re: Enum Structs Available This Holiday Season
 
BAILOPAN, great update, so handy, btw can we wait some update in methodmaps part ? We need some improvements there, something look like a clases with proper constructor and destructor or may be a posibility to create values inside a methodmap class, like in a new struct and use them only there

Timocop 01-06-2019 10:02

Re: Enum Structs Available This Holiday Season
 
methodmaps != classes

While 'enum structs' can hold multiple values because they are arrays, methodmaps can only hold one.

If you want to store something *in* methodmaps use StringMap's (or any other list). StringMap's are more readable. Example:

PHP Code:

methodmap Player StringMap
{
    public 
Player(int id)
    {
        
StringMap map = new StringMap();
        
        
map.SetValue("id"id);
        
map.SetValue("userid"GetClientUserId(id));
        
map.SetValue("money"100);
        
        return 
view_as<Player>(map);
    }
    
    
property int Userid
    
{
        public 
get() {
            
int i;
            
this.GetValue("userid"i);
            return 
i;
        }
    }
    
    
property int Id
    
{
        public 
get() {
            
int i;
            
this.GetValue("id"i);
            return 
i;
        }
    }
    
    
property int Money
    
{
        public 
get() {
            
int i;
            
this.GetValue("money"i);
            return 
i;
        }
        public 
set(int i) {
            
this.SetValue("money"i);
        }
    }
    
    public 
bool IsValid()
    {
        return (
GetClientOfUserId(this.Userid) > 0);
    }
    
    public 
bool InGame()
    {
        return (
IsClientInGame(this.Id));
    }
}

public 
void OnClientPutInServer(int client)
{
    
Player player = new Player(client);
    
    
CreateTimer(30.0SetPlayerMoneyTimerplayer);
}

public 
Action SetPlayerMoneyTimer(Handle timerPlayer player)
{
    if(!
player.IsValid() || !player.InGame())
        return;
    
    
player.Money 2500;
    
    
delete player;


if you remove the sugar it will look like this (decompiled):
PHP Code:

Player:Player.Player(id)
{
    new 
StringMap:map StringMap.StringMap();
    
StringMap.SetValue(map"id"idtrue);
    
StringMap.SetValue(map"userid"GetClientUserId(id), true);
    
StringMap.SetValue(map"money"any:100true);
    return 
map;
}

Player.Userid.get(Player:this)
{
    new 
i;
    
StringMap.GetValue(this"userid"i);
    return 
i;
}

Player.Id.get(Player:this)
{
    new 
i;
    
StringMap.GetValue(this"id"i);
    return 
i;
}

void:Player.Money.set(Player:thisi)
{
    
StringMap.SetValue(this"money"itrue);
    return 
void:0;
}

bool:Player.IsValid(Player:this)
{
    return 
GetClientOfUserId(Player.Userid.get(this)) > 0;
}

bool:Player.InGame(Player:this)
{
    return 
IsClientInGame(Player.Id.get(this));
}

public 
void:OnClientPutInServer(client)
{
    new 
Player:player Player.Player(client);
    
CreateTimer(30.0SetPlayerMoneyTimerplayer0);
    return 
void:0;
}

public 
Action:SetPlayerMoneyTimer(Handle:timerPlayer:player)
{
    new 
var1;
    if (!
Player.IsValid(player) || !Player.InGame(player))
    {
        return 
Action:0;
    }
    
Player.Money.set(player2500);
    
CloseHandle(player);
    
player MissingTAG:0;
    return 
Action:0;



asherkin 01-06-2019 10:38

Re: Enum Structs Available This Holiday Season
 
New-style enum structs having a "methodmap" built-in is meant to solve the problem of methodmaps not having storage - what is lacking?

Santi. 01-09-2019 17:21

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by BAILOPAN (Post 2629530)
Hi Folks,

As of PR #934, SourceMod 1.10 has support for enum structs. This is some long-overdue syntactic sugar that makes SourcePawn feel more like a real language. Enum Structs are internally implemented as arrays, but the syntax is a lot nicer than before and we've fixed a lot of the corner cases and rough edges around using them. You can also have enum struct methods now.

You can read more about enum structs either in the Transitional Syntax Docs, or in the commit message.

If you're too impatient to read that, I'll just copy and paste the sample code from the doc:

PHP Code:

enum struct Rectangle {
  
int x;
  
int y;
  
int width;
  
int height;
 
  
int Area() {
    return 
this.width this.height;
  }
};
 
void DoStuff(const Rectangle r) {
  
PrintToServer("%d, %d, %d, %d"r.xr.yr.widthr.height);



I love you man.. this is what we needed. Thanks bro!

Powerlord 02-07-2019 01:48

Re: Enum Structs Available This Holiday Season
 
I can't help but notice when I try to include an enum struct in a native definition that the compiler tells me that I can't do this:

Code:

error 135: cannot use enum struct type "MapChoices_GetMapData" in natives
Won't this limit their usefulness?

Also, the error is reporting the native name rather than the enum struct name.

asherkin 02-07-2019 04:11

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by Powerlord (Post 2638498)
I can't help but notice when I try to include an enum struct in a native definition that the compiler tells me that I can't do this:

Code:

error 135: cannot use enum struct type "MapChoices_GetMapData" in natives
Won't this limit their usefulness?

Also, the error is reporting the native name rather than the enum struct name.

https://github.com/alliedmodders/sou...ment-445578252

https://github.com/alliedmodders/sourcepawn/issues/295

Ilusion9 02-11-2019 08:15

Re: Enum Structs Available This Holiday Season
 
PHP Code:


#pragma semicolon 1
#pragma newdecls required

#include <sourcemod>

enum struct PlayerInfo
{
    
char steam[65];
    
char name[65];
    
int time;
};

ArrayList g_Players;

public 
void OnPluginStart()
{
    
g_Players = new ArrayList(sizeof(PlayerInfo));
    
HookEvent("player_disconnect"Event_PlayerDisconnect);
    
    
RegConsoleCmd("sm_lastpl"Command_Last);
}

public 
void Event_PlayerDisconnect(Event event, const char[] namebool dontBroadcast
{
    
PlayerInfo info;
    
event.GetString("networkid"info.steamsizeof(PlayerInfo::steam));
    
    if (
StrEqual(info.steam"BOT"))
    {
        return;
    }
    
    
event.GetString("name"info.namesizeof(PlayerInfo::name));
    
info.time GetTime();
    
    
g_Players.PushArray(info);
    if (
g_Players.Length 10)
    {
        
g_Players.Erase(0);
    }
}

public 
Action Command_Last(int clientint args)
{    
    for (
int i 0g_Players.Lengthi++)
    {
        
PlayerInfo info;
        
g_Players.GetArray(iinfo);

        
char time[65];
        
FormatTimeDuration(timesizeof(time), GetTime() - info.time);
        
PrintToConsole(client"[%02d] %s : %s : %s ago"1info.steaminfo.nametime);
    }
    
    return 
Plugin_Handled;
}


int FormatTimeDuration(char[] bufferint maxlenint time)
{
    
int hours time 3600;
    
int minutes = (time 60) % 60;

    if (
hours 0)
    {
        return 
Format(buffermaxlen"%dh %dm"hoursminutes);        
    }
    
    if (
minutes 0)
    {
        return 
Format(buffermaxlen"%dm"minutes);        
    }
    
    return 
Format(buffermaxlen"%ds"time 60);        


Here's an example with structs and arraylists.
I don't know how sizeof of structs works, but if i have 3 members, calling g_Players = new ArrayList(3) it's wrong (only the first paramater - "steam" works fine), so g_Players = new ArrayList(sizeof(PlayerInfo)) it's the correct one.

BAILOPAN 02-18-2019 17:00

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by gubka (Post 2633119)
BAILOPAN, great update, so handy, btw can we wait some update in methodmaps part ? We need some improvements there, something look like a clases with proper constructor and destructor or may be a posibility to create values inside a methodmap class, like in a new struct and use them only there

Enum structs are the near-term workaround for lack of instance-variables in methodmaps.

BAILOPAN 02-18-2019 17:02

Re: Enum Structs Available This Holiday Season
 
I've made a very slight change to the enum struct syntax. The final closing brace (}) must now be followed by a newline. Semicolons are not allowed even with #pragma semicolon, to be consistent with most other close-brace scenarios.

SZOKOZ 02-27-2019 01:58

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by BAILOPAN (Post 2640204)
I've made a very slight change to the enum struct syntax. The final closing brace (}) must now be followed by a newline. Semicolons are not allowed even with #pragma semicolon, to be consistent with most other close-brace scenarios.

That explains the error I just encountered with the latest build. The snippet in the original post should be updated to reflect the change.

BAILOPAN 03-10-2019 20:19

Re: Enum Structs Available This Holiday Season
 
Done, thanks!

kossolax 05-30-2019 17:29

Re: Enum Structs Available This Holiday Season
 
Hello,

Why this one is invalid ?
error 008: must be a constant expression; assumed zero


PHP Code:

enum struct Foo {
    
int a;
    
int b;
}

Foo bar[65];

public 
void OnPluginStart() {    
    
Foo i bar[0];
    
i.1;
    
i.2;


this is valid though: bar[0].a


used version 6421

Fyren 05-30-2019 21:36

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by kossolax (Post 2653741)
Why this one is invalid ?

For now, I think you can do Foo i; i = bar[0];. I checked that it compiled, but not that it worked as expected. Assignment here is handled differently than initialization and initialization only works with constants. We'll look into it further.

TheDS1337 06-27-2019 12:04

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by Fyren (Post 2653765)
For now, I think you can do Foo i; i = bar[0];. I checked that it compiled, but not that it worked as expected. Assignment here is handled differently than initialization and initialization only works with constants. We'll look into it further.

I just noticed that enum structs works like Arrays (I pushed a struct to an array using PushArray and retrieved it back and it worked), but it doesn't actually work in the same sense as arrays can be accessed using pointers

Fyren 06-28-2019 01:32

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by TheDS1337 (Post 2656933)
I just noticed that enum structs works like Arrays

As the very first post says, this feature is merely syntactic sugar.

milutinke 11-29-2019 06:00

Re: Enum Structs Available This Holiday Season
 
Can we get the following methods and properties:?
  • .getEnumStructName() - Returns the name of the enum struct as a string.
  • .getMethods() - Returns array list of methods present in the enum struct.
  • [<method name>] (Example: rectangle["x"]) - Same as rectangle.x, if non existant, returns Invalid_Handle or if non existant while setting, gets created and gets assigned a value.

Those would be useful for serialization/deserialization.

_pHabb 12-11-2019 15:09

Re: Enum Structs Available This Holiday Season
 
Code:

enum _:Roles
{
    Vip,
    Moderator,
    Admin
};

new players[MAXPLAYERS + 1];

// Usage: players[client] = Admin;

How this code will look in the new syntax?

Ilusion9 12-11-2019 16:19

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by _pHabb (Post 2676624)
Code:

enum _:Roles
{
    Vip,
    Moderator,
    Admin
};

new players[MAXPLAYERS + 1];

// Usage: players[client] = Admin;

How this code will look in the new syntax?

PHP Code:


enum Role
{
    
Vip 0,
    
Moderator,
    
Admin
};

Role players[MAXPLAYERS 1];
// Usage: players[client] = Admin; 


LeeStrong 12-22-2019 07:35

Re: Enum Structs Available This Holiday Season
 
Is anyone able to help with the above, like many others I'm running a fork of ckSurf which if using the latest SM compiler, will not compile due to the use of enums.

I'm not the most knowledgeable when it comes to the transitional syntax and I've been having trouble getting things to compile and function when making my own efforts to convert my fork of the timer.
Notepad++ isn't the most forthcoming either!

Sample of Code
Code:

enum MapZone
{
        zoneId,                                  // ID within the map
        zoneType,                                  // Types: Start(1), End(2), Stage(3), Checkpoint(4), Speed(5), TeleToStart(6), Validator(7), Checker(8), Stop(0)
        zoneTypeId,                        // ID of the same type eg. Start-1, Start-2, Start-3...
        Float:PointA[3],
        Float:PointB[3],
        Float:CenterPoint[3],
        String:zoneName[128],
        zoneGroup,
        Vis,
        Team,
        Float:TeleportPosition[3],
        Float:TeleportAngles[3]
}

Usage:
Code:

int g_mapZones[MAXZONES][MapZone];                                                                // Map Zone array
                        if (g_mapZones[i][zoneType] == 3 && g_mapZones[i][zoneGroup] == zonegroup)
                        {
                                StageIds[amount] = i;
                                amount++;
                        }

The above is just some example usage, but there's a lot of work to be done with this timer to make it happy with the up to date syntax. Are there any relatively simple ways to convert the above without having to make too many modifications to how they are used within the code?

Many thanks in advance for anyones input on the above.

MAGNAT2645 12-26-2019 08:52

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by LeeStrong (Post 2677695)
Is anyone able to help with the above, like many others I'm running a fork of ckSurf which if using the latest SM compiler, will not compile due to the use of enums.

I'm not the most knowledgeable when it comes to the transitional syntax and I've been having trouble getting things to compile and function when making my own efforts to convert my fork of the timer.
Notepad++ isn't the most forthcoming either!

Sample of Code
Code:

enum MapZone
{
        zoneId,                                  // ID within the map
        zoneType,                                  // Types: Start(1), End(2), Stage(3), Checkpoint(4), Speed(5), TeleToStart(6), Validator(7), Checker(8), Stop(0)
        zoneTypeId,                        // ID of the same type eg. Start-1, Start-2, Start-3...
        Float:PointA[3],
        Float:PointB[3],
        Float:CenterPoint[3],
        String:zoneName[128],
        zoneGroup,
        Vis,
        Team,
        Float:TeleportPosition[3],
        Float:TeleportAngles[3]
}

Usage:
Code:

int g_mapZones[MAXZONES][MapZone];                                                                // Map Zone array
                        if (g_mapZones[i][zoneType] == 3 && g_mapZones[i][zoneGroup] == zonegroup)
                        {
                                StageIds[amount] = i;
                                amount++;
                        }

The above is just some example usage, but there's a lot of work to be done with this timer to make it happy with the up to date syntax. Are there any relatively simple ways to convert the above without having to make too many modifications to how they are used within the code?

Many thanks in advance for anyones input on the above.

Code:

enum struct MapZone
{
        int zoneId,                                  // ID within the map
        int zoneType,                                  // Types: Start(1), End(2), Stage(3), Checkpoint(4), Speed(5), TeleToStart(6), Validator(7), Checker(8), Stop(0)
        int zoneTypeId,                        // ID of the same type eg. Start-1, Start-2, Start-3...
        float PointA[3],
        float PointB[3],
        float CenterPoint[3],
        char zoneName[128],
        int zoneGroup,
        int Vis,
        int Team,
        float TeleportPosition[3],
        float TeleportAngles[3]
}

MapZone g_mapZones[MAXZONES];

Example, instead of g_mapZones[i][zoneType] use g_mapZones[i].zoneType

LeeStrong 12-27-2019 22:51

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by MAGNAT2645 (Post 2678080)
Code:

enum struct MapZone
{
        int zoneId,                                  // ID within the map
        int zoneType,                                  // Types: Start(1), End(2), Stage(3), Checkpoint(4), Speed(5), TeleToStart(6), Validator(7), Checker(8), Stop(0)
        int zoneTypeId,                        // ID of the same type eg. Start-1, Start-2, Start-3...
        float PointA[3],
        float PointB[3],
        float CenterPoint[3],
        char zoneName[128],
        int zoneGroup,
        int Vis,
        int Team,
        float TeleportPosition[3],
        float TeleportAngles[3]
}

MapZone g_mapZones[MAXZONES];

Example, instead of g_mapZones[i][zoneType] use g_mapZones[i].zoneType

Brilliant! This looks easier than I anticipated, I'll give this a try tomorrow and report in.
Thank you so much. :)

NiagaraDryGuy 12-28-2019 01:21

Re: Enum Structs Available This Holiday Season
 
Quote:

Originally Posted by _pHabb (Post 2676624)
Code:

enum _:Roles

I wish I knew why the hell the enum is using _: which is the old syntax version of view_as<int>.

enum view_as<int>(Roles) just doesn't seem right to me.

Deather 06-24-2020 14:30

Re: Enum Structs Available This Holiday Season
 
Is it possible to return enum struct in function? Code below doesn't work.

Code:

enum struct STest
{
    int a;
    int b;
}
STest test;

STest GetTest()
{
  return test;
}


asherkin 06-24-2020 15:46

Re: Enum Structs Available This Holiday Season
 
The compiler doesn't appear to currently understand it as a type when parsing the function declaration, interestingly using it as any[] appears to work correctly but I have no idea if that is intended.

As with other array-like things in SourcePawn, it's almost certainly better to pass it as a param to be filled in by the callee.

PHP Code:

enum struct STest
{
    
int a;
    
int b;
}

STest test;

any[] GetTest()
{
   return 
test;
}

public 
void OnPluginStart()
{
    
test.4;
    
test.8;
    
    
STest other;
    
other GetTest();
    
    
PrintToServer("%d = %d, %d = %d"test.aother.atest.bother.b);



Deather 06-24-2020 17:10

Re: Enum Structs Available This Holiday Season
 
Code:

enum struct STest
{
    int a;
    int b;
}
STest test;

STest[] GetTest()
{
  return test;
}

Its works, but there is a problem with calling struct methods.

There is also a problem with using the same struct type as a method argument type:
Code:

enum
struct STest
{
    int a;

    void Add(STest x)
    {
      a += x.a;
    }
}
STest test;



All times are GMT -4. The time now is 00:48.

Powered by vBulletin®
Copyright ©2000 - 2020, vBulletin Solutions, Inc.