mirror of
https://github.com/LCE-Hub/LCE-Emerald-Launcher.git
synced 2026-09-24 09:03:44 +00:00
feat(plugins): custom splashes
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useRef, useCallback } from "react";
|
||||
import { SPLASHES } from "../data/splashes";
|
||||
import { PluginManager } from "../plugins/PluginManager";
|
||||
|
||||
const TRACKS = [
|
||||
"music/Moog City 2.opus",
|
||||
@@ -29,10 +29,16 @@ export function useAudioController({
|
||||
isGameRunning,
|
||||
isWindowVisible,
|
||||
}: AudioControllerProps) {
|
||||
const [splashes, setSplashes] = useState<string[]>(() => PluginManager.instance.getSplashes());
|
||||
const [currentTrack, setCurrentTrack] = useState(0);
|
||||
const [splashIndex, setSplashIndex] = useState(
|
||||
() => Math.floor(Math.random() * SPLASHES.length),
|
||||
() => Math.floor(Math.random() * PluginManager.instance.getSplashes().length),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
PluginManager.instance.setSplashesChangedCallback((s) => setSplashes(s));
|
||||
setSplashes(PluginManager.instance.getSplashes());
|
||||
}, []);
|
||||
const audioContextRef = useRef<AudioContext | null>(null);
|
||||
const musicSourceRef = useRef<AudioBufferSourceNode | null>(null);
|
||||
const musicGainRef = useRef<GainNode | null>(null);
|
||||
@@ -235,11 +241,12 @@ export function useAudioController({
|
||||
const cycleSplash = useCallback(() => {
|
||||
playSplashSound();
|
||||
let newIndex;
|
||||
if (splashes.length === 0) return;
|
||||
do {
|
||||
newIndex = Math.floor(Math.random() * SPLASHES.length);
|
||||
} while (newIndex === splashIndex && SPLASHES.length > 1);
|
||||
newIndex = Math.floor(Math.random() * splashes.length);
|
||||
} while (newIndex === splashIndex && splashes.length > 1);
|
||||
setSplashIndex(newIndex);
|
||||
}, [playSplashSound, splashIndex]);
|
||||
}, [playSplashSound, splashIndex, splashes]);
|
||||
const skipTrack = useCallback(() => {
|
||||
isManualSkipRef.current = true;
|
||||
setCurrentTrack((prev) => (prev + 1) % TRACKS.length);
|
||||
@@ -346,7 +353,7 @@ export function useAudioController({
|
||||
playBackSound,
|
||||
playSfx,
|
||||
tracks: TRACKS,
|
||||
splashes: SPLASHES,
|
||||
splashes: splashes,
|
||||
startMusic,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -189,6 +189,9 @@ export function buildPluginAPI(
|
||||
playSound(name: string): void {
|
||||
manager.playSound(name);
|
||||
},
|
||||
addSplash(splash: string): UnsubscribeFn {
|
||||
return manager.registerSplash(pluginId, splash);
|
||||
},
|
||||
async openUrl(url: string): Promise<void> {
|
||||
if (
|
||||
perms.size > 0 &&
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { buildPluginAPI } from "./PluginAPI";
|
||||
import { PluginSandbox } from "./PluginSandbox";
|
||||
import { SPLASHES } from "../data/splashes";
|
||||
import type {
|
||||
PluginManifest,
|
||||
LoadedPlugin,
|
||||
@@ -39,12 +40,14 @@ export class PluginManager {
|
||||
private hooks: Map<HookEvent, Map<string, HookCallback>> = new Map();
|
||||
private views: Map<string, PluginViewRegistration> = new Map();
|
||||
private actions: Map<ActionSlot, Map<string, { action: ActionDef; pluginId: string }>> = new Map();
|
||||
private splashes: Map<string, Set<string>> = new Map();
|
||||
private stateSubs: Map<string, StateChangeCallback> = new Map();
|
||||
private pluginEvents: Map<string, Map<string, Set<PluginEventHandler>>> = new Map();
|
||||
private onViewsChanged: ViewChangeCallback | null = null;
|
||||
private onNavigate: NavigateCallback | null = null;
|
||||
private onToast: ToastCallback | null = null;
|
||||
private onSound: SoundCallback | null = null;
|
||||
private onSplashesChanged: ((splashes: string[]) => void) | null = null;
|
||||
private onEnabledChanged: (() => void) | null = null;
|
||||
private configSnapshot: Record<string, unknown> = {};
|
||||
private gameStateSnapshot: Record<string, unknown> = {};
|
||||
@@ -71,6 +74,7 @@ export class PluginManager {
|
||||
this.enabledMap.set(id, enabled);
|
||||
localStorage.setItem(`plugin:enabled:${id}`, String(enabled));
|
||||
this.notifyViewsChanged();
|
||||
this.notifySplashesChanged();
|
||||
this.onEnabledChanged?.();
|
||||
}
|
||||
|
||||
@@ -97,6 +101,10 @@ export class PluginManager {
|
||||
this.onSound = cb;
|
||||
}
|
||||
|
||||
setSplashesChangedCallback(cb: (splashes: string[]) => void): void {
|
||||
this.onSplashesChanged = cb;
|
||||
}
|
||||
|
||||
updateSnapshots(
|
||||
config: Record<string, unknown>,
|
||||
game: Record<string, unknown>,
|
||||
@@ -139,9 +147,11 @@ export class PluginManager {
|
||||
this.hooks.clear();
|
||||
this.views.clear();
|
||||
this.actions.clear();
|
||||
this.splashes.clear();
|
||||
this.plugins.clear();
|
||||
this.enabledMap.clear();
|
||||
this.pluginEvents.clear();
|
||||
this.notifySplashesChanged();
|
||||
await this.init();
|
||||
}
|
||||
|
||||
@@ -369,7 +379,33 @@ export class PluginManager {
|
||||
this.onSound?.(name);
|
||||
}
|
||||
|
||||
registerSplash(pluginId: string, splash: string): UnsubscribeFn {
|
||||
if (!this.splashes.has(pluginId)) {
|
||||
this.splashes.set(pluginId, new Set());
|
||||
}
|
||||
this.splashes.get(pluginId)!.add(splash);
|
||||
this.notifySplashesChanged();
|
||||
return () => {
|
||||
this.splashes.get(pluginId)?.delete(splash);
|
||||
this.notifySplashesChanged();
|
||||
};
|
||||
}
|
||||
|
||||
getSplashes(): string[] {
|
||||
const pluginSplashes: string[] = [];
|
||||
this.splashes.forEach((set, pid) => {
|
||||
if (this.isPluginEnabled(pid)) {
|
||||
pluginSplashes.push(...set);
|
||||
}
|
||||
});
|
||||
return [...SPLASHES, ...pluginSplashes];
|
||||
}
|
||||
|
||||
private notifyViewsChanged(): void {
|
||||
this.onViewsChanged?.(this.getViews());
|
||||
}
|
||||
|
||||
private notifySplashesChanged(): void {
|
||||
this.onSplashesChanged?.(this.getSplashes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ export interface PluginAPI {
|
||||
ui: {
|
||||
showToast(message: string, options?: ToastOptions): void;
|
||||
playSound(name: string): void;
|
||||
addSplash(splash: string): UnsubscribeFn;
|
||||
openUrl(url: string): Promise<void>;
|
||||
};
|
||||
log: {
|
||||
|
||||
Reference in New Issue
Block a user