Important Player.SteamID

DreTaX

Probably knows the answer...
Administrator
Jun 29, 2014
4,095
4,815
113
At your house.
github.com
Hello there.

You might have noticed on some plugins, but there are usually SteamID request errors in the plugins.
In my opinion that happens when the player disconnects before we could request his ID. Now at me, for example HomeSystem, TpFriend and many other plugins uses timers.
Inside the timers, I usually want to find the player by his ID, but. When the player disconnects during the timer, he becomes null, and you cannot request his SteamID.

JavaScript:
case "jointpdelay":
    var checkn = config.GetSetting("Settings", "safetpcheck");
    var joinplayer = BZHJ.getPlayer(params[0]); // Get player via ID
    if (joinplayer != null) { // Check if null
        joinplayer.TeleportTo(params[1], params[2], params[3]);
        BZHJ.addJob('jointp', checkn, jobxData.params);
    }
    else { // If so remove
        BZHJ.killJob(params[0]);
    }
break;
Now just right when I requested the player's id, and he was null I was getting huge amount of spam in my logs, which later affected the console, and then made my server crash.

JavaScript:
getPlayer: function(stam) {
    for (var player in Server.Players) {
        var id = player.SteamID;
        if (id == stam && player != null) {
            return player;
        }
    }
    return null;
},
When the player was null, the method it self didn't even return null in the code. I guess thats cause of Jint, since I noticed when there is an error, It breaks just right at that line, and won't continoue. Now when that happened at me, the player was stuck inside the DataStore, and remained null. That made my server to be flooded.

Code:
System.NullReferenceException: Object reference not set to an instance of an object
at Fougerite.Player.get_SteamID () <0x0002a>
at (wrapper dynamic-method) Jint.Marshal.ProxyHelper.dynamicPropertyGetter (Jint.Marshaller,Jint.Native.JsDictionaryObject) <0x00029>
at Jint.Native.NativeDescriptor.Get (Jint.Native.JsDictionaryObject) <0x0002a>
at Jint.Native.JsDictionaryObject.TryGetProperty (string,Jint.Native.JsInstance&) <0x00047>
The solution that I found, which might others already know is a simple try-catch. With that I don't get any problems, or more error lines than 1.

For example:

JavaScript:
getPlayer: function(stam) {
    try {
        for (var player in Server.Players) {
            var id = player.SteamID;
            if (id == stam && player != null) {
                return player;
            }
        }
        return null;
    } catch(err) {
        // You may also put "err" in the log method.
        Plugin.Log("HomeSystemError", "Error caught at getPlayer method. Player was null, removing it from the timer.");
        // Return null JUST right the moment when error occurs.
        return null;
    }
},
When I used the Try-Catch method, my plugin finally returned null, and the plugin finally "killed" the job in the DataStore (removed).

I don't get the error in my main logs anymore, and It will only appear in your Plugin's log, but really rare. Like it contains 5 lines atm about null players, but not flooding my server atleast.
I didn't receive any floods since that I'm testing this (From around 14:00 pm).

I hope I helped some people out. Also, note that the same thing can happen with player's name or what ever.


Python:
def TrytoGrabID(self, Player):
        try:
            id = Player.SteamID
            return id
        except:
            return None
JavaScript:
function TrytoGrabID(Player) {
    try {
        var id = Player.SteamID;
        return id;
    } catch(err) {
        //Plugin.Log("Error", "Player was null.");
        return null;
    }
}
 
Last edited:
  • Like
Reactions: Snake

mikec

Master Of All That I Survey
Retired Staff
Trusted Member
Jul 12, 2014
296
152
28
Los Angeles, California, USA
Good advice, Dretax. try / catch is a good tool. Don't rely on it too heavily though. There is some significant overhead, and there are some things you can't do in the vicinity of a try /catch block. There's also the handy ignore argument to catch, when you can't do anything about the exception but move on.

Code:
  var id = "unknown";
try { 
   id = Player.SteamID;
} catch(ignore) {}
// the keyword 'ignore' must be used, and the block that follows must be empty
I am going to create a new kind of Player object which will solve these problems. It will be instanced from actual Player data when a player connects, like the Player object we all know. But it will also be able to be instanced from data Fougerite is going to store, so Player data can be manipulated offline. I have a Magma plugin I wrote but never released called LastSeen which swept Player data into the DataStore on a timer every 10 seconds. Inventory contents, health status, active item, crafting status, location, time online, everything.

I could use it to do things like teleport to a Player's location right after he logged off, and see if he left a Sleeper.
 
  • Like
Reactions: Snake

DreTaX

Probably knows the answer...
Administrator
Jun 29, 2014
4,095
4,815
113
At your house.
github.com
Relying at the for cycle where i find the player b the steamdid should never cause any probs.

Sent from my Samsung Galaxy S4
 

DreTaX

Probably knows the answer...
Administrator
Jun 29, 2014
4,095
4,815
113
At your house.
github.com
What i meant is with the try catch. IT wont flood ur console....You just simply didn't understand what im saying?..

Sent from my Samsung Galaxy S4
 
Last edited: