Fixed master address, admin cheats (money, needs, goto/bring), docs page
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
using HutongGames.PlayMaker;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MSCO
|
||||
{
|
||||
/// <summary>
|
||||
/// Admin-Cheats für den eigenen Spieler (Geld, Bedürfnisse). Nur aus dem Admin-Menü erreichbar, also nur für
|
||||
/// Server-Admins bzw. den P2P-Host. Geld wird über MoneySync automatisch an alle weitergegeben.
|
||||
/// </summary>
|
||||
public static class Cheats
|
||||
{
|
||||
// Globale PlayMaker-Variablen des Spielers: Wert, auf den "auffüllen" sie setzt
|
||||
static readonly KeyValuePair<string, float>[] Needs =
|
||||
{
|
||||
new KeyValuePair<string, float>("PlayerHunger", 0f),
|
||||
new KeyValuePair<string, float>("PlayerThirst", 0f),
|
||||
new KeyValuePair<string, float>("PlayerStress", 0f),
|
||||
new KeyValuePair<string, float>("PlayerUrine", 0f),
|
||||
new KeyValuePair<string, float>("PlayerFatigue", 0f),
|
||||
new KeyValuePair<string, float>("PlayerDirtiness", 0f),
|
||||
};
|
||||
|
||||
public static string AddMoney(float amount)
|
||||
{
|
||||
FsmFloat money = FsmVariables.GlobalVariables.FindFsmFloat("PlayerMoney");
|
||||
if (money == null) return "Money not found (only works in the game)";
|
||||
money.Value += amount;
|
||||
return "+" + amount.ToString("0") + " MK (now " + money.Value.ToString("0") + " MK)";
|
||||
}
|
||||
|
||||
public static string FillNeeds()
|
||||
{
|
||||
int done = 0;
|
||||
foreach (KeyValuePair<string, float> need in Needs)
|
||||
{
|
||||
FsmFloat v = FsmVariables.GlobalVariables.FindFsmFloat(need.Key);
|
||||
if (v == null) continue;
|
||||
v.Value = need.Value;
|
||||
done++;
|
||||
}
|
||||
return done > 0 ? "Hunger, thirst, stress, fatigue, bladder and dirt reset" : "Player needs not found (only works in the game)";
|
||||
}
|
||||
|
||||
/// <summary>Eigenen Spieler an eine Position setzen (etwas darüber, damit er nicht im Boden steckt).</summary>
|
||||
public static bool Teleport(Transform player, Vector3 position)
|
||||
{
|
||||
if (player == null) return false;
|
||||
player.position = position + Vector3.up * 0.3f;
|
||||
Rigidbody rb = player.GetComponent<Rigidbody>();
|
||||
if (rb != null && !rb.isKinematic) rb.velocity = Vector3.zero;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-6
@@ -13,10 +13,9 @@ namespace MSCO
|
||||
"disconnect - leave the server / game\n" +
|
||||
"host [port] / join <ip> [port] - direct LAN game (no Steam)\n" +
|
||||
"save - save the game (host / singleplayer)\n" +
|
||||
"/admin - admin menu (kick / ban)\n" +
|
||||
"/admin - admin menu (kick / ban / teleport / cheats)\n" +
|
||||
"vehicles | rig - debug info about vehicles / player models\n" +
|
||||
"debug - toggle sync debug output\n" +
|
||||
"master [url] - show / change the server list address\n" +
|
||||
"clear - clear this console";
|
||||
|
||||
public static void Execute(string[] args, Action<string> print)
|
||||
@@ -59,10 +58,6 @@ namespace MSCO
|
||||
mp.JoinServer(host, serverPort);
|
||||
break;
|
||||
}
|
||||
case "master":
|
||||
if (args.Length > 1) ServerBrowser.MasterUrl = args[1];
|
||||
print("Master server: " + ServerBrowser.MasterUrl);
|
||||
break;
|
||||
case "save":
|
||||
mp.SaveGame();
|
||||
break;
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
<Compile Include="MoneySync.cs" />
|
||||
<Compile Include="MpCommand.cs" />
|
||||
<Compile Include="Commands.cs" />
|
||||
<Compile Include="Cheats.cs" />
|
||||
<Compile Include="InputLock.cs" />
|
||||
<Compile Include="Overlays.cs" />
|
||||
<Compile Include="SafetyPatches.cs" />
|
||||
|
||||
@@ -221,6 +221,66 @@ namespace MSCO
|
||||
return list;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- Cheats (Admin-Menü)
|
||||
|
||||
/// <summary>Cheats nur im Spiel und nur für Server-Admins bzw. den P2P-Host.</summary>
|
||||
public bool CanCheat { get { return session != null && MenuHelper.InGame && (dedicated ? isAdmin : session.IsHost); } }
|
||||
|
||||
public void CheatMoney(float amount)
|
||||
{
|
||||
if (!CanCheat) return;
|
||||
overlays.Log(Cheats.AddMoney(amount));
|
||||
AnnounceCheat("gave themselves " + amount.ToString("0") + " MK");
|
||||
}
|
||||
|
||||
public void CheatNeeds()
|
||||
{
|
||||
if (!CanCheat) return;
|
||||
overlays.Log(Cheats.FillNeeds());
|
||||
AnnounceCheat("refilled their needs");
|
||||
}
|
||||
|
||||
/// <summary>Zu einem Mitspieler teleportieren.</summary>
|
||||
public void GotoPlayer(int playerId)
|
||||
{
|
||||
PlayerInfo p;
|
||||
if (!CanCheat || !players.TryGetValue(playerId, out p) || p.Avatar == null) { overlays.Log("Player position unknown"); return; }
|
||||
passenger.Exit(localPlayer, playerCamera);
|
||||
PlayerState s = p.Avatar.LastState;
|
||||
Vector3 side = Quaternion.Euler(0f, s.RotationY, 0f) * Vector3.right;
|
||||
if (Cheats.Teleport(localPlayer, s.Position + side * TeleportSideOffset)) overlays.Log("Teleported to " + p.Name);
|
||||
}
|
||||
|
||||
/// <summary>Mitspieler zu sich holen (Server prüft, ob man Admin ist).</summary>
|
||||
public void BringPlayer(int playerId)
|
||||
{
|
||||
if (!CanCheat || localPlayer == null || playerId == localId) return;
|
||||
Vector3 pos = localPlayer.position + localPlayer.forward * TeleportSideOffset;
|
||||
if (dedicated)
|
||||
{
|
||||
session.SendTo(NetSession.HostId, MsgType.AdminAction, NetSession.Build(w =>
|
||||
{
|
||||
w.Write((byte)3);
|
||||
w.Write(playerId);
|
||||
w.Write("");
|
||||
w.Write(pos.x); w.Write(pos.y); w.Write(pos.z);
|
||||
}));
|
||||
}
|
||||
else if (players.ContainsKey(playerId))
|
||||
{
|
||||
session.SendTo(playerId, MsgType.Teleport, NetSession.Build(w => { w.Write(pos.x); w.Write(pos.y); w.Write(pos.z); }));
|
||||
overlays.Log("Brought " + players[playerId].Name + " to you");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Cheats für alle sichtbar im Chat melden.</summary>
|
||||
void AnnounceCheat(string what)
|
||||
{
|
||||
string text = OwnName() + " " + what + " (admin)";
|
||||
overlays.AddChat("", text, true);
|
||||
SendGame(MsgType.Chat, NetSession.Build(w => w.Write("* " + text)));
|
||||
}
|
||||
|
||||
public void AdminAction(bool ban, int playerId, string reason)
|
||||
{
|
||||
if (session == null) return;
|
||||
@@ -835,6 +895,17 @@ namespace MSCO
|
||||
SaveSync.WriteFile(file, data);
|
||||
break;
|
||||
|
||||
case MsgType.Teleport:
|
||||
{
|
||||
// Ein Admin holt uns zu sich
|
||||
var pos = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
if (!MenuHelper.InGame || localPlayer == null) break;
|
||||
passenger.Exit(localPlayer, playerCamera);
|
||||
Cheats.Teleport(localPlayer, pos);
|
||||
overlays.AddChat("", "An admin teleported you", true);
|
||||
break;
|
||||
}
|
||||
|
||||
case MsgType.AdminStatus:
|
||||
isAdmin = r.ReadBoolean();
|
||||
if (isAdmin) overlays.Log("You are an admin on this server - type /admin in chat or 'admin' here.");
|
||||
|
||||
+2
-1
@@ -37,7 +37,8 @@ namespace MSCO
|
||||
AdminAction = 26, // Client -> Server: byte (1 = kick, 2 = ban), int Spieler-ID, string Grund
|
||||
AdminResult = 27, // Server -> Client: string Meldung
|
||||
Chat = 28, // Chatnachricht (string)
|
||||
VarSync = 29 // Fahrzeugzustand: int n, je [int key, byte typ, wert]
|
||||
VarSync = 29, // Fahrzeugzustand: int n, je [int key, byte typ, wert]
|
||||
Teleport = 30 // Admin holt einen Spieler zu sich: 3 float Position
|
||||
}
|
||||
|
||||
public struct Message
|
||||
|
||||
+24
-1
@@ -263,7 +263,7 @@ namespace MSCO
|
||||
|
||||
void DrawAdmin(MultiplayerManager mp)
|
||||
{
|
||||
float width = Mathf.Min(600, Screen.width - 40), height = Mathf.Min(460, Screen.height - 40);
|
||||
float width = Mathf.Min(680, Screen.width - 40), height = Mathf.Min(560, Screen.height - 40);
|
||||
var rect = new Rect((Screen.width - width) / 2f, (Screen.height - height) / 2f, width, height);
|
||||
GUI.Box(rect, GUIContent.none, panel);
|
||||
|
||||
@@ -284,6 +284,21 @@ namespace MSCO
|
||||
GUILayout.Label(mp.IsDedicated ? "Players on this server. Banned players cannot join again." : "Players in your game.", small);
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Cheats für den eigenen Spieler (nur im Spiel)
|
||||
if (mp.CanCheat)
|
||||
{
|
||||
GUILayout.Label("CHEATS", caption);
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("+1.000 MK", primary, GUILayout.Height(30))) mp.CheatMoney(1000f);
|
||||
GUILayout.Space(6);
|
||||
if (GUILayout.Button("+10.000 MK", primary, GUILayout.Height(30))) mp.CheatMoney(10000f);
|
||||
GUILayout.Space(6);
|
||||
if (GUILayout.Button("REFILL NEEDS", primary, GUILayout.Height(30))) mp.CheatNeeds();
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Label("Cheats are announced in the chat. GOTO / BRING teleport you to a player or a player to you.", small);
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
|
||||
GUILayout.Label("REASON (optional)", caption);
|
||||
adminReason = GUILayout.TextField(adminReason, 100, field, GUILayout.Height(32));
|
||||
GUILayout.Space(12);
|
||||
@@ -304,6 +319,14 @@ namespace MSCO
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
bool self = p.Id == mp.LocalId;
|
||||
if (mp.CanCheat)
|
||||
{
|
||||
GUI.enabled = !self;
|
||||
if (GUILayout.Button("GOTO", secondary, GUILayout.Height(30), GUILayout.Width(70))) mp.GotoPlayer(p.Id);
|
||||
GUILayout.Space(6);
|
||||
if (GUILayout.Button("BRING", secondary, GUILayout.Height(30), GUILayout.Width(70))) mp.BringPlayer(p.Id);
|
||||
GUILayout.Space(12);
|
||||
}
|
||||
GUI.enabled = !self && !p.IsAdmin;
|
||||
if (GUILayout.Button("KICK", secondary, GUILayout.Height(30), GUILayout.Width(80)))
|
||||
mp.AdminAction(false, p.Id, adminReason);
|
||||
|
||||
@@ -31,7 +31,8 @@ Multiplayer-Mod für **My Summer Car** (MSCLoader). Spiel mit bis zu 3 Spielern
|
||||
**Im Spiel**
|
||||
- **T** – Chat
|
||||
- **F8** – MSCO-Konsole mit allen Befehlen
|
||||
- **/admin** – Admin-Menü (Spieler kicken/bannen) für Server-Admins bzw. den P2P-Host
|
||||
- **/admin** – Admin-Menü für Server-Admins bzw. den P2P-Host: Spieler kicken/bannen, GOTO/BRING (teleportieren),
|
||||
Cheats (+1.000 / +10.000 MK, Bedürfnisse auffüllen) – Cheats werden im Chat angezeigt
|
||||
- **P** – als Beifahrer ein-/aussteigen
|
||||
- Alle Tasten sind in den MSCLoader-Einstellungen der Mod änderbar
|
||||
- Discord Rich Presence („In the Menus“, Server, Spielerzahl)
|
||||
@@ -71,7 +72,6 @@ In der F8-Konsole direkt, in der MSCLoader-Konsole mit `mp` davor (z.B. `mp conn
|
||||
| `admin` bzw. `/admin` im Chat | Admin-Menü |
|
||||
| `vehicles`, `rig` | Diagnose: Fahrzeuge / Spielermodelle |
|
||||
| `debug` | Sync-Debugausgaben an/aus |
|
||||
| `master [url]` | Adresse der Serverliste anzeigen/ändern |
|
||||
| `clear` | Konsole leeren |
|
||||
|
||||
## Selbst bauen
|
||||
|
||||
+2
-9
@@ -37,8 +37,8 @@ namespace MSCO
|
||||
/// </summary>
|
||||
public class ServerBrowser
|
||||
{
|
||||
public const string DefaultMasterUrl = "https://msco.mbm.wtf";
|
||||
const string PrefMasterUrl = "MSCO_MasterUrl";
|
||||
/// <summary>Offizieller Master (Serverliste) - fest eingebaut.</summary>
|
||||
public const string MasterUrl = "https://msco.mbm.wtf";
|
||||
const int QueryTimeoutMs = 3000;
|
||||
|
||||
// Ein Server auf diesem PC erscheint automatisch oben in der Liste
|
||||
@@ -54,13 +54,6 @@ namespace MSCO
|
||||
/// <summary>Zeitpunkt der letzten Aktualisierung (Time.realtimeSinceStartup), für das Auto-Refresh.</summary>
|
||||
public float LastRefresh { get; private set; }
|
||||
|
||||
/// <summary>Adresse des Master-Servers (änderbar mit "mp master <url>", z.B. zum lokalen Testen).</summary>
|
||||
public static string MasterUrl
|
||||
{
|
||||
get { return PlayerPrefs.GetString(PrefMasterUrl, DefaultMasterUrl).TrimEnd('/'); }
|
||||
set { PlayerPrefs.SetString(PrefMasterUrl, string.IsNullOrEmpty(value) ? DefaultMasterUrl : value.TrimEnd('/')); }
|
||||
}
|
||||
|
||||
/// <summary>Lokale Server zuerst, dann die öffentliche Liste.</summary>
|
||||
public List<ServerListEntry> Servers
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user