@fps-games/editor-deployment 0.2.3-beta.13 → 0.2.3-beta.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/bin/fps-editor-prepare.mjs +3 -4
  2. package/bin/fps-editor-server.mjs +1 -1
  3. package/licenses/THIRD_PARTY_NOTICES.txt +2 -2
  4. package/manifest.json +62 -73
  5. package/npm-shrinkwrap.json +3 -4
  6. package/package.json +7 -7
  7. package/public/assets/{editor-core-plugin-host-c2002442.js → editor-core-plugin-host-94e73c63.js} +1 -1
  8. package/public/assets/editor-core-plugin-host-94e73c63.js.br +0 -0
  9. package/public/assets/editor-core-plugin-host-94e73c63.js.gz +0 -0
  10. package/public/assets/index-CToRH9gy.js +1 -0
  11. package/public/assets/index-CToRH9gy.js.br +0 -0
  12. package/public/assets/index-CToRH9gy.js.gz +0 -0
  13. package/public/assets/playable-sdk-CrrQJDf4.js +4 -0
  14. package/public/assets/playable-sdk-CrrQJDf4.js.br +0 -0
  15. package/public/assets/playable-sdk-CrrQJDf4.js.gz +0 -0
  16. package/public/assets/playable-standard-project-DkUozryX.js +5249 -0
  17. package/public/assets/playable-standard-project-DkUozryX.js.br +0 -0
  18. package/public/assets/playable-standard-project-DkUozryX.js.gz +0 -0
  19. package/public/index.html +3 -3
  20. package/public/index.html.br +0 -0
  21. package/public/index.html.gz +0 -0
  22. package/runtime/editor-control-plane.mjs +96 -5
  23. package/worker/editor-service-worker.mjs +17 -24
  24. package/bin/fps-editor-agent.mjs +0 -5
  25. package/public/assets/editor-core-plugin-host-c2002442.js.br +0 -0
  26. package/public/assets/editor-core-plugin-host-c2002442.js.gz +0 -0
  27. package/public/assets/index-c2oXc5B5.js +0 -5
  28. package/public/assets/index-c2oXc5B5.js.br +0 -0
  29. package/public/assets/index-c2oXc5B5.js.gz +0 -0
  30. package/public/assets/playable-sdk-Dfz54Mv_.js +0 -5
  31. package/public/assets/playable-sdk-Dfz54Mv_.js.br +0 -0
  32. package/public/assets/playable-sdk-Dfz54Mv_.js.gz +0 -0
  33. package/public/assets/playable-standard-project-C61X2B53.js +0 -5247
  34. package/public/assets/playable-standard-project-C61X2B53.js.br +0 -0
  35. package/public/assets/playable-standard-project-C61X2B53.js.gz +0 -0
  36. package/runtime/runtime-debug-authoring-bridge.mjs +0 -1
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import{createHash as Oe,randomUUID as H}from"node:crypto";import{constants as _e,createReadStream as Q}from"node:fs";import{access as Ae,readFile as F,realpath as B,stat as U}from"node:fs/promises";import S from"node:path";import{Readable as be}from"node:stream";var V="/__fps_editor_agent/v1/asset-source-grants";var Ze=32*1024;var et=8*1024*1024,ne=128,oe=256*1024;function ie(e){let{transport:t,createRequestId:n,createIdempotencyKey:o,createUnavailableError:i}=e,c=a=>t.describeCommand(a),s=async a=>{let d=await c(a),u=d?.ok===!1&&Array.isArray(d.diagnostics)?d.diagnostics[0]:null;if(u&&typeof u.code=="string")throw i(u.code,typeof u.message=="string"&&u.message?u.message:`Editor command admission failed: ${a}`);let r=d?.ok&&d.kind==="command"?d.command:null;if(!r)throw i("command.unknown",`Editor command is not registered: ${a}`);if(!r.availability.available)throw i("command.unavailable",r.availability.reasons.map(f=>f.message).join("; ")||`Editor command is unavailable: ${a}`);return Object.freeze({commandId:a,access:r.manifest.access})};return Object.freeze({describeCommand:c,listCommands:a=>t.listCommands(a),searchCommands:a=>t.searchCommands(a),prepareCommand:s,async invokeCommand(a){let d=a.preparedCommand??await s(a.commandId),u=a.requestId??n(),r=a.idempotencyKey??(d.access==="write"?o():void 0);return t.invokeCommand({commandId:d.commandId,access:d.access,input:a.input,requestId:u,...r?{idempotencyKey:r}:{},...a.expectedDocumentRevision===void 0?{}:{expectedDocumentRevision:a.expectedDocumentRevision},...a.timeoutMs===void 0?{}:{timeoutMs:a.timeoutMs},...a.traceId?{traceId:a.traceId}:{},...a.clientId?{clientId:a.clientId}:{},...a.transactionId?{transactionId:a.transactionId}:{},...a.settlement?{settlement:a.settlement}:{}})}})}function re(e){return Object.freeze({describeCommand(t){return e.request({kind:"commands.describe",commandId:t})},listCommands(t={}){return e.request({kind:"commands.list",...t})},searchCommands(t){return e.request({kind:"commands.search",...t})},async invokeCommand(t){let n=t.expectedDocumentRevision,o=e.serviceInstanceId;if(t.access==="write"&&n===void 0){let c=await e.request({kind:"status"});n=c.status.authority?.documentRevision,o=c.status.serviceInstanceId}let i=await e.request({kind:"command.invoke",invocation:{commandId:t.commandId,input:t.input,requestId:t.requestId,...t.idempotencyKey?{idempotencyKey:t.idempotencyKey}:{},...n===void 0?{}:{expectedRevision:{serviceInstanceId:o,document:n}},principal:{type:"agent",id:"fps-editor-agent"},source:"agent-cli",...t.transactionId?{transactionId:t.transactionId}:{},...t.traceId?{traceId:t.traceId}:{},...t.clientId?{clientId:t.clientId}:{}},...t.timeoutMs===void 0?{}:{timeoutMs:t.timeoutMs}});if(t.settlement==="query-once"&&i.operation&&!Ee(i.operation.status)){let c=await e.request({kind:"operation.get",operationId:i.operation.operationId});return{...i,operation:c.operation??i.operation}}return i}})}function Ee(e){return e==="completed"||e==="failed"||e==="cancelled"}var l=Object.freeze({ok:0,usage:2,discovery:3,unavailable:4,conflict:5,execution:6,running:7,interrupted:130}),W=1024*1024,Z=3e4,se=S.join(".fps-editor","state","agent-runtime.json"),k=Object.freeze({kind:"fps-editor-agent-deadline"}),q=!1,$=Number.POSITIVE_INFINITY,pe=Z,O=new AbortController;process.once("SIGINT",()=>{q=!0,O.abort(),process.exitCode=l.interrupted,setTimeout(()=>process.exit(l.interrupted),25).unref?.()});Ne().catch(e=>{let t=q?L():Se(e);v(t.result??{ok:!1,error:{code:t.code,message:t.message}}),t.log!==!1&&process.stderr.write(`[fps-editor-agent] ${t.message}
3
- `),process.exitCode=t.exitCode});async function Ne(){let e=Fe(process.argv.slice(2)),t=e.argv,n=e.projectRoot??process.cwd(),o=e.projectRoot!==void 0;if(pe=e.deadlineMs,$=Date.now()+e.deadlineMs,t.length===0||t.includes("--help")||t[0]==="help"){v({ok:!0,usage:Qe()});return}if(t.includes("--version")){let a=JSON.parse(await F(new URL("../package.json",import.meta.url),"utf8"));v({ok:!0,package:a.name,version:a.version,protocolVersion:4});return}let i=t.shift();if(i==="doctor"){let a=await Ie(n,{validateService:!1,exactProjectRoot:o}),d=await ge(a),r=await(await de(n,{exactProjectRoot:o})).request({kind:"status"});v({ok:!0,descriptorPath:a.descriptorPath,projectRoot:a.projectRoot,checks:d,status:r.status});return}let c=await de(n,{exactProjectRoot:o}),s=ie({transport:re(c),createRequestId:H,createIdempotencyKey:H,createUnavailableError:(a,d)=>I(l.unavailable,a,d)});if(i==="status"){v(await c.request({kind:"status"}));return}if(i==="commands"){await xe(s,t);return}if(i==="command"){await Ce(s,c,t);return}if(i==="transaction"){await ke(c,t);return}if(i==="apply"){await De(c,s,t);return}if(i==="operation"){await je(c,t);return}if(i==="trace"){await Le(c,t);return}throw p(`Unknown command: ${String(i)}`)}async function xe(e,t){let n=t.shift();if(n==="describe"){let s=j(t,"command id");ye(t),v(await e.describeCommand(s));return}let o=x(t,new Set(["--cursor","--limit"])),i=h(o.options,"--cursor"),c=_(o.options,"--limit",{minimum:1});if(n==="list"){if(o.positionals.length)throw p("commands list does not accept positional arguments.");v(await e.listCommands({...i?{cursor:i}:{},...c?{limit:c}:{}}));return}if(n==="search"){let s=j(o.positionals,"search query");if(o.positionals.length)throw p("commands search accepts one query.");v(await e.searchCommands({query:s,...i?{cursor:i}:{},...c?{limit:c}:{}}));return}throw p("commands requires list, search, or describe.")}async function Ce(e,t,n){let o=x(n,new Set(["--stdin","--input-file","--input-json","--expected-revision","--idempotency-key","--request-id","--timeout","--trace-id","--client-id","--source-file"]),new Set(["--stdin"])),i=j(o.positionals,"command id");if(o.positionals.length)throw p("command accepts one command id.");let c=await Je(o.options),s=await e.prepareCommand(i),a=h(o.options,"--source-file"),d=null;if(a){if(i!=="asset.import")throw p("--source-file is only valid for asset.import.");if(!c||typeof c!="object"||Array.isArray(c))throw p("asset.import input must be a JSON object.");if(Object.prototype.hasOwnProperty.call(c,"sourceGrantId"))throw p("Do not combine --source-file with input.sourceGrantId.");let w=await t.uploadAssetSource(S.resolve(a));d=w.sourceGrantId,c={...c,sourceGrantId:w.sourceGrantId}}let u=!1,r=!1,f=null;try{let w=_(o.options,"--expected-revision",{minimum:0}),m=_(o.options,"--timeout",{minimum:0});u=!0;let g=await e.invokeCommand({preparedCommand:s,input:c,...w===void 0?{}:{expectedDocumentRevision:w},...h(o.options,"--request-id")?{requestId:h(o.options,"--request-id")}:{},...h(o.options,"--idempotency-key")?{idempotencyKey:h(o.options,"--idempotency-key")}:{},...m===void 0?{}:{timeoutMs:m},...h(o.options,"--trace-id")?{traceId:h(o.options,"--trace-id")}:{},...h(o.options,"--client-id")?{clientId:h(o.options,"--client-id")}:{}});r=!0,v(g),G(g.operation)}catch(w){throw f=w,w}finally{let w=u&&!r&&["cli.deadlineExceeded","cli.interrupted","service.unreachable"].includes(f?.code);d&&!w&&await t.revokeAssetSource(d).catch(()=>{})}}async function ke(e,t){let n=t.shift();if(n==="begin"){let s=x(t,new Set(["--expected-revision","--label","--transaction-id","--trace-id","--service-instance-id"]));if(s.positionals.length)throw p("transaction begin does not accept positional arguments.");let a=await le(e),d=h(s.options,"--transaction-id")??H(),u=await e.request({kind:"transaction.begin",serviceInstanceId:h(s.options,"--service-instance-id")??a.serviceInstanceId,expectedDocumentRevision:_(s.options,"--expected-revision",{minimum:0})??a.documentRevision,...h(s.options,"--label")?{label:h(s.options,"--label")}:{},transactionId:d,...h(s.options,"--trace-id")?{traceId:h(s.options,"--trace-id")}:{}});v(u),P(u.transaction);return}let o=x(t,new Set(["--service-instance-id","--sequence","--stdin","--input-file","--cursor","--limit"]),new Set(["--stdin"])),i=j(o.positionals,"transaction id");if(o.positionals.length)throw p(`transaction ${String(n)} accepts one transaction id.`);let c=h(o.options,"--service-instance-id")??e.serviceInstanceId;if(n==="append"){Y(o.options,new Set(["--service-instance-id","--sequence","--stdin","--input-file"]));let s=_(o.options,"--sequence",{minimum:0});s===void 0&&(s=(await e.request({kind:"transaction.get",transactionId:i,serviceInstanceId:c,limit:1})).transaction.acceptedOperations);let a,d=me(o.options);await fe({client:e,source:d,transactionId:i,serviceInstanceId:c,sequence:s,maxOperations:e.status.transactions.maxOperationsPerAppend,maxBytes:e.status.transactions.maxBytesPerAppend,onAppend(u){a=u,v(u)}}),P(a?.transaction);return}if(n==="preflight"||n==="commit"||n==="abort"){Y(o.options,new Set(["--service-instance-id"]));let s=await e.request({kind:`transaction.${n}`,transactionId:i,serviceInstanceId:c});v(s),P(s.transaction,{abortedIsSuccess:n==="abort"});return}if(n==="get"){Y(o.options,new Set(["--service-instance-id","--cursor","--limit"]));let s=await e.request({kind:"transaction.get",transactionId:i,serviceInstanceId:c,...h(o.options,"--cursor")?{cursor:h(o.options,"--cursor")}:{},..._(o.options,"--limit",{minimum:1})?{limit:_(o.options,"--limit",{minimum:1})}:{}});v(s),P(s.transaction);return}throw p("transaction requires begin, append, preflight, commit, get, or abort.")}async function De(e,t,n){let o=x(n,new Set(["--stdin","--input-file","--save","--expected-revision","--label","--transaction-id","--trace-id","--service-instance-id","--timeout"]),new Set(["--stdin","--save"]));if(o.positionals.length)throw p("apply does not accept positional arguments.");let i=await le(e),c=h(o.options,"--service-instance-id")??i.serviceInstanceId,s=_(o.options,"--expected-revision",{minimum:0})??i.documentRevision,a=_(o.options,"--timeout",{minimum:0}),d=h(o.options,"--transaction-id")??H(),u=h(o.options,"--trace-id"),r,f="begin";try{r=(await e.request({kind:"transaction.begin",serviceInstanceId:c,expectedDocumentRevision:s,transactionId:d,...h(o.options,"--label")?{label:h(o.options,"--label")}:{},...u?{traceId:u}:{}})).transaction,M("begin",r),f="append";let m=me(o.options);if(await fe({client:e,source:m,transactionId:r.transactionId,serviceInstanceId:r.serviceInstanceId,sequence:r.acceptedOperations,maxOperations:i.transactions.maxOperationsPerAppend,maxBytes:i.transactions.maxBytesPerAppend,onAppend(Te){r=Te.transaction,M("append",r)}}),f="commit",r=(await e.request({kind:"transaction.commit",transactionId:r.transactionId,serviceInstanceId:r.serviceInstanceId})).transaction,M("commit",r),r.state!=="working_committed"){b(!1,"commit_failed",r),P(r);return}if(!o.options.has("--save")){b(!0,"working_committed",r);return}f="document.export";let R=await t.invokeCommand({commandId:"document.export",input:{},expectedDocumentRevision:r.workingDocumentRevision,transactionId:r.transactionId,traceId:u,timeoutMs:a,settlement:"query-once"}),y={response:R,operation:R.operation};if(ae("document.export",r,y.operation),y.operation?.status==="accepted"||y.operation?.status==="running"){b(!1,"awaiting_export_operation",r,{operation:N(y.operation),allowedActions:["operation.get","transaction.get"],retry:{retryable:!0,requiresRebase:!1}}),process.exitCode=l.running;return}if(y.operation?.status!=="completed"){b(!1,"save_failed",r,{operation:N(y.operation),allowedActions:["command document.export","transaction.get"],retry:{retryable:!0,requiresRebase:!1}}),G(y.operation);return}let E=y.operation.output;if(!E||typeof E!="object"||Array.isArray(E))throw I(l.execution,"document.exportReceiptInvalid","document.export returned an invalid receipt.");if(E.persistedByEditor===!1){b(!1,"awaiting_persistence_confirmation",r,{operation:N(y.operation),allowedActions:["operation.get","transaction.get"],retry:{retryable:!0,requiresRebase:!1}}),process.exitCode=l.running;return}let T=typeof E.transactionId=="string"&&E.transactionId.trim()?E.transactionId:null;if(!T)throw I(l.execution,"document.exportReceiptInvalid","document.export receipt is missing transactionId.");f="document.commit";let Re=Number.isSafeInteger(E.documentRevision)?E.documentRevision:r.workingDocumentRevision,te=await t.invokeCommand({commandId:"document.commit",input:{transactionId:T},expectedDocumentRevision:Re,transactionId:r.transactionId,traceId:u,timeoutMs:a,settlement:"query-once"}),A={response:te,operation:te.operation};if(ae("document.commit",r,A.operation),A.operation?.status==="accepted"||A.operation?.status==="running"){b(!1,"awaiting_commit_operation",r,{saveTransactionId:T,operation:N(A.operation),allowedActions:["operation.get","transaction.get"],retry:{retryable:!0,requiresRebase:!1}}),process.exitCode=l.running;return}if(A.operation?.status!=="completed"){b(!1,"save_commit_failed",r,{saveTransactionId:T,operation:N(A.operation),allowedActions:["command document.commit","transaction.get"],retry:{retryable:!0,requiresRebase:!1}}),G(A.operation);return}b(!0,"saved",r,{saveTransactionId:T,operation:N(A.operation),receipt:qe(A.operation.output)})}catch(w){let m=Se(w);if(m.result?.kind==="cli.deadline"){v({...m.result,kind:"apply.result",phase:f,...r?{transaction:C(r)}:{}}),process.exitCode=m.exitCode;return}let g;if(r&&(r.state==="open"||r.state==="preflighted"))try{r=(await e.request({kind:"transaction.abort",transactionId:r.transactionId,serviceInstanceId:r.serviceInstanceId})).transaction,g=C(r),M("abort",r)}catch{}v({ok:!1,kind:"apply.result",state:r?.state==="working_committed"?"save_failed":"failed",phase:f,...r?{transaction:C(r)}:{},...g?{aborted:g}:{},error:{code:m.code,message:m.message},allowedActions:r?.state==="working_committed"?["command document.export","transaction.get"]:["status"],retry:{retryable:r?.state==="working_committed",requiresRebase:/revision|serviceInstance/i.test(m.code)}}),process.exitCode=m.exitCode}}async function le(e){let t=await e.request({kind:"status"});if(t.kind!=="status"||!t.status)throw I(l.discovery,"protocol.statusInvalid","Editor Service returned an invalid status response.");return t.status}function me(e){if(["--stdin","--input-file"].filter(o=>e.has(o)).length>1)throw p("Use only one of --stdin or --input-file.");let n=h(e,"--input-file");return!n||n==="-"?process.stdin:Q(S.resolve(n),{encoding:"utf8"})}async function fe(e){let t=ce(e.maxOperations,ne),n=ce(e.maxBytes,oe),o=[],i=2,c=e.sequence,s=0,a=0,d=async()=>{if(o.length===0)return;let u=o.length,r=await e.client.request({kind:"transaction.append",transactionId:e.transactionId,serviceInstanceId:e.serviceInstanceId,sequence:c,operations:o});if(r.kind!=="transaction"||r.transaction.acceptedOperations<c+u)throw I(l.execution,"transaction.appendReceiptInvalid","Editor Service returned an invalid append receipt.");c=r.transaction.acceptedOperations,s+=u,e.onAppend(r),o=[],i=2};for await(let u of Ke(e.source,O.signal,n)){a+=1;let r=u.endsWith("\r")?u.slice(0,-1):u;if(!r.trim())continue;let f;try{f=JSON.parse(r)}catch(R){throw p(`NDJSON line ${a} is not valid JSON: ${R instanceof Error?R.message:String(R)}`)}Pe(f,a);let w=JSON.stringify(f),m=Buffer.byteLength(w);if(m+2>n)throw p(`NDJSON line ${a} exceeds the ${n}-byte transaction append limit.`);let g=i+m+(o.length?1:0);o.length&&(o.length>=t||g>n)&&await d(),o.push(f),i+=m+(o.length>1?1:0),(o.length>=t||i>=n)&&await d()}if(await d(),s===0)throw p("Transaction input must contain at least one NDJSON operation.");return{acceptedOperations:s,nextSequence:c}}function Pe(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw p(`NDJSON line ${t} must be a transaction operation object.`);if(typeof e.opId!="string"||!e.opId.trim())throw p(`NDJSON line ${t} requires a non-empty opId.`);if(typeof e.commandId!="string"||!e.commandId.trim())throw p(`NDJSON line ${t} requires a non-empty commandId.`);if(e.as!==void 0&&(typeof e.as!="string"||!e.as.trim()))throw p(`NDJSON line ${t} as must be a non-empty string.`)}function M(e,t){v({ok:t.state!=="failed",kind:"apply.event",phase:e,state:t.state,transaction:C(t)})}function ae(e,t,n){v({ok:n?.status!=="failed"&&n?.status!=="cancelled",kind:"apply.event",phase:e,state:n?.status??"unavailable",transaction:C(t),operation:N(n)})}function b(e,t,n,o={}){v({ok:e,kind:"apply.result",state:t,phase:t==="saved"?"complete":n.phase,transaction:C(n),...o.allowedActions?{}:{allowedActions:n.allowedActions},...o.retry?{}:{retry:n.retry},...o})}function C(e){return{transactionId:e.transactionId,serviceInstanceId:e.serviceInstanceId,state:e.state,phase:e.phase,baseDocumentRevision:e.baseDocumentRevision,...e.workingDocumentRevision===void 0?{}:{workingDocumentRevision:e.workingDocumentRevision},dirty:e.dirty,acceptedOperations:e.acceptedOperations,acceptedBytes:e.acceptedBytes,processedOperations:e.processedOperations,allowedActions:e.allowedActions,retry:e.retry,diagnostics:e.diagnostics,results:{offset:e.results.offset,returned:e.results.returned,total:e.results.total,...e.results.nextCursor?{nextCursor:e.results.nextCursor}:{}}}}function N(e){return e?{operationId:e.operationId,requestId:e.requestId,commandId:e.commandId,status:e.status,...e.transactionId?{transactionId:e.transactionId}:{},...e.traceId?{traceId:e.traceId}:{},...e.output===void 0?{}:{output:e.output},...e.diagnostics?{diagnostics:e.diagnostics}:{}}:null}function qe(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function ce(e,t){return Number.isSafeInteger(e)&&e>0?e:t}async function je(e,t){let n=t.shift();if(n==="get"){let o=x(t,new Set(["--request-id","--service-instance-id"])),i=o.positionals.shift();if(o.positionals.length)throw p("operation get accepts at most one operation id.");let c=h(o.options,"--request-id");if(!i&&!c||i&&c)throw p("operation get requires exactly one operation id or --request-id.");let s=h(o.options,"--service-instance-id");if(s&&s!==e.serviceInstanceId)throw I(l.conflict,"operation.serviceInstanceChanged",`Expected Editor Service ${s}, received ${e.serviceInstanceId}.`);let a=await e.request(i?{kind:"operation.get",operationId:i}:{kind:"operation.get",requestId:c});v(a),a.operation?G(a.operation):process.exitCode=l.unavailable;return}if(n==="cancel"){let o=j(t,"operation id");ye(t);let i=await e.request({kind:"operation.cancel",operationId:o});v(i),i.operation?!i.cancelled&&!ze(i.operation.status)&&(process.exitCode=l.running):process.exitCode=l.unavailable;return}throw p("operation requires get or cancel.")}async function Le(e,t){if(t.shift()!=="get")throw p("trace requires get.");let o=x(t,new Set(["--cursor","--limit"])),i=o.positionals.shift();if(o.positionals.length)throw p("trace get accepts at most one trace id.");v(await e.request({kind:"trace.get",...i?{traceId:i}:{},...h(o.options,"--cursor")?{cursor:h(o.options,"--cursor")}:{},..._(o.options,"--limit",{minimum:1})?{limit:_(o.options,"--limit",{minimum:1})}:{}}))}async function de(e,t={}){let n=await Ie(e,{validateService:!0,...t}),o=he(process.env.FPS_EDITOR_AGENT_ENDPOINT?.trim()||n.descriptor.endpoint),i=process.env.FPS_EDITOR_AGENT_TOKEN?.trim()||n.descriptor.token,c=async u=>{if(q)throw I(l.interrupted,"cli.interrupted","Interrupted.");let r=$-Date.now();if(r<=0)throw D(n,u);let f=new AbortController,w=()=>f.abort(O.signal.reason);O.signal.addEventListener("abort",w,{once:!0});let m=setTimeout(()=>f.abort(k),r);m.unref?.();try{let g=await fetch(o,{method:"POST",headers:{authorization:`Bearer ${i}`,"content-type":"application/json"},body:JSON.stringify(u),signal:f.signal}),R=await K(g),y;try{y=JSON.parse(R)}catch{throw I(l.discovery,"protocol.invalidJson","Editor Service returned invalid JSON.")}if(g.status===401||g.status===403)throw I(l.discovery,"auth.invalidToken",we(y)||"Editor Service authentication failed.");if(!y?.ok)throw X(y);return y}catch(g){throw q||O.signal.aborted?L():f.signal.reason===k?D(n,u):g&&Number.isInteger(g.exitCode)?g:I(l.discovery,"service.unreachable",`Editor Service is unreachable: ${g instanceof Error?g.message:String(g)}`)}finally{clearTimeout(m),O.signal.removeEventListener("abort",w)}},s=await c({kind:"status"});Ge(n,s);let a=async u=>{let r=await Me(u),f=new URL(V,o),w=new AbortController,m=$-Date.now();if(m<=0)throw D(n,{kind:"asset.sourceGrant"});let g=()=>w.abort(O.signal.reason);O.signal.addEventListener("abort",g,{once:!0});let R=setTimeout(()=>w.abort(k),m);R.unref?.();try{let y=await fetch(f,{method:"POST",headers:{authorization:`Bearer ${i}`,"content-type":"application/vnd.fps-editor.asset-source-bundle-v1"},body:be.from($e(r)),duplex:"half",signal:w.signal}),E=await K(y),T;try{T=JSON.parse(E)}catch{throw I(l.discovery,"protocol.invalidJson","Editor Service returned invalid JSON for asset source upload.")}if(!y.ok||!T?.ok||T.kind!=="asset.sourceGrant"||!T.grant?.sourceGrantId)throw X(T);return T.grant}catch(y){throw q||O.signal.aborted?L():w.signal.reason===k?D(n,{kind:"asset.sourceGrant"}):y&&Number.isInteger(y.exitCode)?y:I(l.discovery,"asset.sourceUploadFailed",`Asset source upload failed: ${y instanceof Error?y.message:String(y)}`)}finally{clearTimeout(R),O.signal.removeEventListener("abort",g)}},d=async u=>{let r=$-Date.now();if(r<=0)throw D(n,{kind:"asset.sourceGrant.revoke"});let f=new AbortController,w=setTimeout(()=>f.abort(k),r);w.unref?.();try{let m=new URL(V,o);m.searchParams.set("sourceGrantId",u);let g=await fetch(m,{method:"DELETE",headers:{authorization:`Bearer ${i}`},signal:f.signal}),R=await K(g),y;try{y=JSON.parse(R)}catch{throw I(l.discovery,"protocol.invalidJson","Editor Service returned invalid JSON for asset source revocation.")}if(!g.ok||!y?.ok)throw X(y);return y}finally{clearTimeout(w)}};return Object.freeze({discovery:n,serviceInstanceId:n.descriptor.serviceInstanceId,status:s.status,request:c,uploadAssetSource:a,revokeAssetSource:d})}async function Me(e){let t;try{t=await B(e)}catch(d){throw I(l.usage,"asset.sourceNotFound",`Asset source is unavailable: ${d instanceof Error?d.message:String(d)}`)}let n=await U(t);if(!n.isFile())throw p("Asset source must be a regular file.");let o=S.extname(t).toLowerCase();if(![".glb",".gltf",".png",".jpg",".jpeg",".env"].includes(o))throw p("Asset source must be GLB, glTF, PNG, JPG, JPEG, or Babylon ENV.");let i=S.dirname(t),c=new Map([[S.basename(t),t]]);if(o===".gltf"){if(n.size>16*1024*1024)throw p("glTF JSON source exceeds the 16 MiB manifest limit.");let d;try{d=JSON.parse(await F(t,"utf8"))}catch(r){throw p(`glTF source is not valid JSON: ${r instanceof Error?r.message:String(r)}`)}let u=[...Array.isArray(d?.buffers)?d.buffers:[],...Array.isArray(d?.images)?d.images:[]];for(let r of u){let f=typeof r?.uri=="string"?r.uri:null;if(!f||f.startsWith("data:"))continue;if(/^[a-z][a-z0-9+.-]*:/i.test(f)||f.startsWith("//"))throw p("glTF dependencies must use local relative URIs.");let w;try{w=decodeURIComponent(f.split(/[?#]/,1)[0])}catch{throw p(`glTF dependency URI is malformed: ${f}`)}let m=S.posix.normalize(w.replaceAll("\\","/"));if(!m||m==="."||m===".."||m.startsWith("../")||S.posix.isAbsolute(m))throw p(`glTF dependency escapes the source directory: ${f}`);let g;try{g=await B(S.resolve(i,...m.split("/")))}catch{throw p(`glTF dependency is missing: ${m}`)}if(He(i,g,m),!(await U(g)).isFile())throw p(`glTF dependency is not a regular file: ${m}`);c.set(m,g)}}let s=[];for(let[d,u]of c){let r=await U(u);if(r.size<1||r.size>256*1024*1024)throw p(`Asset source file size is outside the supported range: ${d}`);s.push({path:d,filePath:u,byteSize:r.size,contentHash:await Ue(u)})}let a=s.reduce((d,u)=>d+u.byteSize,0);if(s.length>128||a>512*1024*1024)throw p("Asset source bundle exceeds the supported file-count or total-size limit.");return{primaryPath:S.basename(t),files:s}}async function Ue(e){let t=Oe("sha256");for await(let n of Q(e))t.update(n);return`sha256:${t.digest("hex")}`}async function*$e(e){let t=Buffer.from(JSON.stringify({schemaVersion:1,primaryPath:e.primaryPath,files:e.files.map(({path:o,byteSize:i,contentHash:c})=>({path:o,byteSize:i,contentHash:c}))}),"utf8"),n=Buffer.allocUnsafe(4);n.writeUInt32BE(t.length,0),yield n,yield t;for(let o of e.files)for await(let i of Q(o.filePath))yield i}function He(e,t,n){let o=S.relative(e,t);if(!o||o===".."||o.startsWith(`..${S.sep}`)||S.isAbsolute(o))throw p(`glTF dependency escapes the source directory: ${n}`)}async function Ie(e,t={}){let n;try{n=await B(S.resolve(e))}catch(o){throw I(l.discovery,"projectRoot.invalid",`Project root is unavailable: ${o instanceof Error?o.message:String(o)}`)}for(;;){let o=S.join(n,se);if(await Ye(o)){let c=await Be(o),s=await B(n);if(c.canonicalProjectRoot!==s)throw I(l.discovery,"descriptor.projectMismatch",`Runtime descriptor does not own ${s}.`);let a={descriptorPath:o,projectRoot:s,descriptor:c};return t.validateService!==!1&&await ge(a),a}if(t.exactProjectRoot===!0)break;let i=S.dirname(n);if(i===n)break;n=i}throw I(l.discovery,"descriptor.notFound",`No ${se} was found from ${e}.`)}async function Be(e){let t;try{t=JSON.parse(await F(e,"utf8"))}catch(n){throw I(l.discovery,"descriptor.invalid",`Runtime descriptor is unreadable: ${n instanceof Error?n.message:String(n)}`)}if(t?.schemaVersion!==1||t?.protocolVersion!==4||t?.packageName!=="@fps-games/editor"||typeof t?.serviceInstanceId!="string"||typeof t?.canonicalProjectRoot!="string"||typeof t?.endpoint!="string"||typeof t?.token!="string"||!Number.isSafeInteger(t?.pid))throw I(l.discovery,"descriptor.incompatible","Runtime descriptor schema or protocol is incompatible.");if(he(t.endpoint),process.platform!=="win32"){let n=(await U(e)).mode&511;if(n&63)throw I(l.discovery,"descriptor.permissions",`Runtime descriptor permissions must be 0600; received ${n.toString(8)}.`)}return t}function he(e){let t;try{t=new URL(e)}catch{throw I(l.discovery,"descriptor.endpoint","Runtime descriptor endpoint is invalid.")}if(t.protocol!=="http:"||!["127.0.0.1","localhost","[::1]"].includes(t.hostname))throw I(l.discovery,"descriptor.endpoint","Runtime descriptor endpoint must be project-local loopback HTTP.");return t.toString()}async function ge(e){let t=[];t.push({id:"descriptor.schema",ok:e.descriptor.schemaVersion===1}),t.push({id:"descriptor.protocol",ok:e.descriptor.protocolVersion===4}),t.push({id:"descriptor.project",ok:e.descriptor.canonicalProjectRoot===e.projectRoot});let n=Ve(e.descriptor.pid);if(t.push({id:"descriptor.process",ok:n,pid:e.descriptor.pid}),!n)throw I(l.discovery,"descriptor.stale",`Editor Service process is not alive: ${e.descriptor.pid}.`);return t}function Ge(e,t){let n=t?.kind==="status"?t.status:null;if(!n||n.protocolVersion!==4)throw I(l.discovery,"protocol.incompatible","Editor Service status protocol is incompatible.");if(n.serviceInstanceId!==e.descriptor.serviceInstanceId||n.canonicalProjectRoot!==e.projectRoot||n.packageVersion!==e.descriptor.packageVersion||n.buildKey!==e.descriptor.buildKey)throw I(l.discovery,"service.identityMismatch","Editor Service identity does not match the project runtime descriptor.")}async function Je(e){if(["--stdin","--input-file","--input-json"].filter(i=>e.has(i)).length>1)throw p("Use only one of --stdin, --input-file, or --input-json.");if(e.has("--stdin"))return z(await Xe(process.stdin,O.signal),"--stdin");let n=h(e,"--input-file");if(n)return z(await F(S.resolve(n),"utf8"),"--input-file");let o=h(e,"--input-json");return o===void 0?{}:z(o,"--input-json")}function z(e,t){try{return JSON.parse(e)}catch(n){throw p(`${t} is not valid JSON: ${n instanceof Error?n.message:String(n)}`)}}function x(e,t,n=new Set){let o=new Map,i=[];for(;e.length;){let c=e.shift();if(!c.startsWith("--")){i.push(c);continue}let[s,a]=c.split("=",2);if(!t.has(s))throw p(`Unknown option: ${s}`);if(o.has(s))throw p(`Option may only be provided once: ${s}`);if(n.has(s)){if(a!==void 0)throw p(`${s} does not accept a value.`);o.set(s,!0);continue}let d=a??e.shift();if(d===void 0||d.startsWith("--"))throw p(`${s} requires a value.`);o.set(s,d)}return{options:o,positionals:i}}function h(e,t){let n=e.get(t);if(n!==void 0){if(typeof n!="string"||!n.trim())throw p(`${t} requires a non-empty value.`);return n.trim()}}function Fe(e){let t=[],n=Z,o=!1,i;for(let c=0;c<e.length;c+=1){let s=e[c];if(s==="--project-root"||s.startsWith("--project-root=")){if(i!==void 0)throw p("--project-root may only be provided once.");let u=s==="--project-root"?e[++c]:s.slice(15);if(u===void 0||!u.trim()||u.startsWith("--"))throw p("--project-root requires a non-empty path.");i=S.resolve(process.cwd(),u);continue}if(s!=="--deadline"&&!s.startsWith("--deadline=")){t.push(s);continue}if(o)throw p("--deadline may only be provided once.");o=!0;let a=s==="--deadline"?e[++c]:s.slice(11);if(a===void 0||a.startsWith("--"))throw p("--deadline requires a value.");let d=Number(a);if(!Number.isSafeInteger(d)||d<1)throw p("--deadline must be an integer >= 1.");n=d}return{argv:t,deadlineMs:n,projectRoot:i}}function _(e,t,{minimum:n}){let o=h(e,t);if(o===void 0)return;let i=Number(o);if(!Number.isSafeInteger(i)||i<n)throw p(`${t} must be an integer >= ${n}.`);return i}function j(e,t){let n=e.shift();if(!n)throw p(`Missing ${t}.`);return n}function ye(e){if(e.length)throw p(`Unexpected argument: ${e[0]}`)}function Y(e,t){for(let n of e.keys())if(!t.has(n))throw p(`Option is not valid for this action: ${n}`)}function G(e){if(!e){process.exitCode=l.unavailable;return}if(e.status==="accepted"||e.status==="running"){process.exitCode=l.running;return}(e.status==="failed"||e.status==="cancelled")&&(process.exitCode=ee(e.diagnostics))}function P(e,t={}){if(!e){process.exitCode=l.unavailable;return}if(e.state==="preflighting"||e.state==="committing"){process.exitCode=l.running;return}if(e.state==="failed"){process.exitCode=ee(e.diagnostics);return}e.state==="aborted"&&t.abortedIsSuccess!==!0&&(process.exitCode=l.execution)}function ee(e=[]){let t=e.map(n=>n?.code??"");return t.some(n=>/revision|idempotency|conflict|serviceInstance/i.test(n))?l.conflict:t.some(n=>/unknown|unavailable|notFound|sessionUnavailable/i.test(n))?l.unavailable:l.execution}function X(e){let t=Array.isArray(e?.diagnostics)?e.diagnostics:[];return I(ee(t),t[0]?.code??"service.requestFailed",we(e)||"Editor Service request failed.")}function we(e){return Array.isArray(e?.diagnostics)?e.diagnostics.map(t=>t?.message).filter(Boolean).join("; "):""}function Ve(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}function ze(e){return e==="completed"||e==="failed"||e==="cancelled"}async function K(e){let t=Number(e.headers.get("content-length"));if(Number.isFinite(t)&&t>W)throw I(l.execution,"response.tooLarge","Editor Service response exceeds 1 MiB.");let n=await e.text();if(Buffer.byteLength(n)>W)throw I(l.execution,"response.tooLarge","Editor Service response exceeds 1 MiB.");return n}async function Ye(e){try{return await Ae(e,_e.R_OK),!0}catch{return!1}}async function Xe(e,t){let n=[];for await(let o of ve(e,t))n.push(Buffer.isBuffer(o)?o:Buffer.from(o));return Buffer.concat(n).toString("utf8")}async function*Ke(e,t,n=Number.POSITIVE_INFINITY){let o="";for await(let i of ve(e,t)){o+=i.toString();let c;for(;(c=o.indexOf(`
4
- `))>=0;){let s=o.slice(0,c);if(Buffer.byteLength(s)>n)throw p(`NDJSON line exceeds the ${n}-byte transaction append limit.`);yield s,o=o.slice(c+1)}if(Buffer.byteLength(o)>n)throw p(`NDJSON line exceeds the ${n}-byte transaction append limit.`)}o&&(yield o)}async function*ve(e,t){let n=e[Symbol.asyncIterator]();for(;;){let o=await We(n,t);if(o.done)return;yield o.value}}function We(e,t){return t.aborted?Promise.reject(L()):new Promise((n,o)=>{let i=()=>o(L());t.addEventListener("abort",i,{once:!0}),e.next().then(n,o).finally(()=>t.removeEventListener("abort",i))})}function v(e){let t=JSON.stringify(e);if(Buffer.byteLength(t)>W)throw I(l.execution,"output.tooLarge","CLI output exceeds 1 MiB.");process.stdout.write(`${t}
5
- `)}function Qe(){return{globalOptions:{deadline:`End-to-end CLI deadline in milliseconds (default ${Z}).`,projectRoot:"Exact target project root. Required for deployment-owned usage from outside the project."},commands:["status","commands list [--cursor CURSOR] [--limit N]","commands search QUERY [--cursor CURSOR] [--limit N]","commands describe COMMAND_ID","command COMMAND_ID [--stdin|--input-file FILE|--input-json JSON] [--source-file FILE for asset.import] [--expected-revision N] [--idempotency-key KEY] [--request-id ID] [--trace-id ID] [--client-id ID] [--timeout MS]","apply [--stdin|--input-file FILE] [--save] [--expected-revision N] [--transaction-id ID] [--label TEXT] [--trace-id ID] [--timeout MS]","transaction begin [--expected-revision N] [--transaction-id ID] [--label TEXT] [--trace-id ID]","transaction append TRANSACTION_ID [--stdin|--input-file FILE] [--sequence N] [--service-instance-id ID]","transaction preflight TRANSACTION_ID [--service-instance-id ID]","transaction commit TRANSACTION_ID [--service-instance-id ID]","transaction get TRANSACTION_ID [--service-instance-id ID] [--cursor CURSOR] [--limit N]","transaction abort TRANSACTION_ID [--service-instance-id ID]","operation get OPERATION_ID [--service-instance-id ID]","operation get --request-id REQUEST_ID [--service-instance-id ID]","operation cancel OPERATION_ID","trace get [TRACE_ID] [--cursor CURSOR] [--limit N]","doctor"],exitCodes:l}}function p(e){return I(l.usage,"cli.usage",e)}function I(e,t,n,o=!0,i){return Object.assign(new Error(n),{exitCode:e,code:t,log:o,...i?{result:i}:{}})}function D(e,t){let n=t?.kind==="command.invoke"?t.invocation:null,o=t?.kind?.startsWith("transaction.")?t.transactionId:n?.transactionId,i=!!n||typeof t?.kind=="string"&&/^transaction\.(begin|append|preflight|commit|abort)$/.test(t.kind),c=n?.requestId,s=c?`operation get --request-id ${c} --service-instance-id ${e.descriptor.serviceInstanceId}`:null,a=o?`transaction get ${o} --service-instance-id ${e.descriptor.serviceInstanceId}`:null,d=[s,a].filter(Boolean);d.length||d.push("status");let u=`Agent CLI exceeded its ${pe}ms end-to-end deadline.`;return I(l.running,"cli.deadlineExceeded",u,!0,{ok:!1,kind:"cli.deadline",state:i?"outcome_unknown":"timed_out",serviceInstanceId:e.descriptor.serviceInstanceId,...n?.commandId?{commandId:n.commandId}:{},...c?{requestId:c}:{},...o?{transactionId:o}:{},error:{code:"cli.deadlineExceeded",message:u},allowedActions:d,retry:{retryable:!i,requiresOperationQuery:i}})}function L(){return I(l.interrupted,"cli.interrupted","Interrupted.")}function Se(e){return e&&Number.isInteger(e.exitCode)&&typeof e.code=="string"?e:I(l.execution,"cli.failure",e instanceof Error?e.message:String(e))}
@@ -1,5 +0,0 @@
1
- import{fC as Ae,W as U,a1 as Pe,by as z,aF as fe,nq as Ce,mR as je,fB as $e,$ as Fe,es as Te,a0 as G,mq as ke,iV as Oe,fT as te,jL as De,hW as Ne}from"./playable-standard-project-C61X2B53.js";import{registerFpsEditorContribution as Le}from"@fps-games/editor-core/plugin-host";import"./hemisphericLight-C4swwL68.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))n(s);new MutationObserver(s=>{for(const o of s)if(o.type==="childList")for(const i of o.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&n(i)}).observe(document,{childList:!0,subtree:!0});function r(s){const o={};return s.integrity&&(o.integrity=s.integrity),s.referrerPolicy&&(o.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?o.credentials="include":s.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function n(s){if(s.ep)return;s.ep=!0;const o=r(s);fetch(s.href,o)}})();const Ue="0.2.3-beta.13",me="fps.plugin.hierarchy";function He(){return Ae({id:me,version:Ue,apiVersion:1,requires:{},provides:{features:["fps.editor.hierarchy"]},entries:{editor:"./editor"},environmentContracts:{editor:{requires:{services:["fps.editor.contributions"]},provides:{}}},deploymentConstraints:{allowedTargets:["editor"]}})}const Be="fps-editor.pending-recovery.v1",Ve=10*60*1e3,qe=32,ze=128*1024;function re(e,t){try{const r=JSON.parse(e.getItem(t)??"[]");return Array.isArray(r)?r.filter(he):[]}catch{return[]}}function he(e){if(!e||typeof e!="object")return!1;const t=e;return t.schemaVersion===1&&typeof t.documentId=="string"&&typeof t.projectEpoch=="string"&&typeof t.serviceInstanceId=="string"&&typeof t.operationId=="string"&&typeof t.idempotencyKey=="string"&&typeof t.commandId=="string"&&!!t.invocation&&typeof t.invocation=="object"&&typeof t.createdAt=="number"&&Number.isFinite(t.createdAt)}function Ge(e={}){const t=e.storage===void 0?typeof sessionStorage>"u"?null:sessionStorage:e.storage,r=e.key??Be,n=e.now??(()=>Date.now()),s=e.ttlMs??Ve,o=e.maxRecords??qe,i=e.maxBytes??ze,a=()=>{if(!t)return[];const c=n()-s,u=re(t,r).filter(l=>l.createdAt>=c);if(u.length!==re(t,r).length)try{t.setItem(r,JSON.stringify(u))}catch{}return u},d=c=>{if(!t)return!1;try{return t.setItem(r,JSON.stringify(c)),!0}catch{return!1}},h=c=>new TextEncoder().encode(JSON.stringify(c)).byteLength;return{list(c){return a().filter(u=>(c?.documentId===void 0||u.documentId===c.documentId)&&(c?.projectEpoch===void 0||u.projectEpoch===c.projectEpoch))},upsert(c){if(!t||!he(c))return{accepted:!1,reason:t?"invalid":"unavailable"};const l=[...a().filter(g=>g.operationId!==c.operationId),c];return l.length>o||h(l)>i?{accepted:!1,reason:"capacity"}:d(l)?{accepted:!0}:{accepted:!1,reason:"unavailable"}},remove(c){d(a().filter(u=>u.operationId!==c))},clearForDocument(c){d(a().filter(u=>u.documentId!==c))},clearForProject(c,u){d(a().filter(l=>l.documentId!==c||l.projectEpoch!==u))},clear(){t?.removeItem(r)},getBytes(){return h(a())}}}function We(e){let t=!1;const r=e.host.onAuthorityChanged(n=>e.onAuthorityChanged?.(n));return{async recover(){if(t)return{status:"unavailable",error:new Error("Recovery controller is disposed.")};try{const n=await e.host.bootstrap();if(n.protocolVersion!==U)throw new Error("Editor recovery bootstrap protocol is incompatible.");e.onBootstrap?.(n);const s=e.store.list({documentId:e.documentId});if(e.projectEpoch&&e.projectEpoch!==n.projectEpoch)return e.store.clearForDocument(e.documentId),{status:"blocked",bootstrap:n,reason:"project-epoch-changed"};const o=s.filter(a=>a.projectEpoch===n.projectEpoch);if(o.some(a=>a.serviceInstanceId!==n.serviceInstanceId))return{status:"blocked",bootstrap:n,reason:"service-instance-changed"};const i=[];for(const a of o){const d=await e.host.request({kind:"operation.get",operationId:a.operationId});if(d.ok&&d.kind==="operation"&&d.operation&&(d.operation.status==="completed"||d.operation.status==="failed"||d.operation.status==="cancelled")){e.store.remove(a.operationId);continue}(await e.host.request({kind:"command.invoke",invocation:a.invocation})).ok&&(i.push(a.operationId),e.store.remove(a.operationId))}return{status:"ready",bootstrap:n,replayedOperationIds:i}}catch(n){return{status:"unavailable",error:n}}},dispose(){t||(t=!0,r())}}}function Ke(e){const{doc:t}=e,r=t.createElement("div");r.classList.add(Pe,"fps-editor-ui-modal-root"),r.dataset.editorFatalRecovery="true",r.dataset.editorWorkbenchRegion="fatal-recovery";const n=t.createElement("div");n.className="fps-editor-ui-modal",n.setAttribute("role","alertdialog"),n.setAttribute("aria-modal","true");const s=t.createElement("div");s.className="fps-editor-ui-modal-header";const o=t.createElement("h2");o.className="fps-editor-ui-modal-title",s.appendChild(o);const i=t.createElement("div");i.className="fps-editor-ui-modal-message";const a=t.createElement("div");a.className="fps-editor-ui-modal-decision";const d=W(t,"影响范围"),h=W(t,"当前状态"),c=W(t,"恢复方式");a.append(d.root,h.root,c.root);const u=t.createElement("pre");u.className="fps-editor-ui-modal-details";const l=z(t,"查看技术详情");l.classList.add("fps-editor-ui-modal-details-toggle"),l.dataset.editorFatalRecoveryDetails="true",l.setAttribute("aria-expanded","false");const g=t.createElement("div");g.className="fps-editor-ui-modal-footer";const b=z(t,"复制诊断信息");b.dataset.editorFatalRecoveryCopy="true";const f=z(t,"重试连接");f.dataset.editorFatalRecoveryAction="true",g.append(b,f),n.append(s,i,a,l,u,g),r.appendChild(n),(e.host??t.body).appendChild(r);let p=null,w=!1,_=!1,S=!1;const A=m=>{S=m,u.style.display=m?"block":"none",l.setAttribute("aria-expanded",String(m)),l.textContent=m?"收起技术详情":"查看技术详情"},P=m=>{const y=m.target instanceof Element?m.target:null;if(!(!y||!p)){if(y.closest("[data-editor-fatal-recovery-details]")){m.preventDefault(),A(!S);return}if(y.closest("[data-editor-fatal-recovery-copy]")){m.preventDefault(),V(p);return}!y.closest("[data-editor-fatal-recovery-action]")||_||(m.preventDefault(),_=!0,f.disabled=!0,p.onRecover())}},F=m=>{if(w){if(m.key==="Tab"&&Ce(m,n)){m.stopPropagation();return}m.key==="Escape"&&(m.preventDefault(),m.stopPropagation())}},V=async m=>{const y=je(["FPS Game Editor Fatal Recovery",`标题:${m.title}`,`提示:${m.message}`,`影响范围:${m.target}`,`当前状态:${m.consequence}`,`恢复方式:${m.recovery}`,...m.details?[`技术详情:
2
- ${m.details}`]:[]].join(`
3
- `));try{const E=e.writeClipboardText??(t.defaultView?.navigator.clipboard?.writeText?M=>t.defaultView.navigator.clipboard.writeText(M):null);if(!E)throw new Error("Clipboard API is unavailable.");await E(y),b.textContent="已复制"}catch(E){b.textContent="复制失败",console.error("[LocalEditorFatalRecoveryDialog] copy failed",E)}};return r.addEventListener("click",P),t.addEventListener("keydown",F,{capture:!0}),{isOpen:()=>w,show(m){p=m,w=!0,_=!1,f.disabled=!1,fe(r,e.getTheme?.()),o.textContent=m.title,n.setAttribute("aria-label",m.title),i.textContent=m.message,d.value.textContent=m.target,h.value.textContent=m.consequence,c.value.textContent=m.recovery,u.textContent=m.details??"",l.style.display=m.details?"inline-flex":"none",f.textContent=m.actionLabel,b.textContent="复制诊断信息",A(!1),r.style.display="flex",setTimeout(()=>f.focus({preventScroll:!0}),0)},dispose(){!w&&!r.isConnected||(w=!1,p=null,r.removeEventListener("click",P),t.removeEventListener("keydown",F,{capture:!0}),r.remove())}}}function W(e,t){const r=e.createElement("div");r.className="fps-editor-ui-modal-decision-row";const n=e.createElement("div");n.className="fps-editor-ui-modal-decision-label",n.textContent=t;const s=e.createElement("div");return s.className="fps-editor-ui-modal-decision-value",r.append(n,s),{root:r,value:s}}const Je=$e({pluginId:me,environment:"editor",register(e){Le(e,{id:Fe,kind:"hierarchy",value:Te()})}});class B extends Error{constructor(){super("Editor Host service protocol is incompatible."),this.name="EditorHostProtocolIncompatibleError"}}function Ye(e){const t=new Set;let r=null;const n=(i=new B)=>{throw r??(r=i),r},s=()=>{if(r)throw r},o=e.onAuthorityChanged?.(i=>{for(const a of t)a(i)});return Object.freeze({async bootstrap(){s();try{const i=await e.bootstrap();return i.protocolVersion!==U&&n(),i}catch(i){throw i instanceof B&&n(i),i}},async request(i){s();try{const a=await e.request(i);return a.ok&&a.kind==="status"&&a.status.protocolVersion!==U&&n(),a}catch(a){throw a instanceof B&&n(a),a}},async watch(i){return s(),e.watch(i)},...e.resolveAssetUrl?{resolveAssetUrl:e.resolveAssetUrl}:{},onAuthorityChanged(i){return t.add(i),()=>t.delete(i)},dispose(){o?.(),t.clear()}})}function Xe(e){const t=e.fetch??globalThis.fetch;if(typeof t!="function")throw new Error("Editor Host requires fetch.");const r=e.origin??(typeof location<"u"?location.origin:void 0);if(!r)throw new Error("Editor Host requires an absolute origin.");const n=new URL(e.runtime.gatewayPath,r).href,s=new URL(e.bootstrapPath??"/__fps_editor/bootstrap.json",r).href,o=async i=>{const a=await t(n,{method:"POST",headers:{authorization:`Bearer ${e.runtime.token}`,"content-type":"application/json"},body:JSON.stringify(i)}),d=await a.json();if(!a.ok&&d.ok)throw new Error(`Editor Host gateway returned HTTP ${a.status}.`);if(d.ok&&d.kind==="status"&&d.status.protocolVersion!==U)throw new B;return d};return Ye({bootstrap:async()=>{const i=await t(s,{cache:"no-store"});if(!i.ok)throw new Error(`Editor Host bootstrap returned HTTP ${i.status}.`);const a=await i.json(),d=await o({kind:"status"});if(!d.ok||d.kind!=="status")throw new Error("Editor Host bootstrap service status is unavailable.");if(d.status.protocolVersion!==U)throw new B;const h=await o({kind:"authoring.snapshot"});if(!h.ok||h.kind!=="authoring.snapshot"||h.result.kind!=="snapshot-required")throw new Error("Editor Host bootstrap did not return an authoring snapshot.");const c=h.result.snapshot;if(c.serviceInstanceId!==d.status.serviceInstanceId)throw new Error("Editor Host bootstrap service identity changed during bootstrap.");if(typeof a.projectEpoch!="string"||!a.projectEpoch)throw new Error("Editor Host bootstrap identity is incomplete.");return{protocolVersion:U,documentId:e.documentId,projectEpoch:a.projectEpoch,serviceInstanceId:d.status.serviceInstanceId,...typeof a.serverInstanceId=="string"?{serverInstanceId:a.serverInstanceId}:{},...typeof a.worker?.generation=="number"?{workerGeneration:a.worker.generation}:{},documentRevision:c.documentRevision,eventCursor:c.eventCursor,dirty:c.dirty,...c.draftRevision===void 0?{}:{draftRevision:c.draftRevision},...c.savedRevision===void 0?{}:{savedRevision:c.savedRevision}}},request:o,watch:async i=>{const a=await o({kind:"authoring.snapshot",afterEventCursor:i,timeoutMs:25e3});if(!a.ok||a.kind!=="authoring.snapshot")throw new Error("Editor Host authoring watch failed.");return a.result},...e.onAuthorityChanged?{onAuthorityChanged:e.onAuthorityChanged}:{}})}async function Ze(e){let t=null,r=!1,n=Promise.resolve(),s=null;const o=e.recoveryStore??Ge();let i=e.recoveryProjectEpoch??"default",a=null,d=null,h=null,c=null,u=null,l=!1;const g=e.container.ownerDocument,b=g.defaultView??window,f=g.createElement("canvas");f.id="renderCanvas",f.style.cssText="display:block;width:100%;height:100%;touch-action:none;outline:none";const p=()=>{h?.dispose(),h=null},w=()=>{s?.(),s=null,f.remove(),p()},_=()=>{d?.dispose?.(),d=null},S=()=>{u?.dispose(),u=null,l=!1},A=y=>{if(r||l||!t)return;l=!0;const E=Qe(y);let M=null;try{M=t.getHost()?.harness.getUnsavedChangesState()??null}catch(v){console.error("[FpsGameEditor] failed to inspect Working Draft before reconnect",v)}te(g),u??(u=Ke({doc:g,host:e.container,getTheme:()=>"dark"}));const I=M?.dirty&&M.hasWorkingDocument?"草稿状态:检测到尚未保存的 Working Draft。重新连接后将以 Editor Service 可恢复的最新状态为准。":"草稿状态:未检测到尚未保存的 Working Draft。";u.show({title:"编辑服务已更新",message:"当前页面与可写场景 Authority 的连续性已经中断。为避免旧页面继续提交命令,编辑操作已暂停。",target:"当前页面的编辑与保存命令",consequence:"旧页面已停止向新的 Editor Service 提交命令。",recovery:"重新连接后,编辑器会重新读取服务身份和可恢复场景状态。",details:[I,`服务:${e.commandRuntime.serviceInstanceId}`,`文档:${e.recoveryDocumentId??"scene"}`,`原因:${E.code} - ${E.message}`,"影响:当前页面不能继续编辑或保存。"].join(`
4
- `),actionLabel:"重新连接编辑器",onRecover(){r||b.location.reload()}})};b.addEventListener(G,A);const P=y=>{const E=n.then(y,y);return n=E.catch(()=>{}),E},F=(y,E)=>{if(e.recoveryHost)return e.recoveryHost;if(!E)return null;if(d)return d;try{return d=Xe({runtime:e.commandRuntime,documentId:e.recoveryDocumentId??"scene",origin:y.location?.origin}),d}catch{return null}},V=(y,E,M=[])=>{f.remove(),c=E,h||(te(g),h=rt(g,()=>{P(async()=>{const I=h;if(!(!I||r)){I.setBusy(!0);try{const v=await y.request({kind:"scene.load.retry"});if(!v.ok||v.kind!=="scene.load.retry"){I.update(c??E,v.ok?[]:v.diagnostics);return}if(c=v.status,!J(v.status)){I.update(v.status);return}p();try{await m()}catch(q){V(y,v.status,[ne("editor.workbenchMountFailed",q)])}}catch(v){I.update(c??E,[ne("scene.load.retryFailed",v)])}finally{h?.setBusy(!1)}}})}),e.container.appendChild(h.root)),h.update(E,M)};async function m(){if(r)return;let y=null;try{const E=ke(e.projectDefinition);s?.(),s=ot(b,e);const M=!!b.__FPS_EDITOR_HOSTED_SANDBOX__,I=F(b,M);if(I){const x=await et(I);if(!J(x)){V(I,x);return}}if(p(),f.parentNode!==e.container&&e.container.appendChild(f),I){a?.dispose(),a=We({host:I,store:o,documentId:e.recoveryDocumentId??"scene",...e.recoveryProjectEpoch?{projectEpoch:e.recoveryProjectEpoch}:{}});const x=await a.recover();if(x.status==="unavailable"&&e.recoveryHost)throw x.error;x.status!=="unavailable"&&(i=x.bootstrap.projectEpoch)}const v=He(),q=Object.freeze({environment:"editor",buildTarget:"editor",manifests:Object.freeze([v]),entries:Object.freeze([{pluginId:v.id,config:null,load:async()=>Je}]),pluginConfigs:Object.freeze({...Object.fromEntries(E.plugins.map(x=>[x.pluginId,x.config])),[v.id]:null})});if(y=await Oe(E.project,{root:e.container,window:b,authoringEndpointBase:e.authoringEndpointBase,authoringFetchJson:e.authoringFetchJson,pendingRecovery:{store:o,documentId:e.recoveryDocumentId??"scene",projectEpoch:i},onExternalAssetDrop:e.onExternalAssetDrop?async x=>{const Q=await e.onExternalAssetDrop?.(x);if(!Q)return;const ee=t?.getHost();if(!ee)throw new Error("Editor host is unavailable for external asset import.");await ee.handleProjectAssetCommand("asset.import",{...Q,point:{space:"scene-view-normalized",x:x.point.sceneX,y:x.point.sceneY}})}:void 0,projectMode:{async enterEditorMode(){},...e.onEnterPlayMode?{enterPlayMode:e.onEnterPlayMode}:{}},pluginModule:q,getCanvas:()=>f,...e.materialShaderDefinitions?{materialShaderDefinitions:e.materialShaderDefinitions}:{},...e.materialProjectionAdapters?{materialProjectionAdapters:e.materialProjectionAdapters}:{}}),r){await y.dispose(),a?.dispose(),a=null,w();return}t=y,await y.enterEditor()}catch(E){t===y&&(t=null);let M=null;try{await y?.dispose()}catch(I){M=I}finally{a?.dispose(),a=null,w()}if(M){const I=M instanceof Error?M.message:String(M),v=new Error(`Editor mount failed and cleanup also failed: ${I}`);throw Object.assign(v,{cause:E,cleanupError:M}),v}throw E}}try{await P(m)}catch(y){throw b.removeEventListener(G,A),S(),_(),y}return{async save(){const y=t?.getHost();return y?y.saveScene():!1},reload(){return P(async()=>{const y=t;t=null;try{await y?.dispose()}finally{a?.dispose(),a=null,w()}await m()})},async importAsset(y){const E=t?.getHost();if(!E)throw new Error("Editor host is unavailable for asset import.");await E.handleProjectAssetCommand("asset.import",{...y,...y.point?{point:{space:"scene-view-normalized",x:y.point.x,y:y.point.y}}:{}})},dispose(){return r=!0,b.removeEventListener(G,A),P(async()=>{const y=t;t=null;try{await y?.dispose()}finally{a?.dispose(),a=null,w(),S(),_()}})}}}function Qe(e){const t=e.detail;return t&&typeof t=="object"&&(t.code==="authentication-invalidated"||t.code==="service-instance-changed")&&typeof t.message=="string"&&t.message.trim()?Object.freeze({code:t.code,message:t.message}):Object.freeze({code:"service-instance-changed",message:"编辑服务已更新,当前页面需要重新连接。"})}async function et(e){let t=await oe(e);const r=t.sceneLoad.attempt;for(let n=0;!t.authority&&t.sceneLoad.phase==="loading"&&t.sceneLoad.attempt===r&&n<200;n+=1)await new Promise(s=>setTimeout(s,25)),t=await oe(e);return t}async function oe(e){const t=await e.request({kind:"status"});if(!t.ok||t.kind!=="status")throw new Error(tt(t,"Editor Service status is unavailable."));return t.status}function J(e){return e.authority!==null&&e.sceneLoad.phase==="ready"}function ne(e,t){return{severity:"error",source:"browser-bootstrap",code:e,message:t instanceof Error?t.message:String(t)}}function tt(e,t){return!e.ok&&e.diagnostics[0]?.message?e.diagnostics[0].message:t}function rt(e,t){const r=e.createElement("div");r.className="fps-editor-ui-scene-recovery",r.dataset.editorWorkbench="true",r.dataset.editorSceneRecovery="true",r.setAttribute("role","main"),fe(r,"dark");const n=e.createElement("header");n.className="fps-editor-ui-scene-recovery-header";const s=e.createElement("span");s.className="fps-editor-ui-scene-recovery-product",s.textContent="FPS Game Editor";const o=e.createElement("span");o.className="fps-editor-ui-scene-recovery-badge",n.append(s,o);const i=e.createElement("div");i.className="fps-editor-ui-scene-recovery-body";const a=e.createElement("section");a.className="fps-editor-ui-scene-recovery-card";const d=e.createElement("h1");d.id="fps-editor-scene-recovery-title",d.className="fps-editor-ui-scene-recovery-title",r.setAttribute("aria-labelledby",d.id);const h=e.createElement("p");h.className="fps-editor-ui-scene-recovery-summary",h.setAttribute("aria-live","polite");const c=e.createElement("pre");c.id="fps-editor-scene-recovery-details",c.className="fps-editor-ui-scene-recovery-details";const u=e.createElement("div");u.className="fps-editor-ui-scene-recovery-meta";const l=e.createElement("div");l.className="fps-editor-ui-scene-recovery-actions";const g=e.createElement("button");g.type="button",g.className="fps-editor-ui-button",g.dataset.editorSceneRecoveryRetry="true",g.setAttribute("aria-describedby",c.id),g.addEventListener("click",t),l.appendChild(g),a.append(d,h,c,u,l),i.appendChild(a),r.append(n,i);let b=!1,f=!1,p=null,w=[];const _=()=>{if(b||!p)return;const S=J(p);r.dataset.editorSceneRecoveryPhase=p.sceneLoad.phase,o.textContent=S?"初始化未完成":"场景未加载",d.textContent=S?"编辑器界面初始化失败":"当前场景暂时无法打开",h.textContent=f?"正在重新读取并校验场景数据,请稍候。":S?"场景 Authority 已恢复,但 Workbench 初始化尚未完成。可以在当前页面重试。":"编辑器服务已经启动,但当前场景数据未通过加载或校验。修复数据后可在这里重试,无需重启服务。";const A=p.sceneLoad.phase==="failed"?p.sceneLoad.diagnostics:[],P=[...w,...A].slice(0,5);c.textContent=P.length?P.map(F=>`${F.code}: ${F.message}`).join(`
5
- `):"scene.authorityUnavailable: 尚未安装可编辑的场景 Authority。",u.textContent=`Service ${p.serviceInstanceId} · Attempt ${p.sceneLoad.attempt}`,g.disabled=f,g.setAttribute("aria-busy",f?"true":"false"),g.textContent=f?"正在重新加载…":S?"重试初始化":"重新加载场景"};return{root:r,update(S,A=[]){p=S,w=A,_()},setBusy(S){f=S,_()},dispose(){b||(b=!0,g.removeEventListener("click",t),r.remove())}}}function ot(e,t){const r=e,n=Object.getOwnPropertyDescriptor(r,"__FPS_EDITOR_AGENT_RUNTIME__"),s=Object.getOwnPropertyDescriptor(r,"__FPS_EDITOR_RUNTIME_URL__"),o=Object.freeze({...t.commandRuntime});r.__FPS_EDITOR_AGENT_RUNTIME__=o,t.runtimeAssetBaseUrl&&(r.__FPS_EDITOR_RUNTIME_URL__=t.runtimeAssetBaseUrl);let i=!1;return()=>{i||(i=!0,r.__FPS_EDITOR_AGENT_RUNTIME__===o&&(n?Object.defineProperty(r,"__FPS_EDITOR_AGENT_RUNTIME__",n):delete r.__FPS_EDITOR_AGENT_RUNTIME__),t.runtimeAssetBaseUrl&&r.__FPS_EDITOR_RUNTIME_URL__===t.runtimeAssetBaseUrl&&(s?Object.defineProperty(r,"__FPS_EDITOR_RUNTIME_URL__",s):delete r.__FPS_EDITOR_RUNTIME_URL__))}}const C=(e,t)=>({kind:"number",...e!=null?{min:e}:{},...t!=null?{max:t}:{}}),T={kind:"texture"},se={kind:"color"},nt={kind:"enum",values:["lit","unlit"]},st={kind:"enum",values:["opaque","mask","blend"]},ye={lightingModel:nt,baseColor:{kind:"object",properties:{color:se,texture:T,brightness:C(0),saturation:C(0),contrast:C(0),hue:C(-180,180)}},normal:{kind:"object",properties:{texture:T,strength:C(0)}},emission:{kind:"object",properties:{color:se,intensity:C(0),texture:T,maskTexture:T}},alpha:{kind:"object",properties:{mode:st,opacity:C(0,1),cutoff:C(0,1),texture:T}}},at={kind:"object",properties:{...ye,metallic:C(0,1),roughness:C(0,1),metallicRoughness:{kind:"object",properties:{texture:T}},occlusion:{kind:"object",properties:{texture:T,strength:C(0)}}}},it={kind:"object",properties:ye},ct={lightingModel:"lit",baseColor:{color:{r:1,g:1,b:1},brightness:1,saturation:1,contrast:1,hue:0},metallic:0,roughness:1,emission:{color:{r:0,g:0,b:0},intensity:0}},lt={lightingModel:"lit",baseColor:{color:{r:1,g:1,b:1},brightness:1,saturation:1,contrast:1,hue:0},emission:{color:{r:0,g:0,b:0},intensity:0}},ae=[{id:"surface",title:"Surface",order:40},{id:"geometry",title:"Geometry",order:50},{id:"emission",title:"Emission",order:60},{id:"alpha",title:"Alpha",order:70}],k={path:"properties.lightingModel",operator:"equals",value:"lit",inactiveReasonKey:"litMaterial"},ge=[N("properties.lightingModel","surface",1,"enum","assetLightingModel","lightingModel","lit",{options:[{value:"lit",labelKey:"assetLightingModelLit"},{value:"unlit",labelKey:"assetLightingModelUnlit"}],binding:"lightingModel",updateClass:"define"}),N("properties.baseColor.color","surface",2,"color","assetBaseColor","baseColor",{r:1,g:1,b:1},{binding:"baseColor.color"}),L("properties.baseColor.texture.textureAssetId","properties.baseColor.texture","surface",3,"assetBaseTexture","baseTexture","baseColor.texture"),j("properties.baseColor.brightness","surface",4,"assetBrightness","brightness",1,{softMin:0,softMax:4,step:.05,conditions:[O("properties.baseColor.texture.textureAssetId","baseTexture")]}),j("properties.baseColor.saturation","surface",5,"assetSaturation","saturation",1,{softMin:0,softMax:2,step:.05,conditions:[O("properties.baseColor.texture.textureAssetId","baseTexture")]}),j("properties.baseColor.contrast","surface",6,"assetContrast","contrast",1,{softMin:0,softMax:2,step:.05,conditions:[O("properties.baseColor.texture.textureAssetId","baseTexture")]}),j("properties.baseColor.hue","surface",7,"assetHue","hue",0,{step:1,conditions:[O("properties.baseColor.texture.textureAssetId","baseTexture")]}),L("properties.normal.texture.textureAssetId","properties.normal.texture","geometry",10,"assetNormalTexture","normalTexture","normal.texture",[k]),j("properties.normal.strength","geometry",11,"assetNormalStrength","normalStrength",1,{softMin:0,softMax:4,step:.05,conditions:[k,O("properties.normal.texture.textureAssetId","normalTexture")]}),N("properties.emission.color","emission",50,"color","assetEmissionColor","emissionColor",{r:0,g:0,b:0},{binding:"emission.color"}),j("properties.emission.intensity","emission",51,"assetEmissionIntensity","emissionIntensity",0,{softMin:0,softMax:8,step:.05}),L("properties.emission.texture.textureAssetId","properties.emission.texture","emission",52,"assetEmissionTexture","emissionTexture","emission.texture"),N("properties.alpha.mode","alpha",60,"enum","assetAlphaMode","alphaMode","opaque",{options:[{value:"opaque",labelKey:"assetAlphaModeOpaque"},{value:"mask",labelKey:"assetAlphaModeMask"},{value:"blend",labelKey:"assetAlphaModeBlend"}],binding:"alpha.mode",updateClass:"pipeline"}),j("properties.alpha.opacity","alpha",61,"assetAlphaOpacity","alphaOpacity",1,{step:.05,conditions:[{path:"properties.alpha.mode",operator:"equals",value:"blend",inactiveReasonKey:"alphaBlend"}]}),j("properties.alpha.cutoff","alpha",62,"assetAlphaCutoff","alphaCutoff",.5,{step:.01,conditions:[{path:"properties.alpha.mode",operator:"equals",value:"mask",inactiveReasonKey:"alphaMask"}]}),L("properties.alpha.texture.textureAssetId","properties.alpha.texture","alpha",63,"assetAlphaTexture","alphaTexture","alpha.texture",[{path:"properties.alpha.mode",operator:"not-equals",value:"opaque",inactiveReasonKey:"alphaTransparency"}])],dt=[...ge,j("properties.metallic","geometry",20,"assetMetallic","metallic",0,{step:.05,conditions:[k]}),j("properties.roughness","geometry",21,"assetRoughness","roughness",1,{step:.05,conditions:[k]}),L("properties.metallicRoughness.texture.textureAssetId","properties.metallicRoughness.texture","geometry",22,"assetMetallicRoughnessTexture","metallicRoughnessTexture","metallicRoughness.texture",[k]),L("properties.occlusion.texture.textureAssetId","properties.occlusion.texture","geometry",23,"assetOcclusionTexture","occlusionTexture","occlusion.texture",[k]),j("properties.occlusion.strength","geometry",24,"assetOcclusionStrength","occlusionStrength",1,{softMin:0,softMax:4,step:.05,conditions:[k,O("properties.occlusion.texture.textureAssetId","occlusionTexture")]})],be=[{shaderId:"fps.builtin.pbr",version:1,runtimeKind:"pbr",displayName:"PBR",propertiesSchema:at,defaultProperties:ct,inspector:{sections:ae,fields:dt}},{shaderId:"fps.builtin.standard",version:1,runtimeKind:"standard",displayName:"Standard",propertiesSchema:it,defaultProperties:lt,inspector:{sections:ae,fields:ge}}];Ee(be);function Ee(e){const t=new Map;for(const n of e){ut(n,t);const s=pt(n);t.set(n.shaderId,Ie(s))}const r=Object.freeze([...t.values()]);return Object.freeze({get(n){return typeof n=="string"?t.get(n)??null:null},list(){return r}})}function N(e,t,r,n,s,o,i,a){return{path:e,sectionId:t,order:r,control:n,labelKey:s,tooltipKey:o,defaultValue:i,updateClass:"uniform",...a}}function j(e,t,r,n,s,o,i={}){return N(e,t,r,"number",n,s,o,{binding:e.replace(/^properties\./,""),step:i.step??.05,displayPrecision:2,precision:2,...i})}function L(e,t,r,n,s,o,i,a){return N(e,r,n,"texture",s,o,"",{schemaPath:t,binding:i,updateClass:"texture",conditions:a})}function O(e,t){return{path:e,operator:"truthy",inactiveReasonKey:t}}function ut(e,t){if(!De(e.shaderId)&&!Ne(e.shaderId))throw new Error("Material Shader Definition shaderId must be a supported built-in id or a lowercase namespaced project id.");if(!Number.isInteger(e.version)||e.version<=0)throw new Error(`Material Shader Definition ${e.shaderId} must use a positive integer version.`);if(t.has(e.shaderId))throw new Error(`Duplicate Material Shader Definition: ${e.shaderId}`);if(e.sourceFile!=null&&!mt(e.sourceFile))throw new Error(`Material Shader Definition ${e.shaderId} sourceFile must be a safe project-relative path.`);we(e.shaderId,e.propertiesSchema,"properties");const r=[];if(Se(e.propertiesSchema,e.defaultProperties,"properties",r),r.length>0){const o=r[0];throw new Error(`Material Shader Definition ${e.shaderId} default ${o.path} ${o.message}.`)}const n=new Set;for(const o of e.inspector.sections){if(!o.id.trim()||n.has(o.id))throw new Error(`Material Shader Definition ${e.shaderId} contains an invalid or duplicate section: ${o.id}`);n.add(o.id)}const s=new Set;for(const o of e.inspector.fields){if(!o.path.startsWith("properties.")||s.has(o.path))throw new Error(`Material Shader Definition ${e.shaderId} contains an invalid or duplicate field: ${o.path}`);if(!n.has(o.sectionId))throw new Error(`Material Shader Definition ${e.shaderId} field ${o.path} references an unknown section.`);ft(e,o),s.add(o.path)}}function pt(e){const t=structuredClone(e);return{...t,inspector:{...t.inspector,fields:t.inspector.fields.map(r=>{if(r.control!=="number")return r;const n=ve(t.propertiesSchema,r.schemaPath??r.path);return n?.kind!=="number"?r:{...r,...n.min!=null?{min:n.min}:{},...n.max!=null?{max:n.max}:{}}})}}}function ft(e,t){const r=[["min",t.min],["max",t.max],["softMin",t.softMin],["softMax",t.softMax]];for(const[s,o]of r)if(o!=null&&!Number.isFinite(o))throw new Error(`Material Shader Definition ${e.shaderId} field ${t.path} ${s} must be finite.`);if(t.control!=="number"){if(r.some(([,s])=>s!=null))throw new Error(`Material Shader Definition ${e.shaderId} field ${t.path} uses numeric ranges with a non-number control.`);return}const n=ve(e.propertiesSchema,t.schemaPath??t.path);if(n?.kind!=="number")throw new Error(`Material Shader Definition ${e.shaderId} field ${t.path} must reference a number schema.`);for(const[s,o,i]of[["min",t.min,n.min],["max",t.max,n.max]])if(o!=null&&o!==i)throw new Error(`Material Shader Definition ${e.shaderId} field ${t.path} ${s} must match propertiesSchema.`);if(t.softMin!=null&&t.softMax!=null&&t.softMin>t.softMax)throw new Error(`Material Shader Definition ${e.shaderId} field ${t.path} softMin must not exceed softMax.`);if(n.min!=null&&t.softMin!=null&&t.softMin<n.min)throw new Error(`Material Shader Definition ${e.shaderId} field ${t.path} softMin must not be below the schema minimum.`);if(n.max!=null&&t.softMax!=null&&t.softMax>n.max)throw new Error(`Material Shader Definition ${e.shaderId} field ${t.path} softMax must not exceed the schema maximum.`)}function we(e,t,r){if(t.kind==="object"){for(const[n,s]of Object.entries(t.properties))we(e,s,`${r}.${n}`);return}if(t.kind==="number"){if(t.min!=null&&!Number.isFinite(t.min))throw new Error(`Material Shader Definition ${e} number field ${r} min must be finite.`);if(t.max!=null&&!Number.isFinite(t.max))throw new Error(`Material Shader Definition ${e} number field ${r} max must be finite.`);if(t.min!=null&&t.max!=null&&t.min>t.max)throw new Error(`Material Shader Definition ${e} number field ${r} min must not exceed max.`);return}if(t.kind==="color"&&t.channels!=null&&t.channels!==3&&t.channels!==4)throw new Error(`Material Shader Definition ${e} color field ${r} channels must be 3 or 4.`)}function mt(e){const t=e.trim();return!t||t.startsWith("/")||t.includes("\\")||t.includes(":")?!1:!t.split("/").includes("..")}function ht(e){const t=e.trim();return t.startsWith("properties.")?t:`properties.${t}`}function ve(e,t){const r=ht(t).replace(/^properties\./,"").split(".").filter(Boolean);if(r.length===0)return null;let n=e;for(const s of r){if(n.kind!=="object")return null;const o=n.properties[s];if(!o)return null;n=o}return n}function Se(e,t,r,n){if(e.kind==="object"){if(!Y(t)){n.push({path:r,message:"must be an object"});return}for(const o of Object.keys(t))Object.prototype.hasOwnProperty.call(e.properties,o)||n.push({path:`${r}.${o}`,message:"is not supported by the selected shader"});for(const[o,i]of Object.entries(e.properties))t[o]!==void 0&&Se(i,t[o],`${r}.${o}`,n);return}if(e.kind==="number"){if(typeof t!="number"||!Number.isFinite(t)){n.push({path:r,message:"must be a finite number"});return}e.min!=null&&t<e.min&&n.push({path:r,message:`must be greater than or equal to ${e.min}`}),e.max!=null&&t>e.max&&n.push({path:r,message:`must be less than or equal to ${e.max}`});return}if(e.kind==="boolean"){typeof t!="boolean"&&n.push({path:r,message:"must be a boolean"});return}if(e.kind==="string"){t!==null&&typeof t!="string"?n.push({path:r,message:"must be a string"}):t===null&&!e.nullable&&n.push({path:r,message:"must not be null"});return}if(e.kind==="enum"){(typeof t!="string"||!e.values.includes(t))&&n.push({path:r,message:`must be one of: ${e.values.join(", ")}`});return}if(e.kind==="color"){const o=e.channels===4?["r","g","b","a"]:["r","g","b"];ie(t,r,o,n,e.channels===4?"an RGBA object":"an RGB object");return}if(e.kind==="vec2"||e.kind==="vec3"){ie(t,r,e.kind==="vec2"?["x","y"]:["x","y","z"],n,`a ${e.kind} object`);return}if(t===null)return;if(!Y(t)){n.push({path:r,message:"must be a texture reference object or null"});return}Object.keys(t).some(o=>o!=="url"&&o!=="textureAssetId")&&n.push({path:r,message:"must contain only url or textureAssetId"});for(const o of["url","textureAssetId"]){const i=t[o];i!==void 0&&(typeof i!="string"||!i.trim())&&n.push({path:`${r}.${o}`,message:"must be a non-empty string"})}}function ie(e,t,r,n,s){if(!Y(e)){n.push({path:t,message:`must be ${s}`});return}Object.keys(e).some(o=>!r.includes(o))&&n.push({path:t,message:`must contain only ${r.join(", ")}`});for(const o of r)(typeof e[o]!="number"||!Number.isFinite(e[o]))&&n.push({path:`${t}.${o}`,message:"must be a finite number"})}function Ie(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){Object.freeze(e);for(const t of Object.values(e))Ie(t)}return e}function Y(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}const yt=Object.freeze([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),gt=Object.freeze([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]);function X(e){return Et(new TextEncoder().encode(e))}function bt(e){return`sha256:${X(JSON.stringify(e))}`}function Et(e){const t=Math.ceil((e.length+9)/64)*64,r=new Uint8Array(t);r.set(e),r[e.length]=128;const n=new DataView(r.buffer);n.setUint32(t-8,Math.floor(e.length/536870912),!1),n.setUint32(t-4,e.length*8>>>0,!1);const s=[...yt],o=new Uint32Array(64);for(let i=0;i<r.length;i+=64){for(let f=0;f<16;f+=1)o[f]=n.getUint32(i+f*4,!1);for(let f=16;f<64;f+=1){const p=o[f-15],w=o[f-2],_=$(p,7)^$(p,18)^p>>>3,S=$(w,17)^$(w,19)^w>>>10;o[f]=o[f-16]+_+o[f-7]+S>>>0}let[a,d,h,c,u,l,g,b]=s;for(let f=0;f<64;f+=1){const p=$(u,6)^$(u,11)^$(u,25),w=u&l^~u&g,_=b+p+w+gt[f]+o[f]>>>0,S=$(a,2)^$(a,13)^$(a,22),A=a&d^a&h^d&h,P=S+A>>>0;b=g,g=l,l=u,u=c+_>>>0,c=h,h=d,d=a,a=_+P>>>0}s[0]=s[0]+a>>>0,s[1]=s[1]+d>>>0,s[2]=s[2]+h>>>0,s[3]=s[3]+c>>>0,s[4]=s[4]+u>>>0,s[5]=s[5]+l>>>0,s[6]=s[6]+g>>>0,s[7]=s[7]+b>>>0}return s.map(i=>i.toString(16).padStart(8,"0")).join("")}function $(e,t){return e>>>t|e<<32-t}const wt="fps.plugin.materials";function vt(e){const t=e?.[wt];if(t==null)return null;if(!D(t)||t.schemaVersion!==1||typeof t.snapshotId!="string"||!Array.isArray(t.shaders))throw new Error("Materials Plugin snapshot is invalid. Run fps-editor-prepare again.");const r=structuredClone(t);return St(r),_e(r)}function Me(e){return Ee([...be,...e?.shaders.map(t=>t.definition)??[]])}function St(e){if(!/^sha256:[a-f0-9]{64}$/.test(e.snapshotId)||e.shaders.length===0)throw new Error("Materials Plugin snapshot identity is invalid. Run fps-editor-prepare again.");for(const r of e.shaders)if(!D(r)||!D(r.definition)||!D(r.program))throw new Error("Materials Plugin Shader snapshot is invalid. Run fps-editor-prepare again.");Me(e);for(const r of e.shaders){const{definition:n,program:s}=r;if(s.shaderId!==n.shaderId||s.definitionVersion!==n.version)throw new Error(`Material snapshot Definition identity does not match its program: ${n.shaderId}`);if(s.language!=="glsl"||!ce(s.vertexSourcePath)||!ce(s.fragmentSourcePath)||!/^[a-f0-9]{64}$/.test(s.vertexSourceHash)||!/^[a-f0-9]{64}$/.test(s.fragmentSourceHash)||typeof s.vertexSource!="string"||!s.vertexSource.trim()||typeof s.fragmentSource!="string"||!s.fragmentSource.trim())throw new Error(`Material snapshot program is invalid: ${n.shaderId}`);if(X(s.vertexSource)!==s.vertexSourceHash||X(s.fragmentSource)!==s.fragmentSourceHash)throw new Error(`Material snapshot source hash does not match its GLSL content: ${n.shaderId}`);if(!Array.isArray(s.attributes)||s.attributes.length===0||s.attributes.some(o=>!/^[A-Za-z_][A-Za-z0-9_]*$/.test(o))||new Set(s.attributes).size!==s.attributes.length)throw new Error(`Material snapshot attributes are invalid: ${n.shaderId}`);if(!["opaque","combine","add"].includes(s.alphaMode)||!D(s.enumUniformValues)||!D(s.frame)||!["on-demand","continuous"].includes(s.frame.mode))throw new Error(`Material snapshot rendering policy is invalid: ${n.shaderId}`)}const t={schemaVersion:e.schemaVersion,shaders:e.shaders};if(bt(t)!==e.snapshotId)throw new Error("Materials Plugin snapshot payload does not match its identity. Run fps-editor-prepare again.")}function ce(e){return typeof e=="string"&&!!e&&!e.startsWith("/")&&!e.includes("\\")&&!e.includes(":")&&e.split("/").every(t=>!!t&&t!=="."&&t!=="..")}function _e(e){if(!e||typeof e!="object"||Object.isFrozen(e))return e;for(const t of Object.values(e))_e(t);return Object.freeze(e)}function D(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function It(e){let t=0;const r=new WeakMap;return Object.freeze(e.shaders.map(({definition:n,program:s})=>Object.freeze({shaderId:n.shaderId,definitionVersion:n.version,snapshotId:e.snapshotId,createMaterial(o){const i=o.babylon,a=`${Pt(n.shaderId)}-${t+=1}`;if(!i.Effect?.ShadersStore||!i.ShaderMaterial||!i.StandardMaterial||!i.Color3)throw new Error(`Babylon ShaderMaterial is unavailable for ${n.shaderId}.`);le(n,o.definitionVersion),i.Effect.ShadersStore[`${a}VertexShader`]=s.vertexSource,i.Effect.ShadersStore[`${a}FragmentShader`]=s.fragmentSource;const d=n.inspector.fields.filter(p=>p.updateClass==="uniform").map(p=>p.binding),h=[...new Set(["world","worldViewProjection",...s.frame.timeUniform?[s.frame.timeUniform]:[],...s.frame.cameraPositionUniform?[s.frame.cameraPositionUniform]:[],...d])];let c;try{c=new i.ShaderMaterial(a,o.scene,{vertex:a,fragment:a},{attributes:s.attributes,uniforms:h,needAlphaBlending:s.alphaMode!=="opaque"}),c.backFaceCulling=s.alphaMode==="opaque",c.alphaMode=s.alphaMode==="add"?i.Constants.ALPHA_ADD:s.alphaMode==="combine"?i.Constants.ALPHA_COMBINE:i.Constants.ALPHA_DISABLE,de(i,c,n,s,o.properties)}catch(p){throw delete i.Effect.ShadersStore[`${a}VertexShader`],delete i.Effect.ShadersStore[`${a}FragmentShader`],c?.dispose?.(),p}const u=Mt(i,o.scene,a),l={material:c,mesh:o.mesh,setMaterial:o.setMaterial,placeholder:u,compiled:!1,disposed:!1,failed:!1,failure:null,compilation:null,invalidateFrameParticipant:null,shaderName:a,shadersStore:i.Effect.ShadersStore};r.set(u,l),r.set(c,l);const g=()=>{l.disposed||l.failed||l.compiled||(l.compiled=!0,l.setMaterial(l.material),xt(l.mesh))},b=p=>{l.disposed||l.failed||(l.failed=!0,l.failure=p,l.invalidateFrameParticipant?.(),l.setMaterial(l.placeholder),_t(l.mesh,{code:"material.shaderCompilationFailed",severity:"error",shaderId:n.shaderId,definitionVersion:n.version,snapshotId:e.snapshotId,message:String(p??"Shader compilation failed.").slice(0,2048)}))};c.onCompiled=()=>{queueMicrotask(()=>{g()})},c.onError=(p,w)=>{b(w)};try{if(typeof c.forceCompilationAsync!="function")throw new Error("Babylon ShaderMaterial.forceCompilationAsync() is unavailable.");l.compilation=Promise.resolve(c.forceCompilationAsync(l.mesh)).then(()=>{if(l.failed)throw l.failure;g()}).catch(p=>{throw b(p),p})}catch(p){b(p),l.compilation=Promise.reject(p)}l.compilation.catch(()=>{}),u.forceCompilationAsync=()=>l.compilation;const f=u.dispose.bind(u);return u.dispose=(...p)=>{l.disposed||(l.disposed=!0,l.invalidateFrameParticipant?.(),delete l.shadersStore[`${l.shaderName}VertexShader`],delete l.shadersStore[`${l.shaderName}FragmentShader`],l.material.dispose?.(),f(...p))},u},updateMaterial(o){const i=o.babylon,a=ue(o.material)?r.get(o.material):void 0;return!a||a.disposed||a.failed?!1:(le(n,o.definitionVersion),de(i,a.material,n,s,o.properties),!0)},...s.frame.mode==="continuous"?{createFrameParticipant(o){const i=o.babylon,a=ue(o.material)?r.get(o.material):void 0;if(!a)throw new Error(`ShaderMaterial state is unavailable for ${n.shaderId}.`);let d=!1;const h=new Set;return a.invalidateFrameParticipant=()=>{for(const c of[...h])c()},{frameMode:"continuous",resolveFrameMode(){return a.failed||a.disposed||d?"on-demand":"continuous"},isActive(){return!a.failed&&!a.disposed&&!d},onFrameModeChanged(c){return h.add(c),()=>h.delete(c)},updateFrame(c){if(!(a.failed||a.disposed||d)&&(s.frame.timeUniform&&a.material.setFloat(s.frame.timeUniform,c.elapsedSeconds),s.frame.cameraPositionUniform)){const u=o.scene.activeCamera;a.material.setVector3(s.frame.cameraPositionUniform,u?.globalPosition??u?.position??i.Vector3.Zero())}},dispose(){d||(d=!0,h.clear(),a.invalidateFrameParticipant&&(a.invalidateFrameParticipant=null))}}}}:{}})))}function le(e,t){if(t!==e.version)throw Object.assign(new Error(`Material Definition version mismatch for ${e.shaderId}: expected ${e.version}, received ${String(t)}.`),{code:"material.shaderDefinitionVersionMismatch",shaderId:e.shaderId,expectedVersion:e.version,actualVersion:t})}function Mt(e,t,r){const n=new e.StandardMaterial(`${r}.diagnostic`,t);return n.diffuseColor=new e.Color3(.8,.02,.45),n.emissiveColor=new e.Color3(.35,0,.12),n.specularColor=new e.Color3(0,0,0),n.backFaceCulling=!1,n}function _t(e,t){const r=H(e.metadata)?e.metadata:{},n=H(r.editorProjection)?r.editorProjection:{};e.metadata={...r,editorProjection:{...n,materialDiagnostic:Object.freeze({...t})}}}function xt(e){if(!H(e.metadata)||!H(e.metadata.editorProjection)||!Object.prototype.hasOwnProperty.call(e.metadata.editorProjection,"materialDiagnostic"))return;const t={...e.metadata.editorProjection};delete t.materialDiagnostic,e.metadata={...e.metadata,editorProjection:t}}function de(e,t,r,n,s){for(const o of r.inspector.fields){if(o.updateClass!=="uniform")continue;const i=At(s,o.path.replace(/^properties\./,""));if(o.control==="number")t.setFloat(o.binding,R(i,o.path));else if(o.control==="boolean")t.setFloat(o.binding,i===!0?1:0);else if(o.control==="enum"){const a=n.enumUniformValues[o.path],d=typeof i=="string"?a?.[i]:void 0;if(!Number.isFinite(d))throw new Error(`Enum uniform value is not mapped: ${o.path}=${String(i)}`);t.setFloat(o.binding,d)}else if(o.control==="color"){const a=K(i,o.path);Rt(r,o.path)===4?t.setColor4(o.binding,new e.Color4(R(a.r,`${o.path}.r`),R(a.g,`${o.path}.g`),R(a.b,`${o.path}.b`),R(a.a,`${o.path}.a`))):t.setColor3(o.binding,new e.Color3(R(a.r,`${o.path}.r`),R(a.g,`${o.path}.g`),R(a.b,`${o.path}.b`)))}else if(o.control==="vec2"){const a=K(i,o.path);t.setVector2(o.binding,new e.Vector2(R(a.x,`${o.path}.x`),R(a.y,`${o.path}.y`)))}else if(o.control==="vec3"){const a=K(i,o.path);t.setVector3(o.binding,new e.Vector3(R(a.x,`${o.path}.x`),R(a.y,`${o.path}.y`),R(a.z,`${o.path}.z`)))}else throw new Error(`Unsupported ShaderMaterial uniform control: ${o.path} (${o.control})`)}}function Rt(e,t){let r=e.propertiesSchema;for(const n of t.replace(/^properties\./,"").split(".")){if(r.kind!=="object"||!r.properties[n])return 3;r=r.properties[n]}return r.kind==="color"&&r.channels===4?4:3}function At(e,t){let r=e;for(const n of t.split(".").filter(Boolean)){if(!H(r))return;r=r[n]}return r}function K(e,t){if(!H(e))throw new Error(`Material property must be an object: ${t}`);return e}function R(e,t){if(typeof e!="number"||!Number.isFinite(e))throw new Error(`Material property must be a finite number: ${t}`);return e}function Pt(e){return e.replace(/[^a-z0-9_-]/gi,"_")}function ue(e){return!!e&&typeof e=="object"}function H(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}const xe=window.__FPS_EDITOR_PROJECT_DEFINITION__;if(!xe)throw new Error("Editor Project definition was not provided by the control plane.");const Re=window.__FPS_EDITOR_AGENT_RUNTIME__;if(!Re)throw new Error("Editor command runtime was not provided by the control plane.");const Z=vt(window.__FPS_EDITOR_PLUGIN_SNAPSHOTS__),Ct=Me(Z),pe=Z?It(Z):void 0,jt=await Ze({container:document.body,projectDefinition:xe,commandRuntime:Re,runtimeAssetBaseUrl:window.__FPS_EDITOR_RUNTIME_URL__,async onEnterPlayMode(){const e=window.__FPS_EDITOR_RUNTIME_URL__;if(!e)throw new Error("Editor Runtime URL was not provided by the control plane.");window.location.assign(e)},materialShaderDefinitions:Ct,...pe?{materialProjectionAdapters:pe}:{}});window.addEventListener("pagehide",()=>void jt.dispose(),{once:!0});
Binary file
Binary file