mirror of
https://github.com/LCE-Hub/LCE-Emerald-Launcher.git
synced 2026-07-18 00:10:45 +00:00
1.6.0 drop 1 (#132)
This commit is contained in:
@@ -281,7 +281,7 @@ export default function ModelEditorView() {
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (document.activeElement?.tagName === "INPUT") return;
|
||||
if (e.key === "Escape" || e.key === "Backspace") {
|
||||
if (e.key === "Escape") {
|
||||
playBackSound();
|
||||
setActiveView("devtools");
|
||||
}
|
||||
|
||||
@@ -128,7 +128,13 @@ export default function PckEditorView() {
|
||||
setExpandedFolders(next);
|
||||
};
|
||||
|
||||
type TreeNode = { name: string; path: string; isFolder: boolean; children: TreeNode[]; asset?: PCKAsset };
|
||||
type TreeNode = {
|
||||
name: string;
|
||||
path: string;
|
||||
isFolder: boolean;
|
||||
children: TreeNode[];
|
||||
asset?: PCKAsset;
|
||||
};
|
||||
|
||||
const renderTree = (nodes: TreeNode[], depth = 0) => {
|
||||
return nodes.map((node) => {
|
||||
@@ -448,7 +454,7 @@ export default function PckEditorView() {
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (document.activeElement?.tagName === "INPUT") return;
|
||||
if (e.key === "Escape" || e.key === "Backspace") {
|
||||
if (e.key === "Escape") {
|
||||
if (isEditingProperty) {
|
||||
setIsEditingProperty(null);
|
||||
return;
|
||||
@@ -768,18 +774,14 @@ export default function PckEditorView() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2 shrink-0">
|
||||
<button
|
||||
onClick={() => handleMoveAsset("up")}
|
||||
>
|
||||
<button onClick={() => handleMoveAsset("up")}>
|
||||
<img
|
||||
src="/images/Settings_Arrow_Up.png"
|
||||
className="w-4 h-4 object-contain"
|
||||
style={{ imageRendering: "pixelated" }}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleMoveAsset("down")}
|
||||
>
|
||||
<button onClick={() => handleMoveAsset("down")}>
|
||||
<img
|
||||
src="/images/Settings_Arrow_Down.png"
|
||||
className="w-4 h-4 object-contain"
|
||||
|
||||
@@ -23,7 +23,6 @@ const SettingsView = memo(function SettingsView() {
|
||||
sfxVol: sfxVolume,
|
||||
setSfxVol: setSfxVolume,
|
||||
layout,
|
||||
setLayout,
|
||||
linuxRunner,
|
||||
setLinuxRunner,
|
||||
perfBoost,
|
||||
@@ -62,7 +61,7 @@ const SettingsView = memo(function SettingsView() {
|
||||
const { isLinux, isMac } = usePlatform();
|
||||
const [focusIndex, setFocusIndex] = useState<number | null>(null);
|
||||
const [currentSubMenu, setCurrentSubMenu] = useState<
|
||||
"main" | "audio" | "video" | "controls" | "launcher" | "game" | "plugins"
|
||||
"main" | "audio" | "video" | "launcher" | "game" | "plugins"
|
||||
>("main");
|
||||
const [runners, setRunners] = useState<Runner[]>([]);
|
||||
const [pluginsInfo, setPluginsInfo] = useState<PluginInfo[]>([]);
|
||||
@@ -74,9 +73,6 @@ const SettingsView = memo(function SettingsView() {
|
||||
const [showModal, setShowModal] = useState<
|
||||
"args" | "prefix" | "envVars" | null
|
||||
>(null);
|
||||
|
||||
const layouts = ["KBM", "PLAYSTATION", "XBOX"];
|
||||
|
||||
useEffect(() => {
|
||||
TauriService.getAvailableRunners().then(setRunners);
|
||||
}, [isRunnerDownloading]);
|
||||
@@ -91,13 +87,6 @@ const SettingsView = memo(function SettingsView() {
|
||||
return () => PluginManager.instance.setEnabledChangedCallback(null!);
|
||||
}, [refreshPlugins]);
|
||||
|
||||
const handleLayoutToggle = () => {
|
||||
playPressSound();
|
||||
const currentIndex = layouts.indexOf(layout);
|
||||
const nextIndex = (currentIndex + 1) % layouts.length;
|
||||
setLayout(layouts[nextIndex]);
|
||||
};
|
||||
|
||||
const handleVfxToggle = () => {
|
||||
playPressSound();
|
||||
setVfxEnabled(!vfxEnabled);
|
||||
@@ -302,16 +291,6 @@ const SettingsView = memo(function SettingsView() {
|
||||
setFocusIndex(0);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
id: "controls_menu",
|
||||
label: "Controls",
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
setCurrentSubMenu("controls");
|
||||
setFocusIndex(0);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
id: "launcher_menu",
|
||||
label: "Launcher",
|
||||
@@ -395,13 +374,6 @@ const SettingsView = memo(function SettingsView() {
|
||||
onClick: handlePerfToggle,
|
||||
});
|
||||
}
|
||||
} else if (currentSubMenu === "controls") {
|
||||
items.push({
|
||||
id: "layout",
|
||||
label: `Layout: ${layout}`,
|
||||
type: "button",
|
||||
onClick: handleLayoutToggle,
|
||||
});
|
||||
} else if (currentSubMenu === "game") {
|
||||
const envVarsCount = launchEnvVars
|
||||
? Object.keys(launchEnvVars).length
|
||||
@@ -521,6 +493,7 @@ const SettingsView = memo(function SettingsView() {
|
||||
playPressSound();
|
||||
try {
|
||||
await TauriService.importSettings();
|
||||
window.location.reload();
|
||||
} catch (e) {
|
||||
if (e !== "CANCELED") console.error(e);
|
||||
}
|
||||
@@ -585,7 +558,6 @@ const SettingsView = memo(function SettingsView() {
|
||||
handleRpcToggle,
|
||||
handleLegacyToggle,
|
||||
handleAnimationsToggle,
|
||||
handleLayoutToggle,
|
||||
handleRunnerToggle,
|
||||
handlePerfToggle,
|
||||
handleMangohudToggle,
|
||||
@@ -712,13 +684,11 @@ const SettingsView = memo(function SettingsView() {
|
||||
? "Audio"
|
||||
: currentSubMenu === "video"
|
||||
? "Video"
|
||||
: currentSubMenu === "controls"
|
||||
? "Controls"
|
||||
: currentSubMenu === "game"
|
||||
? "Game"
|
||||
: currentSubMenu === "plugins"
|
||||
? "Plugins"
|
||||
: "Launcher"}
|
||||
: currentSubMenu === "game"
|
||||
? "Game"
|
||||
: currentSubMenu === "plugins"
|
||||
? "Plugins"
|
||||
: "Launcher"}
|
||||
</h2>
|
||||
|
||||
{currentSubMenu === "main" ? (
|
||||
|
||||
@@ -1940,16 +1940,24 @@ function InstallModal({
|
||||
isPluginTab?: boolean;
|
||||
}) {
|
||||
const game = useContext(GameContext);
|
||||
const allInstalled =
|
||||
game?.editions.filter((e) => game.installs.includes(e.id)) || [];
|
||||
const availableEditions =
|
||||
const matchingEditions =
|
||||
pkg.required_versions && pkg.required_versions.length > 0
|
||||
? allInstalled.filter((e) =>
|
||||
? (game?.editions || []).filter((e) =>
|
||||
pkg.required_versions!.some(
|
||||
(rv) => e.id === rv || e.id.startsWith(rv + "_"),
|
||||
),
|
||||
)
|
||||
: allInstalled;
|
||||
: game?.editions || [];
|
||||
const editionOptions = matchingEditions.flatMap((ed) => {
|
||||
const branches =
|
||||
ed.branches && ed.branches.length > 0 ? ed.branches : ["Stable"];
|
||||
return branches
|
||||
.map((branch) => ({
|
||||
label: branches.length > 1 ? `${ed.name} (${branch})` : ed.name,
|
||||
instanceId: branch === "Stable" ? ed.id : `${ed.id}_${branch}`,
|
||||
}))
|
||||
.filter((opt) => game?.installs.includes(opt.instanceId));
|
||||
});
|
||||
const [focusedIdx, setFocusedIdx] = useState(0);
|
||||
const [status, setStatus] = useState<
|
||||
"idle" | "installing" | "success" | "error"
|
||||
@@ -2040,16 +2048,16 @@ function InstallModal({
|
||||
} else if (e.key === "ArrowDown") {
|
||||
e.preventDefault();
|
||||
playPressSound();
|
||||
setFocusedIdx((p) => Math.min(p + 1, availableEditions.length - 1));
|
||||
setFocusedIdx((p) => Math.min(p + 1, editionOptions.length - 1));
|
||||
} else if (e.key === "Enter") {
|
||||
if (availableEditions.length > 0) {
|
||||
installTo(availableEditions[focusedIdx].id);
|
||||
if (editionOptions.length > 0) {
|
||||
installTo(editionOptions[focusedIdx].instanceId);
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [availableEditions, focusedIdx, status, onClose, playPressSound]);
|
||||
}, [editionOptions, focusedIdx, status, onClose, playPressSound]);
|
||||
|
||||
const installDeps = async (instanceId: string) => {
|
||||
for (const depId of dependencies) {
|
||||
@@ -2216,24 +2224,24 @@ function InstallModal({
|
||||
|
||||
{status === "idle" &&
|
||||
!isPluginTab &&
|
||||
(availableEditions.length === 0 ? (
|
||||
(editionOptions.length === 0 ? (
|
||||
<div className="py-6 flex items-center justify-center">
|
||||
<span className="text-[#FF5555] mc-text-shadow">
|
||||
No installed editions found
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
availableEditions.map((ed, i) => (
|
||||
editionOptions.map((opt, i) => (
|
||||
<div
|
||||
key={ed.id}
|
||||
onClick={() => installTo(ed.id)}
|
||||
key={opt.instanceId}
|
||||
onClick={() => installTo(opt.instanceId)}
|
||||
onMouseEnter={() => setFocusedIdx(i)}
|
||||
className={`flex flex-col p-3 cursor-pointer border-2 transition-none ${focusedIdx === i ? "border-[#FFFF55] bg-black/40" : "border-[#444] bg-black/20"}`}
|
||||
>
|
||||
<span
|
||||
className={`text-lg mc-text-shadow ${focusedIdx === i ? "text-[#FFFF55]" : "text-white"}`}
|
||||
>
|
||||
{ed.name}
|
||||
{opt.label}
|
||||
</span>
|
||||
</div>
|
||||
))
|
||||
|
||||
@@ -215,7 +215,7 @@ export const SPLASHES = [
|
||||
"I don't know what woke means can someone tell me",
|
||||
"I HATE WHEN PEOPLE USE UPPERCASE LETTERS",
|
||||
"Erm.... He's right behind me, isn't he?",
|
||||
"What does \"the\" even mean man",
|
||||
'What does "the" even mean man',
|
||||
"Tip: Bigger, longer and uncut.",
|
||||
"This is the longest sentence ever",
|
||||
"This is the shortest sentence scientifically possible, according to me.",
|
||||
@@ -231,4 +231,5 @@ export const SPLASHES = [
|
||||
"Edgy humor is soo edgy",
|
||||
"I LOVE YURI!!!!!!! oh and yaoi ig",
|
||||
"RIP PrismaChunk0's Dog 2010-2026",
|
||||
];
|
||||
"Guess who's back, back again!",
|
||||
];
|
||||
|
||||
@@ -43,7 +43,10 @@ export function useDiscordRPC({
|
||||
: `Logged in as ${username}`;
|
||||
|
||||
if (isGameRunning) {
|
||||
details = `Playing ${versionName}`;
|
||||
details =
|
||||
activeView === "lceonline"
|
||||
? `Playing ${versionName} Multiplayer`
|
||||
: `Playing ${versionName}`;
|
||||
} else if (downloadingIds.length > 0) {
|
||||
const firstId = downloadingIds[0];
|
||||
const pct = downloadProgress[firstId];
|
||||
|
||||
@@ -30,7 +30,7 @@ export const BASE_EDITIONS = [
|
||||
id: "legacy_evolved",
|
||||
name: "neoLegacy",
|
||||
desc: "Backporting newer title updates and Minigames back to LCE",
|
||||
url: "https://git.neolegacy.dev/neoStudiosLCE/neoLegacy/releases/download/1.0.8b/neoLegacyWindows64.zip",
|
||||
url: "https://bucket.ibatv.xyz/neolegacy/Release.zip",
|
||||
titleImage: "/images/minecraft_title_neoLegacy.png",
|
||||
supportsSlimSkins: true,
|
||||
logo: "/images/neoLegacy.png",
|
||||
@@ -500,7 +500,8 @@ export function useGameManager({
|
||||
? (extraLaunchArgs ?? []).concat([
|
||||
"-token",
|
||||
localStorage.getItem("lceonline_session")
|
||||
? JSON.parse(localStorage.getItem("lceonline_session")!).accessToken
|
||||
? JSON.parse(localStorage.getItem("lceonline_session")!)
|
||||
.accessToken
|
||||
: "",
|
||||
])
|
||||
: extraLaunchArgs,
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { lceOnlineService } from "../services/LceOnlineService";
|
||||
export function useLceOnlineNotifications() {
|
||||
const [friendRequestMessage, setFriendRequestMessage] = useState<string | null>(null);
|
||||
const [friendRequestMessage, setFriendRequestMessage] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [InviteMessage, setInviteMessage] = useState<string | null>(null);
|
||||
const [invites, setInvites] = useState<Array<{ inviteid: string; from: { uuid: string; username: string; }; sessionid: string; }>>([]);
|
||||
const [invites, setInvites] = useState<
|
||||
Array<{
|
||||
inviteid: string;
|
||||
from: { uuid: string; username: string };
|
||||
sessionid: string;
|
||||
}>
|
||||
>([]);
|
||||
const seenRequests = useRef<Set<string>>(new Set());
|
||||
const seenInvites = useRef<Set<string>>(new Set());
|
||||
useEffect(() => {
|
||||
@@ -24,12 +32,12 @@ export function useLceOnlineNotifications() {
|
||||
const invitesData = await lceOnlineService.getInvites();
|
||||
setInvites(invitesData);
|
||||
invitesData.forEach((i) => {
|
||||
if (!seenInvites.current.has(i.inviteid)) {
|
||||
seenInvites.current.add(i.inviteid);
|
||||
setInviteMessage(`${i.from.username} invited you to play!`);
|
||||
}
|
||||
});
|
||||
} catch { }
|
||||
if (!seenInvites.current.has(i.inviteid)) {
|
||||
seenInvites.current.add(i.inviteid);
|
||||
setInviteMessage(`${i.from.username} invited you to play!`);
|
||||
}
|
||||
});
|
||||
} catch {}
|
||||
};
|
||||
|
||||
const init = async () => {
|
||||
@@ -39,7 +47,6 @@ export function useLceOnlineNotifications() {
|
||||
lists.requests.forEach((r: string) => {
|
||||
if (!seenRequests.current.has(r)) {
|
||||
seenRequests.current.add(r);
|
||||
setFriendRequestMessage(`${r} wants to be friends!`);
|
||||
}
|
||||
});
|
||||
} catch (e) {}
|
||||
@@ -47,12 +54,12 @@ export function useLceOnlineNotifications() {
|
||||
const invitesData = await lceOnlineService.getInvites();
|
||||
setInvites(invitesData);
|
||||
invitesData.forEach((i) => {
|
||||
if (!seenInvites.current.has(i.inviteid)) {
|
||||
seenInvites.current.add(i.inviteid);
|
||||
setInviteMessage(`${i.from.username} invited you to play!`);
|
||||
}
|
||||
});
|
||||
} catch { }
|
||||
if (!seenInvites.current.has(i.inviteid)) {
|
||||
seenInvites.current.add(i.inviteid);
|
||||
setInviteMessage(`${i.from.username} invited you to play!`);
|
||||
}
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
pollInterval = setInterval(poll, 3000);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user