improve Torque GUI markup parsing

This commit is contained in:
Brian Beck 2026-02-19 19:39:01 -08:00
parent b833c34110
commit 3c8cce685d
33 changed files with 659 additions and 694 deletions

View file

@ -576,296 +576,6 @@ input[type="range"] {
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 {
display: flex;
border-left: 1px solid rgba(0, 190, 220, 0.3);
height: 100%;
width: auto;
margin-left: auto;
margin-right: 0;
}
.MapInfoDialog-preview {
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;
white-space: pre-line;
}
.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 {
position: fixed;
bottom: 20px;
@ -906,7 +616,3 @@ input[type="range"] {
inset 0 1px 0 rgba(255, 255, 255, 0.15),
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

View file

@ -1,9 +1,9 @@
1:"$Sreact.fragment"
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/74f04865c68de700.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
3:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.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"]
7:"$Sreact.suspense"
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/74f04865c68de700.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/eced4fe19bc9da99.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}
0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/15f5b04504a3a132.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/eced4fe19bc9da99.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:{}
5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
8:null

View file

@ -3,14 +3,14 @@
3:I[39756,["/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"]
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/74f04865c68de700.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.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"]
a:"$Sreact.suspense"
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
10:I[68027,[],"default"]
:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.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/74f04865c68de700.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/eced4fe19bc9da99.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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.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/15f5b04504a3a132.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/eced4fe19bc9da99.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:{}
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"}]]

View file

@ -3,4 +3,4 @@
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
4:"$Sreact.suspense"
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","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":"-NrDAGL0vu_8RrgSU0FFY","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}

View file

@ -2,5 +2,5 @@
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
3:I[39756,["/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/f9ef36e323faaaed.css","style"]
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.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}

View file

@ -1,2 +1,2 @@
:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","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}

View file

@ -0,0 +1,2 @@
.GuiMarkup-module__CLgNnq__GuiMarkup{white-space:pre-wrap;font-size:14px;line-height:1.5}.GuiMarkup-module__CLgNnq__GuiMarkup a{color:inherit;text-decoration:underline}.GuiMarkup-module__CLgNnq__Bullet{margin-left:.5em;margin-right:.5em}
.MapInfoDialog-module__m0lXla__Dialog{color:#bccec3;-webkit-user-select:text;user-select:text;-webkit-touch-callout:default;background:#142526cc;border:1px solid #41838b99;border-radius:4px;outline:none;grid-template-rows:1fr auto;grid-template-columns:100%;width:800px;max-width:calc(100dvw - 40px);height:600px;max-height:calc(100dvh - 40px);font-size:14px;line-height:1.5;display:grid;position:relative;overflow:hidden;box-shadow:0 0 50px #0006,inset 0 0 60px #01070d99}.MapInfoDialog-module__m0lXla__Overlay{z-index:10;background:#000000b3;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.MapInfoDialog-module__m0lXla__Body{grid-template-rows:100%;grid-template-columns:1fr auto;min-height:0;display:grid;overflow:hidden}.MapInfoDialog-module__m0lXla__Left{padding:24px 28px;overflow-y:auto}.MapInfoDialog-module__m0lXla__PreviewImage{border-left:1px solid #00bedc40;height:100%;display:block}.MapInfoDialog-module__m0lXla__PreviewImageFloating{float:right;clear:right;width:auto;max-width:30%;max-height:260px;margin:0 0 16px 20px;display:block}.MapInfoDialog-module__m0lXla__Title{color:#7dffff;text-shadow:0 1px 6px #0006;margin:0;font-size:26px;font-weight:500}.MapInfoDialog-module__m0lXla__MapMeta{flex-wrap:wrap;gap:8px 16px;margin-bottom:4px;font-size:15px;font-weight:400;display:flex}.MapInfoDialog-module__m0lXla__MapPlanet{color:#dbcaa8b3}.MapInfoDialog-module__m0lXla__MapQuote{border-left:2px solid #00bedc59;margin:16px 0;padding:0 0 0 14px;font-style:italic}.MapInfoDialog-module__m0lXla__MapQuote p{white-space:pre-line;margin:0 0 4px}.MapInfoDialog-module__m0lXla__MapQuote cite{color:#ffffff73;font-size:12px;font-style:normal;display:block}.MapInfoDialog-module__m0lXla__MapBlurb{margin:0 0 16px;font-size:13px}.MapInfoDialog-module__m0lXla__Section{margin-top:20px}.MapInfoDialog-module__m0lXla__SectionTitle{color:#7dffff;letter-spacing:.04em;text-transform:uppercase;text-shadow:0 0 16px #00d2f040;margin:0 0 8px;font-size:16px;font-weight:500}.MapInfoDialog-module__m0lXla__MusicTrack{color:#cad0ac80;align-items:center;gap:6px;margin-top:16px;font-size:14px;font-style:italic;display:flex}.MapInfoDialog-module__m0lXla__MusicTrack[data-playing=true]{color:#f7fdd8b3}.MapInfoDialog-module__m0lXla__MusicButton{cursor:pointer;color:#557663;opacity:.5;background:0 0;border:0;border-radius:20px;flex-shrink:0;place-content:center;width:32px;height:32px;padding:0;font-size:20px;font-style:normal;line-height:1;display:grid}.MapInfoDialog-module__m0lXla__MusicTrack[data-playing=true] .MapInfoDialog-module__m0lXla__MusicButton{color:#6dffaa;opacity:1}.MapInfoDialog-module__m0lXla__MusicTrack[data-playing=true] .MapInfoDialog-module__m0lXla__MusicButton:hover{opacity:.7}.MapInfoDialog-module__m0lXla__Footer{background:#021415b3;border-top:1px solid #00bedc40;flex-shrink:0;align-items:center;gap:16px;padding:10px 12px;display:flex}.MapInfoDialog-module__m0lXla__CloseButton{color:#9aefe1e6;text-shadow:0 -1px #00000080;cursor:pointer;background:linear-gradient(#29ac9cb3,#005041b3);border:1px solid #29615499;border-top-color:#65b9b080;border-radius:3px;padding:4px 18px;font-size:14px;font-weight:500;box-shadow:inset 0 1px #78dcc333,inset 0 -1px #0000004d,0 2px 4px #0006}.MapInfoDialog-module__m0lXla__CloseButton:active{transform:translateY(1px)}.MapInfoDialog-module__m0lXla__Hint{color:#c9dcd84d;margin-left:auto;font-size:12px}.MapInfoDialog-module__m0lXla__MusicTrackName{text-transform:capitalize}@media (max-width:719px){.MapInfoDialog-module__m0lXla__Body{display:block;overflow:auto}.MapInfoDialog-module__m0lXla__Hint{display:none}.MapInfoDialog-module__m0lXla__Left{width:100%;height:auto;margin:0;padding:16px 20px;overflow:auto}.MapInfoDialog-module__m0lXla__PreviewImage{width:auto;height:auto;margin:16px auto}.MapInfoDialog-module__m0lXla__CloseButton{width:220px;height:36px;margin:0 auto}}

View file

@ -208,4 +208,4 @@
void main() {
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)))},59197,e=>{e.v(t=>Promise.all(["static/chunks/dd460a24fc1df5f8.js"].map(t=>e.l(t))).then(()=>t(94247)))}]);
`}),[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/0be79f7f5e0597a7.css","static/chunks/1cf33c843f96e1c9.js"].map(t=>e.l(t))).then(()=>t(94247)))}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -7,8 +7,8 @@
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","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/f9ef36e323faaaed.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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","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/284925ee1f24c201.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"}]]
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
7:null

View file

@ -3,4 +3,4 @@
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
4:"$Sreact.suspense"
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","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":"-NrDAGL0vu_8RrgSU0FFY","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}

View file

@ -2,5 +2,5 @@
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
3:I[39756,["/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/f9ef36e323faaaed.css","style"]
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.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}

View file

@ -1,5 +1,5 @@
1:"$Sreact.fragment"
2:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
3:"$Sreact.suspense"
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","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":"-NrDAGL0vu_8RrgSU0FFY","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

View file

@ -1,4 +1,4 @@
1:"$Sreact.fragment"
2:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
3:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false}
0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false}

View file

@ -1,2 +1,2 @@
:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","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

View file

@ -7,8 +7,8 @@
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","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/f9ef36e323faaaed.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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","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/284925ee1f24c201.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"}]]
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
7:null

File diff suppressed because one or more lines are too long

View file

@ -3,14 +3,14 @@
3:I[39756,["/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"]
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/74f04865c68de700.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.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"]
a:"$Sreact.suspense"
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
10:I[68027,[],"default"]
:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.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/74f04865c68de700.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/eced4fe19bc9da99.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}
:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.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/15f5b04504a3a132.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/eced4fe19bc9da99.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:{}
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"}]]

View file

@ -0,0 +1,15 @@
.GuiMarkup {
font-size: 14px;
line-height: 1.5;
white-space: pre-wrap;
}
.GuiMarkup a {
color: inherit;
text-decoration: underline;
}
.Bullet {
margin-left: 0.5em;
margin-right: 0.5em;
}

View file

@ -0,0 +1,30 @@
import { describe, expect, it } from "vitest";
import { parseMarkup } from "./GuiMarkup";
const s1 = `<spush><color:00CCFF>Map by: FlyingElmo
Flyersfan leave me alone now pls
Website:<spop> <color:99CCFF><a:www.planettribes.com/elmo>Part of the <spush><color:ffffff>Double Threat<spop> Pack</a><spop>`;
describe("GuiMarkup", () => {
describe("parseMarkup", () => {
it("converts markup to JSX", () => {
expect(parseMarkup(s1)).toEqual(
<span>
<span style={{ color: "#00CCFF" }}>
{`Map by: FlyingElmo\nFlyersfan leave me alone now pls\nWebsite:`}
</span>{" "}
<span style={{ color: "#99CCFF" }}>
<a
href="http://www.planettribes.com/elmo"
rel="noopener noreferrer"
target="_blank"
>
{`Part of the `}
<span style={{ color: "#ffffff" }}>Double Threat</span> Pack
</a>
</span>
</span>,
);
});
});
});

View file

@ -0,0 +1,289 @@
import React, { useMemo } from "react";
import { getUrlForPath } from "../loaders";
import { getStandardTextureResourceKey } from "../manifest";
import styles from "./GuiMarkup.module.css";
// Tokenizer
type Token =
| { type: "text"; value: string }
| { type: "tag"; name: string; args: string[] };
// spop, spush, lmargin, font, color, bitmap, a, a:wwwlink\t
const validTagNames = new Set([
"spop",
"spush",
"lmargin",
"font",
"color",
"bitmap",
"a",
"/a",
]);
export function tokenize(input: string): Token[] {
const pattern = /<([^><]+)>/g;
const tokens = input
.split(pattern)
.map((text, i) => {
if (i % 2 === 0) {
return text ? ({ type: "text", value: text } as Token) : null;
} else {
const [name, ...args] = text.split(":");
if (validTagNames.has(name.toLowerCase())) {
return { type: "tag", name, args } as Token;
} else {
return { type: "text", value: `<${text}>` } as Token;
}
}
})
.filter((token) => token != null);
return tokens;
}
// Parser
function parseFontArgs(args: string[]): {
fontDescription: string;
fontSize?: number;
} {
// arg is "FontName:size" — size is after the last colon
const [fontDescription, fontSizeString] = args;
const fontSize = fontSizeString
? Math.max(11, Math.min(parseInt(fontSizeString.trim(), 10), 16))
: undefined;
return {
fontDescription,
fontSize,
};
}
type Node = {
type: string;
source?: string;
style?: Record<string, string | number | undefined>;
children?: Array<string | Node>;
value?: any;
};
export function parseMarkup(input: string) {
const tokens = tokenize(input);
const rootEl: Node = {
type: "span",
source: "root",
style: {},
children: [],
};
let topEl = rootEl;
const stack = [topEl];
const isUsed = (node: Node): boolean => {
return (
node.children != null &&
node.children.some((child) => typeof child === "string" || isUsed(child))
);
};
for (const token of tokens) {
switch (token.type) {
case "text":
topEl.children.push(token.value);
break;
case "tag":
switch (token.name) {
case "spush": {
const span = {
type: "span",
source: "spush",
style: {},
children: [],
};
topEl.children.push(span);
topEl = span;
stack.push(topEl);
break;
}
case "spop": {
if (topEl.source !== "root") {
let lastPop = stack.pop();
while (lastPop.source !== "spush") {
lastPop = stack.pop();
}
topEl = stack[stack.length - 1];
}
break;
}
case "lmargin": {
// const marginLeft = parseInt(token.args[0].trim(), 10) || 0;
// if (topEl.children.length) {
// topEl.style.marginLeft = marginLeft;
// } else {
// const marginNode: Node = {
// type: "span",
// source: "spush",
// style: { marginLeft },
// children: [],
// };
// topEl.children.push(marginNode);
// topEl = marginNode;
// stack.push(topEl);
// }
break;
}
case "font": {
const fontSize = parseFontArgs(token.args).fontSize;
if (!isUsed(topEl)) {
topEl.style.fontSize = fontSize;
} else {
const fontNode: Node = {
type: "span",
source: "spush",
style: { fontSize },
children: [],
};
topEl.children.push(fontNode);
topEl = fontNode;
stack.push(topEl);
}
break;
}
case "color":
if (!isUsed(topEl)) {
topEl.style.color = `#${token.args[0].trim()}`;
} else {
const colorNode: Node = {
type: "span",
source: "spush",
style: { color: `#${token.args[0].trim()}` },
children: [],
};
topEl.children.push(colorNode);
topEl = colorNode;
stack.push(topEl);
}
break;
case "bitmap": {
const bitmap: Node = {
type: "bitmap",
value: token.args[0],
};
topEl.children.push(bitmap);
break;
}
case "a": {
const arg = token.args[0].trim().split("\t");
const href =
arg.length === 2 && arg[0] === "wwwlink" ? arg[1] : arg[0];
const link: Node = {
type: "a",
source: "a",
value: `http://${href}`,
style: {},
children: [],
};
topEl.children.push(link);
topEl = link;
stack.push(topEl);
break;
}
case "/a": {
let lastPop = stack.pop();
while (lastPop.source !== "a") {
lastPop = stack.pop();
}
topEl = stack[stack.length - 1];
break;
}
}
}
}
return nodeToJsx(rootEl);
}
function nodeToJsx(node: Node): React.ReactNode {
switch (node.type) {
case "span":
return React.createElement(
"span",
{
style: Object.keys(node.style).length === 0 ? undefined : node.style,
},
...node.children.map((child) =>
typeof child === "string" ? child : nodeToJsx(child),
),
);
case "a":
return React.createElement(
"a",
{
href: node.value,
style: Object.keys(node.style).length === 0 ? undefined : node.style,
rel: "noopener noreferrer",
target: "_blank",
},
...node.children.map((child) =>
typeof child === "string" ? child : nodeToJsx(child),
),
);
case "bitmap":
return <GuiBitmap name={node.value} />;
}
}
// 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 GuiBitmap({ name }: { name: string }) {
const url = getBitmapUrl(name);
if (url) {
return <img src={url} alt="" className={styles.Bitmap} />;
}
if (/bullet/i.test(name)) {
return <span className={styles.Bullet}></span>;
}
return null;
}
const guiMarkupTagPattern = /<(?:font|color|bitmap|just|lmargin|a):/i;
/** Whether a string contains Torque GUI markup tags. */
export function hasGuiMarkup(text: string): boolean {
return guiMarkupTagPattern.test(text);
}
/**
* 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 children = useMemo(() => parseMarkup(markup), [markup]);
return <div className={styles.GuiMarkup}>{children}</div>;
}

View file

@ -0,0 +1,240 @@
.Dialog {
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: 4px;
box-shadow:
0 0 50px rgba(0, 0, 0, 0.4),
inset 0 0 60px rgba(1, 7, 13, 0.6);
color: #bccec3;
font-size: 14px;
line-height: 1.5;
overflow: hidden;
outline: none;
user-select: text;
-webkit-touch-callout: default;
}
.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;
}
.Body {
display: grid;
grid-template-columns: 1fr auto;
grid-template-rows: 100%;
min-height: 0;
overflow: hidden;
}
.Left {
overflow-y: auto;
padding: 24px 28px;
}
.PreviewImage {
height: 100%;
display: block;
border-left: 1px solid rgba(0, 190, 220, 0.25);
}
.PreviewImageFloating {
float: right;
clear: right;
margin: 0 0 16px 20px;
max-height: 260px;
max-width: 30%;
width: auto;
display: block;
}
.Title {
font-size: 26px;
font-weight: 500;
color: #7dffff;
margin: 0;
text-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
}
.MapMeta {
display: flex;
flex-wrap: wrap;
gap: 8px 16px;
margin-bottom: 4px;
font-size: 15px;
font-weight: 400;
/* text-transform: uppercase; */
}
.MapPlanet {
color: rgba(219, 202, 168, 0.7);
}
.MapQuote {
margin: 16px 0;
padding: 0 0 0 14px;
border-left: 2px solid rgba(0, 190, 220, 0.35);
font-style: italic;
}
.MapQuote p {
margin: 0 0 4px;
white-space: pre-line;
}
.MapQuote cite {
font-style: normal;
font-size: 12px;
color: rgba(255, 255, 255, 0.45);
display: block;
}
.MapBlurb {
font-size: 13px;
margin: 0 0 16px;
}
.Section {
margin-top: 20px;
}
.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);
}
.MusicTrack {
margin-top: 16px;
font-size: 14px;
color: rgba(202, 208, 172, 0.5);
font-style: italic;
display: flex;
align-items: center;
gap: 6px;
}
.MusicTrack[data-playing="true"] {
color: rgba(247, 253, 216, 0.7);
}
.MusicButton {
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;
}
.MusicTrack[data-playing="true"] .MusicButton {
color: rgb(109, 255, 170);
opacity: 1;
}
.MusicTrack[data-playing="true"] .MusicButton:hover {
opacity: 0.7;
}
.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;
}
.CloseButton {
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;
}
.CloseButton:active {
transform: translate(0, 1px);
}
.Hint {
font-size: 12px;
color: rgba(201, 220, 216, 0.3);
margin-left: auto;
}
.MusicTrackName {
text-transform: capitalize;
}
@media (max-width: 719px) {
.Body {
display: block;
overflow: auto;
}
.Hint {
display: none;
}
.Left {
width: 100%;
height: auto;
margin: 0;
overflow: auto;
padding: 16px 20px;
}
.PreviewImage {
width: auto;
height: auto;
margin: 16px auto;
}
.CloseButton {
width: 220px;
height: 36px;
margin: 0 auto;
}
}

View file

@ -7,8 +7,9 @@ import {
GuiMarkup,
filterMissionStringByMode,
hasGuiMarkup,
} from "../torqueGuiMarkup";
} from "./GuiMarkup";
import type * as AST from "../torqueScript/ast";
import styles from "./MapInfoDialog.module.css";
function useParsedMission(name: string) {
return useQuery({
@ -71,50 +72,46 @@ function getBitmapUrl(
function RawPreviewImage({
src,
alt,
className = "MapInfoDialog-preview",
className = styles.PreviewImage,
}: {
src: string;
alt: string;
className?: string;
}) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const [isLoaded, setLoaded] = useState(false);
const [objectUrl, setObjectUrl] = useState<string | null>(null);
useEffect(() => {
let cancelled = false;
let url: string | undefined;
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);
.then(
(bitmap) =>
new Promise<Blob | null>((resolve) => {
const canvas = document.createElement("canvas");
canvas.width = bitmap.width;
canvas.height = bitmap.height;
canvas.getContext("2d")?.drawImage(bitmap, 0, 0);
bitmap.close();
canvas.toBlob(resolve);
}),
)
.then((blob) => {
if (cancelled || !blob) return;
url = URL.createObjectURL(blob);
setObjectUrl(url);
})
.catch(() => {});
return () => {
cancelled = true;
if (url) URL.revokeObjectURL(url);
};
}, [src]);
return (
<canvas
ref={canvasRef}
className={className}
aria-label={alt}
style={{ display: isLoaded ? "block" : "none" }}
/>
);
if (!objectUrl) return null;
return <img src={objectUrl} alt={alt} className={className} />;
}
function MusicPlayer({ track }: { track: string }) {
@ -140,7 +137,7 @@ function MusicPlayer({ track }: { track: string }) {
};
return (
<div className="MapInfoDialog-musicTrack" data-playing={playing}>
<div className={styles.MusicTrack} data-playing={playing}>
<audio
ref={audioRef}
src={url}
@ -149,10 +146,10 @@ function MusicPlayer({ track }: { track: string }) {
onPause={() => setPlaying(false)}
onError={() => setAvailable(false)}
/>
<span className="MusicTrackName">{track}</span>
<span className={styles.MusicTrackName}>{track}</span>
{available && (
<button
className="MapInfoDialog-musicBtn"
className={styles.MusicButton}
onClick={toggle}
aria-label={playing ? "Pause music" : "Play music"}
>
@ -236,7 +233,7 @@ export function MapInfoDialog({
if (!quoteHasMarkup) {
for (const line of rawQuote.split("\n")) {
const trimmed = line.trim();
if (trimmed.match(/^-+\s/)) {
if (trimmed.match(/^--[^-]/)) {
quoteAttrib = trimmed.replace(/^-+\s*/, "").trim();
} else if (trimmed) {
quoteText += (quoteText ? "\n" : "") + trimmed;
@ -245,10 +242,10 @@ export function MapInfoDialog({
}
return (
<div className="MapInfoDialog-overlay" onClick={onClose}>
<div className={styles.Overlay} onClick={onClose}>
<div
ref={dialogRef}
className="MapInfoDialog"
className={styles.Dialog}
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
role="dialog"
@ -256,55 +253,55 @@ export function MapInfoDialog({
aria-label="Map Information"
tabIndex={-1}
>
<div className="MapInfoDialog-inner">
<div className="MapInfoDialog-left">
<div className={styles.Body}>
<div className={styles.Left}>
{bitmapUrl && isSinglePlayer && (
<RawPreviewImage
key={bitmapUrl}
className="MapInfoDialog-preview--floated"
className={styles.PreviewImageFloating}
src={bitmapUrl}
alt={`${displayName} preview`}
/>
)}
<h1 className="MapInfoDialog-title">{displayName}</h1>
<div className="MapInfoDialog-meta">
<h1 className={styles.Title}>{displayName}</h1>
<div className={styles.MapMeta}>
{parsedMission?.planetName && (
<span className="MapInfoDialog-planet">
<span className={styles.MapPlanet}>
{parsedMission.planetName}
</span>
)}
</div>
{quoteHasMarkup ? (
<blockquote className="MapInfoDialog-quote">
<blockquote className={styles.MapQuote}>
<GuiMarkup markup={rawQuote} />
</blockquote>
) : quoteText ? (
<blockquote className="MapInfoDialog-quote">
<blockquote className={styles.MapQuote}>
<p>{quoteText}</p>
{quoteAttrib && <cite> {quoteAttrib}</cite>}
</blockquote>
) : null}
{parsedMission?.missionBlurb && (
<div className="MapInfoDialog-blurb">
<div className={styles.MapBlurb}>
{hasGuiMarkup(parsedMission.missionBlurb) ? (
<GuiMarkup markup={parsedMission.missionBlurb.trim()} />
) : (
<p>{parsedMission.missionBlurb.trim()}</p>
parsedMission.missionBlurb.trim()
)}
</div>
)}
{missionString && missionString.trim() && (
<div className="MapInfoDialog-section">
<div className={styles.Section}>
<GuiMarkup markup={missionString} />
</div>
)}
{parsedMission?.missionBriefing && (
<div className="MapInfoDialog-section">
<h2 className="MapInfoDialog-sectionTitle">Mission Briefing</h2>
<div className={styles.Section}>
<h2 className={styles.SectionTitle}>Mission Briefing</h2>
<GuiMarkup markup={parsedMission.missionBriefing} />
</div>
)}
@ -313,21 +310,19 @@ export function MapInfoDialog({
</div>
{bitmapUrl && !isSinglePlayer && (
<div className="MapInfoDialog-right">
<RawPreviewImage
key={bitmapUrl}
src={bitmapUrl}
alt={`${displayName} preview`}
/>
</div>
<RawPreviewImage
key={bitmapUrl}
src={bitmapUrl}
alt={`${displayName} preview`}
/>
)}
</div>
<div className="MapInfoDialog-footer">
<button className="MapInfoDialog-closeBtn" onClick={onClose}>
<div className={styles.Footer}>
<button className={styles.CloseButton} onClick={onClose}>
Close
</button>
<span className="MapInfoDialog-hint">I or Esc to close</span>
<span className={styles.Hint}>I or Esc to close</span>
</div>
</div>
</div>

View file

@ -1,312 +0,0 @@
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
const guiMarkupTagPattern = /<(?:font|color|bitmap|just|lmargin):/i;
/** Whether a string contains Torque GUI markup tags. */
export function hasGuiMarkup(text: string): boolean {
return guiMarkupTagPattern.test(text);
}
/**
* 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>
);
}

View file

@ -3,7 +3,7 @@ import { resolve } from "node:path";
export default defineConfig({
test: {
include: ["**/*.spec.ts"],
include: ["**/*.spec.ts", "**/*.spec.tsx"],
},
resolve: {
alias: {