Can someone help me determine the Steam build id version of a running Rust dedicated server from C#? I suppose this can be done by checking the local `steamapps\appmanifest_xxxxxx` file, but I like to see if that number can be determined through some kind of code without file-level parsing.
I know the AppId and BuildId exist somewhere when the server is running because I can find them through WinDbg. Using JustDecompile on Rust.Global.dll shows BuildId declared in Rust.Global.SteamClient as a Client type.
Code:Rust.Global.dllnamespace Rust { public static class Global { ... public static Client SteamClient { get; set; } } }There appears to be a SingletonComponent defined in Assembly-CSharp.dll for SteamClientCode:Facepunch.Steamworks.dllnamespace Facepunch.Steamworks { public class Client : BaseSteamworks, IDisposable { ... public int BuildId { get; private set; } } }
But I can't figure out how to get the value of SteamClient.BuildId . I'm working with an OxideMod extension so I'm outside of the sandboxing. I've used non-OxideMod objects and methods from other core areas of Rust dlls elsewhere, so I'm sure this must be possible. When I try code like below, I get an error "object reference not set to an instance of an object"Code:Assembly-CSharp.dllpublic class SteamClient : SingletonComponent<SteamClient> { public SteamClient() { } }
I've got to be close, because I can do this and it compiles/runs fine (of course without being able to get BuildId)Code:int x1 = (int) SteamClient.Instance.GetInstanceField("BuildId");
TIACode:SteamClient b1 = SteamClient.Instance;
Accessing SteamClient.BuildId on Rust server?
Discussion in 'Rust Development' started by Kolyma, Oct 2, 2017.
-
The Steamworks library is actually used for both the game clients and the server which is why you have the code available for Facepunch.Steamworks.Client and Facepunch.Steamworks.Server. However these two are never initialized together. On a server an instance will be created of Facepunch.Steamworks.Server while the clients will have an instance of Facepunch.Steamworks.Client which is why you are running into a NullReferenceException.
Some debug output:
Code:SteamClient: null SteamServer: Facepunch.Steamworks.Server <Query>k__BackingField: Facepunch.Steamworks.ServerQuery server: Facepunch.Steamworks.Server <Query>k__BackingField: Facepunch.Steamworks.ServerQuery <Stats>k__BackingField: Facepunch.Steamworks.ServerStats <Auth>k__BackingField: Facepunch.Steamworks.ServerAuth _dedicatedServer: True _maxplayers: 10 _botcount: 0 _mapname: Procedural Map _modDir: rust _product: 252490 _gameDescription: Rust _serverName: Mughisi's Playground _passworded: False _gametags: mp10,cp0,qp0,v2017,h4bcc25f1,stok,born1505842473 KeyValue: System.Collections.Generic.Dictionary`2[System.String,System.String] native: Facepunch.Steamworks.Interop.NativeInterface <Stats>k__BackingField: Facepunch.Steamworks.ServerStats server: Facepunch.Steamworks.Server <Query>k__BackingField: Facepunch.Steamworks.ServerQuery <Stats>k__BackingField: Facepunch.Steamworks.ServerStats <Auth>k__BackingField: Facepunch.Steamworks.ServerAuth _dedicatedServer: True _maxplayers: 10 _botcount: 0 _mapname: Procedural Map _modDir: rust _product: 252490 _gameDescription: Rust _serverName: Mughisi's Playground _passworded: False _gametags: mp10,cp0,qp0,v2017,h4bcc25f1,stok,born1505842473 KeyValue: System.Collections.Generic.Dictionary`2[System.String,System.String] native: Facepunch.Steamworks.Interop.NativeInterface <Auth>k__BackingField: Facepunch.Steamworks.ServerAuth server: Facepunch.Steamworks.Server <Query>k__BackingField: Facepunch.Steamworks.ServerQuery <Stats>k__BackingField: Facepunch.Steamworks.ServerStats <Auth>k__BackingField: Facepunch.Steamworks.ServerAuth _dedicatedServer: True _maxplayers: 10 _botcount: 0 _mapname: Procedural Map _modDir: rust _product: 252490 _gameDescription: Rust _serverName: Mughisi's Playground _passworded: False _gametags: mp10,cp0,qp0,v2017,h4bcc25f1,stok,born1505842473 KeyValue: System.Collections.Generic.Dictionary`2[System.String,System.String] native: Facepunch.Steamworks.Interop.NativeInterface OnAuthChange: System.Action`3[System.UInt64,System.UInt64,Facepunch.Steamworks.ServerAuth+Status] _dedicatedServer: True _maxplayers: 10 _botcount: 0 _mapname: Procedural Map length: 14 start_char: P _modDir: rust length: 4 start_char: r _product: 252490 length: 6 start_char: 2 _gameDescription: Rust length: 4 start_char: R _serverName: Mughisi's Playground length: 20 start_char: M _passworded: False _gametags: mp10,cp0,qp0,v2017,h4bcc25f1,stok,born1505842473 length: 48 start_char: m KeyValue: System.Collections.Generic.Dictionary`2[System.String,System.String] table: Array[37] 0 28 27 0 0 25 0 26 0 24 22 0 11 12 13 17 15 16 23 2 3 20 5 6 7 8 9 18 0 0 0 0 0 0 0 21 29 linkSlots: Array[37] System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link System.Collections.Generic.Link keySlots: Array[37] description_0 description_01 description_02 description_03 description_04 description_05 description_06 description_07 description_08 description_09 description_10 description_11 description_12 description_13 description_14 description_15 hash world.seed world.size pve headerimage url uptime gc_mb gc_cl fps fps_avg ent_cnt build valueSlots: Array[37] Powered by Oxide 4bcc25f1 1265 1000 False http://oxidemod.org 1839 103 57 228 262.28 842 23033 touchedSlots: 29 emptySlot: -1 count: 29 threshold: 33 hcp: System.Collections.Generic.GenericEqualityComparer`1[System.String] serialization_info: length: 4 start_char: n generation: 374 native: Facepunch.Steamworks.Interop.NativeInterface api: SteamNative.SteamApi platform: SteamNative.Platform+Win64 client: SteamNative.SteamClient platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server user: SteamNative.SteamUser platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server apps: SteamNative.SteamApps platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server applist: SteamNative.SteamAppList platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server friends: SteamNative.SteamFriends platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server servers: SteamNative.SteamMatchmakingServers platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server matchmaking: SteamNative.SteamMatchmaking platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server inventory: SteamNative.SteamInventory platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server networking: SteamNative.SteamNetworking platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server userstats: SteamNative.SteamUserStats platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server utils: SteamNative.SteamUtils platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server screenshots: SteamNative.SteamScreenshots platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server http: SteamNative.SteamHTTP platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server ugc: SteamNative.SteamUGC platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server gameServer: SteamNative.SteamGameServer platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server gameServerStats: SteamNative.SteamGameServerStats platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server remoteStorage: SteamNative.SteamRemoteStorage platform: SteamNative.Platform+Win64 steamworks: Facepunch.Steamworks.Server isServer: True hUser: SteamNative.HSteamUser hPipe: SteamNative.HSteamPipep
-
OK that's helpful. What tool did you use to pull that info?
The reason why I was chasing it from the SteamClient point of view is because that's where the actual BuildId is defined. I was thinking the Rust server is a Steam client during some early phase of Server boot and then also brought up the SteamServer at some point later.
GitHub - Facepunch/Facepunch.Steamworks: Another fucking c# Steamworks implementation
I believe inside the SteamServer structure, there's no BuildId. Again, I know it exists because I can find the AppId and BuildId current release values inside Windows Server memory by using a search from WinDbg when the Rust server is running. While they're not labeled as such, the values appear in hex very close to each other in only one place in RAM so I'm confident that's what it is. There has to be some way to get those values programmically through code.
Let me see if I can track down where SteamServer is defined. -
The SteamClient is only created during the launch of the actual game client, if you'd open up Assembly-CSharp.dll from the client files you will notice some differences including SteamClient in Assembly-CSharp.dll to have an actual implementation and not an empty class like in the server version of the file.
The debug output that I showed in my previous post was just grabbed through a plugin dumping all the fields and their values through reflection of the Facepunch.Steamworks.SteamServer instance. -
Ugh, I've gotten soo close, right up to being able to call the function that returns BuildId and then I get an indecipherable (to me) error.
Code:var server_instance = Facepunch.Steamworks.Server.Instance;var server_native = server_instance.GetType().GetField("native", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var server_native_instance = server_native.GetValue(server_instance);var server_native_apps = server_native_instance.GetType().GetField("apps", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var server_native_apps_instance = server_native_apps.GetValue(server_native_instance);MethodInfo server_native_apps_method = server_native_apps_instance.GetType().GetMethod("GetAppBuildId"); var bld = server_native_apps_method.Invoke(server_native_apps_instance, null);
Code:steamengine.cpp (2029) : Assertion Failed: Narrowing inPtr to toClass returned NULL.
[Update]
Even trying this creates the same error message:
Code:[DllImport("steam_api64.dll", CharSet = CharSet.None, ExactSpelling = false)] internal static extern int SteamAPI_ISteamApps_GetAppBuildId(IntPtr ISteamApps);var server_native_apps_platform = server_native_apps_instance.GetType().GetField("platform", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var server_native_apps_platform_instance = server_native_apps_platform.GetValue(server_native_apps_instance);var server_native_apps_platform_ptr = server_native_apps_platform_instance.GetType().GetField("_ptr", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var server_native_apps_platform_ptr_instance = server_native_apps_platform_ptr.GetValue(server_native_apps_platform_instance);int b_id = SteamAPI_ISteamApps_GetAppBuildId((IntPtr)server_native_apps_platform_ptr_instance);
Last edited by a moderator: Oct 3, 2017 -
Just to post a follow-up to this, ultimately I had to run a file-based process to pull the installed buildid from parsing the file
Code:C:\Rust\Server\rustds\steamapps\appmanifest_258550.acf
Code:"SizeOnDisk" "5803549654" "buildid" "2217183" "LastOwner" "76561200052722720"