mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-07-16 08:55:52 +00:00
add map info dialog
This commit is contained in:
parent
0b345facea
commit
c44df43a91
36 changed files with 2051 additions and 1068 deletions
44
app/page.tsx
44
app/page.tsx
|
|
@ -1,5 +1,12 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { useState, useEffect, useCallback, Suspense, useRef } from "react";
|
import {
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useCallback,
|
||||||
|
Suspense,
|
||||||
|
useRef,
|
||||||
|
lazy,
|
||||||
|
} from "react";
|
||||||
import { Canvas, GLProps } from "@react-three/fiber";
|
import { Canvas, GLProps } from "@react-three/fiber";
|
||||||
import { NoToneMapping, SRGBColorSpace, PCFShadowMap, Camera } from "three";
|
import { NoToneMapping, SRGBColorSpace, PCFShadowMap, Camera } from "three";
|
||||||
import { Mission } from "@/src/components/Mission";
|
import { Mission } from "@/src/components/Mission";
|
||||||
|
|
@ -25,6 +32,12 @@ import { CamerasProvider } from "@/src/components/CamerasProvider";
|
||||||
import { getMissionList, getMissionInfo } from "@/src/manifest";
|
import { getMissionList, getMissionInfo } from "@/src/manifest";
|
||||||
import { createParser, parseAsBoolean, useQueryState } from "nuqs";
|
import { createParser, parseAsBoolean, useQueryState } from "nuqs";
|
||||||
|
|
||||||
|
const MapInfoDialog = lazy(() =>
|
||||||
|
import("@/src/components/MapInfoDialog").then((mod) => ({
|
||||||
|
default: mod.MapInfoDialog,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
// Three.js has its own loaders for textures and models, but we need to load other
|
// Three.js has its own loaders for textures and models, but we need to load other
|
||||||
// stuff too, e.g. missions, terrains, and more. This client is used for those.
|
// stuff too, e.g. missions, terrains, and more. This client is used for those.
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
@ -94,6 +107,7 @@ function MapInspector() {
|
||||||
|
|
||||||
const isTouch = useTouchDevice();
|
const isTouch = useTouchDevice();
|
||||||
const { missionName, missionType } = currentMission;
|
const { missionName, missionType } = currentMission;
|
||||||
|
const [mapInfoOpen, setMapInfoOpen] = useState(false);
|
||||||
const [loadingProgress, setLoadingProgress] = useState(0);
|
const [loadingProgress, setLoadingProgress] = useState(0);
|
||||||
const [showLoadingIndicator, setShowLoadingIndicator] = useState(true);
|
const [showLoadingIndicator, setShowLoadingIndicator] = useState(true);
|
||||||
const isLoading = loadingProgress < 1;
|
const isLoading = loadingProgress < 1;
|
||||||
|
|
@ -127,6 +141,23 @@ function MapInspector() {
|
||||||
};
|
};
|
||||||
}, [changeMission]);
|
}, [changeMission]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKey = (e: KeyboardEvent) => {
|
||||||
|
if (e.code !== "KeyI" || e.metaKey || e.ctrlKey || e.altKey) return;
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
if (
|
||||||
|
target.tagName === "INPUT" ||
|
||||||
|
target.tagName === "TEXTAREA" ||
|
||||||
|
target.isContentEditable
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setMapInfoOpen(true);
|
||||||
|
};
|
||||||
|
window.addEventListener("keydown", handleKey);
|
||||||
|
return () => window.removeEventListener("keydown", handleKey);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleLoadingChange = useCallback(
|
const handleLoadingChange = useCallback(
|
||||||
(_loading: boolean, progress: number = 0) => {
|
(_loading: boolean, progress: number = 0) => {
|
||||||
setLoadingProgress(progress);
|
setLoadingProgress(progress);
|
||||||
|
|
@ -208,9 +239,20 @@ function MapInspector() {
|
||||||
missionName={missionName}
|
missionName={missionName}
|
||||||
missionType={missionType}
|
missionType={missionType}
|
||||||
onChangeMission={changeMission}
|
onChangeMission={changeMission}
|
||||||
|
onOpenMapInfo={() => setMapInfoOpen(true)}
|
||||||
cameraRef={cameraRef}
|
cameraRef={cameraRef}
|
||||||
isTouch={isTouch}
|
isTouch={isTouch}
|
||||||
/>
|
/>
|
||||||
|
{mapInfoOpen && (
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<MapInfoDialog
|
||||||
|
open={mapInfoOpen}
|
||||||
|
onClose={() => setMapInfoOpen(false)}
|
||||||
|
missionName={missionName}
|
||||||
|
missionType={missionType ?? ""}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
|
)}
|
||||||
</KeyboardControls>
|
</KeyboardControls>
|
||||||
</SettingsProvider>
|
</SettingsProvider>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
300
app/style.css
300
app/style.css
|
|
@ -10,6 +10,9 @@ html {
|
||||||
*:before,
|
*:before,
|
||||||
*:after {
|
*:after {
|
||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
}
|
}
|
||||||
|
|
@ -203,6 +206,10 @@ input[type="range"] {
|
||||||
.LabelledButton .ButtonLabel {
|
.LabelledButton .ButtonLabel {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MapInfoButton {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.CopyCoordinatesButton[data-copied="true"] {
|
.CopyCoordinatesButton[data-copied="true"] {
|
||||||
|
|
@ -569,6 +576,295 @@ input[type="range"] {
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog {
|
||||||
|
position: relative;
|
||||||
|
width: 800px;
|
||||||
|
height: 600px;
|
||||||
|
max-width: calc(100dvw - 40px);
|
||||||
|
max-height: calc(100dvh - 40px);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 100%;
|
||||||
|
grid-template-rows: 1fr auto;
|
||||||
|
background: rgba(20, 37, 38, 0.8);
|
||||||
|
border: 1px solid rgba(65, 131, 139, 0.6);
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px rgba(0, 190, 220, 0.12),
|
||||||
|
0 0 60px rgba(0, 140, 180, 0.12),
|
||||||
|
inset 0 0 60px rgba(1, 7, 13, 0.6);
|
||||||
|
color: #bccec3;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
outline: none;
|
||||||
|
user-select: text;
|
||||||
|
-webkit-touch-callout: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-inner {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
grid-template-rows: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-left {
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 24px 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-right {
|
||||||
|
border-left: 1px solid rgba(0, 190, 220, 0.3);
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-preview {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-preview--floated {
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
margin: 0 0 16px 20px;
|
||||||
|
max-height: 260px;
|
||||||
|
max-width: 30%;
|
||||||
|
width: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-title {
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #7dffff;
|
||||||
|
margin: 0;
|
||||||
|
text-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px 16px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 400;
|
||||||
|
/* text-transform: uppercase; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-planet {
|
||||||
|
color: rgba(219, 202, 168, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-quote {
|
||||||
|
margin: 16px 0;
|
||||||
|
padding: 0 0 0 14px;
|
||||||
|
border-left: 2px solid rgba(0, 190, 220, 0.35);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-quote p {
|
||||||
|
margin: 0 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-quote cite {
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(255, 255, 255, 0.45);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-blurb {
|
||||||
|
font-size: 13px;
|
||||||
|
margin: 0 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-section {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-sectionTitle {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #7dffff;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-shadow: 0 0 16px rgba(0, 210, 240, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-musicTrack {
|
||||||
|
margin-top: 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgba(202, 208, 172, 0.5);
|
||||||
|
font-style: italic;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-musicTrack[data-playing="true"] {
|
||||||
|
color: rgba(247, 253, 216, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-musicBtn {
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
color: rgb(85, 118, 99);
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-musicTrack[data-playing="true"] .MapInfoDialog-musicBtn {
|
||||||
|
color: rgb(109, 255, 170);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-musicTrack[data-playing="true"] .MapInfoDialog-musicBtn:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-top: 1px solid rgba(0, 190, 220, 0.25);
|
||||||
|
background: rgba(2, 20, 21, 0.7);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-closeBtn {
|
||||||
|
padding: 4px 18px;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgba(41, 172, 156, 0.7),
|
||||||
|
rgba(0, 80, 65, 0.7)
|
||||||
|
);
|
||||||
|
border: 1px solid rgba(41, 97, 84, 0.6);
|
||||||
|
border-top-color: rgba(101, 185, 176, 0.5);
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(120, 220, 195, 0.2),
|
||||||
|
inset 0 -1px 0 rgba(0, 0, 0, 0.3),
|
||||||
|
0 2px 4px rgba(0, 0, 0, 0.4);
|
||||||
|
color: rgba(154, 239, 225, 0.9);
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-closeBtn:active {
|
||||||
|
transform: translate(0, 1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-hint {
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(201, 220, 216, 0.3);
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 719px) {
|
||||||
|
.MapInfoDialog-inner {
|
||||||
|
display: block;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-hint {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-left {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 16px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-right {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
overflow: auto;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-preview {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
margin: 16px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MapInfoDialog-closeBtn {
|
||||||
|
width: 220px;
|
||||||
|
height: 36px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.GuiMarkup-line {
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GuiMarkup-spacer {
|
||||||
|
height: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GuiMarkup-bulletLine {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 5px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GuiMarkup-bulletIcon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GuiMarkup-bulletText {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GuiMarkup-bitmap {
|
||||||
|
max-height: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GuiMarkup-bullet {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
.TouchJoystick {
|
.TouchJoystick {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
|
|
@ -609,3 +905,7 @@ input[type="range"] {
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.15),
|
inset 0 1px 0 rgba(255, 255, 255, 0.15),
|
||||||
inset 0 -1px 2px rgba(0, 0, 0, 0.3) !important;
|
inset 0 -1px 2px rgba(0, 0, 0, 0.3) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MusicTrackName {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,9 +1,9 @@
|
||||||
1:"$Sreact.fragment"
|
1:"$Sreact.fragment"
|
||||||
2:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
|
2:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
|
||||||
3:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/69160059bd4715b0.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/05a33d80986f6f4c.js","/t2-mapper/_next/static/chunks/648c99009376fcef.js"],"default"]
|
3:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/fd5173b60870d6fb.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/143bcebca21d60e5.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
|
||||||
6:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
6:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
||||||
7:"$Sreact.suspense"
|
7:"$Sreact.suspense"
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/69160059bd4715b0.js","async":true}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/05a33d80986f6f4c.js","async":true}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/648c99009376fcef.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/fd5173b60870d6fb.js","async":true}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/143bcebca21d60e5.js","async":true}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
|
||||||
4:{}
|
4:{}
|
||||||
5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
|
5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
|
||||||
8:null
|
8:null
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@
|
||||||
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
5:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
|
5:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
|
||||||
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/69160059bd4715b0.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/05a33d80986f6f4c.js","/t2-mapper/_next/static/chunks/648c99009376fcef.js"],"default"]
|
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/fd5173b60870d6fb.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/143bcebca21d60e5.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
|
||||||
9:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
9:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
||||||
a:"$Sreact.suspense"
|
a:"$Sreact.suspense"
|
||||||
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
||||||
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
||||||
10:I[68027,[],"default"]
|
10:I[68027,[],"default"]
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"P":null,"b":"h-5uE8DkCRlEiwNbWUb1K","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/e830bdf778a42251.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/69160059bd4715b0.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/05a33d80986f6f4c.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/648c99009376fcef.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
|
0:{"P":null,"b":"8Gyh12L4dTN96synIylXt","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/748c06086372a1f2.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/fd5173b60870d6fb.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/143bcebca21d60e5.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
|
||||||
7:{}
|
7:{}
|
||||||
8:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
8:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
||||||
d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
||||||
4:"$Sreact.suspense"
|
4:"$Sreact.suspense"
|
||||||
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
|
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
|
||||||
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/e830bdf778a42251.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/748c06086372a1f2.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
528
docs/_next/static/chunks/143bcebca21d60e5.js
Normal file
528
docs/_next/static/chunks/143bcebca21d60e5.js
Normal file
File diff suppressed because one or more lines are too long
351
docs/_next/static/chunks/5619c5b2b1355f74.js
Normal file
351
docs/_next/static/chunks/5619c5b2b1355f74.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
docs/_next/static/chunks/748c06086372a1f2.css
Normal file
1
docs/_next/static/chunks/748c06086372a1f2.css
Normal file
File diff suppressed because one or more lines are too long
1
docs/_next/static/chunks/aa3c97b2da210ead.js
Normal file
1
docs/_next/static/chunks/aa3c97b2da210ead.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/_next/static/chunks/bb0aa1c978feffed.js
Normal file
1
docs/_next/static/chunks/bb0aa1c978feffed.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
52
docs/_next/static/chunks/fcdc907286f09d63.js
Normal file
52
docs/_next/static/chunks/fcdc907286f09d63.js
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -208,4 +208,4 @@
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
`}),[P]);return a.createElement("group",(0,c.default)({},L,{ref:q}),E&&!et&&a.createElement("mesh",{castShadow:T,receiveShadow:w,ref:Q},D||a.createElement("planeGeometry",null),O||a.createElement("shaderMaterial",{side:s.DoubleSide,vertexShader:ea.vertexShader,fragmentShader:ea.fragmentShader})))});e.s(["Html",()=>b],60099);let F=[0,0,0],S=(0,a.memo)(function(e){let t,r,c,u,f,d=(0,o.c)(19),{children:m,color:g,position:h,opacity:v}=e,p=void 0===g?"white":g,x=void 0===h?F:h,y=void 0===v?"fadeWithDistance":v,S="fadeWithDistance"===y,M=(0,a.useRef)(null),P=function(e){let t,r,i=(0,o.c)(3),{camera:c}=(0,l.useThree)(),u=(0,a.useRef)(null),f=(r=(0,a.useRef)(null),(0,n.useFrame)(()=>{e.current&&(r.current??=new s.Vector3,e.current.getWorldPosition(r.current))}),r);return i[0]!==c||i[1]!==f?(t=()=>{f.current?u.current=c.position.distanceTo(f.current):u.current=null},i[0]=c,i[1]=f,i[2]=t):t=i[2],(0,n.useFrame)(t),u}(M),[E,_]=(0,a.useState)(0!==y),T=(0,a.useRef)(null);return d[0]!==P||d[1]!==S?(t=()=>{if(S&&T.current&&null!=P.current){let e=Math.max(0,Math.min(1,1-P.current/200));T.current.style.opacity=e.toString()}},d[0]=P,d[1]=S,d[2]=t):t=d[2],d[3]!==P||d[4]!==S||d[5]!==E?(r=[E,S,P],d[3]=P,d[4]=S,d[5]=E,d[6]=r):r=d[6],(0,a.useEffect)(t,r),d[7]!==P||d[8]!==S||d[9]!==E||d[10]!==y?(c=()=>{if(S){let e=P.current,t=null!=e&&e<200;if(E!==t&&_(t),T.current&&t){let t=Math.max(0,Math.min(1,1-e/200));T.current.style.opacity=t.toString()}}else _(0!==y),T.current&&(T.current.style.opacity=y.toString())},d[7]=P,d[8]=S,d[9]=E,d[10]=y,d[11]=c):c=d[11],(0,n.useFrame)(c),d[12]!==m||d[13]!==p||d[14]!==E||d[15]!==x?(u=E?(0,i.jsx)(b,{position:x,center:!0,children:(0,i.jsx)("div",{ref:T,className:"StaticShapeLabel",style:{color:p},children:m})}):null,d[12]=m,d[13]=p,d[14]=E,d[15]=x,d[16]=u):u=d[16],d[17]!==u?(f=(0,i.jsx)("group",{ref:M,children:u}),d[17]=u,d[18]=f):f=d[18],f});e.s(["FloatingLabel",0,S],89887)},51434,e=>{"use strict";var t=e.i(43476),r=e.i(932),i=e.i(71645),o=e.i(73949),a=e.i(90072);let n=(0,i.createContext)(void 0);function l(e){let l,c,u,f,d=(0,r.c)(7),{children:m}=e,{camera:g}=(0,o.useThree)();d[0]===Symbol.for("react.memo_cache_sentinel")?(l={audioLoader:null,audioListener:null},d[0]=l):l=d[0];let[h,v]=(0,i.useState)(l);return d[1]!==g?(c=()=>{let e=new a.AudioLoader,t=g.children.find(s);t||(t=new a.AudioListener,g.add(t)),v({audioLoader:e,audioListener:t})},u=[g],d[1]=g,d[2]=c,d[3]=u):(c=d[2],u=d[3]),(0,i.useEffect)(c,u),d[4]!==h||d[5]!==m?(f=(0,t.jsx)(n.Provider,{value:h,children:m}),d[4]=h,d[5]=m,d[6]=f):f=d[6],f}function s(e){return e instanceof a.AudioListener}function c(){let e=(0,i.useContext)(n);if(void 0===e)throw Error("useAudio must be used within AudioProvider");return e}e.s(["AudioProvider",()=>l,"useAudio",()=>c])},61921,e=>{e.v(t=>Promise.all(["static/chunks/cb4089eec9313f48.js"].map(t=>e.l(t))).then(()=>t(29055)))},25147,e=>{e.v(t=>Promise.all(["static/chunks/4e5626f3eeee0985.js"].map(t=>e.l(t))).then(()=>t(63724)))},18599,e=>{e.v(t=>Promise.all(["static/chunks/6e74e9455d83b68c.js"].map(t=>e.l(t))).then(()=>t(42585)))},84968,e=>{e.v(t=>Promise.all(["static/chunks/70bf3e06d5674fac.js"].map(t=>e.l(t))).then(()=>t(90208)))}]);
|
`}),[P]);return a.createElement("group",(0,c.default)({},L,{ref:q}),E&&!et&&a.createElement("mesh",{castShadow:T,receiveShadow:w,ref:Q},D||a.createElement("planeGeometry",null),O||a.createElement("shaderMaterial",{side:s.DoubleSide,vertexShader:ea.vertexShader,fragmentShader:ea.fragmentShader})))});e.s(["Html",()=>b],60099);let F=[0,0,0],S=(0,a.memo)(function(e){let t,r,c,u,f,d=(0,o.c)(19),{children:m,color:g,position:h,opacity:v}=e,p=void 0===g?"white":g,x=void 0===h?F:h,y=void 0===v?"fadeWithDistance":v,S="fadeWithDistance"===y,M=(0,a.useRef)(null),P=function(e){let t,r,i=(0,o.c)(3),{camera:c}=(0,l.useThree)(),u=(0,a.useRef)(null),f=(r=(0,a.useRef)(null),(0,n.useFrame)(()=>{e.current&&(r.current??=new s.Vector3,e.current.getWorldPosition(r.current))}),r);return i[0]!==c||i[1]!==f?(t=()=>{f.current?u.current=c.position.distanceTo(f.current):u.current=null},i[0]=c,i[1]=f,i[2]=t):t=i[2],(0,n.useFrame)(t),u}(M),[E,_]=(0,a.useState)(0!==y),T=(0,a.useRef)(null);return d[0]!==P||d[1]!==S?(t=()=>{if(S&&T.current&&null!=P.current){let e=Math.max(0,Math.min(1,1-P.current/200));T.current.style.opacity=e.toString()}},d[0]=P,d[1]=S,d[2]=t):t=d[2],d[3]!==P||d[4]!==S||d[5]!==E?(r=[E,S,P],d[3]=P,d[4]=S,d[5]=E,d[6]=r):r=d[6],(0,a.useEffect)(t,r),d[7]!==P||d[8]!==S||d[9]!==E||d[10]!==y?(c=()=>{if(S){let e=P.current,t=null!=e&&e<200;if(E!==t&&_(t),T.current&&t){let t=Math.max(0,Math.min(1,1-e/200));T.current.style.opacity=t.toString()}}else _(0!==y),T.current&&(T.current.style.opacity=y.toString())},d[7]=P,d[8]=S,d[9]=E,d[10]=y,d[11]=c):c=d[11],(0,n.useFrame)(c),d[12]!==m||d[13]!==p||d[14]!==E||d[15]!==x?(u=E?(0,i.jsx)(b,{position:x,center:!0,children:(0,i.jsx)("div",{ref:T,className:"StaticShapeLabel",style:{color:p},children:m})}):null,d[12]=m,d[13]=p,d[14]=E,d[15]=x,d[16]=u):u=d[16],d[17]!==u?(f=(0,i.jsx)("group",{ref:M,children:u}),d[17]=u,d[18]=f):f=d[18],f});e.s(["FloatingLabel",0,S],89887)},51434,e=>{"use strict";var t=e.i(43476),r=e.i(932),i=e.i(71645),o=e.i(73949),a=e.i(90072);let n=(0,i.createContext)(void 0);function l(e){let l,c,u,f,d=(0,r.c)(7),{children:m}=e,{camera:g}=(0,o.useThree)();d[0]===Symbol.for("react.memo_cache_sentinel")?(l={audioLoader:null,audioListener:null},d[0]=l):l=d[0];let[h,v]=(0,i.useState)(l);return d[1]!==g?(c=()=>{let e=new a.AudioLoader,t=g.children.find(s);t||(t=new a.AudioListener,g.add(t)),v({audioLoader:e,audioListener:t})},u=[g],d[1]=g,d[2]=c,d[3]=u):(c=d[2],u=d[3]),(0,i.useEffect)(c,u),d[4]!==h||d[5]!==m?(f=(0,t.jsx)(n.Provider,{value:h,children:m}),d[4]=h,d[5]=m,d[6]=f):f=d[6],f}function s(e){return e instanceof a.AudioListener}function c(){let e=(0,i.useContext)(n);if(void 0===e)throw Error("useAudio must be used within AudioProvider");return e}e.s(["AudioProvider",()=>l,"useAudio",()=>c])},61921,e=>{e.v(t=>Promise.all(["static/chunks/cb4089eec9313f48.js"].map(t=>e.l(t))).then(()=>t(29055)))},25147,e=>{e.v(t=>Promise.all(["static/chunks/4e5626f3eeee0985.js"].map(t=>e.l(t))).then(()=>t(63724)))},18599,e=>{e.v(t=>Promise.all(["static/chunks/6e74e9455d83b68c.js"].map(t=>e.l(t))).then(()=>t(42585)))},84968,e=>{e.v(t=>Promise.all(["static/chunks/70bf3e06d5674fac.js"].map(t=>e.l(t))).then(()=>t(90208)))},59197,e=>{e.v(t=>Promise.all(["static/chunks/aa3c97b2da210ead.js"].map(t=>e.l(t))).then(()=>t(94247)))}]);
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
||||||
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
||||||
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"P":null,"b":"h-5uE8DkCRlEiwNbWUb1K","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/e830bdf778a42251.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
|
0:{"P":null,"b":"8Gyh12L4dTN96synIylXt","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/748c06086372a1f2.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
|
||||||
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
||||||
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
||||||
7:null
|
7:null
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
||||||
4:"$Sreact.suspense"
|
4:"$Sreact.suspense"
|
||||||
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","rsc":["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","rsc":["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
|
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
|
||||||
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/e830bdf778a42251.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/748c06086372a1f2.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
1:"$Sreact.fragment"
|
1:"$Sreact.fragment"
|
||||||
2:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
2:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
||||||
3:"$Sreact.suspense"
|
3:"$Sreact.suspense"
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","rsc":["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"loading":null,"isPartial":false}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","rsc":["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"loading":null,"isPartial":false}
|
||||||
4:null
|
4:null
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
1:"$Sreact.fragment"
|
1:"$Sreact.fragment"
|
||||||
2:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
2:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
3:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
3:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"buildId":"h-5uE8DkCRlEiwNbWUb1K","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"/_not-found","paramType":null,"paramKey":"/_not-found","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
|
0:{"buildId":"8Gyh12L4dTN96synIylXt","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"/_not-found","paramType":null,"paramKey":"/_not-found","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -7,8 +7,8 @@
|
||||||
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
||||||
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
||||||
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"P":null,"b":"h-5uE8DkCRlEiwNbWUb1K","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/e830bdf778a42251.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
|
0:{"P":null,"b":"8Gyh12L4dTN96synIylXt","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/748c06086372a1f2.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
|
||||||
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
||||||
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
|
||||||
7:null
|
7:null
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -3,14 +3,14 @@
|
||||||
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
|
||||||
5:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
|
5:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
|
||||||
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/69160059bd4715b0.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/05a33d80986f6f4c.js","/t2-mapper/_next/static/chunks/648c99009376fcef.js"],"default"]
|
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/fd5173b60870d6fb.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/143bcebca21d60e5.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
|
||||||
9:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
9:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
|
||||||
a:"$Sreact.suspense"
|
a:"$Sreact.suspense"
|
||||||
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
|
||||||
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
|
||||||
10:I[68027,[],"default"]
|
10:I[68027,[],"default"]
|
||||||
:HL["/t2-mapper/_next/static/chunks/e830bdf778a42251.css","style"]
|
:HL["/t2-mapper/_next/static/chunks/748c06086372a1f2.css","style"]
|
||||||
0:{"P":null,"b":"h-5uE8DkCRlEiwNbWUb1K","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/e830bdf778a42251.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/69160059bd4715b0.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/05a33d80986f6f4c.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/648c99009376fcef.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
|
0:{"P":null,"b":"8Gyh12L4dTN96synIylXt","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/748c06086372a1f2.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/fd5173b60870d6fb.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/143bcebca21d60e5.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
|
||||||
7:{}
|
7:{}
|
||||||
8:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
8:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
||||||
d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,13 @@ import { MissionSelect } from "./MissionSelect";
|
||||||
import { RefObject, useEffect, useState, useRef } from "react";
|
import { RefObject, useEffect, useState, useRef } from "react";
|
||||||
import { Camera } from "three";
|
import { Camera } from "three";
|
||||||
import { CopyCoordinatesButton } from "./CopyCoordinatesButton";
|
import { CopyCoordinatesButton } from "./CopyCoordinatesButton";
|
||||||
import { FiSettings } from "react-icons/fi";
|
import { FiInfo, FiSettings } from "react-icons/fi";
|
||||||
|
|
||||||
export function InspectorControls({
|
export function InspectorControls({
|
||||||
missionName,
|
missionName,
|
||||||
missionType,
|
missionType,
|
||||||
onChangeMission,
|
onChangeMission,
|
||||||
|
onOpenMapInfo,
|
||||||
cameraRef,
|
cameraRef,
|
||||||
isTouch,
|
isTouch,
|
||||||
}: {
|
}: {
|
||||||
|
|
@ -26,6 +27,7 @@ export function InspectorControls({
|
||||||
missionName: string;
|
missionName: string;
|
||||||
missionType: string;
|
missionType: string;
|
||||||
}) => void;
|
}) => void;
|
||||||
|
onOpenMapInfo: () => void;
|
||||||
cameraRef: RefObject<Camera | null>;
|
cameraRef: RefObject<Camera | null>;
|
||||||
isTouch: boolean | null;
|
isTouch: boolean | null;
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -70,110 +72,6 @@ export function InspectorControls({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const settingsFields = (
|
|
||||||
<>
|
|
||||||
<div className="Controls-group">
|
|
||||||
<CopyCoordinatesButton
|
|
||||||
cameraRef={cameraRef}
|
|
||||||
missionName={missionName}
|
|
||||||
missionType={missionType}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="Controls-group">
|
|
||||||
<div className="CheckboxField">
|
|
||||||
<input
|
|
||||||
id="fogInput"
|
|
||||||
type="checkbox"
|
|
||||||
checked={fogEnabled}
|
|
||||||
onChange={(event) => {
|
|
||||||
setFogEnabled(event.target.checked);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<label htmlFor="fogInput">Fog?</label>
|
|
||||||
</div>
|
|
||||||
<div className="CheckboxField">
|
|
||||||
<input
|
|
||||||
id="audioInput"
|
|
||||||
type="checkbox"
|
|
||||||
checked={audioEnabled}
|
|
||||||
onChange={(event) => {
|
|
||||||
setAudioEnabled(event.target.checked);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<label htmlFor="audioInput">Audio?</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="Controls-group">
|
|
||||||
<div className="CheckboxField">
|
|
||||||
<input
|
|
||||||
id="animationInput"
|
|
||||||
type="checkbox"
|
|
||||||
checked={animationEnabled}
|
|
||||||
onChange={(event) => {
|
|
||||||
setAnimationEnabled(event.target.checked);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<label htmlFor="animationInput">Animation?</label>
|
|
||||||
</div>
|
|
||||||
<div className="CheckboxField">
|
|
||||||
<input
|
|
||||||
id="debugInput"
|
|
||||||
type="checkbox"
|
|
||||||
checked={debugMode}
|
|
||||||
onChange={(event) => {
|
|
||||||
setDebugMode(event.target.checked);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<label htmlFor="debugInput">Debug?</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="Controls-group">
|
|
||||||
<div className="Field">
|
|
||||||
<label htmlFor="fovInput">FOV</label>
|
|
||||||
<input
|
|
||||||
id="fovInput"
|
|
||||||
type="range"
|
|
||||||
min={75}
|
|
||||||
max={120}
|
|
||||||
step={5}
|
|
||||||
value={fov}
|
|
||||||
onChange={(event) => setFov(parseInt(event.target.value))}
|
|
||||||
/>
|
|
||||||
<output htmlFor="fovInput">{fov}</output>
|
|
||||||
</div>
|
|
||||||
<div className="Field">
|
|
||||||
<label htmlFor="speedInput">Speed</label>
|
|
||||||
<input
|
|
||||||
id="speedInput"
|
|
||||||
type="range"
|
|
||||||
min={0.1}
|
|
||||||
max={5}
|
|
||||||
step={0.05}
|
|
||||||
value={speedMultiplier}
|
|
||||||
onChange={(event) =>
|
|
||||||
setSpeedMultiplier(parseFloat(event.target.value))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{isTouch && (
|
|
||||||
<div className="Controls-group">
|
|
||||||
<div className="Field">
|
|
||||||
<label htmlFor="touchModeInput">Joystick:</label>{" "}
|
|
||||||
<select
|
|
||||||
id="touchModeInput"
|
|
||||||
value={touchMode}
|
|
||||||
onChange={(e) => setTouchMode(e.target.value as TouchMode)}
|
|
||||||
>
|
|
||||||
<option value="dualStick">Dual Stick</option>
|
|
||||||
<option value="moveLookStick">Single Stick</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id="controls"
|
id="controls"
|
||||||
|
|
@ -208,7 +106,114 @@ export function InspectorControls({
|
||||||
onBlur={handleDropdownBlur}
|
onBlur={handleDropdownBlur}
|
||||||
data-open={settingsOpen}
|
data-open={settingsOpen}
|
||||||
>
|
>
|
||||||
{settingsFields}
|
<div className="Controls-group">
|
||||||
|
<CopyCoordinatesButton
|
||||||
|
cameraRef={cameraRef}
|
||||||
|
missionName={missionName}
|
||||||
|
missionType={missionType}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="IconButton LabelledButton MapInfoButton"
|
||||||
|
aria-label="Show map info"
|
||||||
|
onClick={onOpenMapInfo}
|
||||||
|
>
|
||||||
|
<FiInfo />
|
||||||
|
<span className="ButtonLabel">Show map info</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="Controls-group">
|
||||||
|
<div className="CheckboxField">
|
||||||
|
<input
|
||||||
|
id="fogInput"
|
||||||
|
type="checkbox"
|
||||||
|
checked={fogEnabled}
|
||||||
|
onChange={(event) => {
|
||||||
|
setFogEnabled(event.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="fogInput">Fog?</label>
|
||||||
|
</div>
|
||||||
|
<div className="CheckboxField">
|
||||||
|
<input
|
||||||
|
id="audioInput"
|
||||||
|
type="checkbox"
|
||||||
|
checked={audioEnabled}
|
||||||
|
onChange={(event) => {
|
||||||
|
setAudioEnabled(event.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="audioInput">Audio?</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="Controls-group">
|
||||||
|
<div className="CheckboxField">
|
||||||
|
<input
|
||||||
|
id="animationInput"
|
||||||
|
type="checkbox"
|
||||||
|
checked={animationEnabled}
|
||||||
|
onChange={(event) => {
|
||||||
|
setAnimationEnabled(event.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="animationInput">Animation?</label>
|
||||||
|
</div>
|
||||||
|
<div className="CheckboxField">
|
||||||
|
<input
|
||||||
|
id="debugInput"
|
||||||
|
type="checkbox"
|
||||||
|
checked={debugMode}
|
||||||
|
onChange={(event) => {
|
||||||
|
setDebugMode(event.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="debugInput">Debug?</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="Controls-group">
|
||||||
|
<div className="Field">
|
||||||
|
<label htmlFor="fovInput">FOV</label>
|
||||||
|
<input
|
||||||
|
id="fovInput"
|
||||||
|
type="range"
|
||||||
|
min={75}
|
||||||
|
max={120}
|
||||||
|
step={5}
|
||||||
|
value={fov}
|
||||||
|
onChange={(event) => setFov(parseInt(event.target.value))}
|
||||||
|
/>
|
||||||
|
<output htmlFor="fovInput">{fov}</output>
|
||||||
|
</div>
|
||||||
|
<div className="Field">
|
||||||
|
<label htmlFor="speedInput">Speed</label>
|
||||||
|
<input
|
||||||
|
id="speedInput"
|
||||||
|
type="range"
|
||||||
|
min={0.1}
|
||||||
|
max={5}
|
||||||
|
step={0.05}
|
||||||
|
value={speedMultiplier}
|
||||||
|
onChange={(event) =>
|
||||||
|
setSpeedMultiplier(parseFloat(event.target.value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{isTouch && (
|
||||||
|
<div className="Controls-group">
|
||||||
|
<div className="Field">
|
||||||
|
<label htmlFor="touchModeInput">Joystick:</label>{" "}
|
||||||
|
<select
|
||||||
|
id="touchModeInput"
|
||||||
|
value={touchMode}
|
||||||
|
onChange={(e) => setTouchMode(e.target.value as TouchMode)}
|
||||||
|
>
|
||||||
|
<option value="dualStick">Dual Stick</option>
|
||||||
|
<option value="moveLookStick">Single Stick</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
317
src/components/MapInfoDialog.tsx
Normal file
317
src/components/MapInfoDialog.tsx
Normal file
|
|
@ -0,0 +1,317 @@
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { FaVolumeUp, FaVolumeMute } from "react-icons/fa";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { loadMission, getUrlForPath, RESOURCE_ROOT_URL } from "../loaders";
|
||||||
|
import { getStandardTextureResourceKey } from "../manifest";
|
||||||
|
import { GuiMarkup, filterMissionStringByMode } from "../torqueGuiMarkup";
|
||||||
|
import type * as AST from "../torqueScript/ast";
|
||||||
|
|
||||||
|
function useParsedMission(name: string) {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["parsedMission", name],
|
||||||
|
queryFn: () => loadMission(name),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMissionGroupProps(ast: AST.Program): Record<string, string> {
|
||||||
|
for (const node of ast.body) {
|
||||||
|
if (node.type !== "ObjectDeclaration") continue;
|
||||||
|
const { instanceName, body } = node;
|
||||||
|
if (
|
||||||
|
instanceName &&
|
||||||
|
instanceName.type === "Identifier" &&
|
||||||
|
instanceName.name.toLowerCase() === "missiongroup"
|
||||||
|
) {
|
||||||
|
const props: Record<string, string> = {};
|
||||||
|
for (const item of body) {
|
||||||
|
if (item.type !== "Assignment") continue;
|
||||||
|
const { target, value } = item;
|
||||||
|
if (target.type === "Identifier" && value.type === "StringLiteral") {
|
||||||
|
props[target.name.toLowerCase()] = value.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBitmapUrl(
|
||||||
|
bitmap: string | null,
|
||||||
|
missionName: string,
|
||||||
|
): string | null {
|
||||||
|
// Try bitmap from pragma comment first (single-player missions use this)
|
||||||
|
if (bitmap) {
|
||||||
|
try {
|
||||||
|
const key = getStandardTextureResourceKey(`textures/gui/${bitmap}`);
|
||||||
|
return getUrlForPath(key);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
// Fall back to Load_<MissionName>.png convention (multiplayer missions)
|
||||||
|
try {
|
||||||
|
const key = getStandardTextureResourceKey(
|
||||||
|
`textures/gui/Load_${missionName}`,
|
||||||
|
);
|
||||||
|
return getUrlForPath(key);
|
||||||
|
} catch {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a preview image bypassing browser color management, matching how
|
||||||
|
* Tribes 2 displayed these textures (raw pixel values, no gamma conversion).
|
||||||
|
* Many T2 preview PNGs embed an incorrect gAMA chunk (22727 = gamma 4.4
|
||||||
|
* instead of the correct 45455 = gamma 2.2), which causes browsers to
|
||||||
|
* over-darken them. `colorSpaceConversion: "none"` ignores gAMA/ICC data.
|
||||||
|
*/
|
||||||
|
function RawPreviewImage({
|
||||||
|
src,
|
||||||
|
alt,
|
||||||
|
className = "MapInfoDialog-preview",
|
||||||
|
}: {
|
||||||
|
src: string;
|
||||||
|
alt: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const [isLoaded, setLoaded] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let cancelled = false;
|
||||||
|
fetch(src)
|
||||||
|
.then((r) => r.blob())
|
||||||
|
.then((blob) => createImageBitmap(blob, { colorSpaceConversion: "none" }))
|
||||||
|
.then((bitmap) => {
|
||||||
|
if (cancelled) {
|
||||||
|
bitmap.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const canvas = canvasRef.current;
|
||||||
|
if (!canvas) {
|
||||||
|
bitmap.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
canvas.width = bitmap.width;
|
||||||
|
canvas.height = bitmap.height;
|
||||||
|
canvas.getContext("2d")?.drawImage(bitmap, 0, 0);
|
||||||
|
bitmap.close();
|
||||||
|
setLoaded(true);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
|
}, [src]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<canvas
|
||||||
|
ref={canvasRef}
|
||||||
|
className={className}
|
||||||
|
aria-label={alt}
|
||||||
|
style={{ display: isLoaded ? "block" : "none" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MusicPlayer({ track }: { track: string }) {
|
||||||
|
const [playing, setPlaying] = useState(false);
|
||||||
|
const [available, setAvailable] = useState(true);
|
||||||
|
const audioRef = useRef<HTMLAudioElement>(null);
|
||||||
|
const url = `${RESOURCE_ROOT_URL}music/${track.toLowerCase()}.mp3`;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
audioRef.current?.pause();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
const audio = audioRef.current;
|
||||||
|
if (!audio) return;
|
||||||
|
if (playing) {
|
||||||
|
audio.pause();
|
||||||
|
} else {
|
||||||
|
audio.play().catch(() => setAvailable(false));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="MapInfoDialog-musicTrack" data-playing={playing}>
|
||||||
|
<audio
|
||||||
|
ref={audioRef}
|
||||||
|
src={url}
|
||||||
|
loop
|
||||||
|
onPlay={() => setPlaying(true)}
|
||||||
|
onPause={() => setPlaying(false)}
|
||||||
|
onError={() => setAvailable(false)}
|
||||||
|
/>
|
||||||
|
<span className="MusicTrackName">{track}</span>
|
||||||
|
{available && (
|
||||||
|
<button
|
||||||
|
className="MapInfoDialog-musicBtn"
|
||||||
|
onClick={toggle}
|
||||||
|
aria-label={playing ? "Pause music" : "Play music"}
|
||||||
|
>
|
||||||
|
{playing ? <FaVolumeUp /> : <FaVolumeMute />}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MapInfoDialog({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
missionName,
|
||||||
|
missionType,
|
||||||
|
}: {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
missionName: string;
|
||||||
|
missionType: string;
|
||||||
|
}) {
|
||||||
|
const { data: parsedMission } = useParsedMission(missionName);
|
||||||
|
const dialogRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
dialogRef.current?.focus();
|
||||||
|
document.exitPointerLock();
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
// While open: block keyboard events from reaching drei, and handle close keys.
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return;
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.code === "KeyI" || e.key === "Escape") {
|
||||||
|
onClose();
|
||||||
|
} else if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
||||||
|
onClose();
|
||||||
|
return; // let Cmd-K propagate to open the mission search
|
||||||
|
}
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
};
|
||||||
|
const handleKeyUp = (e: KeyboardEvent) => {
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
};
|
||||||
|
window.addEventListener("keydown", handleKeyDown, { capture: true });
|
||||||
|
window.addEventListener("keyup", handleKeyUp, { capture: true });
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("keydown", handleKeyDown, { capture: true });
|
||||||
|
window.removeEventListener("keyup", handleKeyUp, { capture: true });
|
||||||
|
};
|
||||||
|
}, [open, onClose]);
|
||||||
|
|
||||||
|
if (!open) return null;
|
||||||
|
|
||||||
|
const missionGroupProps = parsedMission
|
||||||
|
? getMissionGroupProps(parsedMission.ast)
|
||||||
|
: {};
|
||||||
|
const bitmapUrl = parsedMission
|
||||||
|
? getBitmapUrl(parsedMission.bitmap, missionName)
|
||||||
|
: null;
|
||||||
|
const displayName = parsedMission?.displayName ?? missionName;
|
||||||
|
const typeKey = missionType.toLowerCase();
|
||||||
|
const isSinglePlayer = typeKey === "singleplayer";
|
||||||
|
|
||||||
|
const musicTrack = missionGroupProps["musictrack"];
|
||||||
|
|
||||||
|
const missionString = parsedMission?.missionString
|
||||||
|
? filterMissionStringByMode(parsedMission.missionString, missionType)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Split quote into body text and attribution line
|
||||||
|
const quoteLines = parsedMission?.missionQuote?.trim().split("\n") ?? [];
|
||||||
|
let quoteText = "";
|
||||||
|
let quoteAttrib = "";
|
||||||
|
for (const line of quoteLines) {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (trimmed.match(/^-+\s/)) {
|
||||||
|
quoteAttrib = trimmed.replace(/^-+\s*/, "").trim();
|
||||||
|
} else if (trimmed) {
|
||||||
|
quoteText += (quoteText ? " " : "") + trimmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="MapInfoDialog-overlay" onClick={onClose}>
|
||||||
|
<div
|
||||||
|
ref={dialogRef}
|
||||||
|
className="MapInfoDialog"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
onKeyDown={(e) => e.stopPropagation()}
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label="Map Information"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
<div className="MapInfoDialog-inner">
|
||||||
|
<div className="MapInfoDialog-left">
|
||||||
|
{bitmapUrl && isSinglePlayer && (
|
||||||
|
<RawPreviewImage
|
||||||
|
key={bitmapUrl}
|
||||||
|
className="MapInfoDialog-preview--floated"
|
||||||
|
src={bitmapUrl}
|
||||||
|
alt={`${displayName} preview`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<h1 className="MapInfoDialog-title">{displayName}</h1>
|
||||||
|
<div className="MapInfoDialog-meta">
|
||||||
|
{parsedMission?.planetName && (
|
||||||
|
<span className="MapInfoDialog-planet">
|
||||||
|
{parsedMission.planetName}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{quoteText && (
|
||||||
|
<blockquote className="MapInfoDialog-quote">
|
||||||
|
<p>{quoteText}</p>
|
||||||
|
{quoteAttrib && <cite>— {quoteAttrib}</cite>}
|
||||||
|
</blockquote>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{parsedMission?.missionBlurb && (
|
||||||
|
<p className="MapInfoDialog-blurb">
|
||||||
|
{parsedMission.missionBlurb.trim()}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{missionString && missionString.trim() && (
|
||||||
|
<div className="MapInfoDialog-section">
|
||||||
|
<GuiMarkup markup={missionString} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{parsedMission?.missionBriefing && (
|
||||||
|
<div className="MapInfoDialog-section">
|
||||||
|
<h2 className="MapInfoDialog-sectionTitle">Mission Briefing</h2>
|
||||||
|
<GuiMarkup markup={parsedMission.missionBriefing} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{musicTrack && <MusicPlayer track={musicTrack} />}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{bitmapUrl && !isSinglePlayer && (
|
||||||
|
<div className="MapInfoDialog-right">
|
||||||
|
<RawPreviewImage
|
||||||
|
key={bitmapUrl}
|
||||||
|
src={bitmapUrl}
|
||||||
|
alt={`${displayName} preview`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="MapInfoDialog-footer">
|
||||||
|
<button className="MapInfoDialog-closeBtn" onClick={onClose}>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
<span className="MapInfoDialog-hint">I or Esc to close</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -91,7 +91,18 @@ export async function loadDetailMapList(name: string) {
|
||||||
export async function loadMission(name: string) {
|
export async function loadMission(name: string) {
|
||||||
const missionInfo = getMissionInfo(name);
|
const missionInfo = getMissionInfo(name);
|
||||||
const res = await fetch(getUrlForPath(missionInfo.resourcePath));
|
const res = await fetch(getUrlForPath(missionInfo.resourcePath));
|
||||||
const missionScript = await res.text();
|
const buffer = await res.arrayBuffer();
|
||||||
|
// Most mission files are Windows-1252 (common circa 2001), but some were
|
||||||
|
// later re-saved as UTF-8. Try strict UTF-8 first; fall back to Windows-1252.
|
||||||
|
let missionScript: string;
|
||||||
|
try {
|
||||||
|
missionScript = new TextDecoder("utf-8", { fatal: true }).decode(buffer);
|
||||||
|
} catch {
|
||||||
|
missionScript = new TextDecoder("windows-1252").decode(buffer);
|
||||||
|
}
|
||||||
|
// Some files were saved as UTF-8 with corrupted Windows-1252 characters
|
||||||
|
// (e.g. smart quotes became U+FFFD replacement characters). Fix these.
|
||||||
|
missionScript = missionScript.replaceAll("\uFFFD", "'");
|
||||||
return parseMissionScript(missionScript);
|
return parseMissionScript(missionScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
305
src/torqueGuiMarkup.tsx
Normal file
305
src/torqueGuiMarkup.tsx
Normal file
|
|
@ -0,0 +1,305 @@
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { getUrlForPath } from "./loaders";
|
||||||
|
import { getStandardTextureResourceKey } from "./manifest";
|
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
interface Style {
|
||||||
|
color?: string;
|
||||||
|
fontSize?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Span {
|
||||||
|
type: "span";
|
||||||
|
text: string;
|
||||||
|
style: Style;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Bitmap {
|
||||||
|
type: "bitmap";
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Inline = Span | Bitmap;
|
||||||
|
|
||||||
|
interface Line {
|
||||||
|
align: "left" | "center" | "right";
|
||||||
|
/** Container padding-left for non-bullet lines. */
|
||||||
|
lmargin: number;
|
||||||
|
/** When > 0, a bitmap precedes indented text — render as bullet layout. */
|
||||||
|
textIndent: number;
|
||||||
|
items: Inline[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tokenizer
|
||||||
|
|
||||||
|
type Token =
|
||||||
|
| { type: "text"; value: string }
|
||||||
|
| { type: "newline" }
|
||||||
|
| { type: "tag"; name: string; arg: string };
|
||||||
|
|
||||||
|
function tokenize(input: string): Token[] {
|
||||||
|
const tokens: Token[] = [];
|
||||||
|
const re = /<([^>]*)>/g;
|
||||||
|
let last = 0;
|
||||||
|
|
||||||
|
const pushText = (text: string) => {
|
||||||
|
const parts = text.split("\n");
|
||||||
|
parts.forEach((part, i) => {
|
||||||
|
if (part) tokens.push({ type: "text", value: part });
|
||||||
|
if (i < parts.length - 1) tokens.push({ type: "newline" });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let m: RegExpExecArray | null;
|
||||||
|
while ((m = re.exec(input))) {
|
||||||
|
if (m.index > last) pushText(input.slice(last, m.index));
|
||||||
|
last = m.index + m[0].length;
|
||||||
|
const raw = m[1].trim();
|
||||||
|
const sep = raw.indexOf(":");
|
||||||
|
const name = (sep === -1 ? raw : raw.slice(0, sep)).toLowerCase();
|
||||||
|
const arg = sep === -1 ? "" : raw.slice(sep + 1);
|
||||||
|
tokens.push({ type: "tag", name, arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last < input.length) pushText(input.slice(last));
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
function parseFontSize(arg: string): number {
|
||||||
|
// arg is "FontName:size" — size is after the last colon
|
||||||
|
const last = arg.lastIndexOf(":");
|
||||||
|
const size = parseInt(last === -1 ? arg : arg.slice(last + 1), 10) || 14;
|
||||||
|
return Math.min(size, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseMarkup(input: string): Line[] {
|
||||||
|
const tokens = tokenize(input);
|
||||||
|
|
||||||
|
// Style state (affected by spush/spop)
|
||||||
|
const styleStack: Style[] = [];
|
||||||
|
let style: Style = {};
|
||||||
|
|
||||||
|
// Layout state (persistent, not stack-based)
|
||||||
|
let align: Line["align"] = "left";
|
||||||
|
let lmargin = 0;
|
||||||
|
|
||||||
|
// Current line being accumulated
|
||||||
|
let items: Inline[] = [];
|
||||||
|
let lineAlign: Line["align"] = "left";
|
||||||
|
let lineLmargin = 0;
|
||||||
|
let hasBitmap = false;
|
||||||
|
let textIndent = 0;
|
||||||
|
|
||||||
|
const lines: Line[] = [];
|
||||||
|
|
||||||
|
const flushLine = () => {
|
||||||
|
lines.push({ align: lineAlign, lmargin: lineLmargin, textIndent, items });
|
||||||
|
items = [];
|
||||||
|
lineAlign = align;
|
||||||
|
lineLmargin = lmargin;
|
||||||
|
hasBitmap = false;
|
||||||
|
textIndent = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addSpan = (text: string) => {
|
||||||
|
if (!text) return;
|
||||||
|
// Merge adjacent spans with identical style
|
||||||
|
const prev = items[items.length - 1];
|
||||||
|
if (
|
||||||
|
prev?.type === "span" &&
|
||||||
|
prev.style.color === style.color &&
|
||||||
|
prev.style.fontSize === style.fontSize
|
||||||
|
) {
|
||||||
|
prev.text += text;
|
||||||
|
} else {
|
||||||
|
items.push({ type: "span", text, style: { ...style } });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const tok of tokens) {
|
||||||
|
if (tok.type === "newline") {
|
||||||
|
flushLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tok.type === "text") {
|
||||||
|
addSpan(tok.value.replace(/\t/g, " "));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, arg } = tok;
|
||||||
|
switch (name) {
|
||||||
|
case "spush":
|
||||||
|
styleStack.push({ ...style });
|
||||||
|
break;
|
||||||
|
case "spop":
|
||||||
|
if (styleStack.length > 0) style = styleStack.pop()!;
|
||||||
|
break;
|
||||||
|
case "color":
|
||||||
|
style = { ...style, color: `#${arg.trim()}` };
|
||||||
|
break;
|
||||||
|
case "font":
|
||||||
|
style = { ...style, fontSize: parseFontSize(arg) };
|
||||||
|
break;
|
||||||
|
case "lmargin": {
|
||||||
|
const px = parseInt(arg, 10) || 0;
|
||||||
|
lmargin = px;
|
||||||
|
if (hasBitmap && px > 0) {
|
||||||
|
// lmargin after a bitmap → bullet indent for this line's text
|
||||||
|
textIndent = px;
|
||||||
|
} else if (items.length === 0) {
|
||||||
|
lineLmargin = px;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "just": {
|
||||||
|
const v = arg.trim().toLowerCase();
|
||||||
|
if (v === "left" || v === "center" || v === "right") {
|
||||||
|
align = v;
|
||||||
|
if (items.length === 0) lineAlign = v;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "bitmap":
|
||||||
|
hasBitmap = true;
|
||||||
|
items.push({ type: "bitmap", name: arg.trim() });
|
||||||
|
break;
|
||||||
|
case "br":
|
||||||
|
flushLine();
|
||||||
|
break;
|
||||||
|
case "sbreak":
|
||||||
|
if (items.length > 0) flushLine();
|
||||||
|
flushLine(); // empty spacer line
|
||||||
|
break;
|
||||||
|
// Intentionally ignored: tab, rmargin, clip, /clip, a, /a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items.length > 0) flushLine();
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitmap rendering
|
||||||
|
|
||||||
|
const bitmapUrlCache = new Map<string, string | null>();
|
||||||
|
|
||||||
|
function getBitmapUrl(name: string): string | null {
|
||||||
|
if (bitmapUrlCache.has(name)) return bitmapUrlCache.get(name)!;
|
||||||
|
let url: string | null;
|
||||||
|
try {
|
||||||
|
url = getUrlForPath(getStandardTextureResourceKey(`textures/gui/${name}`));
|
||||||
|
} catch {
|
||||||
|
url = null;
|
||||||
|
}
|
||||||
|
bitmapUrlCache.set(name, url);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GuiBitmapEl({ name }: { name: string }) {
|
||||||
|
const url = getBitmapUrl(name);
|
||||||
|
if (url) {
|
||||||
|
return <img src={url} alt="" className="GuiMarkup-bitmap" />;
|
||||||
|
}
|
||||||
|
if (/bullet/i.test(name)) {
|
||||||
|
return <span className="GuiMarkup-bullet">•</span>;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SpanEl({ span }: { span: Span }) {
|
||||||
|
const { color, fontSize } = span.style;
|
||||||
|
if (!color && !fontSize) return <>{span.text}</>;
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color,
|
||||||
|
fontSize: fontSize != null ? `${fontSize}px` : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{span.text}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter a mission string by game mode prefix, e.g. `[CTF]`, `[DM Bounty]`.
|
||||||
|
* Lines without a prefix are shown for all modes.
|
||||||
|
*/
|
||||||
|
export function filterMissionStringByMode(
|
||||||
|
str: string,
|
||||||
|
missionType: string,
|
||||||
|
): string {
|
||||||
|
const type = missionType.toUpperCase();
|
||||||
|
return str
|
||||||
|
.split("\n")
|
||||||
|
.flatMap((line) => {
|
||||||
|
const m = line.match(/^\[([^\]]+)\]/);
|
||||||
|
if (m && !m[1].toUpperCase().split(/\s+/).includes(type)) return [];
|
||||||
|
return [line.replace(/^\[[^\]]+\]/, "")];
|
||||||
|
})
|
||||||
|
.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Renders Torque `GuiMLTextCtrl` markup as React elements. */
|
||||||
|
export function GuiMarkup({ markup }: { markup: string }) {
|
||||||
|
const lines = useMemo(() => parseMarkup(markup), [markup]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="GuiMarkup">
|
||||||
|
{lines.map((line, i) => {
|
||||||
|
const { align, lmargin, textIndent, items } = line;
|
||||||
|
const bitmaps = items.filter(
|
||||||
|
(it): it is Bitmap => it.type === "bitmap",
|
||||||
|
);
|
||||||
|
const spans = items.filter((it): it is Span => it.type === "span");
|
||||||
|
const hasText = spans.some((s) => s.text.trim().length > 0);
|
||||||
|
|
||||||
|
// Bullet layout: bitmap + lmargin indent + text on the same line
|
||||||
|
if (bitmaps.length > 0 && textIndent > 0 && hasText) {
|
||||||
|
return (
|
||||||
|
<div key={i} className="GuiMarkup-bulletLine">
|
||||||
|
<div className="GuiMarkup-bulletIcon">
|
||||||
|
{bitmaps.map((b, j) => (
|
||||||
|
<GuiBitmapEl key={j} name={b.name} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="GuiMarkup-bulletText">
|
||||||
|
{spans.map((s, j) => (
|
||||||
|
<SpanEl key={j} span={s} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty line → vertical spacer
|
||||||
|
if (!hasText && bitmaps.length === 0) {
|
||||||
|
return <div key={i} className="GuiMarkup-spacer" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="GuiMarkup-line"
|
||||||
|
style={{
|
||||||
|
textAlign: align !== "left" ? align : undefined,
|
||||||
|
paddingLeft: lmargin > 0 ? `${lmargin}px` : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{items.map((item, j) =>
|
||||||
|
item.type === "bitmap" ? (
|
||||||
|
<GuiBitmapEl key={j} name={item.name} />
|
||||||
|
) : (
|
||||||
|
<SpanEl key={j} span={item} />
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue