diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index 28a5eb5dd6..d230f1fa34 100644 --- a/source/gui/scripting/ScriptFunctions.cpp +++ b/source/gui/scripting/ScriptFunctions.cpp @@ -26,28 +26,18 @@ #include "gui/IGUIObject.h" #include "gui/scripting/JSInterface_GUIManager.h" #include "gui/scripting/JSInterface_GUITypes.h" -#include "i18n/L10n.h" #include "i18n/scripting/JSInterface_L10n.h" -#include "lib/svn_revision.h" #include "lib/sysdep/sysdep.h" #include "lib/utf8.h" #include "lobby/scripting/JSInterface_Lobby.h" -#include "network/NetClient.h" -#include "network/NetServer.h" #include "network/scripting/JSInterface_Network.h" -#include "ps/CConsole.h" -#include "ps/CLogger.h" -#include "ps/Errors.h" #include "ps/GUID.h" -#include "ps/Game.h" #include "ps/GameSetup/Atlas.h" #include "ps/Globals.h" // g_frequencyFilter #include "ps/Hotkey.h" -#include "ps/ProfileViewer.h" -#include "ps/Profile.h" -#include "ps/UserReport.h" #include "ps/scripting/JSInterface_ConfigDB.h" #include "ps/scripting/JSInterface_Console.h" +#include "ps/scripting/JSInterface_Debug.h" #include "ps/scripting/JSInterface_Game.h" #include "ps/scripting/JSInterface_Mod.h" #include "ps/scripting/JSInterface_SavedGame.h" @@ -116,60 +106,6 @@ bool HotkeyIsPressed_(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std: return HotkeyIsPressed(hotkeyName); } -void DisplayErrorDialog(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& msg) -{ - debug_DisplayError(msg.c_str(), DE_NO_DEBUG_INFO, NULL, NULL, NULL, 0, NULL, NULL); -} - -JS::Value GetProfilerState(ScriptInterface::CxPrivate* pCxPrivate) -{ - return g_ProfileViewer.SaveToJS(*(pCxPrivate->pScriptInterface)); -} - -bool IsUserReportEnabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) -{ - return g_UserReporter.IsReportingEnabled(); -} - -void SetUserReportEnabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool enabled) -{ - g_UserReporter.SetReportingEnabled(enabled); -} - -std::string GetUserReportStatus(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) -{ - return g_UserReporter.GetStatus(); -} - -void SubmitUserReport(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& type, int version, const std::wstring& data) -{ - g_UserReporter.SubmitReport(type.c_str(), version, utf8_from_wstring(data)); -} - -// Deliberately cause the game to crash. -// Currently implemented via access violation (read of address 0). -// Useful for testing the crashlog/stack trace code. -int Crash(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) -{ - debug_printf("Crashing at user's request.\n"); - return *(volatile int*)0; -} - -void DebugWarn(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) -{ - debug_warn(L"Warning at user's request."); -} - -// Force a JS garbage collection cycle to take place immediately. -// Writes an indication of how long this took to the console. -void ForceGC(ScriptInterface::CxPrivate* pCxPrivate) -{ - double time = timer_Time(); - JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime()); - time = timer_Time() - time; - g_Console->InsertMessage(fmt::sprintf("Garbage collection completed in: %f", time)); -} - void Script_EndGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { EndGame(); @@ -180,12 +116,6 @@ CStrW GetSystemUsername(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) return sys_get_user_name(); } -// Cause the game to exit gracefully. -// params: -// returns: -// notes: -// - Exit happens after the current main loop iteration ends -// (since this only sets a flag telling it to end) void ExitProgram(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { kill_mainloop(); @@ -201,70 +131,6 @@ int GetFps(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) return freq; } -// Return the date/time at which the current executable was compiled. -// params: mode OR an integer specifying -// what to display: -1 for "date time (svn revision)", 0 for date, 1 for time, 2 for svn revision -// returns: string with the requested timestamp info -// notes: -// - Displayed on main menu screen; tells non-programmers which auto-build -// they are running. Could also be determined via .EXE file properties, -// but that's a bit more trouble. -// - To be exact, the date/time returned is when scriptglue.cpp was -// last compiled, but the auto-build does full rebuilds. -// - svn revision is generated by calling svnversion and cached in -// lib/svn_revision.cpp. it is useful to know when attempting to -// reproduce bugs (the main EXE and PDB should be temporarily reverted to -// that revision so that they match user-submitted crashdumps). -std::wstring GetBuildTimestamp(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int mode) -{ - char buf[200]; - if (mode == -1) // Date, time and revision. - { - UDate dateTime = g_L10n.ParseDateTime(__DATE__ " " __TIME__, "MMM d yyyy HH:mm:ss", Locale::getUS()); - std::string dateTimeString = g_L10n.LocalizeDateTime(dateTime, L10n::DateTime, SimpleDateFormat::DATE_TIME); - char svnRevision[32]; - sprintf_s(svnRevision, ARRAY_SIZE(svnRevision), "%ls", svn_revision); - if (strcmp(svnRevision, "custom build") == 0) - { - // Translation: First item is a date and time, item between parenthesis is the Subversion revision number of the current build. - sprintf_s(buf, ARRAY_SIZE(buf), g_L10n.Translate("%s (custom build)").c_str(), dateTimeString.c_str()); - } - else - { - // Translation: First item is a date and time, item between parenthesis is the Subversion revision number of the current build. - // dennis-ignore: * - sprintf_s(buf, ARRAY_SIZE(buf), g_L10n.Translate("%s (%ls)").c_str(), dateTimeString.c_str(), svn_revision); - } - } - else if (mode == 0) // Date. - { - UDate dateTime = g_L10n.ParseDateTime(__DATE__, "MMM d yyyy", Locale::getUS()); - std::string dateTimeString = g_L10n.LocalizeDateTime(dateTime, L10n::Date, SimpleDateFormat::MEDIUM); - sprintf_s(buf, ARRAY_SIZE(buf), "%s", dateTimeString.c_str()); - } - else if (mode == 1) // Time. - { - UDate dateTime = g_L10n.ParseDateTime(__TIME__, "HH:mm:ss", Locale::getUS()); - std::string dateTimeString = g_L10n.LocalizeDateTime(dateTime, L10n::Time, SimpleDateFormat::MEDIUM); - sprintf_s(buf, ARRAY_SIZE(buf), "%s", dateTimeString.c_str()); - } - else if (mode == 2) // Revision. - { - char svnRevision[32]; - sprintf_s(svnRevision, ARRAY_SIZE(svnRevision), "%ls", svn_revision); - if (strcmp(svnRevision, "custom build") == 0) - { - sprintf_s(buf, ARRAY_SIZE(buf), "%s", g_L10n.Translate("custom build").c_str()); - } - else - { - sprintf_s(buf, ARRAY_SIZE(buf), "%ls", svn_revision); - } - } - - return wstring_from_utf8(buf); -} - int GetTextWidth(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const CStr& fontName, const CStrW& text) { int width = 0; @@ -275,14 +141,6 @@ int GetTextWidth(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const CStr& fon return width; } -/** - * Microseconds since the epoch. - */ -double GetMicroseconds(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) -{ - return JS_Now(); -} - } // namespace void GuiScriptingInit(ScriptInterface& scriptInterface) @@ -294,6 +152,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface) JSI_Renderer::RegisterScriptFunctions(scriptInterface); JSI_Console::RegisterScriptFunctions(scriptInterface); JSI_ConfigDB::RegisterScriptFunctions(scriptInterface); + JSI_Debug::RegisterScriptFunctions(scriptInterface); JSI_Game::RegisterScriptFunctions(scriptInterface); JSI_GUIManager::RegisterScriptFunctions(scriptInterface); JSI_Mod::RegisterScriptFunctions(scriptInterface); @@ -314,23 +173,8 @@ void GuiScriptingInit(ScriptInterface& scriptInterface) scriptInterface.RegisterFunction("IsAtlasRunning"); scriptInterface.RegisterFunction("LoadMapSettings"); scriptInterface.RegisterFunction("HotkeyIsPressed"); - scriptInterface.RegisterFunction("DisplayErrorDialog"); - scriptInterface.RegisterFunction("GetProfilerState"); scriptInterface.RegisterFunction("Exit"); scriptInterface.RegisterFunction("GetFPS"); - scriptInterface.RegisterFunction("GetBuildTimestamp"); scriptInterface.RegisterFunction("GetTextWidth"); - - // User report functions - scriptInterface.RegisterFunction("IsUserReportEnabled"); - scriptInterface.RegisterFunction("SetUserReportEnabled"); - scriptInterface.RegisterFunction("GetUserReportStatus"); - scriptInterface.RegisterFunction("SubmitUserReport"); - - // Development/debugging functions - scriptInterface.RegisterFunction("GetMicroseconds"); - scriptInterface.RegisterFunction("Crash"); - scriptInterface.RegisterFunction("DebugWarn"); - scriptInterface.RegisterFunction("ForceGC"); scriptInterface.RegisterFunction("GetSystemUsername"); } diff --git a/source/ps/scripting/JSInterface_Debug.cpp b/source/ps/scripting/JSInterface_Debug.cpp new file mode 100644 index 0000000000..7849c82e2f --- /dev/null +++ b/source/ps/scripting/JSInterface_Debug.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2017 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "JSInterface_Debug.h" + +#include "i18n/L10n.h" +#include "lib/svn_revision.h" +#include "ps/CConsole.h" +#include "ps/CLogger.h" +#include "ps/Profile.h" +#include "ps/ProfileViewer.h" +#include "ps/UserReport.h" + +/** + * Microseconds since the epoch. + */ +double JSI_Debug::GetMicroseconds(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +{ + return JS_Now(); +} + +// Deliberately cause the game to crash. +// Currently implemented via access violation (read of address 0). +// Useful for testing the crashlog/stack trace code. +int JSI_Debug::Crash(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +{ + debug_printf("Crashing at user's request.\n"); + return *(volatile int*)0; +} + +void JSI_Debug::DebugWarn(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +{ + debug_warn(L"Warning at user's request."); +} + +void JSI_Debug::DisplayErrorDialog(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& msg) +{ + debug_DisplayError(msg.c_str(), DE_NO_DEBUG_INFO, NULL, NULL, NULL, 0, NULL, NULL); +} + +JS::Value JSI_Debug::GetProfilerState(ScriptInterface::CxPrivate* pCxPrivate) +{ + return g_ProfileViewer.SaveToJS(*(pCxPrivate->pScriptInterface)); +} + +// Return the date/time at which the current executable was compiled. +// params: mode OR an integer specifying +// what to display: -1 for "date time (svn revision)", 0 for date, 1 for time, 2 for svn revision +// returns: string with the requested timestamp info +// notes: +// - Displayed on main menu screen; tells non-programmers which auto-build +// they are running. Could also be determined via .EXE file properties, +// but that's a bit more trouble. +// - To be exact, the date/time returned is when scriptglue.cpp was +// last compiled, but the auto-build does full rebuilds. +// - svn revision is generated by calling svnversion and cached in +// lib/svn_revision.cpp. it is useful to know when attempting to +// reproduce bugs (the main EXE and PDB should be temporarily reverted to +// that revision so that they match user-submitted crashdumps). +std::wstring JSI_Debug::GetBuildTimestamp(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int mode) +{ + char buf[200]; + if (mode == -1) // Date, time and revision. + { + UDate dateTime = g_L10n.ParseDateTime(__DATE__ " " __TIME__, "MMM d yyyy HH:mm:ss", Locale::getUS()); + std::string dateTimeString = g_L10n.LocalizeDateTime(dateTime, L10n::DateTime, SimpleDateFormat::DATE_TIME); + char svnRevision[32]; + sprintf_s(svnRevision, ARRAY_SIZE(svnRevision), "%ls", svn_revision); + if (strcmp(svnRevision, "custom build") == 0) + { + // Translation: First item is a date and time, item between parenthesis is the Subversion revision number of the current build. + sprintf_s(buf, ARRAY_SIZE(buf), g_L10n.Translate("%s (custom build)").c_str(), dateTimeString.c_str()); + } + else + { + // Translation: First item is a date and time, item between parenthesis is the Subversion revision number of the current build. + // dennis-ignore: * + sprintf_s(buf, ARRAY_SIZE(buf), g_L10n.Translate("%s (%ls)").c_str(), dateTimeString.c_str(), svn_revision); + } + } + else if (mode == 0) // Date. + { + UDate dateTime = g_L10n.ParseDateTime(__DATE__, "MMM d yyyy", Locale::getUS()); + std::string dateTimeString = g_L10n.LocalizeDateTime(dateTime, L10n::Date, SimpleDateFormat::MEDIUM); + sprintf_s(buf, ARRAY_SIZE(buf), "%s", dateTimeString.c_str()); + } + else if (mode == 1) // Time. + { + UDate dateTime = g_L10n.ParseDateTime(__TIME__, "HH:mm:ss", Locale::getUS()); + std::string dateTimeString = g_L10n.LocalizeDateTime(dateTime, L10n::Time, SimpleDateFormat::MEDIUM); + sprintf_s(buf, ARRAY_SIZE(buf), "%s", dateTimeString.c_str()); + } + else if (mode == 2) // Revision. + { + char svnRevision[32]; + sprintf_s(svnRevision, ARRAY_SIZE(svnRevision), "%ls", svn_revision); + if (strcmp(svnRevision, "custom build") == 0) + { + sprintf_s(buf, ARRAY_SIZE(buf), "%s", g_L10n.Translate("custom build").c_str()); + } + else + sprintf_s(buf, ARRAY_SIZE(buf), "%ls", svn_revision); + } + + return wstring_from_utf8(buf); +} + +// Force a JS garbage collection cycle to take place immediately. +// Writes an indication of how long this took to the console. +void JSI_Debug::ForceGC(ScriptInterface::CxPrivate* pCxPrivate) +{ + double time = timer_Time(); + JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime()); + time = timer_Time() - time; + g_Console->InsertMessage(fmt::sprintf("Garbage collection completed in: %f", time)); +} + +bool JSI_Debug::IsUserReportEnabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +{ + return g_UserReporter.IsReportingEnabled(); +} + +void JSI_Debug::SetUserReportEnabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool enabled) +{ + g_UserReporter.SetReportingEnabled(enabled); +} + +std::string JSI_Debug::GetUserReportStatus(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) +{ + return g_UserReporter.GetStatus(); +} + +void JSI_Debug::SubmitUserReport(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& type, int version, const std::wstring& data) +{ + g_UserReporter.SubmitReport(type.c_str(), version, utf8_from_wstring(data)); +} + +void JSI_Debug::RegisterScriptFunctions(const ScriptInterface& scriptInterface) +{ + scriptInterface.RegisterFunction("GetMicroseconds"); + scriptInterface.RegisterFunction("Crash"); + scriptInterface.RegisterFunction("DebugWarn"); + scriptInterface.RegisterFunction("DisplayErrorDialog"); + scriptInterface.RegisterFunction("GetProfilerState"); + scriptInterface.RegisterFunction("GetBuildTimestamp"); + scriptInterface.RegisterFunction("ForceGC"); + + // User report functions + scriptInterface.RegisterFunction("IsUserReportEnabled"); + scriptInterface.RegisterFunction("SetUserReportEnabled"); + scriptInterface.RegisterFunction("GetUserReportStatus"); + scriptInterface.RegisterFunction("SubmitUserReport"); +} diff --git a/source/ps/scripting/JSInterface_Debug.h b/source/ps/scripting/JSInterface_Debug.h new file mode 100644 index 0000000000..7c67de36f6 --- /dev/null +++ b/source/ps/scripting/JSInterface_Debug.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2017 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_JSI_DEBUG +#define INCLUDED_JSI_DEBUG + +#include "scriptinterface/ScriptInterface.h" + +namespace JSI_Debug +{ + int Crash(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)); + void DebugWarn(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)); + void DisplayErrorDialog(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& msg); + JS::Value GetProfilerState(ScriptInterface::CxPrivate* pCxPrivate); + bool IsUserReportEnabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)); + void SetUserReportEnabled(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool enabled); + std::string GetUserReportStatus(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)); + void SubmitUserReport(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& type, int version, const std::wstring& data); + std::wstring GetBuildTimestamp(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int mode); + double GetMicroseconds(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)); + void ForceGC(ScriptInterface::CxPrivate* pCxPrivate); + + void RegisterScriptFunctions(const ScriptInterface& ScriptInterface); +} + +#endif