Player List Filters

Discuss API design here.
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Player List Filters

Postby satoon101 » Tue Aug 07, 2012 3:59 am

I have not had a lot of time lately to work on much, but the time I have had has been spent mostly on a Messaging module. This also led me to working on a Recipient Filter module, which I have expanded into that being just a part of a Filter module. I have a few questions based off of my work so far that I would like to get some opinions on.

First, when it comes to the Messaging module, I plan on having the ability to pass one user, a list/tuple/set of users, or a filter. My first question is, if only passing one user or a list of them, should we (just like EventScripts) assume that all users passed are in the form of their "userid"? Or their index (which is what a RecipientFilter requires to be added)? Or the player's entity (once we get further in development, this will be more robust and full of info you can quickly access, sort of like playerlib)?

With the filtering system, should it be just like EventScripts' playerlib, where you get an instance like?:

Syntax: Select all

playerlist = PlayerList('#alive,!bot')
Or, instead of being one string, should it be a list of strings?:

Syntax: Select all

playerlist = PlayerList(['#alive', '!bot'])
Also, should the "#" symbol be replaced, or even just removed?:

Syntax: Select all

playerlist = PlayerList(['@alive', '!bot'])

# Or
playerlist = PlayerList(['alive', '!bot'])


An idea, that came from XE_ManUp, which we are definitely incorporating, will be to return multiple types of values for players (or other types of filters as well) that the scripter needs. It could possibly look like:

Syntax: Select all

for index, username, steamid in PlayerList(['alive', '!bot'], ['index', 'username', 'steamid']):
print(index)
print('\t%s' % username)
print('\t%s' % steamid)
Does the syntax shown suffice for everyone, or does anyone have any other ideas on how this could be better incorporated? We will also have the ability to store a PlayerList instance, and each time it is iterated over, it will refresh itself with the newest data:

Syntax: Select all

playerlist = PlayerList(['alive', '!bot'], ['index', 'username', 'steamid'])

@Event
def player_say(GameEvent):
if GameEvent.GetString('text') == 'print':
for index, username, steamid in playerlist:
print(index)
print('\t%s' % username)
print('\t%s' % steamid)

Also, if no return values are given, should we return the player's index, userid, or entity (which, again, once we get further in development, this will be more robust and full of info you can quickly access, sort of like playerlib)?:

Syntax: Select all

playerlist = PlayerList(['alive', '!bot'])

@Event
def player_say(GameEvent):
if GameEvent.GetString('text') == 'print':
for index in playerlist:
print(index)
And, should we return one of these by default as the first value when return values are given (the following automatically adds "index" to the start of the list for each player)?:

Syntax: Select all

playerlist = PlayerList(['alive', '!bot'], ['username', 'steamid'])

@Event
def player_say(GameEvent):
if GameEvent.GetString('text') == 'print':
for index, username, steamid in playerlist:
print(index)
print('\t%s' % username)
print('\t%s' % steamid)

I'm sure I have other questions, but that is all I can think of right now. If anyone has any input, other suggestions, questions, etc..., please feel free to comment here.

Thank you,
Satoon
User avatar
[NIN]
Junior Member
Posts: 5
Joined: Fri Jul 20, 2012 10:19 am

Postby [NIN] » Fri Aug 10, 2012 4:50 pm

I'm guessing if the Scripting is going to be more 'incorporated' into the Source Engine then a player's index should be used.
Also, the "#" symbol for PlayerList is really annoying in Eventscripts (For me at least).

Consider that "#" is a commentary in Python, and shouldn't be used as another resource.

Hope it helps...
[NIN]
Omega_K2
Senior Member
Posts: 227
Joined: Sat Jul 07, 2012 3:05 am
Location: Europe
Contact:

Postby Omega_K2 » Fri Aug 10, 2012 6:03 pm

I don't think the symbol makes sense anymore. It should just be removed.
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Fri Aug 10, 2012 6:33 pm

I would simply return an iterator (like map, filter, etc. do in Python 3) of all filtered player pointers. All further filtering need to be done by the script author (that isn't really hard or uncomfortable).
User avatar
Monday
Administrator
Posts: 98
Joined: Thu Jul 12, 2012 4:15 am

Postby Monday » Fri Aug 10, 2012 9:22 pm

I like #human more than !bot. Maybe we should change the # to a & or something since it is a python comment char? Everything else looks spiffy!
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sat Aug 11, 2012 1:31 am

I am definitely leaning towards not having a character to denote "is" types, but still using ! to denote "not" types. This seems to make the most sense, especially since we are going to be using a list instead of a string with comma separation. Also, it will probably use an iterator, did forget to mention that initially. Actually, for this reason (since it isn't a "list"), we have been wanting to find a better name than PlayerList. Does PlayerIter work for everyone? Or does anyone have any other suggestions?

Satoon
User avatar
Ayuto
Project Leader
Posts: 2195
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Sat Aug 11, 2012 3:51 am

What's about something like this:

Syntax: Select all

def GetPlayers(players, *filters):
# Code...
pass

So you would do it like this:

Syntax: Select all

# Get a tuple of all alive players
alive = tuple(GetPlayers('alive'))

# Get a list of all dead terrorists
dead_terrorists = list(GetPlayers('t', 'alive'))

players will be the start group of players and all additional arguments will filter players out of the start group.
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sun Aug 12, 2012 5:36 am

For now, I have decided to go with PlayerIter(<is_filters>, <not_filters>, <return_types>). This splits up the "is" and "not" filters into their own separate arguments. If you pass a string argument to either, it will turn it into a list with just that one item. Then, when iterating, it will first check each "is" filter, and any items that pass the "is" filters will be checked against the "not" filters. Any items passing all checks will be yielded. There is also no need to use denoters this way, as we are eliminating the need for them.

Satoon
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Aug 13, 2012 5:46 am

Ok, another question for everyone.

In order to better server multiple games with these filters, should we change from using un, spec, t, and ct to using team0, team1, team2, and team3? I realize that currently this mod is specific to only CS:GO, but I really want to avoid future issues by setting it up for compatibility with any mods we might support in the future.

Maybe there is another way that we haven't thought of, so please, if you think of something, share it.

Thanks again,
Satoon
Tuck
Global Moderator
Posts: 205
Joined: Sat Jul 14, 2012 9:35 pm
Location: Copenhagen

Postby Tuck » Mon Aug 13, 2012 5:51 am

aren't there spectators/unsigned for all the games ?,
-Tuck
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Aug 13, 2012 6:00 am

Not all games have unassigned. Also, not all games have spectators as team1. I cannot remember which mod it was, but there was one that had spectators as team4, with team0 and team1 never being used... Not sure that I will account for team4 or not at this point, would be easy to add in the future.

Satoon
Tuck
Global Moderator
Posts: 205
Joined: Sat Jul 14, 2012 9:35 pm
Location: Copenhagen

Postby Tuck » Mon Aug 13, 2012 6:11 am

idk if python has enum's but making the filter use 0 1 2 3 4 and then use enum's to return the value to filter so the code for the coder would be more reading friendly ?
-Tuck
User avatar
Monday
Administrator
Posts: 98
Joined: Thu Jul 12, 2012 4:15 am

Postby Monday » Mon Aug 13, 2012 10:05 am

I think we should go with T/CT for readability and ease... we can always add team aliases later. (I think we are quite a ways off from multi-game support anyways)
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Tue Aug 14, 2012 1:04 pm

How about the C++ variant? Like you open a file with[cpp]fstream fs;

fs.open("filename", ios::out | ios::app | ios::binary); // I mean exactly this "|" ![/cpp]I saw this method in EventScripts playerlib I guess, I just can't remember where it was... So we could use

Syntax: Select all

# of course we would need constants like "ios::out" and stuff.... let's just take this for example (can be done in C++ of course) - just so we know what's going on:

# the definitions:
PLAYERLIST_T = 0
PLAYERLIST_CT = 1

# or
PLAYERLIST_T = "t"
PLAYERLIST_CT = "ct"

PLAYERLIST_DEAD = "dead"

# or whatever you wish them to be...

# the script:
players = PlayerList(PLAYERLIST_T | PLAYERLIST_DEAD)

# or use it directly which would be the simpliest I guess:
players = PlayerList("t" | "dead")
If we need more arguments, I *think* this would work, too:

Syntax: Select all

player = PlayerList("t" | "dead", ["index", "steamid"])
I'm not sure about the not keyword, tho. In C++ you'd do it with !, but IDK about python...

Hope this is a good idea :D
Absolute
Junior Member
Posts: 13
Joined: Sat Jul 07, 2012 6:48 pm

Postby Absolute » Tue Aug 14, 2012 7:44 pm

the | is the bitwise or
We should have constants anyways, so you can for example import the cstrike info and then have cstrike.TEAM_CT = 3, I can never remember that stuff..

I think you can invert bits with the ~ operator in python.
User avatar
BackRaw
Senior Member
Posts: 537
Joined: Sun Jul 15, 2012 1:46 am
Location: Germany
Contact:

Postby BackRaw » Thu Aug 16, 2012 1:57 pm

yeah, constants would be the best I think =)
Tuck
Global Moderator
Posts: 205
Joined: Sat Jul 14, 2012 9:35 pm
Location: Copenhagen

Postby Tuck » Thu Aug 16, 2012 2:08 pm

In my opinion enum would be the best for multiple game support (pretty sure it's a constant to in c++):

Code: Select all

<gamename>.<name team1> (returns the byte/short/integer)
<gamename>.<name team2> (returns the byte/short/integer)


Syntax: Select all

enum csgo {
unsigned = 0,
spectator = 1,
terrorist = 2,
counter_terrorist = 3};
//I'm aware that i could leave out the declaretions, when i've already put them in order since enum's start from 0 and up
enum css {
unsigned = 0,
spectator = 1,
terrorist = 2,
counter_terrorist = 3};
-Tuck
Logifl3x
Junior Member
Posts: 17
Joined: Sat Jul 07, 2012 3:53 am

Postby Logifl3x » Sun Jan 20, 2013 12:43 am

Has player list filters been included yet? If so, could someone give me an example of how I could get a list of all alive players.
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sun Jan 20, 2013 1:55 am

This has been implemented for quite some time. I think there used to be a few more examples on the forums prior to the site going down, so they got lost. I did just create this thread, though, to explain their use:
http://www.sourcepython.com/showthread.php?259

Satoon
SkinN
Junior Member
Posts: 25
Joined: Fri Jul 19, 2013 7:29 am

Postby SkinN » Wed Mar 26, 2014 6:07 am

satoon101 is it possible for you to fix the python code not showing as it should on the your post?...I know I could just paste it on my editor, but so everyone could see it right as well.

Thanks in advance.

PS: When you have the time of course.

SkinN!

Return to “API Design”

Who is online

Users browsing this forum: No registered users and 7 guests