VmAbortReporter
Table of Contents
1. About
VM abort reports: - system time - map name - total time - multiplayer status - player class - skill - compat flags - dm flags - autoaim - event handler list - a request for the user to report the bug If there are several VM abort handlers loaded, only the first one will print stuff. For this to work, all handlers must have ~VmAbortHandler~ somewhere in their class name. To use (besides ZScript code): - define cvars: user bool NAMESPACE_vm_abort_report_enabled = true; - add event handlers in mapinfo: GameInfo { EventHandlers = "NAMESPACE_VmAbortHandler" } VmAbortReporter module version: 1.0.0 VmAbortReporter is a part of DoomToolbox. The source code is available on GitHub https://github.com/mmaulwurff/doom-toolbox/ and Codeberg https://codeberg.org/m8f/doom-toolbox
user bool NAMESPACE_vm_abort_report_enabled = true;
GameInfo
{
EventHandlers = "NAMESPACE_VmAbortHandler"
}
2. License
SPDX-FileCopyrightText: © 2021 Alexander Kromm <mmaulwurff@gmail.com> SPDX-License-Identifier: BSD-3-Clause
3. Source
3.1. VmAbortHandler
TODO: make VmAbortHandler savefile-compatible (StaticEventHandler).
class NAMESPACE_VmAbortHandler : EventHandler { override void playerSpawned(PlayerEvent event) { mReport = new("NAMESPACE_Report"); if (event.playerNumber == consolePlayer) mReport.writePlayerInfo(); } override void uiTick() { bool isOnceASecond = level.totalTime % TICRATE == 0; if (isOnceASecond) mReport.writeSystemTime(); } override void onDestroy() { if (gameState != GS_FullConsole || !amIFirst() || !Cvar.getCvar("NAMESPACE_vm_abort_report_enabled", players[consolePlayer]).getBool()) { return; } Console.printf("%s\n%s", mReport.report(), getAttentionMessage()); } override void consoleProcess(ConsoleEvent event) { if (amIFirst() && event.name == "NAMESPACE_report") { Console.printf("%s", mReport.report()); } } private clearscope bool amIFirst() { foreach (aClass : AllClasses) { string className = aClass.getClassName(); bool isVmAbortHandler = (className.indexOf("VmAbortHandler") != -1); if (!isVmAbortHandler) continue; return className == getClassName(); } return false; } private clearscope string getAttentionMessage() { string userName = players[consolePlayer].getUserName(); string hashes = "\cg############################################################"; Array<string> lines = { "", hashes, " " .. userName .. "\cg, please report this VM abort to mod author.", " Attach screenshot to the report.", " Type \"screenshot\" below to take a screenshot.", hashes }; return NAMESPACE_su.join(lines, "\n"); } private NAMESPACE_Report mReport; }
3.2. Report
class NAMESPACE_Report { clearscope void writePlayerInfo() { mPlayerClassName = players[consolePlayer].mo.getClassName(); mSkillName = g_SkillName(); } ui void writeSystemTime() { mSystemTime = SystemTime.now(); } clearscope string report() { Array<string> lines = { getSystemTime(), getGameInfo(), getConfiguration(), getEventHandlers() }; return NAMESPACE_su.join(lines, "\n"); } private static clearscope string getConfiguration() { return new("NAMESPACE_Description") .addCvar("compatflags") .addCvar("compatflags2") .addCvar("dmflags") .addCvar("dmflags2") .addCvar("autoaim").compose(); } private clearscope string getGameInfo() { return new("NAMESPACE_Description") .add("level", level.mapName) .addInt("time", level.totalTime) .addBool("multiplayer", multiplayer) .add("player class", mPlayerClassName) .add("skill", mSkillName).compose(); } private static clearscope string getEventHandlers() { Array<string> normalEventHandlers; Array<string> staticEventHandlers; foreach (aClass : AllClasses) { if (!(aClass is "StaticEventHandler")) continue; if (aClass == "StaticEventHandler" || aClass == "EventHandler") continue; if (aClass is "EventHandler") normalEventHandlers.push(aClass.getClassName()); else staticEventHandlers.push(aClass.getClassName()); } return "Event handlers: " .. NAMESPACE_su.join(normalEventHandlers) .. "\n" .. "Static event handlers: " .. NAMESPACE_su.join(staticEventHandlers); } private clearscope string getSystemTime() { return "System time: " .. SystemTime.format("%F %T %Z", mSystemTime); } private string mPlayerClassName; private string mSkillName; private int mSystemTime; }
4. Tests
wait 2; map map01; wait 2; event NAMESPACE_report; wait 2; quit
GameInfo
{
EventHandlers = "NAMESPACE_VmAbortHandler"
}
user bool NAMESPACE_vm_abort_report_enabled = true;
version 4.14.3 #include "VmAbortReporter.zs" #include "zscript/NAMESPACE_StringUtils.zs"