Skip to content

Commit 6f1a309

Browse files
committed
Make SteamAPI intialization more robust
1 parent e9c2927 commit 6f1a309

5 files changed

Lines changed: 87 additions & 7 deletions

File tree

SEToolbox/Interop/SpaceEngineersCore.cs

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Reflection;
99
using System.Runtime.CompilerServices;
1010
using System.Threading;
11+
using System.Windows.Forms;
1112
using Sandbox;
1213
using Sandbox.Engine.Networking;
1314
using Sandbox.Engine.Utils;
@@ -17,6 +18,7 @@
1718
using SEToolbox.Models;
1819
using SEToolbox.Support;
1920
using SpaceEngineers.Game;
21+
using Steamworks;
2022
using VRage;
2123
using VRage.Collections;
2224
using VRage.FileSystem;
@@ -111,7 +113,7 @@ public SpaceEngineersCore()
111113
// This will start the Steam Service, and Steam will think SE is running.
112114
// TODO: we don't want to be doing this all the while SEToolbox is running,
113115
// perhaps a once off during load to fetch of mods then disconnect/Dispose.
114-
_steamService = MySteamGameService.Create(Sandbox.Engine.Platform.Game.IsDedicated, AppId);
116+
_steamService = CreateSteamService();
115117
MyServiceManager.Instance.AddService(_steamService);
116118

117119
Log.Debug("Init VRage platform.");
@@ -194,6 +196,81 @@ public SpaceEngineersCore()
194196
_manageDeleteVoxelList = [];
195197
}
196198

199+
// Re-implement most of MySteamService constructor (with adjustments) to
200+
// bypass the call to Environment.Exit
201+
static IMyGameService CreateSteamService()
202+
{
203+
//return MySteamGameService.Create(Sandbox.Engine.Platform.Game.IsDedicated, AppId);
204+
205+
var appIdStr = AppId.ToString();
206+
Environment.SetEnvironmentVariable("SteamAppId", appIdStr);
207+
Environment.SetEnvironmentVariable("SteamGameId", appIdStr);
208+
209+
// isDedicated: true skips the initialization that is done here instead.
210+
var service = MySteamGameService.Create(isDedicated: true, AppId);
211+
var serviceType = service.GetType();
212+
213+
var steamAppId = (AppId_t)AppId;
214+
215+
//if (SteamAPI.RestartAppIfNecessary(steamAppId))
216+
// Log.Error("SteamAPI.RestartAppIfNecessary returned true.");
217+
218+
bool isActive = SteamAPI.Init();
219+
serviceType.GetProperty("IsActive").SetValue(service, isActive);
220+
221+
if (!isActive)
222+
Log.Error("Failed to initialize Steam service.");
223+
224+
IMyInventoryService serviceInstance;
225+
226+
const ulong OFFLINE_STEAM_ID = 1234567891011uL;
227+
228+
if (isActive)
229+
{
230+
var steamUserId = SteamUser.GetSteamID();
231+
service.UserId = (ulong)steamUserId;
232+
233+
var userName = "\ue030" + SteamFriends.GetPersonaName();
234+
var hasLicenseResult = SteamUser.UserHasLicenseForApp(steamUserId, steamAppId);
235+
bool ownsGame = hasLicenseResult == EUserHasLicenseForAppResult.k_EUserHasLicenseResultHasLicense;
236+
var userUniverse = (MyGameServiceUniverse)SteamUtils.GetConnectedUniverse();
237+
var branchName = SteamApps.GetCurrentBetaName(out var pchName, 512) ? pchName : "default";
238+
239+
serviceType.GetField("SteamUserId", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(service, steamUserId);
240+
serviceType.GetProperty("UserName").SetValue(service, userName);
241+
serviceType.GetProperty("OwnsGame").SetValue(service, ownsGame);
242+
serviceType.GetProperty("UserUniverse").SetValue(service, userUniverse);
243+
serviceType.GetProperty("BranchName").SetValue(service, branchName);
244+
245+
SteamUserStats.RequestCurrentStats();
246+
serviceType.GetMethod("RegisterCallbacks", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(service, []);
247+
248+
var remoteStorage = Activator.CreateInstance(Type.GetType("VRage.Steam.MySteamRemoteStorage, VRage.Steam"));
249+
250+
serviceType.GetField("m_remoteStorage", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(service, remoteStorage);
251+
252+
serviceInstance = (IMyInventoryService)Activator.CreateInstance(Type.GetType("VRage.Steam.MySteamInventory, VRage.Steam"), [service]);
253+
}
254+
else
255+
{
256+
service.UserId = OFFLINE_STEAM_ID;
257+
serviceInstance = new MyNullInventoryService();
258+
}
259+
260+
MyServiceManager.Instance.AddService(serviceInstance);
261+
262+
if (!isActive)
263+
{
264+
var errMsg = """
265+
Failed to initialize Steam API. Please ensure Steam is running and re-launch SEToolbox.
266+
You can try to continue anyway but modded worlds may not work correctly.
267+
""";
268+
MessageBox.Show(errMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
269+
}
270+
271+
return service;
272+
}
273+
197274
static void InitMultithreading()
198275
{
199276
//MySandboxGame.InitMultithreading();

SEToolbox/Interop/SpaceEngineersWorkshop.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ public class SpaceEngineersWorkshop
1414
{
1515
public static MyWorkshop.ResultData DownloadWorldModsBlocking(List<MyObjectBuilder_Checkpoint.ModItem> mods, MyWorkshop.CancelToken cancelToken)
1616
{
17+
if (!MyGameService.IsActive)
18+
return default;
19+
1720
MyWorkshop.ResultData ret = default;
1821

1922
Task task = Parallel.Start(() =>

SEToolbox/Models/WorldResource.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,13 @@ public void LoadDefinitionsAndMods()
287287
if (_resources == null || Checkpoint == null || Checkpoint.Mods == null)
288288
return;
289289

290-
SpaceEngineersWorkshop.DownloadWorldModsBlocking(Checkpoint.Mods, cancelToken: null);
290+
List<MyObjectBuilder_Checkpoint.ModItem> mods = [.. Checkpoint.Mods];
291+
var result = SpaceEngineersWorkshop.DownloadWorldModsBlocking(mods, cancelToken: null);
291292

292-
_resources.LoadDefinitionsAndMods(DataPath.ModsPath, Checkpoint.Mods);
293+
if (result.Result == 0)
294+
mods.Clear();
295+
296+
_resources.LoadDefinitionsAndMods(DataPath.ModsPath, mods);
293297
}
294298

295299
public bool LoadSector(out string errorInformation, bool snapshot = false)

SEToolbox/SEToolbox.csproj

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,6 @@
125125
<Link>VRage.Native.dll</Link>
126126
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
127127
</Content>
128-
<None Include="steam_appid.txt">
129-
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
130-
</None>
131128
</ItemGroup>
132129

133130
<ItemGroup>

SEToolbox/steam_appid.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)