mirror of
https://github.com/open-goal/launcher.git
synced 2024-10-20 04:57:38 -04:00
Update launcher to support up-coming new texture_replacement format (#494)
Didn't bother trying to make this backwards compatible, texture packs will need to update, and users will need to update the launcher and tooling to the latest version. It would be too annoying to make this fully non-breaking (ie. people update their tooling but not the launcher or vise-versa). Not worth the effort. Release once 0.2.13 is out, this has been tested end-to-end: ![Screenshot 2024-05-30 212348](https://github.com/open-goal/launcher/assets/13153231/2765059a-c414-4f1b-bbfb-0a8470907bac) ![Screenshot 2024-05-30 212539](https://github.com/open-goal/launcher/assets/13153231/62346158-f498-4793-8cb8-c2529722e495) ![Screenshot 2024-05-30 212402](https://github.com/open-goal/launcher/assets/13153231/f6df5a8f-d807-4960-b10a-362837fed514)
This commit is contained in:
parent
45e8b8311d
commit
4e09bc805a
|
@ -472,3 +472,32 @@ pub async fn get_playtime(
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn does_active_tooling_version_meet_minimum(
|
||||||
|
config: tauri::State<'_, tokio::sync::Mutex<LauncherConfig>>,
|
||||||
|
minimum_patch: u64,
|
||||||
|
minimum_minor: u64,
|
||||||
|
minimum_major: u64,
|
||||||
|
) -> Result<bool, CommandError> {
|
||||||
|
let config_lock = config.lock().await;
|
||||||
|
match &config_lock.active_version {
|
||||||
|
Some(version) => {
|
||||||
|
// If we can't determine the version, assume 0,0,0
|
||||||
|
let tooling_version = Version::parse(version.strip_prefix('v').unwrap_or(&version))
|
||||||
|
.unwrap_or(Version::new(0, 0, 0));
|
||||||
|
if tooling_version.patch >= minimum_patch
|
||||||
|
&& tooling_version.minor >= minimum_minor
|
||||||
|
&& tooling_version.major >= minimum_major
|
||||||
|
{
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
log::warn!("No active tooling version set, can't check if the minimum!");
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ pub async fn list_extracted_texture_pack_info(
|
||||||
let mut file_list = Vec::new();
|
let mut file_list = Vec::new();
|
||||||
for entry in glob::glob(
|
for entry in glob::glob(
|
||||||
&entry_path
|
&entry_path
|
||||||
|
.join("custom_assets")
|
||||||
|
.join(&game_name)
|
||||||
.join("texture_replacements/**/*.png")
|
.join("texture_replacements/**/*.png")
|
||||||
.to_string_lossy(),
|
.to_string_lossy(),
|
||||||
)
|
)
|
||||||
|
@ -96,7 +98,12 @@ pub async fn list_extracted_texture_pack_info(
|
||||||
match entry {
|
match entry {
|
||||||
Ok(path) => {
|
Ok(path) => {
|
||||||
let relative_path = path
|
let relative_path = path
|
||||||
.strip_prefix(&entry_path.join("texture_replacements"))
|
.strip_prefix(
|
||||||
|
&entry_path
|
||||||
|
.join("custom_assets")
|
||||||
|
.join(&game_name)
|
||||||
|
.join("texture_replacements"),
|
||||||
|
)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
CommandError::GameFeatures(format!(
|
CommandError::GameFeatures(format!(
|
||||||
"Unable to read texture packs from {}",
|
"Unable to read texture packs from {}",
|
||||||
|
@ -178,7 +185,7 @@ pub async fn extract_new_texture_pack(
|
||||||
Some(path) => Path::new(path),
|
Some(path) => Path::new(path),
|
||||||
};
|
};
|
||||||
|
|
||||||
// First, we'll check the zip file to make sure it has a `texture_replacements` folder before extracting
|
// First, we'll check the zip file to make sure it has a `custom_assets/<game>/texture_replacements` folder before extracting
|
||||||
let zip_path_buf = PathBuf::from(zip_path);
|
let zip_path_buf = PathBuf::from(zip_path);
|
||||||
let texture_pack_name = match zip_path_buf.file_stem() {
|
let texture_pack_name = match zip_path_buf.file_stem() {
|
||||||
Some(name) => name.to_string_lossy().to_string(),
|
Some(name) => name.to_string_lossy().to_string(),
|
||||||
|
@ -188,15 +195,18 @@ pub async fn extract_new_texture_pack(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let expected_top_level_dir = format!("custom_assets/{}/texture_replacements", &game_name);
|
||||||
let valid_zip =
|
let valid_zip =
|
||||||
check_if_zip_contains_top_level_dir(&zip_path_buf, "texture_replacements".to_string())
|
check_if_zip_contains_top_level_dir(&zip_path_buf, expected_top_level_dir.clone()).map_err(
|
||||||
.map_err(|err| {
|
|err| {
|
||||||
log::error!("Unable to read texture replacement zip file: {}", err);
|
log::error!("Unable to read texture replacement zip file: {}", err);
|
||||||
CommandError::GameFeatures(format!("Unable to read texture replacement pack: {}", err))
|
CommandError::GameFeatures(format!("Unable to read texture replacement pack: {}", err))
|
||||||
})?;
|
},
|
||||||
|
)?;
|
||||||
if !valid_zip {
|
if !valid_zip {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Invalid texture pack, no top-level `texture_replacements` folder: {}",
|
"Invalid texture pack, no top-level `{}` folder in: {}",
|
||||||
|
&expected_top_level_dir,
|
||||||
zip_path_buf.display()
|
zip_path_buf.display()
|
||||||
);
|
);
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
|
@ -250,6 +260,8 @@ pub async fn update_texture_pack_data(
|
||||||
.join("active")
|
.join("active")
|
||||||
.join(&game_name)
|
.join(&game_name)
|
||||||
.join("data")
|
.join("data")
|
||||||
|
.join("custom_assets")
|
||||||
|
.join(&game_name)
|
||||||
.join("texture_replacements");
|
.join("texture_replacements");
|
||||||
// Reset texture replacement directory
|
// Reset texture replacement directory
|
||||||
delete_dir(&game_texture_pack_dir)?;
|
delete_dir(&game_texture_pack_dir)?;
|
||||||
|
@ -264,6 +276,8 @@ pub async fn update_texture_pack_data(
|
||||||
.join(&game_name)
|
.join(&game_name)
|
||||||
.join("texture-packs")
|
.join("texture-packs")
|
||||||
.join(&pack)
|
.join(&pack)
|
||||||
|
.join("custom_assets")
|
||||||
|
.join(&game_name)
|
||||||
.join("texture_replacements");
|
.join("texture_replacements");
|
||||||
log::info!("Appending textures from: {}", texture_pack_dir.display());
|
log::info!("Appending textures from: {}", texture_pack_dir.display());
|
||||||
match overwrite_dir(&texture_pack_dir, &game_texture_pack_dir) {
|
match overwrite_dir(&texture_pack_dir, &game_texture_pack_dir) {
|
||||||
|
|
|
@ -161,6 +161,7 @@ fn main() {
|
||||||
commands::config::get_installed_version,
|
commands::config::get_installed_version,
|
||||||
commands::config::get_locale,
|
commands::config::get_locale,
|
||||||
commands::config::get_playtime,
|
commands::config::get_playtime,
|
||||||
|
commands::config::does_active_tooling_version_meet_minimum,
|
||||||
commands::config::has_old_data_directory,
|
commands::config::has_old_data_directory,
|
||||||
commands::config::is_avx_requirement_met,
|
commands::config::is_avx_requirement_met,
|
||||||
commands::config::is_diskspace_requirement_met,
|
commands::config::is_diskspace_requirement_met,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use log::info;
|
||||||
use std::io::{BufReader, Cursor};
|
use std::io::{BufReader, Cursor};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -122,6 +123,7 @@ pub fn check_if_zip_contains_top_level_dir(
|
||||||
for i in 0..zip.len() {
|
for i in 0..zip.len() {
|
||||||
let file = zip.by_index(i)?;
|
let file = zip.by_index(i)?;
|
||||||
// Check if the entry is a directory and has the desired folder name
|
// Check if the entry is a directory and has the desired folder name
|
||||||
|
info!("{}", file.name());
|
||||||
if file.name().starts_with(&expected_dir) {
|
if file.name().starts_with(&expected_dir) {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"features_textures_description": "You can enable as many packs as you want, but if multiple packs replace the same file the order matters. For example if two packs replace the grass, the first pack in the list will take precedence.",
|
"features_textures_description": "You can enable as many packs as you want, but if multiple packs replace the same file the order matters. For example if two packs replace the grass, the first pack in the list will take precedence.",
|
||||||
"features_textures_disabled": "Disabled",
|
"features_textures_disabled": "Disabled",
|
||||||
"features_textures_enabled": "Enabled",
|
"features_textures_enabled": "Enabled",
|
||||||
"features_textures_invalidPack": "Invalid texture pack format, ensure it contains a top-level `texture_replacements` folder.",
|
"features_textures_invalidPack": "Invalid texture pack format, ensure it contains the correct top-level folder and valid metadata.",
|
||||||
"features_textures_listHeading": "Currently Added Packs",
|
"features_textures_listHeading": "Currently Added Packs",
|
||||||
"features_textures_moveDown_buttonAlt": "move texture pack down in order",
|
"features_textures_moveDown_buttonAlt": "move texture pack down in order",
|
||||||
"features_textures_moveUp_buttonAlt": "move texture pack up in order",
|
"features_textures_moveUp_buttonAlt": "move texture pack up in order",
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
"gameControls_button_decompile_helpText": "Extracts game assets (ie. to apply texture replacements)",
|
"gameControls_button_decompile_helpText": "Extracts game assets (ie. to apply texture replacements)",
|
||||||
"gameControls_button_decompile": "Decompile",
|
"gameControls_button_decompile": "Decompile",
|
||||||
"gameControls_button_features_textures": "Texture Packs",
|
"gameControls_button_features_textures": "Texture Packs",
|
||||||
|
"gameControls_button_features_textures_disabled": "Texture pack feature disabled, update your launcher and tooling version",
|
||||||
"gameControls_button_features": "Features",
|
"gameControls_button_features": "Features",
|
||||||
"gameControls_button_openREPL": "Open REPL",
|
"gameControls_button_openREPL": "Open REPL",
|
||||||
"gameControls_button_openSavesFolder": "Open Saves Folder",
|
"gameControls_button_openSavesFolder": "Open Saves Folder",
|
||||||
|
|
|
@ -13,11 +13,15 @@
|
||||||
DropdownItem,
|
DropdownItem,
|
||||||
DropdownDivider,
|
DropdownDivider,
|
||||||
Helper,
|
Helper,
|
||||||
|
Tooltip,
|
||||||
} from "flowbite-svelte";
|
} from "flowbite-svelte";
|
||||||
import { resetGameSettings, uninstallGame } from "$lib/rpc/game";
|
import { resetGameSettings, uninstallGame } from "$lib/rpc/game";
|
||||||
import { platform } from "@tauri-apps/api/os";
|
import { platform } from "@tauri-apps/api/os";
|
||||||
import { getLaunchGameString, launchGame, openREPL } from "$lib/rpc/binaries";
|
import { getLaunchGameString, launchGame, openREPL } from "$lib/rpc/binaries";
|
||||||
import { getPlaytime } from "$lib/rpc/config";
|
import {
|
||||||
|
doesActiveToolingVersionMeetMinimum,
|
||||||
|
getPlaytime,
|
||||||
|
} from "$lib/rpc/config";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { navigate } from "svelte-navigator";
|
import { navigate } from "svelte-navigator";
|
||||||
import { listen } from "@tauri-apps/api/event";
|
import { listen } from "@tauri-apps/api/event";
|
||||||
|
@ -35,6 +39,7 @@
|
||||||
let isLinux = false;
|
let isLinux = false;
|
||||||
let playtime = "";
|
let playtime = "";
|
||||||
let modSupportEnabled = false;
|
let modSupportEnabled = false;
|
||||||
|
let textureSupportEnabled = true;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
modSupportEnabled = await isModSupportEanbled();
|
modSupportEnabled = await isModSupportEanbled();
|
||||||
|
@ -58,6 +63,8 @@
|
||||||
playtime = formatPlaytime(result);
|
playtime = formatPlaytime(result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textureSupportEnabled = await doesActiveToolingVersionMeetMinimum(0, 2, 13);
|
||||||
});
|
});
|
||||||
|
|
||||||
// format the time from the settings file which is stored as seconds
|
// format the time from the settings file which is stored as seconds
|
||||||
|
@ -152,12 +159,18 @@
|
||||||
>
|
>
|
||||||
<Dropdown placement="top-end" class="!bg-slate-900">
|
<Dropdown placement="top-end" class="!bg-slate-900">
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
|
disabled={!textureSupportEnabled}
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
navigate(`/${getInternalName(activeGame)}/features/texture_packs`);
|
navigate(`/${getInternalName(activeGame)}/features/texture_packs`);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{$_("gameControls_button_features_textures")}
|
{$_("gameControls_button_features_textures")}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
|
{#if !textureSupportEnabled}
|
||||||
|
<Tooltip
|
||||||
|
>{$_("gameControls_button_features_textures_disabled")}</Tooltip
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
{#if modSupportEnabled}
|
{#if modSupportEnabled}
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
|
|
|
@ -274,3 +274,19 @@ export async function doesActiveToolingVersionSupportGame(
|
||||||
export async function getPlaytime(gameName: string): Promise<number> {
|
export async function getPlaytime(gameName: string): Promise<number> {
|
||||||
return await invoke_rpc("get_playtime", { gameName: gameName }, () => 0);
|
return await invoke_rpc("get_playtime", { gameName: gameName }, () => 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function doesActiveToolingVersionMeetMinimum(
|
||||||
|
minimumMajor: number,
|
||||||
|
minimumMinor: number,
|
||||||
|
minimumPatch: number,
|
||||||
|
): Promise<boolean> {
|
||||||
|
return await invoke_rpc(
|
||||||
|
"does_active_tooling_version_meet_minimum",
|
||||||
|
{
|
||||||
|
minimumPatch: minimumPatch,
|
||||||
|
minimumMinor: minimumMinor,
|
||||||
|
minimumMajor: minimumMajor,
|
||||||
|
},
|
||||||
|
() => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue