Admin: spawn items (saved on the server), unban (menu tab + console), tabbed admin menu; dashboard needles and steering wheel synced; server browser row opens the profile
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+92
-10
@@ -206,7 +206,11 @@ namespace MSCO
|
||||
overlays.OpenAdmin(null);
|
||||
RequestAdminList();
|
||||
}
|
||||
else if (session.IsHost) overlays.OpenAdmin(LocalAdminList());
|
||||
else if (session.IsHost)
|
||||
{
|
||||
overlays.OpenAdmin(LocalAdminList());
|
||||
overlays.SetBanned(new List<string>(bannedNames));
|
||||
}
|
||||
else overlays.Log("Only the host can kick or ban players.");
|
||||
}
|
||||
|
||||
@@ -214,7 +218,11 @@ namespace MSCO
|
||||
{
|
||||
if (session == null) return;
|
||||
if (dedicated) session.SendTo(NetSession.HostId, MsgType.AdminListRequest);
|
||||
else if (session.IsHost) overlays.SetAdminPlayers(LocalAdminList());
|
||||
else if (session.IsHost)
|
||||
{
|
||||
overlays.SetAdminPlayers(LocalAdminList());
|
||||
overlays.SetBanned(new List<string>(bannedNames));
|
||||
}
|
||||
}
|
||||
|
||||
List<AdminPlayer> LocalAdminList()
|
||||
@@ -332,6 +340,56 @@ namespace MSCO
|
||||
if (result.EndsWith("next to you")) AnnounceCheat("brought the Satsuma to themselves");
|
||||
}
|
||||
|
||||
/// <summary>Admin: Item vor sich spawnen - bei allen, und auf dem Server gespeichert.</summary>
|
||||
public void SpawnItem(string item)
|
||||
{
|
||||
if (!CanCheat || localPlayer == null) return;
|
||||
Transform head = playerCamera != null ? playerCamera.transform : localPlayer;
|
||||
Vector3 forward = new Vector3(head.forward.x, 0f, head.forward.z).normalized;
|
||||
if (forward.sqrMagnitude < 0.01f) forward = localPlayer.forward;
|
||||
Vector3 pos = head.position + forward * 1.2f;
|
||||
Quaternion rot = Quaternion.LookRotation(forward, Vector3.up);
|
||||
if (!ItemSpawner.Spawn(item, pos, rot)) { overlays.Log("No '" + item + "' in this game"); return; }
|
||||
rescanSoon = true;
|
||||
SendGame(MsgType.SpawnItem, NetSession.Build(w =>
|
||||
{
|
||||
w.Write(item);
|
||||
w.Write(pos.x); w.Write(pos.y); w.Write(pos.z);
|
||||
w.Write(rot.x); w.Write(rot.y); w.Write(rot.z); w.Write(rot.w);
|
||||
}));
|
||||
AnnounceCheat("spawned " + item);
|
||||
}
|
||||
|
||||
/// <summary>Gespawntes Item eines Admins (live oder aus dem Weltzustand) nachbauen.</summary>
|
||||
static bool ApplySpawn(BinaryReader r)
|
||||
{
|
||||
string item = r.ReadString();
|
||||
var pos = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
var rot = new Quaternion(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
if (System.Array.IndexOf(ItemSpawner.Items, item) < 0) return false; // nur bekannte Items
|
||||
return ItemSpawner.Spawn(item, pos, rot);
|
||||
}
|
||||
|
||||
/// <summary>Admin: Bann aufheben (Server: SteamID oder name:..., P2P: Name).</summary>
|
||||
public void Unban(string id)
|
||||
{
|
||||
if (session == null) return;
|
||||
if (dedicated)
|
||||
{
|
||||
session.SendTo(NetSession.HostId, MsgType.AdminAction, NetSession.Build(w =>
|
||||
{
|
||||
w.Write((byte)4);
|
||||
w.Write(-1);
|
||||
w.Write(id);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
if (!session.IsHost) return;
|
||||
bannedNames.Remove(id);
|
||||
overlays.SetBanned(new List<string>(bannedNames));
|
||||
overlays.AddChat("", id + " is no longer banned", true);
|
||||
}
|
||||
|
||||
/// <summary>Cheats für alle sichtbar im Chat melden.</summary>
|
||||
void AnnounceCheat(string what)
|
||||
{
|
||||
@@ -807,7 +865,7 @@ namespace MSCO
|
||||
{
|
||||
return t == MsgType.Player || t == MsgType.ObjStates || t == MsgType.ObjOwn
|
||||
|| t == MsgType.ObjRelease || t == MsgType.FsmEvent || t == MsgType.VehicleFx || t == MsgType.WorldTime || t == MsgType.MoneyDelta || t == MsgType.DoorState
|
||||
|| t == MsgType.Chat || t == MsgType.VarSync;
|
||||
|| t == MsgType.Chat || t == MsgType.VarSync || t == MsgType.SpawnItem;
|
||||
}
|
||||
|
||||
void OnMessage(int peerId, Message m)
|
||||
@@ -996,6 +1054,13 @@ namespace MSCO
|
||||
for (int i = 0; i < count; i++)
|
||||
list.Add(new AdminPlayer { Id = r.ReadInt32(), Name = r.ReadString(), SteamId = r.ReadString(), IsAdmin = r.ReadBoolean() });
|
||||
overlays.SetAdminPlayers(list);
|
||||
var banned = new List<string>();
|
||||
if (r.BaseStream.Length - r.BaseStream.Position >= 4)
|
||||
{
|
||||
int bans = r.ReadInt32();
|
||||
for (int i = 0; i < bans; i++) banned.Add(r.ReadString());
|
||||
}
|
||||
overlays.SetBanned(banned);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1066,6 +1131,9 @@ namespace MSCO
|
||||
case MsgType.VarSync:
|
||||
vehicleState.Handle(from, r, objects, localId);
|
||||
break;
|
||||
case MsgType.SpawnItem:
|
||||
if (ApplySpawn(r)) rescanSoon = true; // neues Item gleich in den Objekt-Sync aufnehmen
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1407,13 +1475,6 @@ namespace MSCO
|
||||
if ((i + 1) % SnapshotEventsPerFrame == 0) yield return null; // nicht alles in einem Frame
|
||||
}
|
||||
|
||||
// Abgebaute Teile sind jetzt eigene Objekte: erfassen, dann alle Positionen setzen
|
||||
yield return null;
|
||||
objects.ScanNow();
|
||||
int applied = 0;
|
||||
foreach (KeyValuePair<int, Pose> p in poses)
|
||||
if (objects.ApplySnapshotPose(p.Key, p.Value.Position, p.Value.Rotation)) applied++;
|
||||
|
||||
// Geld: Summe aller Änderungen seit dem Spielstand des Servers
|
||||
if (r.BaseStream.Length - r.BaseStream.Position >= 4) moneySync.Apply(r.ReadSingle());
|
||||
|
||||
@@ -1427,6 +1488,27 @@ namespace MSCO
|
||||
// Fahrzeugzustand (Tank, Öl, Schrauben ...)
|
||||
if (r.BaseStream.Length - r.BaseStream.Position >= 4) vehicleState.ApplySnapshot(r);
|
||||
|
||||
// Von Admins gespawnte Items (in der Reihenfolge des Servers, damit alle sie gleich benennen)
|
||||
int spawned = 0;
|
||||
if (r.BaseStream.Length - r.BaseStream.Position >= 4)
|
||||
{
|
||||
int spawns = r.ReadInt32();
|
||||
for (int i = 0; i < spawns; i++)
|
||||
{
|
||||
byte[] payload = r.ReadBytes(r.ReadInt32());
|
||||
try { if (ApplySpawn(new BinaryReader(new MemoryStream(payload)))) spawned++; }
|
||||
catch (System.Exception e) { MscoLog.Warning("Could not spawn a saved item: " + e.Message); }
|
||||
}
|
||||
}
|
||||
|
||||
// Abgebaute Teile und gespawnte Items sind jetzt eigene Objekte: erfassen, dann alle Positionen setzen
|
||||
yield return null;
|
||||
objects.ScanNow();
|
||||
int applied = 0;
|
||||
foreach (KeyValuePair<int, Pose> p in poses)
|
||||
if (objects.ApplySnapshotPose(p.Key, p.Value.Position, p.Value.Rotation)) applied++;
|
||||
if (spawned > 0) MscoLog.Info(spawned + " spawned item(s) restored");
|
||||
|
||||
MscoLog.Info("[MSCO] World synced: " + applied + "/" + objectCount + " objects, " + eventCount + " part/bolt actions");
|
||||
SetStatus("Connected");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user