diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96848af1e..169b17c6b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@
* The app is now able to handle having music, voicelines etc selected that
aren't defined in loaded packages. Exporting will fail, but no crash will
occur and the selection will still be saved.
+* If an error occurs, the compiler will now prepare a zip containing all the
+ relevant files for debugging the error.
### Bugfixes:
* The case where no voicelines are set is once again handled correctly.
diff --git a/error_display/static/script.js b/error_display/static/script.js
index 16769dc7d..cfaa9f533 100644
--- a/error_display/static/script.js
+++ b/error_display/static/script.js
@@ -14,6 +14,10 @@ window.addEventListener("load", () => {
let heartbeatID = setInterval(fireHeartbeat, FREQ);
+ document.getElementById("archive-btn").addEventListener("click", () => {
+ fetch("/open_archive").catch(console.error);
+ });
+
// If the window is hidden (including when the Steam Overlay is closed!!), stop sending
// heartbeat messages so the server can die.
document.addEventListener("visibilitychange", () => {
diff --git a/error_display/static/styles.css b/error_display/static/styles.css
index aa74bbfad..8a7d5eb03 100644
--- a/error_display/static/styles.css
+++ b/error_display/static/styles.css
@@ -33,3 +33,13 @@ details pre {
color: black;
white-space: pre-wrap;
}
+
+aside {
+ margin-top: 16px;
+}
+
+#archive-btn {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
diff --git a/error_display/templates/index.html.jinja2 b/error_display/templates/index.html.jinja2
index a18e42407..1c04eeb0e 100644
--- a/error_display/templates/index.html.jinja2
+++ b/error_display/templates/index.html.jinja2
@@ -15,6 +15,10 @@
{% if context %}
{% endif %}
+
Chamber Preview
diff --git a/i18n/BEE2.pot b/i18n/BEE2.pot
index 70586f8ac..64b96a37a 100644
--- a/i18n/BEE2.pot
+++ b/i18n/BEE2.pot
@@ -4,7 +4,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: https://github.com/BEEmod/BEE2.4/issues\n"
-"POT-Creation-Date: 2024-11-08 16:23+1000\n"
+"POT-Creation-Date: 2024-12-17 18:35+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -141,6 +141,19 @@ msgid ""
"in a browser on this computer to see:"
msgstr ""
+#. This uses HTML syntax.
+#: user_errors.py
+msgid ""
+"If submitting a bug report, please include this map archive. It contains "
+"your level, the displayed preview, relevant log files and configs to help"
+" with identifying the issue. "
+msgstr ""
+
+#. This uses HTML syntax.
+#: user_errors.py
+msgid "Open Archive Folder"
+msgstr ""
+
#. This uses HTML syntax.
#: user_errors.py
msgid ""
diff --git a/i18n/es.po b/i18n/es.po
index 72db04382..86000534c 100644
--- a/i18n/es.po
+++ b/i18n/es.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2024-11-08 16:23+1000\n"
+"POT-Creation-Date: 2024-12-17 18:35+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language: es\n"
@@ -147,6 +147,19 @@ msgid ""
"in a browser on this computer to see:"
msgstr ""
+#. This uses HTML syntax.
+#: user_errors.py
+msgid ""
+"If submitting a bug report, please include this map archive. It contains "
+"your level, the displayed preview, relevant log files and configs to help"
+" with identifying the issue. "
+msgstr ""
+
+#. This uses HTML syntax.
+#: user_errors.py
+msgid "Open Archive Folder"
+msgstr ""
+
#. This uses HTML syntax.
#: user_errors.py
msgid ""
@@ -2891,3 +2904,4 @@ msgstr "Recomendado"
#~ "Solo recomendable con la gran sala "
#~ "de observación. Usar con precaución, "
#~ "¡esto puede dar resultados extraños!"
+
diff --git a/i18n/fr.po b/i18n/fr.po
index e88908c9d..3230e2826 100644
--- a/i18n/fr.po
+++ b/i18n/fr.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: BEEMOD2\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2024-11-08 16:23+1000\n"
+"POT-Creation-Date: 2024-12-17 18:35+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language: fr\n"
@@ -146,6 +146,19 @@ msgid ""
"in a browser on this computer to see:"
msgstr ""
+#. This uses HTML syntax.
+#: user_errors.py
+msgid ""
+"If submitting a bug report, please include this map archive. It contains "
+"your level, the displayed preview, relevant log files and configs to help"
+" with identifying the issue. "
+msgstr ""
+
+#. This uses HTML syntax.
+#: user_errors.py
+msgid "Open Archive Folder"
+msgstr ""
+
#. This uses HTML syntax.
#: user_errors.py
msgid ""
diff --git a/i18n/ja.po b/i18n/ja.po
index 5bccdcceb..19c22cec1 100644
--- a/i18n/ja.po
+++ b/i18n/ja.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2024-11-08 16:23+1000\n"
+"POT-Creation-Date: 2024-12-17 18:35+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language: ja\n"
@@ -143,6 +143,19 @@ msgid ""
"in a browser on this computer to see:"
msgstr ""
+#. This uses HTML syntax.
+#: user_errors.py
+msgid ""
+"If submitting a bug report, please include this map archive. It contains "
+"your level, the displayed preview, relevant log files and configs to help"
+" with identifying the issue. "
+msgstr ""
+
+#. This uses HTML syntax.
+#: user_errors.py
+msgid "Open Archive Folder"
+msgstr ""
+
#. This uses HTML syntax.
#: user_errors.py
msgid ""
diff --git a/i18n/pl.po b/i18n/pl.po
index 022a05711..6febfd41c 100644
--- a/i18n/pl.po
+++ b/i18n/pl.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: https://github.com/BEEmod/BEE2.4/issues\n"
-"POT-Creation-Date: 2024-11-08 16:23+1000\n"
+"POT-Creation-Date: 2024-12-17 18:35+1000\n"
"PO-Revision-Date: 2021-06-07 15:18+0200\n"
"Last-Translator: \n"
"Language: pl\n"
@@ -147,6 +147,19 @@ msgid ""
"in a browser on this computer to see:"
msgstr ""
+#. This uses HTML syntax.
+#: user_errors.py
+msgid ""
+"If submitting a bug report, please include this map archive. It contains "
+"your level, the displayed preview, relevant log files and configs to help"
+" with identifying the issue. "
+msgstr ""
+
+#. This uses HTML syntax.
+#: user_errors.py
+msgid "Open Archive Folder"
+msgstr ""
+
#. This uses HTML syntax.
#: user_errors.py
msgid ""
diff --git a/i18n/ru.po b/i18n/ru.po
index bf06a9c89..48dc59789 100644
--- a/i18n/ru.po
+++ b/i18n/ru.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: BEEMOD2\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2024-11-08 16:23+1000\n"
+"POT-Creation-Date: 2024-12-17 18:35+1000\n"
"PO-Revision-Date: 2021-11-18 17:18+0300\n"
"Last-Translator: \n"
"Language: ru\n"
@@ -147,6 +147,19 @@ msgid ""
"in a browser on this computer to see:"
msgstr ""
+#. This uses HTML syntax.
+#: user_errors.py
+msgid ""
+"If submitting a bug report, please include this map archive. It contains "
+"your level, the displayed preview, relevant log files and configs to help"
+" with identifying the issue. "
+msgstr ""
+
+#. This uses HTML syntax.
+#: user_errors.py
+msgid "Open Archive Folder"
+msgstr ""
+
#. This uses HTML syntax.
#: user_errors.py
msgid ""
diff --git a/i18n/zh_cn.po b/i18n/zh_cn.po
index 46432b730..5b88c0955 100644
--- a/i18n/zh_cn.po
+++ b/i18n/zh_cn.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: https://github.com/BEEmod/BEE2.4/issues\n"
-"POT-Creation-Date: 2024-11-08 16:23+1000\n"
+"POT-Creation-Date: 2024-12-17 18:35+1000\n"
"PO-Revision-Date: 2019-11-22 10:47+1000\n"
"Last-Translator: Antecer \n"
"Language: zh\n"
@@ -146,6 +146,19 @@ msgid ""
"in a browser on this computer to see:"
msgstr ""
+#. This uses HTML syntax.
+#: user_errors.py
+msgid ""
+"If submitting a bug report, please include this map archive. It contains "
+"your level, the displayed preview, relevant log files and configs to help"
+" with identifying the issue. "
+msgstr ""
+
+#. This uses HTML syntax.
+#: user_errors.py
+msgid "Open Archive Folder"
+msgstr ""
+
#. This uses HTML syntax.
#: user_errors.py
msgid ""
diff --git a/src/error_server.py b/src/error_server.py
index 334650e16..0fb65de67 100644
--- a/src/error_server.py
+++ b/src/error_server.py
@@ -10,8 +10,9 @@
"""
from __future__ import annotations
-
from typing_extensions import override
+
+from zipfile import ZIP_DEFLATED, ZipFile
import functools
import gettext
import http
@@ -32,7 +33,8 @@
from user_errors import (
ErrorInfo, DATA_LOC, SERVER_INFO_FILE, ServerInfo, PackageTranslations,
- TOK_ERR_FAIL_LOAD, TOK_ERR_MISSING, TOK_COOP_SHOWURL,
+ TOK_ERR_FAIL_LOAD, TOK_ERR_MISSING, TOK_COOP_SHOWURL, TOK_WEBPAGE_ARCHIVE_INFO,
+ TOK_WEBPAGE_ARCHIVE_BTN,
)
import utils
import transtoken
@@ -55,6 +57,7 @@
# That happens either if Portal 2 is detected to quit, or if no response is heard from clients
# for DELAY seconds. It starts with an infinite deadline, to ensure there's time to boot the server.
SHUTDOWN_SCOPE = trio.CancelScope(deadline=math.inf)
+ARCHIVE_LOC = utils.conf_location('error_dump/map_dump.zip')
current_error = ErrorInfo(message=TOK_ERR_MISSING)
@@ -69,6 +72,7 @@ async def route_display_errors() -> str:
context=current_error.context,
log_vbsp=LOGS['vbsp'],
log_vrad=LOGS['vrad'],
+ archive_url=ARCHIVE_LOC.as_uri(),
# Start the render visible if it has annotations.
start_render_open=bool(
current_error.points
@@ -76,6 +80,8 @@ async def route_display_errors() -> str:
or current_error.lines
or current_error.barrier_holes
),
+ trans_archive_info=TOK_WEBPAGE_ARCHIVE_INFO,
+ trans_archive_btn=TOK_WEBPAGE_ARCHIVE_BTN,
)
@@ -134,6 +140,51 @@ async def route_shutdown() -> quart.ResponseReturnValue:
return 'DONE'
+@app.route('/open_archive')
+async def route_open_archive() -> quart.ResponseReturnValue:
+ """The overlay browser doesn't allow downloads, so open a file explorer window with the file."""
+ LOGGER.info('Opening map archive.')
+ utils.display_directory(ARCHIVE_LOC.parent)
+ return 'OPENED'
+
+
+async def generate_archive() -> None:
+ """Generate a zip containing data useful for solving a compile error."""
+ with ZipFile(ARCHIVE_LOC, 'w', compression=ZIP_DEFLATED) as archive:
+ vmf_name: trio.Path | None = None
+ styled_name: trio.Path | None = None
+ name_stem = 'unknown_map'
+ if current_error.vmf_fname_orig is not None:
+ vmf_name = trio.Path(current_error.vmf_fname_orig)
+ name_stem = vmf_name.stem
+ if current_error.vmf_fname_new is not None:
+ styled_name = trio.Path(current_error.vmf_fname_new)
+
+ for file, dest in [
+ (vmf_name, f'{name_stem}_orig.vmf'),
+ (styled_name, f'{name_stem}_styled.vmf'),
+ (trio.Path(DATA_LOC), 'user_error.pickle'),
+ (trio.Path('bee2/config.dmx'), 'export_config.dmx'),
+ (trio.Path(utils.conf_location('config/config.vdf')), 'app_config.vdf'),
+ ]:
+ if file is None:
+ LOGGER.debug('No file defined for {}', dest)
+ continue
+ try:
+ data = await file.read_bytes()
+ except FileNotFoundError:
+ LOGGER.debug('Missing file: {}', file)
+ else:
+ await trio.to_thread.run_sync(archive.writestr, dest, data)
+ for log_key, log_data in LOGS.items():
+ if data:
+ await trio.to_thread.run_sync(archive.writestr, log_key + '.log', log_data)
+ LOGGER.info(
+ 'Generated dump with files:\n{}',
+ '\n'.join(f'- {info.filename}' for info in archive.filelist),
+ )
+
+
async def check_portal2_running(allow_exit: trio.Event) -> None:
"""Check if Portal 2 is our parent process, and if so exit early when that dies."""
try:
@@ -267,8 +318,10 @@ async def load_compiler(name: str) -> None:
allow_exit = trio.Event()
SERVER_INFO_FILE.unlink(missing_ok=True)
+ ARCHIVE_LOC.unlink(missing_ok=True)
try:
async with trio.open_nursery() as nursery:
+ nursery.start_soon(generate_archive)
nursery.start_soon(check_portal2_running, allow_exit)
await trio.lowlevel.checkpoint()
binds = await nursery.start(functools.partial(
diff --git a/src/user_errors.py b/src/user_errors.py
index 250a73a08..cc3e401b2 100644
--- a/src/user_errors.py
+++ b/src/user_errors.py
@@ -186,6 +186,13 @@ def __str__(self) -> str:
'in a browser on this computer to see:'
)
+# Used to format the webpage
+TOK_WEBPAGE_ARCHIVE_INFO = TransToken.ui(
+ 'If submitting a bug report, please include this map archive. It contains your level, '
+ 'the displayed preview, relevant log files and configs to help with identifying the issue. '
+)
+TOK_WEBPAGE_ARCHIVE_BTN = TransToken.ui('Open Archive Folder')
+
# Generic tokens:
TOK_INVALID_PARAM = TransToken.ui(
'Invalid {option}=
"{value}
" for {kind} "{id}"!'