Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9644de3ff5 |
@@ -1,6 +1,6 @@
|
||||
# PristonTale EU for Linux
|
||||
|
||||
Version 0.9.8 installs, updates, repairs, and launches PristonTale EU through a
|
||||
Version 0.9.11 installs, updates, repairs, and launches PristonTale EU through a
|
||||
native Linux dashboard. Game files come directly from the publisher and are not
|
||||
included in this archive.
|
||||
|
||||
@@ -15,11 +15,11 @@ Then run:
|
||||
```text
|
||||
openssl pkey -pubin -in launcher-update-public.pem -outform DER | sha256sum
|
||||
openssl dgst -sha256 -verify launcher-update-public.pem \
|
||||
-signature pristontale-eu-linux-installer-v0-9-8.tar.gz.sig \
|
||||
pristontale-eu-linux-installer-v0-9-8.tar.gz
|
||||
sha256sum -c pristontale-eu-linux-installer-v0-9-8.tar.gz.sha256
|
||||
tar -xzf pristontale-eu-linux-installer-v0-9-8.tar.gz
|
||||
cd pristontale-eu-linux-installer-v0-9-8
|
||||
-signature pristontale-eu-linux-installer-v0-9-11.tar.gz.sig \
|
||||
pristontale-eu-linux-installer-v0-9-11.tar.gz
|
||||
sha256sum -c pristontale-eu-linux-installer-v0-9-11.tar.gz.sha256
|
||||
tar -xzf pristontale-eu-linux-installer-v0-9-11.tar.gz
|
||||
cd pristontale-eu-linux-installer-v0-9-11
|
||||
./install.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -4,4 +4,4 @@ from .paths import AppPaths
|
||||
|
||||
__all__ = ["AppPaths", "__version__"]
|
||||
|
||||
__version__ = "0.9.8"
|
||||
__version__ = "0.9.11"
|
||||
|
||||
@@ -7,7 +7,6 @@ from typing import Any, Callable
|
||||
from ...paths import AppPaths
|
||||
from ...self_update import (
|
||||
LauncherRemoteHistory,
|
||||
LauncherRemoteRelease,
|
||||
LauncherUpdateCheck,
|
||||
LauncherUpdateHistory,
|
||||
inspect_launcher_update_history,
|
||||
@@ -52,6 +51,46 @@ def release_notes_preview(markdown: str | None) -> str:
|
||||
return preview
|
||||
|
||||
|
||||
def update_version_heading(
|
||||
running_version: str,
|
||||
latest_version: str,
|
||||
channel: str,
|
||||
*,
|
||||
update_available: bool,
|
||||
) -> str:
|
||||
"""Describe update versions without confusing an older channel head as current."""
|
||||
|
||||
if update_available:
|
||||
return f"Update: {running_version} → {latest_version}"
|
||||
return (
|
||||
f"Current version: {running_version}\n"
|
||||
f"Latest {channel.title()} release: {latest_version}"
|
||||
)
|
||||
|
||||
|
||||
def release_history_state(
|
||||
release_status: str,
|
||||
*,
|
||||
is_running: bool,
|
||||
local_active: bool,
|
||||
local_retained: bool,
|
||||
is_older: bool,
|
||||
) -> str:
|
||||
"""Label running and installed releases without treating them as synonymous."""
|
||||
|
||||
if is_running:
|
||||
return "Current"
|
||||
if local_active:
|
||||
return "Installed"
|
||||
if release_status != "active":
|
||||
return release_status.title()
|
||||
if local_retained:
|
||||
return "Retained locally"
|
||||
if is_older:
|
||||
return "Available rollback"
|
||||
return "Published"
|
||||
|
||||
|
||||
class LauncherUpdateDialog:
|
||||
"""Own the update window and expose small refresh/error entry points."""
|
||||
|
||||
@@ -97,6 +136,8 @@ class LauncherUpdateDialog:
|
||||
self._history: Any = None
|
||||
self._history_filter_value: Any = None
|
||||
self._history_items: dict[str, tuple[str, str, str | None, bool]] = {}
|
||||
self._release_notes_frame: Any = None
|
||||
self._release_notes_text: Any = None
|
||||
self._release_notes_button: Any = None
|
||||
self._check_button: Any = None
|
||||
self._rollback_button: Any = None
|
||||
@@ -120,7 +161,7 @@ class LauncherUpdateDialog:
|
||||
dialog.withdraw()
|
||||
self._window = dialog
|
||||
dialog.title("PristonTale EU — Launcher Updates")
|
||||
dialog.resizable(False, False)
|
||||
dialog.resizable(False, True)
|
||||
dialog.configure(background="#0c0908")
|
||||
dialog.transient(self._root)
|
||||
self._apply_window_icon(dialog)
|
||||
@@ -201,6 +242,53 @@ class LauncherUpdateDialog:
|
||||
sticky="e",
|
||||
padx=(12, 0),
|
||||
)
|
||||
self._release_notes_frame = ttk.Frame(
|
||||
overview,
|
||||
style="SettingsCard.TFrame",
|
||||
)
|
||||
self._release_notes_frame.grid(
|
||||
row=2,
|
||||
column=0,
|
||||
columnspan=2,
|
||||
sticky="ew",
|
||||
pady=(10, 0),
|
||||
)
|
||||
self._release_notes_frame.columnconfigure(0, weight=1)
|
||||
ttk.Label(
|
||||
self._release_notes_frame,
|
||||
text="WHAT'S NEW",
|
||||
style="SettingsText.TLabel",
|
||||
).grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 4))
|
||||
self._release_notes_text = tk.Text(
|
||||
self._release_notes_frame,
|
||||
name="launcher_update_release_notes",
|
||||
width=1,
|
||||
height=3,
|
||||
wrap="word",
|
||||
background="#100d0c",
|
||||
foreground="#c8b8a8",
|
||||
selectbackground="#6a482d",
|
||||
selectforeground="#ffffff",
|
||||
font=("Sans", 8),
|
||||
borderwidth=0,
|
||||
highlightthickness=0,
|
||||
padx=8,
|
||||
pady=6,
|
||||
state="disabled",
|
||||
takefocus=False,
|
||||
)
|
||||
release_notes_scrollbar = ttk.Scrollbar(
|
||||
self._release_notes_frame,
|
||||
orient="vertical",
|
||||
style="News.Vertical.TScrollbar",
|
||||
command=self._release_notes_text.yview,
|
||||
)
|
||||
self._release_notes_text.configure(
|
||||
yscrollcommand=release_notes_scrollbar.set,
|
||||
)
|
||||
self._release_notes_text.grid(row=1, column=0, sticky="ew")
|
||||
release_notes_scrollbar.grid(row=1, column=1, sticky="ns", padx=(6, 0))
|
||||
self._release_notes_frame.grid_remove()
|
||||
|
||||
history_card = ttk.LabelFrame(
|
||||
content,
|
||||
@@ -244,7 +332,7 @@ class LauncherUpdateDialog:
|
||||
history_card,
|
||||
columns=("version", "channel", "state", "installed"),
|
||||
show="headings",
|
||||
height=6,
|
||||
height=4,
|
||||
style="Update.Treeview",
|
||||
selectmode="browse",
|
||||
)
|
||||
@@ -333,8 +421,8 @@ class LauncherUpdateDialog:
|
||||
self._check_again()
|
||||
dialog.update_idletasks()
|
||||
updates_width, updates_height = fitted_window_size(
|
||||
760,
|
||||
620,
|
||||
820,
|
||||
680,
|
||||
scale=self._ui_scale,
|
||||
screen_width=dialog.winfo_screenwidth(),
|
||||
screen_height=dialog.winfo_screenheight(),
|
||||
@@ -365,6 +453,8 @@ class LauncherUpdateDialog:
|
||||
assert self._status_value is not None
|
||||
assert self._details_value is not None
|
||||
assert self._history is not None
|
||||
assert self._release_notes_frame is not None
|
||||
assert self._release_notes_text is not None
|
||||
assert self._release_notes_button is not None
|
||||
assert self._check_button is not None
|
||||
assert self._rollback_button is not None
|
||||
@@ -381,10 +471,11 @@ class LauncherUpdateDialog:
|
||||
if check is None:
|
||||
self._status_value.set("Checking the signed update channel…")
|
||||
self._details_value.set(
|
||||
"Installed launcher "
|
||||
"Running launcher "
|
||||
+ self._launcher_version
|
||||
+ " · release information pending"
|
||||
)
|
||||
self._set_release_notes_preview("")
|
||||
self._install_button.configure(state="disabled")
|
||||
self._refresh_history_actions(busy=busy)
|
||||
return
|
||||
@@ -400,13 +491,14 @@ class LauncherUpdateDialog:
|
||||
for release in (
|
||||
remote_history.releases if remote_history is not None else ()
|
||||
)
|
||||
if release.version == check.current_version and release.status != "active"
|
||||
if release.version == self._launcher_version
|
||||
and release.status != "active"
|
||||
),
|
||||
None,
|
||||
)
|
||||
if installed_status is not None:
|
||||
status_prefix += (
|
||||
f"Warning: installed launcher {check.current_version} is "
|
||||
f"Warning: running launcher {self._launcher_version} is "
|
||||
f"{installed_status}; install the next active eligible release.\n"
|
||||
)
|
||||
self._status_value.set(status_prefix + check.reason)
|
||||
@@ -418,18 +510,24 @@ class LauncherUpdateDialog:
|
||||
if check.manifest.channel == "prerelease"
|
||||
else ""
|
||||
)
|
||||
summary_line = f"{release_summary}\n" if not notes_preview else ""
|
||||
version_line = update_version_heading(
|
||||
self._launcher_version,
|
||||
check.latest_version,
|
||||
check.manifest.channel,
|
||||
update_available=check.available,
|
||||
)
|
||||
details = (
|
||||
f"{check.current_version} → {check.latest_version}\n"
|
||||
f"{version_line}\n"
|
||||
f"{release_title}{prerelease_label}\n"
|
||||
f"{release_summary}\n"
|
||||
f"{summary_line}"
|
||||
f"Channel: {check.manifest.channel.title()} · "
|
||||
f"{format_bytes(check.manifest.archive_size)} · "
|
||||
f"published {check.manifest.published_at} · "
|
||||
f"checked {check.checked_at or 'time unavailable'}"
|
||||
)
|
||||
if notes_preview:
|
||||
details += f"\n\nWhat's new:\n{notes_preview}"
|
||||
self._details_value.set(details)
|
||||
self._set_release_notes_preview(notes_preview)
|
||||
self._install_button.configure(
|
||||
state=(
|
||||
"normal"
|
||||
@@ -442,6 +540,20 @@ class LauncherUpdateDialog:
|
||||
)
|
||||
self._refresh_history_actions(busy=busy)
|
||||
|
||||
def _set_release_notes_preview(self, preview: str) -> None:
|
||||
assert self._release_notes_frame is not None
|
||||
assert self._release_notes_text is not None
|
||||
self._release_notes_text.configure(state="normal")
|
||||
self._release_notes_text.delete("1.0", "end")
|
||||
if preview:
|
||||
self._release_notes_text.insert("1.0", preview)
|
||||
self._release_notes_text.configure(state="disabled")
|
||||
self._release_notes_text.yview_moveto(0.0)
|
||||
if preview:
|
||||
self._release_notes_frame.grid()
|
||||
else:
|
||||
self._release_notes_frame.grid_remove()
|
||||
|
||||
def _populate_history(self, *, busy: bool) -> None:
|
||||
assert self._history is not None
|
||||
assert self._history_filter_value is not None
|
||||
@@ -461,16 +573,22 @@ class LauncherUpdateDialog:
|
||||
else ()
|
||||
)
|
||||
}
|
||||
current_version = (
|
||||
installed_current_version = (
|
||||
self._installed_history.current_version
|
||||
if self._installed_history is not None
|
||||
and self._installed_history.current_version is not None
|
||||
else self._launcher_version
|
||||
)
|
||||
try:
|
||||
current_semantic = SemanticVersion.parse(current_version)
|
||||
installed_current_semantic = SemanticVersion.parse(
|
||||
installed_current_version
|
||||
)
|
||||
except ReleaseModelError:
|
||||
current_semantic = None
|
||||
installed_current_semantic = None
|
||||
try:
|
||||
running_channel = SemanticVersion.parse(self._launcher_version).channel
|
||||
except ReleaseModelError:
|
||||
running_channel = "unknown"
|
||||
filter_name = str(self._history_filter_value.get()).casefold()
|
||||
|
||||
def channel_visible(channel: str) -> bool:
|
||||
@@ -478,20 +596,27 @@ class LauncherUpdateDialog:
|
||||
|
||||
remote_history = self._get_remote_history()
|
||||
remote_versions: set[str] = set()
|
||||
displayed_versions: set[str] = set()
|
||||
if remote_history is not None:
|
||||
for index, release in enumerate(remote_history.releases):
|
||||
if not channel_visible(release.channel):
|
||||
continue
|
||||
remote_versions.add(release.version)
|
||||
displayed_versions.add(release.version)
|
||||
local = installed.get(release.version)
|
||||
is_older = (
|
||||
current_semantic is not None
|
||||
and SemanticVersion.parse(release.version) < current_semantic
|
||||
installed_current_semantic is not None
|
||||
and SemanticVersion.parse(release.version)
|
||||
< installed_current_semantic
|
||||
)
|
||||
can_rollback = release.status == "active" and is_older
|
||||
state = self._remote_release_state(
|
||||
release,
|
||||
local_active=bool(local is not None and local.active),
|
||||
local_active = bool(local is not None and local.active)
|
||||
can_rollback = (
|
||||
release.status == "active" and is_older and not local_active
|
||||
)
|
||||
state = release_history_state(
|
||||
release.status,
|
||||
is_running=release.version == self._launcher_version,
|
||||
local_active=local_active,
|
||||
local_retained=local is not None,
|
||||
is_older=is_older,
|
||||
)
|
||||
@@ -517,14 +642,23 @@ class LauncherUpdateDialog:
|
||||
for index, release in enumerate(self._installed_history.releases):
|
||||
if release.version in remote_versions or not channel_visible(release.channel):
|
||||
continue
|
||||
displayed_versions.add(release.version)
|
||||
try:
|
||||
is_older = (
|
||||
current_semantic is not None
|
||||
and SemanticVersion.parse(release.version) < current_semantic
|
||||
installed_current_semantic is not None
|
||||
and SemanticVersion.parse(release.version)
|
||||
< installed_current_semantic
|
||||
)
|
||||
except ReleaseModelError:
|
||||
is_older = False
|
||||
state = "Current" if release.active else "Retained locally"
|
||||
state = release_history_state(
|
||||
"active",
|
||||
is_running=release.version == self._launcher_version,
|
||||
local_active=release.active,
|
||||
local_retained=True,
|
||||
is_older=is_older,
|
||||
)
|
||||
can_rollback = is_older and not release.active
|
||||
iid = f"local:{index}:{release.version}"
|
||||
self._history.insert(
|
||||
"",
|
||||
@@ -541,7 +675,29 @@ class LauncherUpdateDialog:
|
||||
release.version,
|
||||
release.channel,
|
||||
None,
|
||||
is_older,
|
||||
can_rollback,
|
||||
)
|
||||
if (
|
||||
self._launcher_version not in displayed_versions
|
||||
and channel_visible(running_channel)
|
||||
):
|
||||
iid = f"running:{self._launcher_version}"
|
||||
self._history.insert(
|
||||
"",
|
||||
0,
|
||||
iid=iid,
|
||||
values=(
|
||||
self._launcher_version,
|
||||
running_channel.title(),
|
||||
"Current",
|
||||
"Running now",
|
||||
),
|
||||
)
|
||||
self._history_items[iid] = (
|
||||
self._launcher_version,
|
||||
running_channel,
|
||||
None,
|
||||
False,
|
||||
)
|
||||
if not self._history.get_children():
|
||||
iid = "placeholder"
|
||||
@@ -567,24 +723,6 @@ class LauncherUpdateDialog:
|
||||
self._history.focus(selected_iid)
|
||||
self._refresh_history_actions(busy=busy)
|
||||
|
||||
@staticmethod
|
||||
def _remote_release_state(
|
||||
release: LauncherRemoteRelease,
|
||||
*,
|
||||
local_active: bool,
|
||||
local_retained: bool,
|
||||
is_older: bool,
|
||||
) -> str:
|
||||
if local_active:
|
||||
return "Current"
|
||||
if release.status != "active":
|
||||
return release.status.title()
|
||||
if local_retained:
|
||||
return "Retained locally"
|
||||
if is_older:
|
||||
return "Available rollback"
|
||||
return "Published"
|
||||
|
||||
def _history_selected(self, _event: object | None = None) -> None:
|
||||
self._refresh_history_actions(busy=self._is_busy())
|
||||
|
||||
@@ -621,6 +759,7 @@ class LauncherUpdateDialog:
|
||||
assert self._check_button is not None
|
||||
self._status_value.set("The signed update channel could not be checked.")
|
||||
self._details_value.set(message)
|
||||
self._set_release_notes_preview("")
|
||||
self._check_button.configure(state="normal")
|
||||
|
||||
def _check_again(self) -> None:
|
||||
@@ -630,6 +769,7 @@ class LauncherUpdateDialog:
|
||||
assert self._install_button is not None
|
||||
self._status_value.set("Checking the signed update channel…")
|
||||
self._details_value.set("Authenticating the selected channel manifests and signatures.")
|
||||
self._set_release_notes_preview("")
|
||||
self._check_button.configure(state="disabled")
|
||||
self._install_button.configure(state="disabled")
|
||||
self._request_check()
|
||||
@@ -637,8 +777,9 @@ class LauncherUpdateDialog:
|
||||
def _view_release_notes(self) -> None:
|
||||
selected = self._selected_history_item()
|
||||
if selected is not None:
|
||||
if selected[2] is not None:
|
||||
self._open_article(selected[2])
|
||||
notes_url = selected[2]
|
||||
if notes_url is not None:
|
||||
self._open_article(notes_url)
|
||||
return
|
||||
check = self._get_check()
|
||||
if check is not None and check.manifest.notes_url is not None:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PTEU-Linux-Launcher"
|
||||
version = "0.9.8"
|
||||
version = "0.9.11"
|
||||
description = "PristonTale EU Linux installer, clean launcher, and diagnostic harness"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = []
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
"application": "PristonTale-EU",
|
||||
"archive": {
|
||||
"layout": "wrapped",
|
||||
"name": "PristonTale-EU-0.9.10.tar.gz",
|
||||
"sha256": "76df8942d2f0b3b533eb967f8a2379b2a7bdd44fd58305d0f8bf061778fbd9ea",
|
||||
"size": 1473687,
|
||||
"url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/download/v0.9.10/PristonTale-EU-0.9.10.tar.gz"
|
||||
"name": "PristonTale-EU-0.9.11.tar.gz",
|
||||
"sha256": "60b13d6fbc8fe27714c7fe1a65fa73785a13962d96d03decfac1aa62c4e3f6db",
|
||||
"size": 1474010,
|
||||
"url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/download/v0.9.11/PristonTale-EU-0.9.11.tar.gz"
|
||||
},
|
||||
"archive_sha256": "76df8942d2f0b3b533eb967f8a2379b2a7bdd44fd58305d0f8bf061778fbd9ea",
|
||||
"archive_size": 1473687,
|
||||
"archive_url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/download/v0.9.10/PristonTale-EU-0.9.10.tar.gz",
|
||||
"archive_sha256": "60b13d6fbc8fe27714c7fe1a65fa73785a13962d96d03decfac1aa62c4e3f6db",
|
||||
"archive_size": 1474010,
|
||||
"archive_url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/download/v0.9.11/PristonTale-EU-0.9.11.tar.gz",
|
||||
"channel": "stable",
|
||||
"commit": "27ed039f327d4d14d1d04717e0fd4f20ad7b7dc9",
|
||||
"commit": "a362b0bb8e2bf74db9075c5f58db5236b1dc98f6",
|
||||
"compatibility": {
|
||||
"config_schema": 1,
|
||||
"manifest_schema": 1,
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
{
|
||||
"path": "ptlinux/__init__.py",
|
||||
"sha256": "a80db24319120aa083e8abf0e099bacc8958bc04e59a2ac17ee270ae0f7094a3",
|
||||
"sha256": "b4eaa89165a506ff593083dd32ad30fefe1d8ec7d09af67b45b29a3d13599df0",
|
||||
"size": 152
|
||||
},
|
||||
{
|
||||
@@ -306,8 +306,8 @@
|
||||
},
|
||||
{
|
||||
"path": "ptlinux/ui/components/update_dialog.py",
|
||||
"sha256": "af5775b07b6872b5e5f465deb8d9f583ddfeeae1df79a126fb2d2fe967bb3d06",
|
||||
"size": 22005
|
||||
"sha256": "1defc85b4cf30f15fa1c30bcfd0cbf961072ba2d2ab8a681ef981e34ef3598d4",
|
||||
"size": 24138
|
||||
},
|
||||
{
|
||||
"path": "ptlinux/ui/dashboard.py",
|
||||
@@ -371,21 +371,21 @@
|
||||
},
|
||||
{
|
||||
"path": "release.json",
|
||||
"sha256": "e1c3a4501457050f00ed98d254b83521f173bccb91cb6176bff2ca89aab99adc",
|
||||
"sha256": "afc50744e1d2cd13c3062b6160cd21a0b25870da81270b75b0a35940ca33b23b",
|
||||
"size": 223
|
||||
}
|
||||
],
|
||||
"minimum_updater_version": "0.5.0",
|
||||
"notes_url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/tag/v0.9.10",
|
||||
"published_at": "2026-09-09T21:01:49Z",
|
||||
"notes_url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/tag/v0.9.11",
|
||||
"published_at": "2026-09-09T21:12:47Z",
|
||||
"release": {
|
||||
"notes_markdown": "# PristonTale EU Launcher 0.9.10\n\nRestores automatic updates for existing launchers and completes the transition to flat release archives.\n\n## Changes\n\n- Updated to new release v0.9.9 (`27ed039`)\n- Added better support for kubuntu and fixed some issues with telemetry. (`290d1a5`)\n- Updated diagnostic message. (`6e62191`)\n- Updated the update system to support multi channels (stable / pre-release). (`5770969`)\n- Released a new version, 0.9.8. (`2a53a59`)\n- Fixed more issues with Cinnamon window resizing and popups. (`76bef94`)\n- Fixed issues with telemetry. (`1a120bb`)\n- Released new stable version 0.9.7. (`108ea94`)\n- Added a fix for X11 / Cinnamon window popups and maximize button not visible. (`1cfe862`)\n- Added telemetry system to get information about issues. (`f06fc2e`)\n- Upload files to \"updates\" (`a1ff479`)\n- Delete updates/stable.json.sig (`6eea3b2`)\n- Update updates/stable.json (`ee9bb06`)\n- Fixed issues with gamescope not properly launching. (`bea9d6f`)\n\n---\n\nVersion: `0.9.10` \nChannel: `stable` \nTag: `v0.9.10` \nSource commit: `27ed039f327d4d14d1d04717e0fd4f20ad7b7dc9`\n",
|
||||
"release_notes_url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/tag/v0.9.10",
|
||||
"summary": "Restores automatic updates for existing launchers and completes the transition to flat release archives.",
|
||||
"title": "PristonTale EU Launcher 0.9.10"
|
||||
"notes_markdown": "# PristonTale EU Launcher 0.9.11\n\nFixes the update window layout so release notes no longer cover version history or controls.\n\n---\n\nVersion: `0.9.11` \nChannel: `stable` \nTag: `v0.9.11` \nSource commit: `a362b0bb8e2bf74db9075c5f58db5236b1dc98f6`\n",
|
||||
"release_notes_url": "https://git.m4ko.net/m4ko/pristontale-eu-linux/releases/tag/v0.9.11",
|
||||
"summary": "Fixes the update window layout so release notes no longer cover version history or controls.",
|
||||
"title": "PristonTale EU Launcher 0.9.11"
|
||||
},
|
||||
"schema": 1,
|
||||
"status": "active",
|
||||
"tag": "v0.9.10",
|
||||
"version": "0.9.10"
|
||||
"tag": "v0.9.11",
|
||||
"version": "0.9.11"
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user