Skip to content

Commit

Permalink
0.2.0 - Add mod loader self updater
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryhon0 committed Oct 11, 2024
1 parent 4fcf904 commit 1011a1c
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 45 deletions.
106 changes: 106 additions & 0 deletions Injector/AutoUpdater.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
extends Node
class_name AutoUpdater

@export var Main : InjectorMain

func _ready() -> void:
pass

func checkInjectorUpdate():
var deletemePath = ProjectSettings.globalize_path(".").path_join("Injector.pck.deleteme")
if FileAccess.file_exists(deletemePath):
DirAccess.remove_absolute(deletemePath)

var httpReq = HTTPRequest.new()
add_child(httpReq)
var err = httpReq.request(Main.githubAPIBaseURL + "repos/Ryhon0/VostokMods/releases", ["accept: application/vnd.github+json"])
if err != OK:
push_error("Failed to create mod loader releases request ", err)
Main.launchOrShowConfig()
return

Main.StatusLabel.text = "Checking for updates"
Main.showHttpProgress(httpReq)

httpReq.request_completed.connect(injectorReleasesRequestCompleted)

func injectorReleasesRequestCompleted(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray):
if result != HTTPRequest.RESULT_SUCCESS:
push_error("Failed to get mod loader releases")
Main.launchOrShowConfig()
return
if response_code < 200 || response_code >= 300:
push_error("Failed to get mod loader releases (HTTP code " + str(response_code) + ")")
Main.launchOrShowConfig()
return

var json = JSON.parse_string(body.get_string_from_utf8())
for r in json:
if r["draft"]: continue
if r["prerelease"] && !Main.config.autoUpdatePreRelease:
continue
var tag = r["tag_name"]

var injectorAsset
for a in r["assets"]:
if a["name"] == "Injector.pck":
injectorAsset = a
break
if !injectorAsset:
continue

print("Latest version: " + tag)
if Main.version != tag:
downloadLoaderUpdate(tag, injectorAsset)
else: Main.launchOrShowConfig()
return

func downloadLoaderUpdate(tag, asset):
var httpReq = HTTPRequest.new()
add_child(httpReq)
var err = httpReq.request(asset["browser_download_url"])
if err != OK:
Main.StatusLabel.text = "Failed to download mod loader update.\nCode " + str(err)
get_tree().create_timer(2).timeout.connect(Main.launchOrShowConfig)
return

Main.StatusLabel.text = "Downloading mod loader version " + tag
Main.showHttpProgress(httpReq)

httpReq.request_completed.connect(injectorFileDownloaded)

func injectorFileDownloaded(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray):
if result != HTTPRequest.RESULT_SUCCESS:
push_error("Failed to download mod loader")
Main.StatusLabel.text = "Failed to save mod loader, error " + str(FileAccess.get_open_error())
get_tree().create_timer(2).timeout.connect(Main.launchOrShowConfig)
return
if response_code < 200 || response_code >= 300:
push_error("Failed to get mod loader releases (HTTP code " + str(response_code) + ")")
Main.StatusLabel.text = "Failed to save mod loader, error " + str(FileAccess.get_open_error())
get_tree().create_timer(2).timeout.connect(Main.launchOrShowConfig)
return

var dir = ProjectSettings.globalize_path(".")
var injectorPath = dir.path_join("Injector.pck")
var deletemePath = dir.path_join("Injector.pck.deleteme")

var err = DirAccess.rename_absolute(injectorPath, deletemePath)
if err != OK:
Main.StatusLabel.text = "Failed to move moad loader, error " + str(err)
get_tree().create_timer(2).timeout.connect(Main.launchOrShowConfig)
return

var f = FileAccess.open(injectorPath, FileAccess.WRITE)
if !f:
DirAccess.rename_absolute(deletemePath, injectorPath)
Main.StatusLabel.text = "Failed to save mod loader, error " + str(FileAccess.get_open_error())
get_tree().create_timer(2).timeout.connect(Main.launchOrShowConfig)
return
f.store_buffer(body)
f.close()

var args = ["--main-pack", "Injector.pck", "--"]
args.append(OS.get_cmdline_user_args())
OS.create_process(OS.get_executable_path(), args, false)
get_tree().quit()
24 changes: 20 additions & 4 deletions Injector/Main.gd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
extends Control
class_name InjectorMain

@export var VersionLabel : Label
@export var StatusLabel: Label
Expand All @@ -8,12 +9,16 @@ extends Control
@export var ConfigScreen : Control

@export var SettingsPage : Control
@export var ModList : Control
@export var Mods : ModList
@export var Updater : AutoUpdater

var version

const configPath = "user://ModConfig.json"
class ModLoaderConfig:
var customModDir : String = ""
var startOnConfigScreen : bool = false
var autoUpdatePreRelease : bool = false
var config : ModLoaderConfig = ModLoaderConfig.new()

func loadConfig():
Expand All @@ -27,13 +32,16 @@ func loadConfig():
config.customModDir = obj["customModDir"]
if "startOnConfigScreen" in obj:
config.startOnConfigScreen = obj["startOnConfigScreen"]
if "autoUpdatePreRelease" in obj:
config.autoUpdatePreRelease = obj["autoUpdatePreRelease"]

SettingsPage.onLoaded()

func saveConfig():
var jarr = {
"customModDir": config.customModDir,
"startOnConfigScreen": config.startOnConfigScreen
"startOnConfigScreen": config.startOnConfigScreen,
"autoUpdatePreRelease": config.autoUpdatePreRelease
}
var jstr = JSON.stringify(jarr)
var f = FileAccess.open(configPath, FileAccess.WRITE)
Expand Down Expand Up @@ -88,9 +96,17 @@ func _ready() -> void:
loadConfig()

var f = FileAccess.open("res://VM_VERSION", FileAccess.READ)
VersionLabel.text = "Version " + f.get_as_text()
version = f.get_as_text()
VersionLabel.text = "Version " + version
f.close()

Mods.loadMods()
showLoadingScreen()
if !OS.has_feature("editor"):
Updater.checkInjectorUpdate()
else: launchOrShowConfig()

func launchOrShowConfig():
if config.startOnConfigScreen:
showConfigScreen()
else:
Expand Down Expand Up @@ -190,7 +206,7 @@ Update the injector or verify game files"
var args = ["--main-pack", pckdir, "--", "--mods-dir", modsDir]
args.append(OS.get_cmdline_user_args())

var pid = OS.create_process(OS.get_executable_path(), args, true)
var pid = OS.create_process(OS.get_executable_path(), args, false)
if pid == -1:
StatusLabel.text = "Failed to start Road to Vostok"
shutdown()
Expand Down
13 changes: 10 additions & 3 deletions Injector/Main.tscn
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
[gd_scene load_steps=6 format=3 uid="uid://b6nywv6aqxm3r"]
[gd_scene load_steps=7 format=3 uid="uid://b6nywv6aqxm3r"]

[ext_resource type="Script" path="res://Main.gd" id="1_x5slr"]
[ext_resource type="Texture2D" uid="uid://wbaqykif8euy" path="res://icon.svg" id="2_74yqq"]
[ext_resource type="Script" path="res://Settings.gd" id="2_b0jil"]
[ext_resource type="Script" path="res://ModList.gd" id="3_xyy35"]
[ext_resource type="Texture2D" uid="uid://bcc6fhil26kqe" path="res://donate_icon.png" id="5_r2nj5"]
[ext_resource type="Script" path="res://AutoUpdater.gd" id="6_etu4i"]

[node name="Main" type="Control" node_paths=PackedStringArray("VersionLabel", "StatusLabel", "Progress", "LoadingScreen", "ConfigScreen", "SettingsPage", "ModList")]
[node name="Main" type="Control" node_paths=PackedStringArray("VersionLabel", "StatusLabel", "Progress", "LoadingScreen", "ConfigScreen", "SettingsPage", "Mods", "Updater")]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
Expand All @@ -20,7 +21,8 @@ Progress = NodePath("LoadingScreen/VBoxContainer/Progress")
LoadingScreen = NodePath("LoadingScreen")
ConfigScreen = NodePath("ConfigScreen")
SettingsPage = NodePath("ConfigScreen/TabContainer/Settings")
ModList = NodePath("ConfigScreen/TabContainer/Mods")
Mods = NodePath("ConfigScreen/TabContainer/Mods")
Updater = NodePath("AutoUpdater")

[node name="LoadingScreen" type="CenterContainer" parent="."]
visible = false
Expand All @@ -46,6 +48,7 @@ layout_mode = 2
max_value = 1.0

[node name="ConfigScreen" type="HBoxContainer" parent="."]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
Expand Down Expand Up @@ -202,6 +205,10 @@ layout_mode = 2
theme_override_font_sizes/font_size = 24
text = "Launch"

[node name="AutoUpdater" type="Node" parent="." node_paths=PackedStringArray("Main")]
script = ExtResource("6_etu4i")
Main = NodePath("..")

[connection signal="tab_changed" from="ConfigScreen/TabContainer" to="ConfigScreen/TabContainer/Mods" method="tabChanged"]
[connection signal="pressed" from="ConfigScreen/TabContainer/Settings/VBoxContainer/GridContainer/HBoxContainer/Button" to="ConfigScreen/TabContainer/Settings" method="openModDirDialog"]
[connection signal="column_title_clicked" from="ConfigScreen/TabContainer/Mods/ModListTree" to="ConfigScreen/TabContainer/Mods" method="titleClicked"]
Expand Down
65 changes: 34 additions & 31 deletions Injector/ModList.gd
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
extends ScrollContainer
class_name ModList

@export var Main : Control
@export var List : Tree
var dirty : bool = true
@export var Main: Control
@export var List: Tree
var mods : Array[ModInfo] = []

class ModInfo:
var zipPath : String
var config : ConfigFile

func _ready():
List.set_column_title(0,"Name")
List.set_column_title(1,"ID")
List.set_column_title(2,"Version")
List.set_column_title(3,"File name")
List.set_column_title(4,"Enabled")
List.set_column_title(0, "Name")
List.set_column_title(1, "ID")
List.set_column_title(2, "Version")
List.set_column_title(3, "File name")
List.set_column_title(4, "Enabled")

for i in range(List.columns):
List.set_column_expand(i,false)
List.set_column_expand(i, false)

List.set_column_expand(0,true)
List.set_column_expand(0, true)
List.set_column_custom_minimum_width(1, 175)
List.set_column_custom_minimum_width(3, 175)

func populateList():
func loadMods():
mods = []
var modsdir = Main.getModsDir()
dirty = false

List.clear()
List.create_item()
Expand Down Expand Up @@ -54,9 +59,14 @@ func populateList():
if !cfg.has_section_key("mod", "name") || !cfg.has_section_key("mod", "id") || !cfg.has_section_key("mod", "version"):
continue

var modname = cfg.get_value("mod","name")
var modid = cfg.get_value("mod","id")
var modver = cfg.get_value("mod","version")
var modname = cfg.get_value("mod", "name")
var modid = cfg.get_value("mod", "id")
var modver = cfg.get_value("mod", "version")

var modi = ModInfo.new()
modi.config = cfg
modi.zipPath = modsdir.path_join(zipname)
mods.append(modi)

var li = List.create_item()
li.set_meta("filename", zipname)
Expand All @@ -65,22 +75,16 @@ func populateList():
li.set_text(1, modid)
li.set_text(2, modver)
li.set_text(3, zipname)
li.set_cell_mode(List.columns-1, TreeItem.CELL_MODE_CHECK)
li.set_checked(List.columns-1, !disabled)
li.set_editable(List.columns-1, true)

func tabChanged(idx: int):
if idx == get_index():
if dirty:
populateList()
dirty = false
li.set_cell_mode(List.columns - 1, TreeItem.CELL_MODE_CHECK)
li.set_checked(List.columns - 1, !disabled)
li.set_editable(List.columns - 1, true)

func itemEdited() -> void:
if List.get_edited_column() != List.columns-1:
if List.get_edited_column() != List.columns - 1:
return

var item : TreeItem = List.get_edited()
var disabled = item.is_checked(List.columns-1)
var item: TreeItem = List.get_edited()
var disabled = item.is_checked(List.columns - 1)
var file = Main.getModsDir().path_join(item.get_meta("filename"))

var from = file + ".zip"
Expand All @@ -89,10 +93,10 @@ func itemEdited() -> void:
else: to += ".disabled"


if DirAccess.rename_absolute(from,to) != OK:
if DirAccess.rename_absolute(from, to) != OK:
OS.alert("Could not move file " + from)

func titleClicked(col : int, mouse : int) -> void:
func titleClicked(col: int, mouse: int) -> void:
if mouse != MOUSE_BUTTON_LEFT:
return

Expand All @@ -101,7 +105,7 @@ func titleClicked(col : int, mouse : int) -> void:
for i in items:
root.remove_child(i)

items.sort_custom(func (a:TreeItem,b : TreeItem) -> bool:
items.sort_custom(func(a: TreeItem, b: TreeItem) -> bool:
if a.get_cell_mode(col) == TreeItem.CELL_MODE_STRING:
return a.get_text(col).naturalnocasecmp_to(b.get_text(col)) < 0

Expand All @@ -111,4 +115,3 @@ func titleClicked(col : int, mouse : int) -> void:

for i in items:
root.add_child(i)

12 changes: 6 additions & 6 deletions Injector/Settings.gd
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
extends Control

@export var Main : Control
@export var CustomModDirLine : LineEdit
@export var StartOnConfigCheckBox : CheckBox
@export var Main: Control
@export var CustomModDirLine: LineEdit
@export var StartOnConfigCheckBox: CheckBox

func _ready() -> void:
CustomModDirLine.text_changed.connect(func(val): Main.config.customModDir = val; Main.ModList.dirty = true)
CustomModDirLine.text_changed.connect(func(val): Main.config.customModDir = val; Main.Mods.loadMods())
StartOnConfigCheckBox.toggled.connect(func(val): Main.config.startOnConfigScreen = val)

func openModDirDialog():
var fd = FileDialog.new()
fd.access = FileDialog.ACCESS_FILESYSTEM
fd.file_mode = FileDialog.FILE_MODE_OPEN_DIR
fd.show_hidden_files = true
fd.dir_selected.connect(func(dir): CustomModDirLine.text = dir; Main.config.customModDir = dir; Main.ModList.dirty = true)
fd.dir_selected.connect(func(dir): CustomModDirLine.text = dir; Main.config.customModDir = dir; Main.Mods.loadMods())
add_child(fd)
fd.popup_centered_ratio()

func onLoaded():
CustomModDirLine.text = Main.config.customModDir
StartOnConfigCheckBox.button_pressed = Main.config.startOnConfigScreen
StartOnConfigCheckBox.button_pressed = Main.config.startOnConfigScreen
2 changes: 1 addition & 1 deletion Injector/VM_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.1
0.2.0

0 comments on commit 1011a1c

Please sign in to comment.