velocity wrote:Now that we are on it:
If I remove all redundancy etc.. which I most certainly will, is this the best way of getting the nearest player (My main goal is actually to determine if the player is stuck inside another player and I actually did share my code there is no difference from my old ES plugin and SP only what SP force me to do differently), maybe the source engine has a function for it?
See, if you told us that from the beginning we would have been able to redirect you to engine_trace right away. Check out
Entity.is_in_solid, a good example that test if an entity's physic box collide with another. Using the search feature would also have yielded some interesting topics such as:
viewtopic.php?p=4084#p4084velocity wrote:Another thing, this is the code I wrote to replace gamethread.delayedname. First of all, is this a valid replacement? Secondly, do I even need to make a gamethread, is it true that player attributes run on the main thread anyway? What doesn't?
I could not tell, to be honest. I personally only use threads for external requests.
EDIT:
I just wanted to share more inputs/thought process about how else you could have optimized your code. Let's say you changed what was previously suggested and this is now your code:
Syntax: Select all
player_instances = PlayerDictionary()
@EntityPreHook(EntityCondition.is_player, 'run_command')
def player_run_command(args):
index = player.index
player = player_instances[index]
if not player.dead or player.team_index < 2:
target = closeplayer(player, radius=200)
def closeplayer(player, radius):
for other in player_instances.values():
if not player.index == other.index and not other.dead:
dist = player.origin.get_distance(other.origin)
if dist <= radius:
return (dist, other)
return (10000, None)
The question you have to ask yourself when you are facing performance issues is, how can I improve my code so it has the same output with minimal work? Let's take in example:
Syntax: Select all
if not player.index == other.index and not other.dead:
Is retrieving the indexes and comparing them a necessity? The answer is no. You know your
player object is contained into
player_instances because this is where you retrieved it:
Syntax: Select all
player = player_instances[index]
So your condition could simply compare the object without any transformation using the
is conditional statement:
Syntax: Select all
if player is not other and not other.dead:
Same result, no transformation; optimization.
Another question you have to ask yourself, especially when your code rely on constant heavy looping is, how could the amount of iterations be reduced? In your specific case, does iterating over all players a necessity? The answer is no. An optimal approach could be to keep a synced list of alive players and iterating over it instead. That way you are not only reducing the amount of iterations but, you are also removing the need to constantly test their dead status. For example, this could be achieved using game events:
Syntax: Select all
from events import Event
from filters.players import PlayerIter
from players.helpers import index_from_userid
alive_players = PlayerDictionary()
def load():
for player in PlayerIter('alive'):
alive_players[player.index] = player
@Event('player_spawn'):
def player_spawn(game_event):
player = Player.from_userid(game_event.get_int('userid'))
if player.team_index <= 1:
return
alive_players[player.index] = player
@Event('player_death')
def player_death(game_event):
del alive_players[index_from_userid(game_event.get_int('userid'))]
Now we are sure that our
alive_players dictionary
always contain all the players that are alive, so we can simply change our implementation to:
Syntax: Select all
def closeplayer(player, radius):
origin = player.origin
for other in alive_players.values():
if player is other:
continue
dist = origin.get_distance(other.origin)
if dist <= radius:
return (dist, other)
return (10000, None)
But what does this means? This means:
- We no longer have to retrieve and check other.dead.
- We no longer have to iterate over dead players because they are being removed from our container as soon as they die (e.g. if there is 20 players on the server, but 10 of them are dead, we now only iterate 10 times instead of 20, etc.).
Same result, less iterations; optimization!
Basically, you always have to think about what your code is doing and how differently it could be implemented so that it doesn't do stuff that are not absolutely required at this exact moment.