- Own JSON reader (MiniJson) instead of Newtonsoft.Json - the server browser failed with "Could not load System.Runtime.Serialization" once MSCLoader was gone - Mouse cursor visible in admin menu/chat/console (PlayerInMenu) - Intro "Press any key" screen replaced by an MSCO loading screen; hook PlayMakerFSM.Awake too - Join links while the game runs: picked up from MSCO\join.txt (written by the launcher) - Admin menu: TELEPORT tab (home, shop, repair shop, inspection, villages, events, Satsuma) - Window title/icon "MSCO - My Summer Car Online", MSCO logo in the main menu - In-game UI restyled like the keymaster website (rounded cards, pills, glow, slim scrollbars) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
114 lines
4.9 KiB
C#
114 lines
4.9 KiB
C#
using System;
|
|
using Microsoft.Win32;
|
|
|
|
namespace MSCO
|
|
{
|
|
/// <summary>
|
|
/// "msco://connect/<host>:<port>"-Links (JOIN-Button auf der Website).
|
|
/// Die Mod registriert den Link-Typ in Windows so, dass ein Klick Steam direkt mit
|
|
/// "-applaunch 516750 +msco_connect <link>" startet - ohne cmd/Skript dazwischen, damit
|
|
/// präparierte Links keine Befehle ausführen können. Die Mod liest die Adresse beim Start
|
|
/// aus der Kommandozeile und fragt im Hauptmenü, ob verbunden werden soll.
|
|
/// (Läuft das Spiel schon, gibt Steam den Link nicht weiter - dann den Server-Browser nutzen.)
|
|
/// </summary>
|
|
public static class JoinLinks
|
|
{
|
|
const string Scheme = "msco";
|
|
const string Argument = "+msco_connect";
|
|
const int MySummerCarAppId = 516750;
|
|
|
|
/// <summary>Link-Typ msco:// für den aktuellen Windows-Benutzer eintragen (kein Admin nötig).</summary>
|
|
public static void Register()
|
|
{
|
|
try
|
|
{
|
|
string steamExe = SteamExePath();
|
|
if (steamExe == null)
|
|
{
|
|
MscoLog.Warning("[MSCO] Steam not found - JOIN links from the website are not available.");
|
|
return;
|
|
}
|
|
string command = "\"" + steamExe + "\" -applaunch " + MySummerCarAppId + " " + Argument + " \"%1\"";
|
|
|
|
// Ist der MSCO Launcher installiert, gehören die Links ihm: er startet das Spiel mit MSCO (ohne MSCLoader)
|
|
using (RegistryKey existing = Registry.CurrentUser.OpenSubKey(@"Software\Classes\" + Scheme + @"\shell\open\command"))
|
|
{
|
|
string current = existing != null ? existing.GetValue("") as string : null;
|
|
if (current != null && current.IndexOf("MSCO-Launcher", StringComparison.OrdinalIgnoreCase) >= 0) return;
|
|
}
|
|
|
|
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + Scheme))
|
|
{
|
|
key.SetValue("", "URL:MSCO Join Link");
|
|
key.SetValue("URL Protocol", "");
|
|
using (RegistryKey cmd = key.CreateSubKey(@"shell\open\command"))
|
|
cmd.SetValue("", command);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MscoLog.Warning("[MSCO] Could not register msco:// links: " + e.Message);
|
|
}
|
|
}
|
|
|
|
static string SteamExePath()
|
|
{
|
|
using (RegistryKey steam = Registry.CurrentUser.OpenSubKey(@"Software\Valve\Steam"))
|
|
{
|
|
string exe = steam != null ? steam.GetValue("SteamExe") as string : null;
|
|
return string.IsNullOrEmpty(exe) ? null : exe.Replace('/', '\\');
|
|
}
|
|
}
|
|
|
|
static float nextPoll;
|
|
|
|
/// <summary>
|
|
/// JOIN-Link, während das Spiel schon läuft: der MSCO Launcher legt ihn als <Spiel>\MSCO\join.txt ab (Steam
|
|
/// gibt Links an ein laufendes Spiel nicht weiter). Einmal pro Sekunde nachsehen.
|
|
/// </summary>
|
|
public static bool TryTakeRequest(out string host, out int port)
|
|
{
|
|
host = null;
|
|
port = 0;
|
|
if (UnityEngine.Time.realtimeSinceStartup < nextPoll) return false;
|
|
nextPoll = UnityEngine.Time.realtimeSinceStartup + 1f;
|
|
try
|
|
{
|
|
string file = System.IO.Path.Combine(Bootstrap.Folder ?? "", "join.txt");
|
|
if (Bootstrap.Folder == null || !System.IO.File.Exists(file)) return false;
|
|
string text = System.IO.File.ReadAllText(file);
|
|
System.IO.File.Delete(file);
|
|
return TryParse(text, out host, out port);
|
|
}
|
|
catch { return false; }
|
|
}
|
|
|
|
/// <summary>Wurde das Spiel über einen JOIN-Link gestartet?</summary>
|
|
public static bool TryGetFromCommandLine(out string host, out int port)
|
|
{
|
|
host = null;
|
|
port = 0;
|
|
string[] args = Environment.GetCommandLineArgs();
|
|
for (int i = 0; i < args.Length - 1; i++)
|
|
if (args[i] == Argument) return TryParse(args[i + 1], out host, out port);
|
|
return false;
|
|
}
|
|
|
|
/// <summary>"msco://connect/1.2.3.4:7777/" -> Host und Port (nur Buchstaben, Ziffern, . - :).</summary>
|
|
static bool TryParse(string text, out string host, out int port)
|
|
{
|
|
host = null;
|
|
port = 0;
|
|
text = text.Trim().Trim('"').Trim();
|
|
const string prefix = "msco://connect/";
|
|
if (!text.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) return false;
|
|
string address = text.Substring(prefix.Length).TrimEnd('/');
|
|
|
|
foreach (char c in address)
|
|
if (!char.IsLetterOrDigit(c) && c != '.' && c != '-' && c != ':') return false;
|
|
|
|
return ServerBrowser.TryParseAddress(address, out host, out port);
|
|
}
|
|
}
|
|
}
|