/* * This mode is used to debug your modes during development. * To use it, you just have to change the line below to put the path of your mode: */ #Extends "Modes/TrackMania/TM_Rounds_Online.Script.txt" // #RequireContext CSmMode #Include "TimeLib" as DebugMode_TiL // @mslint-disable-line include-use-common-namespace #Include "MathLib" as DebugMode_ML // @mslint-disable-line include-use-common-namespace #Include "TextLib" as DebugMode_TL // @mslint-disable-line include-use-common-namespace // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Constants // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #Const C_DebugMode_Version "2024-03-12" #Const C_DebugMode_MainUI "DebugMode_MainUI" // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Settings // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #Setting S_ScriptEnvironment "development" #Setting S_DebugLib_RestrictUIto "" as "Restrict UI Admin to comma separated logins (all if empty)" ***Match_LogVersions*** *** log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log("~~~~~~~~~~~~~ Starting DebugMode v" ^ C_DebugMode_Version ^ " ~~~~~~~~~~~~~"); log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log("~~ Launched at: "^ System.CurrentLocalDateText ^" ("^ System.CurrentTimezone ^")"); log("~~ Server version: "^ System.ExeVersion); log("~~ TitlePack version: "^ DebugMode_TL::Split(" ", LoadedTitle.TitleVersion)[0]); log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); *** ***Match_AfterLoadHud*** *** Layers::Create(C_DebugMode_MainUI, GetManialink()); Layers::SetType(C_DebugMode_MainUI, CUILayer::EUILayerType::Normal); *** ***Match_InitMap*** *** if (S_DebugLib_RestrictUIto == "") { Layers::Attach(C_DebugMode_MainUI); } else { Layers::Detach(C_DebugMode_MainUI); foreach (Login in DebugMode_TL::Split(",", S_DebugLib_RestrictUIto)) { declare CSmPlayer Player = GetPlayer(Login); if (Player != Null) Layers::Attach(C_DebugMode_MainUI, Player); } } *** ***Match_Yield*** *** // Manage Custom UI Events foreach (Event in UIManager.PendingEvents) { +++DebugMode_LogFormat+++ switch (Event.CustomEventType) { case "DebugMode.ClearLogs": { Net_DebugMode_Logs = Prefix ^ "Logs cleared"; } case "DebugMode.Bots.DelBots": { declare Text Name = Event.CustomEventData[0]; declare Integer NumberOfBots = DebugMode_TL::ToInteger(Event.CustomEventData[1]); if (NumberOfBots == -1) { Users_DestroyAllFakes(); } else { foreach (Player in AllPlayers) { if (Player.IsFakePlayer) { if (Name == "" || DebugMode_TL::ToLowerCase(Player.User.Name) == DebugMode_TL::ToLowerCase(Name)) { Net_DebugMode_Logs = Prefix ^ "Bots: Remove bot \"" ^ Player.User.Name ^ "\"\n" ^ Net_DebugMode_Logs; Users_DestroyFake(Player.User); NumberOfBots -= 1; } else { Net_DebugMode_Logs = Prefix ^ "Bots: Player not found\n" ^ Net_DebugMode_Logs; } } if (NumberOfBots == 0) break; } } } case "DebugMode.Bots.AddBots": { declare Text Name = Event.CustomEventData[0]; declare Integer TeamId = DebugMode_TL::ToInteger(Event.CustomEventData[1]); if (TeamId == -1 && Event.CustomEventData[1] == "") TeamId = 0; declare Integer NumberOfBots = DebugMode_TL::ToInteger(Event.CustomEventData[2]); if (TeamId != -1 && Teams.existskey(TeamId)) { for (I, 1, NumberOfBots) { declare CUser User = Users_CreateFake(Name, TeamId); if (User == Null) { Net_DebugMode_Logs = Prefix ^ "Bots: unknown error while adding bot \"" ^ Name ^ "\"\n" ^ Net_DebugMode_Logs; } else { Net_DebugMode_Logs = Prefix ^ "Bots: Add bot \"" ^ User.Name ^ "\"\n" ^ Net_DebugMode_Logs; } } } else { Net_DebugMode_Logs = Prefix ^ "Bots: Invalid TeamId\n" ^ Net_DebugMode_Logs; } } case "DebugMode.PlayersControl.Set": { declare Text TargetText = Event.CustomEventData[2]; declare CSmPlayer[] Targets; if (TargetText == "allbots" || TargetText == "allplayers") { foreach (Player in Players) { if (TargetText == "allbots" && !Player.IsFakePlayer) continue; Targets.add(Player); } } else { declare CSmPlayer TmpPlayer = GetPlayer(TargetText); if (TmpPlayer != Null) { Targets.add(TmpPlayer); } } declare Real[] Speed; foreach (SpeedText in DebugMode_TL::Split(",", Event.CustomEventData[0])) { Speed.add(DebugMode_ML::Clamp(DebugMode_TL::ToReal(SpeedText), -999., 999.)); } if (Speed.count > 0) { declare Real[] Steer; foreach (SteerText in DebugMode_TL::Split(",", Event.CustomEventData[1])) { Steer.add(DebugMode_ML::Clamp(DebugMode_TL::ToReal(SteerText), -1., 1.)); } foreach (Target in Targets) { if (Target.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned) continue; Target.TrustClientSimu = False; SetPlayerVehicle_ControlledByMode(Target, True); declare Real SteerValue; if (Steer.count == 2) { SteerValue = DebugMode_ML::Rand(Steer[0] , Steer[1]); } else if (Steer.count == 1) { SteerValue = Steer[0]; } else { SteerValue = 0.; } SetPlayerVehicle_SteerValue(Target, SteerValue); declare Real SpeedValue; if (Speed.count == 1) { SpeedValue = Speed[0]; } else { SpeedValue = DebugMode_ML::Rand(Speed[0], Speed[1]); } SetPlayerVehicle_TargetSpeedValue(Target, SpeedValue); Net_DebugMode_Logs = Prefix ^ "PlayersControl: Set Player " ^ Target.User.Name ^ " speed to " ^ SpeedValue ^ " & steer to " ^ SteerValue ^ "\n" ^ Net_DebugMode_Logs; } } else { foreach (Target in Targets) { if (Target.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned) continue; SetPlayerVehicle_ControlledByMode(Target, False); Race::ApplyNetworkMode(Target); //< Restore TrustClientSimu to its default value } } } case "DebugMode.VarInsp.Dump.Teams0": { // prevent to dump Net_DebugMode_Logs in the dump declare Text Tmp = Net_DebugMode_Logs; Net_DebugMode_Logs = ""; Net_DebugMode_Logs = Prefix ^ "Teams[0] dump:\n" ^ Dbg_DumpDeclareForVariables(Teams[0], False) ^"\n" ^ Tmp; } case "DebugMode.VarInsp.Dump.UIAll": { Net_DebugMode_Logs = Prefix ^ "UIAll dump:\n" ^ Dbg_DumpDeclareForVariables(UIManager.UIAll, False) ^"\n" ^ Net_DebugMode_Logs; } case "DebugMode.VarInsp.Dump.This": { Net_DebugMode_Logs = Prefix ^ "This dump:\n" ^ Dbg_DumpDeclareForVariables(This, False) ^"\n" ^ Net_DebugMode_Logs; } case "DebugMode.VarInsp.ForVars.Dump.Player": { declare CSmPlayer Player; +++DebugMode_FindPlayer+++ if (Player == Null) { Net_DebugMode_Logs = Prefix ^ "ForVars dump: player not found\n" ^ Net_DebugMode_Logs; } else if (Event.CustomEventData[1] == "player") { Net_DebugMode_Logs = Prefix ^ "Player ForVars dump for " ^ Player.User.Name ^ ":\n" ^ Dbg_DumpDeclareForVariables(Player, False) ^"\n" ^ Net_DebugMode_Logs; } else if (Event.CustomEventData[1] == "score") { Net_DebugMode_Logs = Prefix ^ "Score ForVars dump for " ^ Player.User.Name ^ ":\n" ^ Dbg_DumpDeclareForVariables(Player.Score, False) ^"\n" ^ Net_DebugMode_Logs; } else { declare CUIConfig UI = UIManager.GetUI(Player); if (UI == Null) { Net_DebugMode_Logs = Prefix ^ "UI ForVars dump for " ^ Player.User.Name ^ ": no UI found (it's a bot?)\n" ^ Net_DebugMode_Logs; } else { Net_DebugMode_Logs = Prefix ^ "UI ForVars dump for " ^ Player.User.Name ^ ":\n" ^ Dbg_DumpDeclareForVariables(UI, False) ^"\n" ^ Net_DebugMode_Logs; } } } case "DebugMode.VarInsp.Struct.Dump.Player": { declare CSmPlayer Player; +++DebugMode_FindPlayer+++ if (Player == Null) { Net_DebugMode_Logs = Prefix ^ "Struct dump: player not found\n" ^ Net_DebugMode_Logs; } else if (Event.CustomEventData[1] == "player") { Net_DebugMode_Logs = Prefix ^ "Player Struct dump for " ^ Player.User.Name ^ ":\n" ^ Player ^"\n" ^ Net_DebugMode_Logs; } else if (Event.CustomEventData[1] == "score") { Net_DebugMode_Logs = Prefix ^ "Score Struct dump for " ^ Player.User.Name ^ ":\n" ^ Player.Score ^"\n" ^ Net_DebugMode_Logs; } else { declare CUIConfig UI = UIManager.GetUI(Player); if (UI == Null) { Net_DebugMode_Logs = Prefix ^ "UI ForVars dump for " ^ Player.User.Name ^ ": no UI found (it's a bot?)\n" ^ Net_DebugMode_Logs; } else { Net_DebugMode_Logs = Prefix ^ "UI ForVars dump for " ^ Player.User.Name ^ ":\n" ^ UI ^"\n" ^ Net_DebugMode_Logs; } } } default: { Net_DebugMode_Logs = Prefix ^ "Struct Event received: " ^ Event.CustomEventType ^"\n" ^ Net_DebugMode_Logs; } } } +++DebugMode_LogEvents+++ *** ***DebugMode_FindPlayer*** *** if (DebugMode_TL::Length(Event.CustomEventData[0]) == 36) { Player <=> ModeUtils::GetPlayerFromAccountId(Event.CustomEventData[0]); } else if (DebugMode_TL::Length(Event.CustomEventData[0]) == 22) { Player <=> GetPlayer(Event.CustomEventData[0]); } else { foreach (TmpPlayer in AllPlayers) { if (DebugMode_TL::ToLowerCase(Event.CustomEventData[0]) == DebugMode_TL::ToLowerCase(TmpPlayer.User.Name)) { Player <=> TmpPlayer; break; } } } *** ***DebugMode_LogEvents*** *** foreach (Event in PendingEvents) { +++DebugMode_PendingEvents+++ } foreach (Event in XmlRpc.PendingEvents) { +++DebugMode_XmlRpcPendingEvents+++ } declare Events::K_RaceEvent[] RacePendingEvents = Race::GetPendingEvents(); foreach (Event in RacePendingEvents) { +++DebugMode_RacePendingEvents+++ } *** ***DebugMode_PendingEvents*** *** +++DebugMode_LogFormat+++ Net_DebugMode_Logs = Prefix ^ "CSmMode PendingEvent: " ^ Event.Type ^"\n" ^ Net_DebugMode_Logs; if (Event.Type == CSmModeEvent::EType::OnPlayerAdded) { if (Event.Player != Null && DebugMode_TL::Split(",", S_DebugLib_RestrictUIto).exists(Event.Player.User.Login)) { Layers::Attach(C_DebugMode_MainUI, Event.Player); } } *** ***DebugMode_XmlRpcPendingEvents*** *** +++DebugMode_LogFormat+++ if (Event.Type == CXmlRpcEvent::EType::CallbackArray) { Net_DebugMode_Logs = Prefix ^ "XmlRpc PendingEvent: " ^ Event.ParamArray1 ^"\n" ^ Net_DebugMode_Logs; } else { Net_DebugMode_Logs = Prefix ^ "XmlRpc PendingEvent: " ^ Event.Param1 ^"\n" ^ Net_DebugMode_Logs; } *** ***DebugMode_RacePendingEvents*** *** +++DebugMode_LogFormat+++ declare Text Type = "Unknown"; switch (Event.Type) { case 1: Type = "Waypoint"; case 2: Type = "GiveUp"; case 3: Type = "Respawn"; case 4: Type = "SkipOutro"; case 5: Type = "StartLine"; case 6: Type = "Eliminated"; } Net_DebugMode_Logs = Prefix ^ "Race Pending Event: " ^ Type ^"\n" ^ Net_DebugMode_Logs; *** ***DebugMode_LogFormat*** *** declare Integer CurrentTimeStamp = DebugMode_TL::ToInteger(DebugMode_TiL::GetCurrent()); declare Integer Hours = (CurrentTimeStamp / 3600) % 24; declare Integer Minutes = (CurrentTimeStamp / 60) % 60; declare Integer Seconds = CurrentTimeStamp % 60; declare Text Prefix = "["; if (Hours < 10) Prefix ^= "0" ^ Hours ^ ":"; else Prefix ^= Hours ^ ":"; if (Minutes < 10) Prefix ^= "0" ^ Minutes ^ ":"; else Prefix ^= Minutes ^ ":"; if (Seconds < 10) Prefix ^= "0" ^ Seconds; else Prefix ^= Seconds; Prefix ^= "] "; declare netwrite Text Net_DebugMode_Logs for Teams[0]; if (DebugMode_TL::Length(Net_DebugMode_Logs) > 1000000) { Net_DebugMode_Logs = DebugMode_TL::SubString(Net_DebugMode_Logs, 0, 1000000); } declare netwrite Integer Net_DebugMode_Logs_Serial for Teams[0]; Net_DebugMode_Logs_Serial += 1; *** Text GetManialink() { return """