mirror of
https://github.com/LCE-Hub/LCE-Emerald-Launcher.git
synced 2026-08-20 04:27:29 +00:00
feat: add cafeberry logo
This commit is contained in:
parent
89b422ba6c
commit
7a2650bd48
|
|
@ -27,7 +27,7 @@ pub fn launch_bridge(
|
|||
let intent_class = env.find_class("android/content/Intent")?;
|
||||
let intent = env.new_object(
|
||||
intent_class,
|
||||
"(Landroid/content/Context;Ljava/lang/Class;)V",
|
||||
"(Landroid/content/Context;Ljava/lang/Class;)V", //neo: i hate smali so much
|
||||
&[(&activity).into(), (&bridge_class).into()],
|
||||
)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ fn build_empty_chunk_nbt(chunk_x: i32, chunk_z: i32) -> Vec<u8> {
|
|||
out.extend_from_slice(&0i64.to_be_bytes());
|
||||
out.extend_from_slice(b"\x01\x00\x10TerrainPopulated\x01");
|
||||
out.extend_from_slice(b"\x09\x00\x08Entities\x0a\x00\x00\x00\x00");
|
||||
out.extend_from_slice(b"\x09\x00\x0cTileEntities\x0a\x00\x00\x00\x00");
|
||||
out.extend_from_slice(b"\x09\x00\x0cTileEntities\x0a\x00\x00\x00\x00"); //neo: someone send help
|
||||
out.push(0x00);
|
||||
out.push(0x00);
|
||||
out
|
||||
|
|
|
|||
|
|
@ -731,6 +731,7 @@ fn game_exited_ok(log: &str) -> bool {
|
|||
.rev()
|
||||
.take(3)
|
||||
.any(|line| line.contains("AppPolicyGetProcessTerminationMethod"))
|
||||
//neo: TODO: investigate what Windows outputs for success to prevent false detection lol
|
||||
}
|
||||
|
||||
fn handle_game_exit(
|
||||
|
|
|
|||
|
|
@ -1285,6 +1285,7 @@ static MODERN_DIRECT_MAP: once_cell::sync::Lazy<HashMap<&'static str, LegacyBloc
|
|||
"lava_cauldron",
|
||||
LegacyBlockState { id: 118, data: 0 },
|
||||
);
|
||||
//neo: m.insert("help", neo {thisis: verytiring});
|
||||
m
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pub enum NbtValue {
|
|||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub struct NbtCompound {
|
||||
pub name: String,
|
||||
pub tags: Vec<(String, NbtValue)>,
|
||||
pub tags: Vec<(String, NbtValue)>, //neo: if you came here asking about this, dont. please. dont ask why im storing a tuple in a vec. or why im manually resizing a vec.
|
||||
}
|
||||
|
||||
impl NbtCompound {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
//neo: TODO: Intel macOS support
|
||||
|
||||
use tauri::AppHandle;
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::io::Write;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub async fn add_to_steam(
|
|||
let (exe_str, launch_options, start_dir) = if in_flatpak {
|
||||
(
|
||||
"/usr/bin/flatpak".to_string(),
|
||||
format!("run io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher \"{}\"", instance_id),
|
||||
format!("run io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher \"{}\"", instance_id), //neo: yes i'm hardcoding it lmfao
|
||||
std::env::var("HOME").unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,6 @@ pub async fn start_lce_auth(app: tauri::AppHandle) -> Result<String, String> {
|
|||
#[cfg(not(target_os = "android"))]
|
||||
{
|
||||
let _ = app;
|
||||
Err("LCE Online auth is only supported on Android".into())
|
||||
Err("LCE Online auth is only supported on Android".into()) //neo: erm, rust-side only. its supported on desktop on the typescript side.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
|||
use tokio::net::TcpListener;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tauri::{AppHandle, Emitter};
|
||||
const REGISTRY_URL: &str = "https://raw.githubusercontent.com/LCE-Hub/LCE-Workshop/refs/heads/main";
|
||||
const REGISTRY_URL: &str = "https://raw.githubusercontent.com/LCE-Hub/LCE-Workshop/refs/heads/main"; //neo: more hardcoding!
|
||||
static CLIENT: Lazy<reqwest::Client> = Lazy::new(|| reqwest::Client::new());
|
||||
pub struct Guard {
|
||||
cancel: Option<CancellationToken>,
|
||||
|
|
@ -34,7 +34,7 @@ pub async fn start(app: AppHandle) -> CancellationToken {
|
|||
}
|
||||
|
||||
async fn serve(app: AppHandle, cancel: CancellationToken) {
|
||||
let listener = match TcpListener::bind("127.0.0.1:5582").await {
|
||||
let listener = match TcpListener::bind("127.0.0.1:5582").await { //neo: dont say a word about this weird port.
|
||||
Ok(l) => l,
|
||||
Err(e) => {
|
||||
let _ = app.emit("backend-error", format!("Workshop server failed to bind: {e}"));
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
import { OptionsFile } from "../types/options";
|
||||
export class OptionsService {
|
||||
public static readOptions(buffer: ArrayBuffer, endianness: "little" | "big" = "little"): OptionsFile {
|
||||
public static readOptions(
|
||||
buffer: ArrayBuffer,
|
||||
endianness: "little" | "big" = "little",
|
||||
): OptionsFile {
|
||||
const rawData = new Uint8Array(buffer).slice();
|
||||
const view = new DataView(buffer);
|
||||
const little = endianness === "little";
|
||||
const opt: Partial<OptionsFile> = {
|
||||
endianness,
|
||||
rawData
|
||||
rawData,
|
||||
};
|
||||
|
||||
//neo: someone save me from these values
|
||||
opt.musicVolume = view.getUint8(0x01);
|
||||
opt.soundVolume = view.getUint8(0x02);
|
||||
opt.gameSensitivity = view.getUint8(0x03);
|
||||
|
|
@ -24,7 +27,7 @@ export class OptionsService {
|
|||
opt.verticalSplitscreen = (val06 & (1 << 8)) !== 0;
|
||||
opt.splitscreenGamertags = (val06 & (1 << 9)) !== 0;
|
||||
opt.hints = (val06 & (1 << 10)) !== 0;
|
||||
opt.autosaveTimer = (val06 >> 11) & 0xF;
|
||||
opt.autosaveTimer = (val06 >> 11) & 0xf;
|
||||
opt.inGameTooltips = (val06 & (1 << 15)) !== 0;
|
||||
const val54 = view.getUint32(0x54, little);
|
||||
opt.renderClouds = (val54 & (1 << 0)) !== 0;
|
||||
|
|
@ -45,46 +48,46 @@ export class OptionsService {
|
|||
opt.displaySaveIcon = (val54 & (1 << 29)) !== 0;
|
||||
opt.flyingViewRolling = (val54 & (1 << 30)) === 0;
|
||||
opt.showGlideGhostPath = (val54 & (1 << 31)) !== 0;
|
||||
opt.chosenSkin = view.getUint32(0x4C, little);
|
||||
opt.playerCape = view.getUint32(0x5C, little);
|
||||
opt.chosenSkin = view.getUint32(0x4c, little);
|
||||
opt.playerCape = view.getUint32(0x5c, little);
|
||||
opt.favoriteSkins = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
opt.favoriteSkins.push(view.getUint32(0x60 + i * 4, little));
|
||||
}
|
||||
|
||||
opt.actions = {
|
||||
jump: view.getUint8(0xA4),
|
||||
use: view.getUint8(0xA5),
|
||||
action: view.getUint8(0xA6),
|
||||
cycleHeldItemLeft: view.getUint8(0xA7),
|
||||
cycleHeldItemRight: view.getUint8(0xA8),
|
||||
inventory: view.getUint8(0xA9),
|
||||
drop: view.getUint8(0xAA),
|
||||
sneakDismount: view.getUint8(0xAB),
|
||||
crafting: view.getUint8(0xAC),
|
||||
changeCameraMode: view.getUint8(0xAD),
|
||||
flyLeft: view.getUint8(0xAE),
|
||||
flyRight: view.getUint8(0xAF),
|
||||
flyUp: view.getUint8(0xB0),
|
||||
flyDown: view.getUint8(0xB1),
|
||||
sprint: view.getUint8(0xB2),
|
||||
pickBlock: view.getUint8(0xB3),
|
||||
previousPlayer: view.getUint8(0xB4),
|
||||
nextPlayer: view.getUint8(0xB5),
|
||||
spectateNoise: view.getUint8(0xB6),
|
||||
cancelSpectating: view.getUint8(0xB7),
|
||||
confirmReady: view.getUint8(0xB8),
|
||||
vote: view.getUint8(0xB9),
|
||||
restartSection: view.getUint8(0xBA),
|
||||
restartRace: view.getUint8(0xBB),
|
||||
lookBehind: view.getUint8(0xBC)
|
||||
jump: view.getUint8(0xa4),
|
||||
use: view.getUint8(0xa5),
|
||||
action: view.getUint8(0xa6),
|
||||
cycleHeldItemLeft: view.getUint8(0xa7),
|
||||
cycleHeldItemRight: view.getUint8(0xa8),
|
||||
inventory: view.getUint8(0xa9),
|
||||
drop: view.getUint8(0xaa),
|
||||
sneakDismount: view.getUint8(0xab),
|
||||
crafting: view.getUint8(0xac),
|
||||
changeCameraMode: view.getUint8(0xad),
|
||||
flyLeft: view.getUint8(0xae),
|
||||
flyRight: view.getUint8(0xaf),
|
||||
flyUp: view.getUint8(0xb0),
|
||||
flyDown: view.getUint8(0xb1),
|
||||
sprint: view.getUint8(0xb2),
|
||||
pickBlock: view.getUint8(0xb3),
|
||||
previousPlayer: view.getUint8(0xb4),
|
||||
nextPlayer: view.getUint8(0xb5),
|
||||
spectateNoise: view.getUint8(0xb6),
|
||||
cancelSpectating: view.getUint8(0xb7),
|
||||
confirmReady: view.getUint8(0xb8),
|
||||
vote: view.getUint8(0xb9),
|
||||
restartSection: view.getUint8(0xba),
|
||||
restartRace: view.getUint8(0xbb),
|
||||
lookBehind: view.getUint8(0xbc),
|
||||
};
|
||||
|
||||
return opt as OptionsFile;
|
||||
}
|
||||
|
||||
public static serializeOptions(opt: OptionsFile): ArrayBuffer {
|
||||
const minSize = 0xBC + 1;
|
||||
const minSize = 0xbc + 1;
|
||||
const buffer = new Uint8Array(Math.max(opt.rawData.length, minSize));
|
||||
buffer.set(opt.rawData);
|
||||
const view = new DataView(buffer.buffer);
|
||||
|
|
@ -97,69 +100,69 @@ export class OptionsService {
|
|||
view.setUint8(0x51, opt.interfaceOpacity);
|
||||
let val06 = view.getUint16(0x06, little);
|
||||
val06 = (val06 & ~0x3) | (opt.difficulty & 0x3);
|
||||
val06 = (val06 & ~(1 << 2)) | (opt.viewBobbing ? (1 << 2) : 0);
|
||||
val06 = (val06 & ~(1 << 3)) | (opt.inGameGamertags ? (1 << 3) : 0);
|
||||
val06 = (val06 & ~(1 << 6)) | (opt.invertLook ? (1 << 6) : 0);
|
||||
val06 = (val06 & ~(1 << 7)) | (opt.southpaw ? (1 << 7) : 0);
|
||||
val06 = (val06 & ~(1 << 8)) | (opt.verticalSplitscreen ? (1 << 8) : 0);
|
||||
val06 = (val06 & ~(1 << 9)) | (opt.splitscreenGamertags ? (1 << 9) : 0);
|
||||
val06 = (val06 & ~(1 << 10)) | (opt.hints ? (1 << 10) : 0);
|
||||
val06 = (val06 & ~(0xF << 11)) | ((opt.autosaveTimer & 0xF) << 11);
|
||||
val06 = (val06 & ~(1 << 15)) | (opt.inGameTooltips ? (1 << 15) : 0);
|
||||
val06 = (val06 & ~(1 << 2)) | (opt.viewBobbing ? 1 << 2 : 0);
|
||||
val06 = (val06 & ~(1 << 3)) | (opt.inGameGamertags ? 1 << 3 : 0);
|
||||
val06 = (val06 & ~(1 << 6)) | (opt.invertLook ? 1 << 6 : 0);
|
||||
val06 = (val06 & ~(1 << 7)) | (opt.southpaw ? 1 << 7 : 0);
|
||||
val06 = (val06 & ~(1 << 8)) | (opt.verticalSplitscreen ? 1 << 8 : 0);
|
||||
val06 = (val06 & ~(1 << 9)) | (opt.splitscreenGamertags ? 1 << 9 : 0);
|
||||
val06 = (val06 & ~(1 << 10)) | (opt.hints ? 1 << 10 : 0);
|
||||
val06 = (val06 & ~(0xf << 11)) | ((opt.autosaveTimer & 0xf) << 11);
|
||||
val06 = (val06 & ~(1 << 15)) | (opt.inGameTooltips ? 1 << 15 : 0);
|
||||
view.setUint16(0x06, val06, little);
|
||||
let val54 = view.getUint32(0x54, little);
|
||||
val54 = (val54 & ~(1 << 0)) | (opt.renderClouds ? (1 << 0) : 0);
|
||||
val54 = (val54 & ~(1 << 7)) | (opt.displayHud ? (1 << 7) : 0);
|
||||
val54 = (val54 & ~(1 << 8)) | (opt.displayHand ? (1 << 8) : 0);
|
||||
val54 = (val54 & ~(1 << 9)) | (opt.customSkinAnimation ? (1 << 9) : 0);
|
||||
val54 = (val54 & ~(1 << 10)) | (opt.deathMessages ? (1 << 10) : 0);
|
||||
val54 = (val54 & ~(1 << 0)) | (opt.renderClouds ? 1 << 0 : 0);
|
||||
val54 = (val54 & ~(1 << 7)) | (opt.displayHud ? 1 << 7 : 0);
|
||||
val54 = (val54 & ~(1 << 8)) | (opt.displayHand ? 1 << 8 : 0);
|
||||
val54 = (val54 & ~(1 << 9)) | (opt.customSkinAnimation ? 1 << 9 : 0);
|
||||
val54 = (val54 & ~(1 << 10)) | (opt.deathMessages ? 1 << 10 : 0);
|
||||
val54 = (val54 & ~(0x3 << 11)) | ((opt.hudSize & 0x3) << 11);
|
||||
val54 = (val54 & ~(0x3 << 13)) | ((opt.hudSizeSplitscreen & 0x3) << 13);
|
||||
val54 = (val54 & ~(1 << 15)) | (opt.animatedCharacter ? (1 << 15) : 0);
|
||||
val54 = (val54 & ~(1 << 18)) | (opt.classicCrafting ? (1 << 18) : 0);
|
||||
val54 = (val54 & ~(1 << 19)) | (opt.caveSounds ? (1 << 19) : 0);
|
||||
val54 = (val54 & ~(1 << 20)) | (opt.gameChat ? (1 << 20) : 0);
|
||||
val54 = (val54 & ~(1 << 21)) | (opt.minecartSounds ? (1 << 21) : 0);
|
||||
val54 = (val54 & ~(1 << 22)) | (opt.showGlideGhost ? (1 << 22) : 0);
|
||||
val54 = (val54 & ~(1 << 26)) | (opt.autoJump ? (1 << 26) : 0);
|
||||
val54 = (val54 & ~(1 << 28)) | (opt.displayGameMessages ? (1 << 28) : 0);
|
||||
val54 = (val54 & ~(1 << 29)) | (opt.displaySaveIcon ? (1 << 29) : 0);
|
||||
val54 = (val54 & ~(1 << 30)) | (!opt.flyingViewRolling ? (1 << 30) : 0);
|
||||
val54 = (val54 & ~(1 << 31)) | (opt.showGlideGhostPath ? (1 << 31) : 0);
|
||||
val54 = (val54 & ~(1 << 15)) | (opt.animatedCharacter ? 1 << 15 : 0);
|
||||
val54 = (val54 & ~(1 << 18)) | (opt.classicCrafting ? 1 << 18 : 0);
|
||||
val54 = (val54 & ~(1 << 19)) | (opt.caveSounds ? 1 << 19 : 0);
|
||||
val54 = (val54 & ~(1 << 20)) | (opt.gameChat ? 1 << 20 : 0);
|
||||
val54 = (val54 & ~(1 << 21)) | (opt.minecartSounds ? 1 << 21 : 0);
|
||||
val54 = (val54 & ~(1 << 22)) | (opt.showGlideGhost ? 1 << 22 : 0);
|
||||
val54 = (val54 & ~(1 << 26)) | (opt.autoJump ? 1 << 26 : 0);
|
||||
val54 = (val54 & ~(1 << 28)) | (opt.displayGameMessages ? 1 << 28 : 0);
|
||||
val54 = (val54 & ~(1 << 29)) | (opt.displaySaveIcon ? 1 << 29 : 0);
|
||||
val54 = (val54 & ~(1 << 30)) | (!opt.flyingViewRolling ? 1 << 30 : 0);
|
||||
val54 = (val54 & ~(1 << 31)) | (opt.showGlideGhostPath ? 1 << 31 : 0);
|
||||
view.setUint32(0x54, val54, little);
|
||||
view.setUint32(0x4C, opt.chosenSkin, little);
|
||||
view.setUint32(0x5C, opt.playerCape, little);
|
||||
view.setUint32(0x4c, opt.chosenSkin, little);
|
||||
view.setUint32(0x5c, opt.playerCape, little);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (opt.favoriteSkins[i] !== undefined) {
|
||||
view.setUint32(0x60 + i * 4, opt.favoriteSkins[i], little);
|
||||
}
|
||||
}
|
||||
|
||||
view.setUint8(0xA4, opt.actions.jump);
|
||||
view.setUint8(0xA5, opt.actions.use);
|
||||
view.setUint8(0xA6, opt.actions.action);
|
||||
view.setUint8(0xA7, opt.actions.cycleHeldItemLeft);
|
||||
view.setUint8(0xA8, opt.actions.cycleHeldItemRight);
|
||||
view.setUint8(0xA9, opt.actions.inventory);
|
||||
view.setUint8(0xAA, opt.actions.drop);
|
||||
view.setUint8(0xAB, opt.actions.sneakDismount);
|
||||
view.setUint8(0xAC, opt.actions.crafting);
|
||||
view.setUint8(0xAD, opt.actions.changeCameraMode);
|
||||
view.setUint8(0xAE, opt.actions.flyLeft);
|
||||
view.setUint8(0xAF, opt.actions.flyRight);
|
||||
view.setUint8(0xB0, opt.actions.flyUp);
|
||||
view.setUint8(0xB1, opt.actions.flyDown);
|
||||
view.setUint8(0xB2, opt.actions.sprint);
|
||||
view.setUint8(0xB3, opt.actions.pickBlock);
|
||||
view.setUint8(0xB4, opt.actions.previousPlayer);
|
||||
view.setUint8(0xB5, opt.actions.nextPlayer);
|
||||
view.setUint8(0xB6, opt.actions.spectateNoise);
|
||||
view.setUint8(0xB7, opt.actions.cancelSpectating);
|
||||
view.setUint8(0xB8, opt.actions.confirmReady);
|
||||
view.setUint8(0xB9, opt.actions.vote);
|
||||
view.setUint8(0xBA, opt.actions.restartSection);
|
||||
view.setUint8(0xBB, opt.actions.restartRace);
|
||||
view.setUint8(0xBC, opt.actions.lookBehind);
|
||||
view.setUint8(0xa4, opt.actions.jump);
|
||||
view.setUint8(0xa5, opt.actions.use);
|
||||
view.setUint8(0xa6, opt.actions.action);
|
||||
view.setUint8(0xa7, opt.actions.cycleHeldItemLeft);
|
||||
view.setUint8(0xa8, opt.actions.cycleHeldItemRight);
|
||||
view.setUint8(0xa9, opt.actions.inventory);
|
||||
view.setUint8(0xaa, opt.actions.drop);
|
||||
view.setUint8(0xab, opt.actions.sneakDismount);
|
||||
view.setUint8(0xac, opt.actions.crafting);
|
||||
view.setUint8(0xad, opt.actions.changeCameraMode);
|
||||
view.setUint8(0xae, opt.actions.flyLeft);
|
||||
view.setUint8(0xaf, opt.actions.flyRight);
|
||||
view.setUint8(0xb0, opt.actions.flyUp);
|
||||
view.setUint8(0xb1, opt.actions.flyDown);
|
||||
view.setUint8(0xb2, opt.actions.sprint);
|
||||
view.setUint8(0xb3, opt.actions.pickBlock);
|
||||
view.setUint8(0xb4, opt.actions.previousPlayer);
|
||||
view.setUint8(0xb5, opt.actions.nextPlayer);
|
||||
view.setUint8(0xb6, opt.actions.spectateNoise);
|
||||
view.setUint8(0xb7, opt.actions.cancelSpectating);
|
||||
view.setUint8(0xb8, opt.actions.confirmReady);
|
||||
view.setUint8(0xb9, opt.actions.vote);
|
||||
view.setUint8(0xba, opt.actions.restartSection);
|
||||
view.setUint8(0xbb, opt.actions.restartRace);
|
||||
view.setUint8(0xbc, opt.actions.lookBehind);
|
||||
return buffer.buffer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,12 @@ export interface SwfImage {
|
|||
}
|
||||
|
||||
export class SwfService {
|
||||
static parse(buffer: Uint8Array): { version: number; compressed: boolean; frameHeader: Uint8Array; tags: SwfTag[] } {
|
||||
static parse(buffer: Uint8Array): {
|
||||
version: number;
|
||||
compressed: boolean;
|
||||
frameHeader: Uint8Array;
|
||||
tags: SwfTag[];
|
||||
} {
|
||||
if (buffer.length < 8) throw new Error("Invalid SWF: file too small");
|
||||
const sig = String.fromCharCode(buffer[0], buffer[1], buffer[2]);
|
||||
const version = buffer[3];
|
||||
|
|
@ -48,7 +53,11 @@ export class SwfService {
|
|||
const code = tagHeader >> 6;
|
||||
let length = tagHeader & 0x3f;
|
||||
if (length === 0x3f) {
|
||||
length = data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24);
|
||||
length =
|
||||
data[offset] |
|
||||
(data[offset + 1] << 8) |
|
||||
(data[offset + 2] << 16) |
|
||||
(data[offset + 3] << 24);
|
||||
offset += 4;
|
||||
}
|
||||
const tagData = data.slice(offset, offset + length);
|
||||
|
|
@ -60,7 +69,12 @@ export class SwfService {
|
|||
return { version, compressed: sig === "CWS", frameHeader, tags };
|
||||
}
|
||||
|
||||
static serialize(version: number, compressed: boolean, frameHeader: Uint8Array, tags: SwfTag[]): Uint8Array {
|
||||
static serialize(
|
||||
version: number,
|
||||
compressed: boolean,
|
||||
frameHeader: Uint8Array,
|
||||
tags: SwfTag[],
|
||||
): Uint8Array {
|
||||
const payloads: Uint8Array[] = [frameHeader];
|
||||
let bodyLength = frameHeader.length;
|
||||
|
||||
|
|
@ -89,7 +103,9 @@ export class SwfService {
|
|||
}
|
||||
|
||||
const fileLength = 8 + uncompressedBody.length;
|
||||
const finalBody = compressed ? pako.deflate(uncompressedBody) : uncompressedBody;
|
||||
const finalBody = compressed
|
||||
? pako.deflate(uncompressedBody)
|
||||
: uncompressedBody;
|
||||
const result = new Uint8Array(8 + finalBody.length);
|
||||
result.set(new TextEncoder().encode(compressed ? "CWS" : "FWS"), 0);
|
||||
result[3] = version;
|
||||
|
|
@ -125,15 +141,32 @@ export class SwfService {
|
|||
const charId = tag.data[0] | (tag.data[1] << 8);
|
||||
const imgData = tag.data.slice(2);
|
||||
const fixed = this.fixJpeg(imgData, tag.code === 6 ? jpegTables : null);
|
||||
images.push({ id: charId, type: "jpeg", data: fixed, name: nameMap[charId] });
|
||||
images.push({
|
||||
id: charId,
|
||||
type: "jpeg",
|
||||
data: fixed,
|
||||
name: nameMap[charId],
|
||||
});
|
||||
} else if (tag.code === 35) {
|
||||
const charId = tag.data[0] | (tag.data[1] << 8);
|
||||
const alphaOffset = tag.data[2] | (tag.data[3] << 8) | (tag.data[4] << 16) | (tag.data[5] << 24);
|
||||
const alphaOffset =
|
||||
tag.data[2] |
|
||||
(tag.data[3] << 8) |
|
||||
(tag.data[4] << 16) |
|
||||
(tag.data[5] << 24);
|
||||
const imgData = tag.data.slice(6, 6 + alphaOffset);
|
||||
const alphaRaw = tag.data.slice(6 + alphaOffset);
|
||||
let alpha = undefined;
|
||||
try { alpha = pako.inflate(alphaRaw); } catch (e) { }
|
||||
images.push({ id: charId, type: "jpeg", data: this.fixJpeg(imgData), alphaData: alpha, name: nameMap[charId] });
|
||||
try {
|
||||
alpha = pako.inflate(alphaRaw);
|
||||
} catch (e) {}
|
||||
images.push({
|
||||
id: charId,
|
||||
type: "jpeg",
|
||||
data: this.fixJpeg(imgData),
|
||||
alphaData: alpha,
|
||||
name: nameMap[charId],
|
||||
});
|
||||
} else if (tag.code === 20 || tag.code === 36) {
|
||||
const charId = tag.data[0] | (tag.data[1] << 8);
|
||||
const format = tag.data[2];
|
||||
|
|
@ -144,20 +177,23 @@ export class SwfService {
|
|||
|
||||
images.push({
|
||||
id: charId,
|
||||
type: "lossless",
|
||||
type: "lossless", //neo: aka PNG
|
||||
data: raw,
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
hasAlpha,
|
||||
name: nameMap[charId]
|
||||
name: nameMap[charId],
|
||||
});
|
||||
}
|
||||
}
|
||||
return images;
|
||||
}
|
||||
|
||||
private static fixJpeg(data: Uint8Array, jtt: Uint8Array | null = null): Uint8Array {
|
||||
private static fixJpeg(
|
||||
data: Uint8Array,
|
||||
jtt: Uint8Array | null = null,
|
||||
): Uint8Array {
|
||||
let combined = data;
|
||||
if (jtt && jtt.length > 0) {
|
||||
let tLen = jtt.length;
|
||||
|
|
@ -172,7 +208,8 @@ export class SwfService {
|
|||
}
|
||||
|
||||
static async decodeLosslessToRGBA(img: SwfImage): Promise<Uint8Array> {
|
||||
if (img.type !== "lossless" || !img.width || !img.height) return new Uint8Array(0);
|
||||
if (img.type !== "lossless" || !img.width || !img.height)
|
||||
return new Uint8Array(0);
|
||||
const decoded = pako.inflate(img.data);
|
||||
const rgba = new Uint8Array(img.width * img.height * 4);
|
||||
if (img.format === 3) {
|
||||
|
|
@ -189,7 +226,7 @@ export class SwfService {
|
|||
a > 0 ? Math.min(255, (r_pm * 255) / a) : 0,
|
||||
a > 0 ? Math.min(255, (g_pm * 255) / a) : 0,
|
||||
a > 0 ? Math.min(255, (b_pm * 255) / a) : 0,
|
||||
a
|
||||
a,
|
||||
]);
|
||||
} else {
|
||||
palette.push([decoded[ptr++], decoded[ptr++], decoded[ptr++], 255]);
|
||||
|
|
@ -211,7 +248,9 @@ export class SwfService {
|
|||
const rowStride = Math.ceil((img.width * 2) / 4) * 4;
|
||||
for (let y = 0; y < img.height; y++) {
|
||||
for (let x = 0; x < img.width; x++) {
|
||||
const p = decoded[y * rowStride + x * 2] | (decoded[y * rowStride + x * 2 + 1] << 8);
|
||||
const p =
|
||||
decoded[y * rowStride + x * 2] |
|
||||
(decoded[y * rowStride + x * 2 + 1] << 8);
|
||||
const r = ((p >> 10) & 0x1f) << 3;
|
||||
const g = ((p >> 5) & 0x1f) << 3;
|
||||
const b = (p & 0x1f) << 3;
|
||||
|
|
@ -248,9 +287,20 @@ export class SwfService {
|
|||
return rgba;
|
||||
}
|
||||
|
||||
static updateImageTag(tags: SwfTag[], charId: number, newData: Uint8Array, type: SwfImage["type"]): SwfTag[] {
|
||||
return tags.map(tag => {
|
||||
if (tag.code === 6 || tag.code === 21 || tag.code === 35 || tag.code === 20 || tag.code === 36) {
|
||||
static updateImageTag(
|
||||
tags: SwfTag[],
|
||||
charId: number,
|
||||
newData: Uint8Array,
|
||||
type: SwfImage["type"],
|
||||
): SwfTag[] {
|
||||
return tags.map((tag) => {
|
||||
if (
|
||||
tag.code === 6 ||
|
||||
tag.code === 21 ||
|
||||
tag.code === 35 ||
|
||||
tag.code === 20 ||
|
||||
tag.code === 36
|
||||
) {
|
||||
const id = tag.data[0] | (tag.data[1] << 8);
|
||||
if (id === charId) {
|
||||
let payload: Uint8Array;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export interface Runner {
|
|||
id: string;
|
||||
name: string;
|
||||
path: string;
|
||||
type: "wine" | "proton";
|
||||
type: "wine" | "proton"; //neo: i beg you please use Proton dont use WINE, WineD3D sickens me
|
||||
}
|
||||
|
||||
export interface MacOSSetupProgress {
|
||||
|
|
@ -196,15 +196,25 @@ export class TauriService {
|
|||
return invoke("workshop_list_installed");
|
||||
}
|
||||
|
||||
static onDownloadProgress(callback: (data: { instanceId: string; percent: number }) => void) {
|
||||
return listen<{ instanceId: string; percent: number }>("download-progress", (event) =>
|
||||
callback(event.payload),
|
||||
static onDownloadProgress(
|
||||
callback: (data: { instanceId: string; percent: number }) => void,
|
||||
) {
|
||||
return listen<{ instanceId: string; percent: number }>(
|
||||
"download-progress",
|
||||
(event) => callback(event.payload),
|
||||
);
|
||||
}
|
||||
|
||||
static onWorkshopProgress(callback: (data: { packageId: string; percent: number }) => void) {
|
||||
return listen<{ instanceId: string; percent: number }>("workshop-progress", (event) =>
|
||||
callback({ packageId: event.payload.instanceId, percent: event.payload.percent }),
|
||||
static onWorkshopProgress(
|
||||
callback: (data: { packageId: string; percent: number }) => void,
|
||||
) {
|
||||
return listen<{ instanceId: string; percent: number }>(
|
||||
"workshop-progress",
|
||||
(event) =>
|
||||
callback({
|
||||
packageId: event.payload.instanceId,
|
||||
percent: event.payload.percent,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -221,21 +231,15 @@ export class TauriService {
|
|||
}
|
||||
|
||||
static onBackendError(callback: (message: string) => void) {
|
||||
return listen<string>("backend-error", (event) =>
|
||||
callback(event.payload),
|
||||
);
|
||||
return listen<string>("backend-error", (event) => callback(event.payload));
|
||||
}
|
||||
|
||||
static onGameLog(callback: (log: string) => void) {
|
||||
return listen<string>("game-log", (event) =>
|
||||
callback(event.payload),
|
||||
);
|
||||
return listen<string>("game-log", (event) => callback(event.payload));
|
||||
}
|
||||
|
||||
static onDownloadRetry(callback: (attempt: number) => void) {
|
||||
return listen<number>("download-retry", (event) =>
|
||||
callback(event.payload),
|
||||
);
|
||||
return listen<number>("download-retry", (event) => callback(event.payload));
|
||||
}
|
||||
|
||||
static async openUrl(url: string): Promise<void> {
|
||||
|
|
@ -391,7 +395,9 @@ export class TauriService {
|
|||
return invoke("get_instance_path", { instanceId });
|
||||
}
|
||||
|
||||
static async getInstanceArgsSchema(instanceId: string): Promise<string | null> {
|
||||
static async getInstanceArgsSchema(
|
||||
instanceId: string,
|
||||
): Promise<string | null> {
|
||||
return invoke("get_instance_args_schema", { instanceId });
|
||||
}
|
||||
|
||||
|
|
@ -439,7 +445,12 @@ export class TauriService {
|
|||
branch: string,
|
||||
dlcFolder: string,
|
||||
): Promise<void> {
|
||||
return invoke("download_dlc_files", { instanceId, repoUrl, branch, dlcFolder });
|
||||
return invoke("download_dlc_files", {
|
||||
instanceId,
|
||||
repoUrl,
|
||||
branch,
|
||||
dlcFolder,
|
||||
});
|
||||
}
|
||||
|
||||
static async importWorld(
|
||||
|
|
|
|||
Loading…
Reference in a new issue