xxscreeps-mod-client 0.1.0

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.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # xxscreeps-mod-client
2
+
3
+ [xxscreeps](https://github.com/laverdet/xxscreeps) mod that serves [`screeps-client`](../screeps-client) on the same server it runs on. The client connects to its own origin, so no separate hosting or CORS setup is required.
4
+
5
+ ## Install
6
+
7
+ Add the package to your `.screepsrc.yaml`:
8
+
9
+ ```yaml
10
+ mods:
11
+ - xxscreeps/mods/classic
12
+ - xxscreeps-mod-client
13
+ ```
14
+
15
+ xxscreeps must be installed as a peer dependency.
16
+
17
+ ## Configuration
18
+
19
+ Environment variables:
20
+
21
+ | Setting | ENV | Default |
22
+ | --- | --- | --- |
23
+ | Mount path | `SCREEPS_MOD_CLIENT_MOUNT_PATH` | `/` |
24
+ | Redirect `/` → mount path | `SCREEPS_MOD_CLIENT_ROOT_REDIRECT` | `true` if `mountPath !== '/'`, else `false` |
25
+
26
+ When mounted at `/`, the mod only serves paths that map to an existing file in `dist/` or that look like an SPA route (no file extension). Requests to xxscreeps' own endpoints (`/api/`, `/socket/`, …) are passed through to subsequent middleware.
27
+
28
+ ### Example
29
+
30
+ ```sh
31
+ SCREEPS_MOD_CLIENT_MOUNT_PATH=/play npx xxscreeps start
32
+ ```
33
+
34
+ ## Build
35
+
36
+ ```sh
37
+ pnpm --filter xxscreeps-mod-client build
38
+ ```
39
+
40
+ This builds `screeps-client` with `base=/` (absolute asset URLs at the server root) and copies the artifacts into `dist/`. The shipped bundle is tied to its build-time base path — overriding `SCREEPS_MOD_CLIENT_MOUNT_PATH` at runtime requires a rebuild with a matching base:
41
+
42
+ ```sh
43
+ SCREEPS_MOD_CLIENT_BUILD_BASE=/play/ pnpm --filter xxscreeps-mod-client build
44
+ SCREEPS_MOD_CLIENT_MOUNT_PATH=/play npx xxscreeps start
45
+ ```
46
+
47
+ ## xxscreeps mode
48
+
49
+ The client bundle shipped with this mod is built with `VITE_XXSCREEPS=true`. In this mode the client auto-connects to its own origin as a guest (read-only) on first load, mirroring `@xxscreeps/client`'s default UX. A "Connect as Guest" button stays available in the login form so users can return to guest mode after signing out.
50
+
51
+ The xxscreeps server must allow guest access (`backend.allowGuestAccess: true` in `.screepsrc.yaml`, which is the default).
52
+
53
+ ## Notes
54
+
55
+ This mod serves only the static client bundle. Whether every client feature works against xxscreeps depends on how completely xxscreeps reimplements the Screeps HTTP/WebSocket protocol — that is a concern of [`screeps-connectivity`](../screeps-connectivity), not this mod.
package/backend.js ADDED
@@ -0,0 +1,110 @@
1
+ import path from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
3
+ import { createReadStream, existsSync, statSync } from 'node:fs'
4
+ import { hooks } from 'xxscreeps/backend/index.js'
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
+ const distDir = path.join(__dirname, 'dist')
8
+ const indexFile = path.join(distDir, 'index.html')
9
+
10
+ const CONTENT_TYPES = {
11
+ '.css': 'text/css',
12
+ '.html': 'text/html',
13
+ '.js': 'text/javascript',
14
+ '.json': 'application/json',
15
+ '.map': 'application/json',
16
+ '.png': 'image/png',
17
+ '.svg': 'image/svg+xml',
18
+ '.ico': 'image/x-icon',
19
+ '.gif': 'image/gif',
20
+ '.jpg': 'image/jpeg',
21
+ '.jpeg': 'image/jpeg',
22
+ '.webp': 'image/webp',
23
+ '.ttf': 'font/ttf',
24
+ '.woff': 'font/woff',
25
+ '.woff2': 'font/woff2',
26
+ '.txt': 'text/plain',
27
+ }
28
+
29
+ function readBool(envName, fallback) {
30
+ const env = process.env[envName]
31
+ if (env === undefined) return fallback
32
+ const v = env.toLowerCase()
33
+ return v === '1' || v === 'true' || v === 'yes'
34
+ }
35
+
36
+ function normalizeMount(input) {
37
+ let p = input ?? '/'
38
+ if (!p.startsWith('/')) p = '/' + p
39
+ p = p.replace(/\/+$/, '')
40
+ return p === '' ? '/' : p
41
+ }
42
+
43
+ const mountPath = normalizeMount(process.env.SCREEPS_MOD_CLIENT_MOUNT_PATH ?? '/')
44
+ const rootRedirect = readBool('SCREEPS_MOD_CLIENT_ROOT_REDIRECT', mountPath !== '/')
45
+
46
+ function resolveFile(relPath) {
47
+ const rel = relPath.replace(/^\/+/, '')
48
+ const target = rel === '' ? indexFile : path.join(distDir, rel)
49
+ const normalized = path.normalize(target)
50
+ if (!normalized.startsWith(distDir)) return null
51
+ if (!existsSync(normalized)) return null
52
+ const stat = statSync(normalized)
53
+ if (!stat.isFile()) return null
54
+ return { filePath: normalized, stat }
55
+ }
56
+
57
+ function sendFile(ctx, filePath, stat) {
58
+ const ext = path.extname(filePath).toLowerCase()
59
+ ctx.type = CONTENT_TYPES[ext] ?? 'application/octet-stream'
60
+ ctx.lastModified = stat.mtime
61
+ ctx.set('Content-Length', String(stat.size))
62
+ ctx.body = createReadStream(filePath)
63
+ }
64
+
65
+ hooks.register('middleware', koa => {
66
+ if (!existsSync(indexFile)) {
67
+ console.error(`[xxscreeps-mod-client] dist/index.html not found at ${indexFile}. Run "pnpm --filter xxscreeps-mod-client build" first.`)
68
+ return
69
+ }
70
+
71
+ console.log(`[xxscreeps-mod-client] serving client at ${mountPath === '/' ? '/' : mountPath + '/'} (rootRedirect=${rootRedirect})`)
72
+
73
+ koa.use(async (ctx, next) => {
74
+ if (ctx.method !== 'GET' && ctx.method !== 'HEAD') return next()
75
+
76
+ if (mountPath !== '/' && ctx.path === '/' && rootRedirect) {
77
+ ctx.redirect(mountPath + '/')
78
+ return
79
+ }
80
+
81
+ let relPath
82
+ if (mountPath === '/') {
83
+ relPath = ctx.path
84
+ } else if (ctx.path === mountPath || ctx.path === mountPath + '/') {
85
+ relPath = '/'
86
+ } else if (ctx.path.startsWith(mountPath + '/')) {
87
+ relPath = ctx.path.slice(mountPath.length)
88
+ } else {
89
+ return next()
90
+ }
91
+
92
+ // Serve a real file from dist if it exists.
93
+ const found = resolveFile(relPath)
94
+ if (found) {
95
+ sendFile(ctx, found.filePath, found.stat)
96
+ return
97
+ }
98
+
99
+ // Otherwise let xxscreeps handle the request. If it 404s and the path
100
+ // looks like an SPA route (no file extension on the last segment),
101
+ // fall back to index.html so client-side routing can take over.
102
+ await next()
103
+ if (ctx.status !== 404) return
104
+ const last = relPath.split('/').pop() ?? ''
105
+ if (last.includes('.')) return
106
+ const indexStat = statSync(indexFile)
107
+ ctx.status = 200
108
+ sendFile(ctx, indexFile, indexStat)
109
+ })
110
+ })
@@ -0,0 +1,185 @@
1
+ import{ap as U,a9 as g,S as c,an as S,d as _,e as m,E as I,am as h}from"./index-Cf0rVPz-.js";const x={name:"local-uniform-bit",vertex:{header:`
2
+
3
+ struct LocalUniforms {
4
+ uTransformMatrix:mat3x3<f32>,
5
+ uColor:vec4<f32>,
6
+ uRound:f32,
7
+ }
8
+
9
+ @group(1) @binding(0) var<uniform> localUniforms : LocalUniforms;
10
+ `,main:`
11
+ vColor *= localUniforms.uColor;
12
+ modelMatrix *= localUniforms.uTransformMatrix;
13
+ `,end:`
14
+ if(localUniforms.uRound == 1)
15
+ {
16
+ vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
17
+ }
18
+ `}},C={...x,vertex:{...x.vertex,header:x.vertex.header.replace("group(1)","group(2)")}},D={name:"local-uniform-bit",vertex:{header:`
19
+
20
+ uniform mat3 uTransformMatrix;
21
+ uniform vec4 uColor;
22
+ uniform float uRound;
23
+ `,main:`
24
+ vColor *= uColor;
25
+ modelMatrix = uTransformMatrix;
26
+ `,end:`
27
+ if(uRound == 1.)
28
+ {
29
+ gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
30
+ }
31
+ `}},O={name:"texture-bit",vertex:{header:`
32
+
33
+ struct TextureUniforms {
34
+ uTextureMatrix:mat3x3<f32>,
35
+ }
36
+
37
+ @group(2) @binding(2) var<uniform> textureUniforms : TextureUniforms;
38
+ `,main:`
39
+ uv = (textureUniforms.uTextureMatrix * vec3(uv, 1.0)).xy;
40
+ `},fragment:{header:`
41
+ @group(2) @binding(0) var uTexture: texture_2d<f32>;
42
+ @group(2) @binding(1) var uSampler: sampler;
43
+
44
+
45
+ `,main:`
46
+ outColor = textureSample(uTexture, uSampler, vUV);
47
+ `}},R={name:"texture-bit",vertex:{header:`
48
+ uniform mat3 uTextureMatrix;
49
+ `,main:`
50
+ uv = (uTextureMatrix * vec3(uv, 1.0)).xy;
51
+ `},fragment:{header:`
52
+ uniform sampler2D uTexture;
53
+
54
+
55
+ `,main:`
56
+ outColor = texture(uTexture, vUV);
57
+ `}};function A(e,t){for(const a in e.attributes){const s=e.attributes[a],r=t[a];r?(s.format??(s.format=r.format),s.offset??(s.offset=r.offset),s.instance??(s.instance=r.instance)):U(`Attribute ${a} is not present in the shader, but is present in the geometry. Unable to infer attribute details.`)}M(e)}function M(e){const{buffers:t,attributes:a}=e,s={},r={};for(const n in t){const o=t[n];s[o.uid]=0,r[o.uid]=0}for(const n in a){const o=a[n];s[o.buffer.uid]+=g(o.format).stride}for(const n in a){const o=a[n];o.stride??(o.stride=s[o.buffer.uid]),o.start??(o.start=r[o.buffer.uid]),r[o.buffer.uid]+=g(o.format).stride}}const d=[];d[c.NONE]=void 0;d[c.DISABLED]={stencilWriteMask:0,stencilReadMask:0};d[c.RENDERING_MASK_ADD]={stencilFront:{compare:"equal",passOp:"increment-clamp"},stencilBack:{compare:"equal",passOp:"increment-clamp"}};d[c.RENDERING_MASK_REMOVE]={stencilFront:{compare:"equal",passOp:"decrement-clamp"},stencilBack:{compare:"equal",passOp:"decrement-clamp"}};d[c.MASK_ACTIVE]={stencilWriteMask:0,stencilFront:{compare:"equal",passOp:"keep"},stencilBack:{compare:"equal",passOp:"keep"}};d[c.INVERSE_MASK_ACTIVE]={stencilWriteMask:0,stencilFront:{compare:"not-equal",passOp:"keep"},stencilBack:{compare:"not-equal",passOp:"keep"}};class k{constructor(t){this._syncFunctionHash=Object.create(null),this._adaptor=t,this._systemCheck()}_systemCheck(){if(!S())throw new Error("Current environment does not allow unsafe-eval, please use pixi.js/unsafe-eval module to enable support.")}ensureUniformGroup(t){const a=this.getUniformGroupData(t);t.buffer||(t.buffer=new _({data:new Float32Array(a.layout.size/4),usage:m.UNIFORM|m.COPY_DST}))}getUniformGroupData(t){return this._syncFunctionHash[t._signature]||this._initUniformGroup(t)}_initUniformGroup(t){const a=t._signature;let s=this._syncFunctionHash[a];if(!s){const r=Object.keys(t.uniformStructures).map(l=>t.uniformStructures[l]),n=this._adaptor.createUboElements(r),o=this._generateUboSync(n.uboElements);s=this._syncFunctionHash[a]={layout:n,syncFunction:o}}return this._syncFunctionHash[a]}_generateUboSync(t){return this._adaptor.generateUboSync(t)}syncUniformGroup(t,a,s){const r=this.getUniformGroupData(t);t.buffer||(t.buffer=new _({data:new Float32Array(r.layout.size/4),usage:m.UNIFORM|m.COPY_DST}));let n=null;return a||(a=t.buffer.data,n=t.buffer.dataInt32),s||(s=0),r.syncFunction(t.uniforms,a,n,s),!0}updateUniformGroup(t){if(t.isStatic&&!t._dirtyId)return!1;t._dirtyId=0;const a=this.syncUniformGroup(t);return t.buffer.update(),a}destroy(){this._syncFunctionHash=null}}const p=[{type:"mat3x3<f32>",test:e=>e.value.a!==void 0,ubo:`
58
+ var matrix = uv[name].toArray(true);
59
+ data[offset] = matrix[0];
60
+ data[offset + 1] = matrix[1];
61
+ data[offset + 2] = matrix[2];
62
+ data[offset + 4] = matrix[3];
63
+ data[offset + 5] = matrix[4];
64
+ data[offset + 6] = matrix[5];
65
+ data[offset + 8] = matrix[6];
66
+ data[offset + 9] = matrix[7];
67
+ data[offset + 10] = matrix[8];
68
+ `,uniform:`
69
+ gl.uniformMatrix3fv(ud[name].location, false, uv[name].toArray(true));
70
+ `},{type:"vec4<f32>",test:e=>e.type==="vec4<f32>"&&e.size===1&&e.value.width!==void 0,ubo:`
71
+ v = uv[name];
72
+ data[offset] = v.x;
73
+ data[offset + 1] = v.y;
74
+ data[offset + 2] = v.width;
75
+ data[offset + 3] = v.height;
76
+ `,uniform:`
77
+ cv = ud[name].value;
78
+ v = uv[name];
79
+ if (cv[0] !== v.x || cv[1] !== v.y || cv[2] !== v.width || cv[3] !== v.height) {
80
+ cv[0] = v.x;
81
+ cv[1] = v.y;
82
+ cv[2] = v.width;
83
+ cv[3] = v.height;
84
+ gl.uniform4f(ud[name].location, v.x, v.y, v.width, v.height);
85
+ }
86
+ `},{type:"vec2<f32>",test:e=>e.type==="vec2<f32>"&&e.size===1&&e.value.x!==void 0,ubo:`
87
+ v = uv[name];
88
+ data[offset] = v.x;
89
+ data[offset + 1] = v.y;
90
+ `,uniform:`
91
+ cv = ud[name].value;
92
+ v = uv[name];
93
+ if (cv[0] !== v.x || cv[1] !== v.y) {
94
+ cv[0] = v.x;
95
+ cv[1] = v.y;
96
+ gl.uniform2f(ud[name].location, v.x, v.y);
97
+ }
98
+ `},{type:"vec4<f32>",test:e=>e.type==="vec4<f32>"&&e.size===1&&e.value.red!==void 0,ubo:`
99
+ v = uv[name];
100
+ data[offset] = v.red;
101
+ data[offset + 1] = v.green;
102
+ data[offset + 2] = v.blue;
103
+ data[offset + 3] = v.alpha;
104
+ `,uniform:`
105
+ cv = ud[name].value;
106
+ v = uv[name];
107
+ if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue || cv[3] !== v.alpha) {
108
+ cv[0] = v.red;
109
+ cv[1] = v.green;
110
+ cv[2] = v.blue;
111
+ cv[3] = v.alpha;
112
+ gl.uniform4f(ud[name].location, v.red, v.green, v.blue, v.alpha);
113
+ }
114
+ `},{type:"vec3<f32>",test:e=>e.type==="vec3<f32>"&&e.size===1&&e.value.red!==void 0,ubo:`
115
+ v = uv[name];
116
+ data[offset] = v.red;
117
+ data[offset + 1] = v.green;
118
+ data[offset + 2] = v.blue;
119
+ `,uniform:`
120
+ cv = ud[name].value;
121
+ v = uv[name];
122
+ if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue) {
123
+ cv[0] = v.red;
124
+ cv[1] = v.green;
125
+ cv[2] = v.blue;
126
+ gl.uniform3f(ud[name].location, v.red, v.green, v.blue);
127
+ }
128
+ `}];function B(e,t,a,s){const r=[`
129
+ var v = null;
130
+ var v2 = null;
131
+ var t = 0;
132
+ var index = 0;
133
+ var name = null;
134
+ var arrayOffset = null;
135
+ `];let n=0;for(let l=0;l<e.length;l++){const f=e[l],b=f.data.name;let y=!1,i=0;for(let u=0;u<p.length;u++)if(p[u].test(f.data)){i=f.offset/4,r.push(`name = "${b}";`,`offset += ${i-n};`,p[u][t]||p[u].ubo),y=!0;break}if(!y)if(f.data.size>1)i=f.offset/4,r.push(a(f,i-n));else{const u=s[f.data.type];i=f.offset/4,r.push(`
136
+ v = uv.${b};
137
+ offset += ${i-n};
138
+ ${u};
139
+ `)}n=i}const o=r.join(`
140
+ `);return new Function("uv","data","dataInt32","offset",o)}function v(e,t){return`
141
+ for (let i = 0; i < ${e*t}; i++) {
142
+ data[offset + (((i / ${e})|0) * 4) + (i % ${e})] = v[i];
143
+ }
144
+ `}const F={f32:`
145
+ data[offset] = v;`,i32:`
146
+ dataInt32[offset] = v;`,"vec2<f32>":`
147
+ data[offset] = v[0];
148
+ data[offset + 1] = v[1];`,"vec3<f32>":`
149
+ data[offset] = v[0];
150
+ data[offset + 1] = v[1];
151
+ data[offset + 2] = v[2];`,"vec4<f32>":`
152
+ data[offset] = v[0];
153
+ data[offset + 1] = v[1];
154
+ data[offset + 2] = v[2];
155
+ data[offset + 3] = v[3];`,"vec2<i32>":`
156
+ dataInt32[offset] = v[0];
157
+ dataInt32[offset + 1] = v[1];`,"vec3<i32>":`
158
+ dataInt32[offset] = v[0];
159
+ dataInt32[offset + 1] = v[1];
160
+ dataInt32[offset + 2] = v[2];`,"vec4<i32>":`
161
+ dataInt32[offset] = v[0];
162
+ dataInt32[offset + 1] = v[1];
163
+ dataInt32[offset + 2] = v[2];
164
+ dataInt32[offset + 3] = v[3];`,"mat2x2<f32>":`
165
+ data[offset] = v[0];
166
+ data[offset + 1] = v[1];
167
+ data[offset + 4] = v[2];
168
+ data[offset + 5] = v[3];`,"mat3x3<f32>":`
169
+ data[offset] = v[0];
170
+ data[offset + 1] = v[1];
171
+ data[offset + 2] = v[2];
172
+ data[offset + 4] = v[3];
173
+ data[offset + 5] = v[4];
174
+ data[offset + 6] = v[5];
175
+ data[offset + 8] = v[6];
176
+ data[offset + 9] = v[7];
177
+ data[offset + 10] = v[8];`,"mat4x4<f32>":`
178
+ for (let i = 0; i < 16; i++) {
179
+ data[offset + i] = v[i];
180
+ }`,"mat3x2<f32>":v(3,2),"mat4x2<f32>":v(4,2),"mat2x3<f32>":v(2,3),"mat4x3<f32>":v(4,3),"mat2x4<f32>":v(2,4),"mat3x4<f32>":v(3,4)},w={...F,"mat2x2<f32>":`
181
+ data[offset] = v[0];
182
+ data[offset + 1] = v[1];
183
+ data[offset + 2] = v[2];
184
+ data[offset + 3] = v[3];
185
+ `};class P extends I{constructor({buffer:t,offset:a,size:s}){super(),this.uid=h("buffer"),this._resourceType="bufferResource",this._touched=0,this._resourceId=h("resource"),this._bufferResource=!0,this.destroyed=!1,this.buffer=t,this.offset=a|0,this.size=s,this.buffer.on("change",this.onBufferChange,this)}onBufferChange(){this._resourceId=h("resource"),this.emit("change",this)}destroy(t=!1){this.destroyed=!0,t&&this.buffer.destroy(),this.emit("change",this),this.buffer=null,this.removeAllListeners()}}export{P as B,d as G,k as U,D as a,C as b,B as c,R as d,A as e,w as f,p as g,x as l,O as t,F as u};
@@ -0,0 +1 @@
1
+ import{af as Se,W as Me,ah as ae,M as U,k as R,r as Ve,ap as Xe,al as we,X as Ie,h as Re,T as Ae,a8 as $e,F as Je,l as Ke,g as Qe,D as Be,A as ze,u as Ze,a4 as re}from"./index-Cf0rVPz-.js";import{b as et,c as tt,a as st,B as nt,d as at,R as ot,A as rt,C as it}from"./RenderTargetSystem-BADEJjVe.js";import{a as P,c as ct}from"./canvasUtils--etq-uaC.js";import"./Filter-DCFwFDCZ.js";const ge=class ${static _getPatternRepeat(e,t){const s=e&&e!=="clamp-to-edge",n=t&&t!=="clamp-to-edge";return s&&n?"repeat":s?"repeat-x":n?"repeat-y":"no-repeat"}start(e,t,s){}execute(e,t){var i,c,u,m;const s=t.elements;if(!s||!s.length)return;const n=e.renderer,o=n.canvasContext,r=o.activeContext;for(let x=0;x<s.length;x++){const G=s[x];if(!G.packAsQuad)continue;const y=G,f=y.texture,S=f?P.getCanvasSource(f):null;if(!S)continue;const v=f.source.style,A=o.smoothProperty,Y=v.scaleMode!=="nearest";r[A]!==Y&&(r[A]=Y),o.setBlendMode(t.blendMode);const q=((i=n.globalUniforms.globalUniformData)==null?void 0:i.worldColor)??4294967295,E=y.color,k=(q>>>24&255)/255,C=(E>>>24&255)/255,V=((c=n.filter)==null?void 0:c.alphaMultiplier)??1,z=k*C*V;if(z<=0)continue;r.globalAlpha=z;const Z=q&16777215,J=E&16777215,b=Me(ae(J,Z)),M=f.frame,w=v.addressModeU??v.addressMode,ie=v.addressModeV??v.addressMode,ee=$._getPatternRepeat(w,ie),D=f.source._resolution??f.source.resolution??1,X=(m=(u=y.renderable)==null?void 0:u.renderGroup)==null?void 0:m.isCachedAsTexture,d=M.x*D,p=M.y*D,g=M.width*D,L=M.height*D,I=y.bounds,_=n.renderTarget.renderTarget.isRoot,W=I.minX,F=I.minY,B=I.maxX-I.minX,H=I.maxY-I.minY,O=f.rotate,l=f.uvs,N=Math.min(l.x0,l.x1,l.x2,l.x3,l.y0,l.y1,l.y2,l.y3),j=Math.max(l.x0,l.x1,l.x2,l.x3,l.y0,l.y1,l.y2,l.y3),T=ee!=="no-repeat"&&(N<0||j>1),ce=O&&!(!T&&(b!==16777215||O));ce?($._tempPatternMatrix.copyFrom(y.transform),Se.matrixAppendRotationInv($._tempPatternMatrix,O,W,F,B,H),o.setContextTransform($._tempPatternMatrix,y.roundPixels===1,void 0,X&&_)):o.setContextTransform(y.transform,y.roundPixels===1,void 0,X&&_);const te=ce?0:W,se=ce?0:F,le=B,he=H;if(T){let de=S;const K=b!==16777215&&!O,Q=M.width<=f.source.width&&M.height<=f.source.height;K&&Q&&(de=P.getTintedCanvas({texture:f},b));const pe=r.createPattern(de,ee);if(!pe)continue;const ye=le,xe=he;if(ye===0||xe===0)continue;const Ce=1/ye,Te=1/xe,Pe=(l.x1-l.x0)*Ce,ke=(l.y1-l.y0)*Ce,be=(l.x3-l.x0)*Te,_e=(l.y3-l.y0)*Te,je=l.x0-Pe*te-be*se,Ye=l.y0-ke*te-_e*se,ue=f.source.pixelWidth,me=f.source.pixelHeight;$._tempPatternMatrix.set(Pe*ue,ke*me,be*ue,_e*me,je*ue,Ye*me),P.applyPatternTransform(pe,$._tempPatternMatrix),r.fillStyle=pe,r.fillRect(te,se,le,he)}else{const K=b!==16777215||O?P.getTintedCanvas({texture:f},b):S,Q=K!==S;r.drawImage(K,Q?0:d,Q?0:p,Q?K.width:g,Q?K.height:L,te,se,le,he)}}}};ge._tempPatternMatrix=new U;ge.extension={type:[R.CanvasPipesAdaptor],name:"batch"};let lt=ge;class He{constructor(e){this._colorStack=[],this._colorStackIndex=0,this._currentColor=0,this._renderer=e}buildStart(){this._colorStack[0]=15,this._colorStackIndex=1,this._currentColor=15}push(e,t,s){this._renderer.renderPipes.batch.break(s);const n=this._colorStack;n[this._colorStackIndex]=n[this._colorStackIndex-1]&e.mask;const o=this._colorStack[this._colorStackIndex];o!==this._currentColor&&(this._currentColor=o,s.add({renderPipeId:"colorMask",colorMask:o,canBundle:!1})),this._colorStackIndex++}pop(e,t,s){this._renderer.renderPipes.batch.break(s);const n=this._colorStack;this._colorStackIndex--;const o=n[this._colorStackIndex-1];o!==this._currentColor&&(this._currentColor=o,s.add({renderPipeId:"colorMask",colorMask:o,canBundle:!1}))}execute(e){}destroy(){this._renderer=null,this._colorStack=null}}He.extension={type:[R.CanvasPipes],name:"colorMask"};function ht(a,e,t,s,n,o){o=Math.max(0,Math.min(o,Math.min(s,n)/2)),a.moveTo(e+o,t),a.lineTo(e+s-o,t),a.quadraticCurveTo(e+s,t,e+s,t+o),a.lineTo(e+s,t+n-o),a.quadraticCurveTo(e+s,t+n,e+s-o,t+n),a.lineTo(e+o,t+n),a.quadraticCurveTo(e,t+n,e,t+n-o),a.lineTo(e,t+o),a.quadraticCurveTo(e,t,e+o,t)}function Ge(a,e){switch(e.type){case"rectangle":{const t=e;a.rect(t.x,t.y,t.width,t.height);break}case"roundedRectangle":{const t=e;ht(a,t.x,t.y,t.width,t.height,t.radius);break}case"circle":{const t=e;a.moveTo(t.x+t.radius,t.y),a.arc(t.x,t.y,t.radius,0,Math.PI*2);break}case"ellipse":{const t=e;a.ellipse?(a.moveTo(t.x+t.halfWidth,t.y),a.ellipse(t.x,t.y,t.halfWidth,t.halfHeight,0,0,Math.PI*2)):(a.save(),a.translate(t.x,t.y),a.scale(t.halfWidth,t.halfHeight),a.moveTo(1,0),a.arc(0,0,1,0,Math.PI*2),a.restore());break}case"triangle":{const t=e;a.moveTo(t.x,t.y),a.lineTo(t.x2,t.y2),a.lineTo(t.x3,t.y3),a.closePath();break}case"polygon":default:{const t=e,s=t.points;if(!(s!=null&&s.length))break;a.moveTo(s[0],s[1]);for(let n=2;n<s.length;n+=2)a.lineTo(s[n],s[n+1]);t.closePath&&a.closePath();break}}}function dt(a,e,t){const s=[],n=[],o=[],r=we[e.type];if(!(r!=null&&r.build(e,s)))return!1;const i=e.closePath??!0;Ie(s,t,!1,i,n,o);for(let c=0;c<o.length;c+=3){const u=o[c]*2,m=o[c+1]*2,x=o[c+2]*2;a.moveTo(n[u],n[u+1]),a.lineTo(n[m],n[m+1]),a.lineTo(n[x],n[x+1]),a.closePath()}return!0}function pt(a,e){if(!(e!=null&&e.length))return!1;for(let t=0;t<e.length;t++){const s=e[t];if(!(s!=null&&s.shape))continue;const n=s.transform,o=n&&!n.isIdentity();o&&(a.save(),a.transform(n.a,n.b,n.c,n.d,n.tx,n.ty)),Ge(a,s.shape),o&&a.restore()}return!0}class Ee{constructor(e){this._warnedMaskTypes=new Set,this._canvasMaskStack=[],this._renderer=e}push(e,t,s){this._renderer.renderPipes.batch.break(s),s.add({renderPipeId:"stencilMask",action:"pushMaskBegin",mask:e,inverse:t._maskOptions.inverse,canBundle:!1})}pop(e,t,s){this._renderer.renderPipes.batch.break(s),s.add({renderPipeId:"stencilMask",action:"popMaskEnd",mask:e,inverse:t._maskOptions.inverse,canBundle:!1})}execute(e){var m,x,G;if(e.action!=="pushMaskBegin"&&e.action!=="popMaskEnd")return;const t=this._renderer,s=t.canvasContext,n=s==null?void 0:s.activeContext;if(!n)return;if(e.action==="popMaskEnd"){this._canvasMaskStack.pop()&&n.restore();return}e.inverse&&this._warnOnce("inverse","CanvasRenderer: inverse masks are not supported on Canvas2D; ignoring inverse flag.");const o=e.mask.mask;if(!(o instanceof Ve)){this._warnOnce("nonGraphics","CanvasRenderer: only Graphics masks are supported in Canvas2D; skipping mask."),this._canvasMaskStack.push(!1);return}const r=o,i=(m=r.context)==null?void 0:m.instructions;if(!(i!=null&&i.length)){this._canvasMaskStack.push(!1);return}n.save(),s.setContextTransform(r.groupTransform,(t._roundPixels|r._roundPixels)===1),n.beginPath();let c=!1,u=!1;for(let y=0;y<i.length;y++){const f=i[y],S=f.action;if(S!=="fill"&&S!=="stroke")continue;const v=f.data,A=(x=v==null?void 0:v.path)==null?void 0:x.shapePath;if(!((G=A==null?void 0:A.shapePrimitives)!=null&&G.length))continue;const Y=S==="stroke",q=A.shapePrimitives;for(let E=0;E<q.length;E++){const k=q[E];if(!(k!=null&&k.shape))continue;const C=k.transform,V=C&&!C.isIdentity();V&&(n.save(),n.transform(C.a,C.b,C.c,C.d,C.tx,C.ty)),Y&&v.style?c=dt(n,k.shape,v.style)||c:(Ge(n,k.shape),u=pt(n,k.holes)||u,c=!0),V&&n.restore()}}if(!c){n.restore(),this._canvasMaskStack.push(!1);return}u?n.clip("evenodd"):n.clip(),this._canvasMaskStack.push(!0)}destroy(){this._renderer=null,this._warnedMaskTypes=null,this._canvasMaskStack=null}_warnOnce(e,t){this._warnedMaskTypes.has(e)||(this._warnedMaskTypes.add(e),Xe(t))}}Ee.extension={type:[R.CanvasPipes],name:"stencilMask"};const h="source-over";function ut(){const a=ct(),e=Object.create(null);return e.inherit=h,e.none=h,e.normal="source-over",e.add="lighter",e.multiply=a?"multiply":h,e.screen=a?"screen":h,e.overlay=a?"overlay":h,e.darken=a?"darken":h,e.lighten=a?"lighten":h,e["color-dodge"]=a?"color-dodge":h,e["color-burn"]=a?"color-burn":h,e["hard-light"]=a?"hard-light":h,e["soft-light"]=a?"soft-light":h,e.difference=a?"difference":h,e.exclusion=a?"exclusion":h,e.saturation=a?"saturation":h,e.color=a?"color":h,e.luminosity=a?"luminosity":h,e["linear-burn"]=a?"color-burn":h,e["linear-dodge"]=a?"color-dodge":h,e["linear-light"]=a?"hard-light":h,e["pin-light"]=a?"hard-light":h,e["vivid-light"]=a?"hard-light":h,e["hard-mix"]=h,e.negation=a?"difference":h,e["normal-npm"]=e.normal,e["add-npm"]=e.add,e["screen-npm"]=e.screen,e.erase="destination-out",e.subtract=h,e.divide=h,e.min=h,e.max=h,e}const mt=new U;class We{constructor(e){this.activeResolution=1,this.smoothProperty="imageSmoothingEnabled",this.blendModes=ut(),this._activeBlendMode="normal",this._projTransform=null,this._outerBlend=!1,this._warnedBlendModes=new Set,this._renderer=e}resolutionChange(e){this.activeResolution=e}init(){const e=this._renderer.background.alpha<1;if(this.rootContext=this._renderer.canvas.getContext("2d",{alpha:e}),this.activeContext=this.rootContext,this.activeResolution=this._renderer.resolution,!this.rootContext.imageSmoothingEnabled){const t=this.rootContext;t.webkitImageSmoothingEnabled?this.smoothProperty="webkitImageSmoothingEnabled":t.mozImageSmoothingEnabled?this.smoothProperty="mozImageSmoothingEnabled":t.oImageSmoothingEnabled?this.smoothProperty="oImageSmoothingEnabled":t.msImageSmoothingEnabled&&(this.smoothProperty="msImageSmoothingEnabled")}}setContextTransform(e,t,s,n){var u;const o=n?U.IDENTITY:((u=this._renderer.globalUniforms.globalUniformData)==null?void 0:u.worldTransformMatrix)||U.IDENTITY;let r=mt;r.copyFrom(o),r.append(e);const i=this._projTransform,c=this.activeResolution;if(s=s||c,i){const m=U.shared;m.copyFrom(r),m.prepend(i),r=m}t?this.activeContext.setTransform(r.a*s,r.b*s,r.c*s,r.d*s,r.tx*c|0,r.ty*c|0):this.activeContext.setTransform(r.a*s,r.b*s,r.c*s,r.d*s,r.tx*c,r.ty*c)}clear(e,t){const s=this.activeContext,n=this._renderer;if(s.clearRect(0,0,n.width,n.height),e){const o=Re.shared.setValue(e);s.globalAlpha=t??o.alpha,s.fillStyle=o.toHex(),s.fillRect(0,0,n.width,n.height),s.globalAlpha=1}}setBlendMode(e){if(this._activeBlendMode===e)return;this._activeBlendMode=e,this._outerBlend=!1;const t=this.blendModes[e];if(!t){this._warnedBlendModes.has(e)||(console.warn(`CanvasRenderer: blend mode "${e}" is not supported in Canvas2D; falling back to "source-over".`),this._warnedBlendModes.add(e)),this.activeContext.globalCompositeOperation="source-over";return}this.activeContext.globalCompositeOperation=t}destroy(){this.rootContext=null,this.activeContext=null,this._warnedBlendModes.clear()}}We.extension={type:[R.CanvasSystem],name:"canvasContext"};class Fe{constructor(){this.maxTextures=16,this.maxBatchableTextures=16,this.maxUniformBindings=0}init(){}}Fe.extension={type:[R.CanvasSystem],name:"limits"};const ft="#808080",ne=new U,gt=new U,vt=new U,fe=new U;function yt(a,e,t){a.beginPath();for(let s=0;s<t.length;s+=3){const n=t[s]*2,o=t[s+1]*2,r=t[s+2]*2;a.moveTo(e[n],e[n+1]),a.lineTo(e[o],e[o+1]),a.lineTo(e[r],e[r+1]),a.closePath()}a.fill()}function xt(a){return`#${(a&16777215).toString(16).padStart(6,"0")}`}function Ct(a,e,t,s,n,o){o=Math.max(0,Math.min(o,Math.min(s,n)/2)),a.moveTo(e+o,t),a.lineTo(e+s-o,t),a.quadraticCurveTo(e+s,t,e+s,t+o),a.lineTo(e+s,t+n-o),a.quadraticCurveTo(e+s,t+n,e+s-o,t+n),a.lineTo(e+o,t+n),a.quadraticCurveTo(e,t+n,e,t+n-o),a.lineTo(e,t+o),a.quadraticCurveTo(e,t,e+o,t)}function oe(a,e){switch(e.type){case"rectangle":{const t=e;a.rect(t.x,t.y,t.width,t.height);break}case"roundedRectangle":{const t=e;Ct(a,t.x,t.y,t.width,t.height,t.radius);break}case"circle":{const t=e;a.arc(t.x,t.y,t.radius,0,Math.PI*2);break}case"ellipse":{const t=e;a.ellipse?a.ellipse(t.x,t.y,t.halfWidth,t.halfHeight,0,0,Math.PI*2):(a.save(),a.translate(t.x,t.y),a.scale(t.halfWidth,t.halfHeight),a.arc(0,0,1,0,Math.PI*2),a.restore());break}case"triangle":{const t=e;a.moveTo(t.x,t.y),a.lineTo(t.x2,t.y2),a.lineTo(t.x3,t.y3),a.closePath();break}case"polygon":default:{const t=e,s=t.points;if(!(s!=null&&s.length))break;a.moveTo(s[0],s[1]);for(let n=2;n<s.length;n+=2)a.lineTo(s[n],s[n+1]);t.closePath&&a.closePath();break}}}function Tt(a,e){if(!(e!=null&&e.length))return!1;for(let t=0;t<e.length;t++){const s=e[t];if(!(s!=null&&s.shape))continue;const n=s.transform,o=n&&!n.isIdentity();o&&(a.save(),a.transform(n.a,n.b,n.c,n.d,n.tx,n.ty)),oe(a,s.shape),o&&a.restore()}return!0}function Pt(a,e,t,s){const n=a.fill;if(n instanceof Je){n.buildGradient();const r=n.texture;if(r){const i=P.getTintedPattern(r,e),c=t?fe.copyFrom(t).scale(r.source.pixelWidth,r.source.pixelHeight):fe.copyFrom(n.transform);return s&&!a.textureSpace&&c.append(s),P.applyPatternTransform(i,c),i}}if(n instanceof Ke){const r=P.getTintedPattern(n.texture,e);return P.applyPatternTransform(r,n.transform),r}const o=a.texture;if(o&&o!==Ae.WHITE){if(!o.source.resource)return ft;const r=P.getTintedPattern(o,e),i=t?fe.copyFrom(t).scale(o.source.pixelWidth,o.source.pixelHeight):a.matrix;return P.applyPatternTransform(r,i),r}return xt(e)}class Ue{constructor(){this.shader=null}contextChange(e){}execute(e,t){var Y,q,E,k,C,V,z;const s=e.renderer,n=s.canvasContext,o=n.activeContext,r=t.groupTransform,i=((Y=s.globalUniforms.globalUniformData)==null?void 0:Y.worldColor)??4294967295,c=t.groupColorAlpha,u=(i>>>24&255)/255,m=(c>>>24&255)/255,x=((q=s.filter)==null?void 0:q.alphaMultiplier)??1,G=u*m*x;if(G<=0)return;const y=i&16777215,f=c&16777215,S=Me(ae(f,y)),v=s._roundPixels|t._roundPixels;o.save(),n.setContextTransform(r,v===1),n.setBlendMode(t.groupBlendMode);const A=t.context.instructions;for(let Z=0;Z<A.length;Z++){const J=A[Z];if(J.action==="texture"){const d=J.data,p=d.image,g=p?P.getCanvasSource(p):null;if(!g)continue;const L=d.alpha*G;if(L<=0)continue;const I=ae(d.style,S);o.globalAlpha=L;let _=g;I!==16777215&&(_=P.getTintedCanvas({texture:p},I));const W=p.frame,F=p.source._resolution??p.source.resolution??1;let B=W.x*F,H=W.y*F;const O=W.width*F,l=W.height*F;_!==g&&(B=0,H=0);const N=d.transform,j=N&&!N.isIdentity(),T=p.rotate;j||T?(ne.copyFrom(r),j&&ne.append(N),T&&Se.matrixAppendRotationInv(ne,T,d.dx,d.dy,d.dw,d.dh),n.setContextTransform(ne,v===1)):n.setContextTransform(r,v===1),o.drawImage(_,B,H,_===g?O:_.width,_===g?l:_.height,T?0:d.dx,T?0:d.dy,d.dw,d.dh),(j||T)&&n.setContextTransform(r,v===1);continue}const b=J.data,M=(E=b==null?void 0:b.path)==null?void 0:E.shapePath;if(!((k=M==null?void 0:M.shapePrimitives)!=null&&k.length))continue;const w=b.style,ie=ae(w.color,S),ee=w.alpha*G;if(ee<=0)continue;const D=J.action==="stroke";if(o.globalAlpha=ee,D){const d=w;o.lineWidth=d.width,o.lineCap=d.cap,o.lineJoin=d.join,o.miterLimit=d.miterLimit}const X=M.shapePrimitives;if(!D&&((z=(V=(C=b.hole)==null?void 0:C.shapePath)==null?void 0:V.shapePrimitives)!=null&&z.length)){const d=X[X.length-1];d.holes=b.hole.shapePath.shapePrimitives}for(let d=0;d<X.length;d++){const p=X[d];if(!(p!=null&&p.shape))continue;const g=p.transform,L=g&&!g.isIdentity(),I=w.texture&&w.texture!==Ae.WHITE,_=w.textureSpace==="global"?g:null,W=I?$e(gt,w,p.shape,_):null,F=L?vt.copyFrom(r).append(g):r,B=Pt(w,ie,W,F);if(L&&(o.save(),o.transform(g.a,g.b,g.c,g.d,g.tx,g.ty)),D){const H=w;if(H.alignment!==.5&&!H.pixelLine){const l=[],N=[],j=[],T=we[p.shape.type];if(T!=null&&T.build(p.shape,l)){const ve=p.shape.closePath??!0;Ie(l,H,!1,ve,N,j),o.fillStyle=B,yt(o,N,j)}else o.strokeStyle=B,o.beginPath(),oe(o,p.shape),o.stroke()}else o.strokeStyle=B,o.beginPath(),oe(o,p.shape),o.stroke()}else o.fillStyle=B,o.beginPath(),oe(o,p.shape),Tt(o,p.holes)?o.fill("evenodd"):o.fill();L&&o.restore()}}o.restore()}destroy(){this.shader=null}}Ue.extension={type:[R.CanvasPipesAdaptor],name:"graphics"};class kt{init(e,t){this._renderer=e,this._renderTargetSystem=t}initGpuRenderTarget(e){const t=e.colorTexture,{canvas:s,context:n}=this._ensureCanvas(t);return{canvas:s,context:n,width:s.width,height:s.height}}resizeGpuRenderTarget(e){const t=e.colorTexture,{canvas:s}=this._ensureCanvas(t);s.width=e.pixelWidth,s.height=e.pixelHeight}startRenderPass(e,t,s,n){const o=this._renderTargetSystem.getGpuRenderTarget(e);this._renderer.canvasContext.activeContext=o.context,this._renderer.canvasContext.activeResolution=e.resolution,t&&this.clear(e,t,s,n)}clear(e,t,s,n){const r=this._renderTargetSystem.getGpuRenderTarget(e).context,i=n||{x:0,y:0,width:e.pixelWidth,height:e.pixelHeight};if(r.setTransform(1,0,0,1,0,0),r.clearRect(i.x,i.y,i.width,i.height),s){const c=Re.shared.setValue(s);c.alpha>0&&(r.globalAlpha=c.alpha,r.fillStyle=c.toHex(),r.fillRect(i.x,i.y,i.width,i.height),r.globalAlpha=1)}}finishRenderPass(){}copyToTexture(e,t,s,n,o){const i=this._renderTargetSystem.getGpuRenderTarget(e).canvas,c=t.source,{context:u}=this._ensureCanvas(c),m=(o==null?void 0:o.x)??0,x=(o==null?void 0:o.y)??0;return u.drawImage(i,s.x,s.y,n.width,n.height,m,x,n.width,n.height),c.update(),t}destroyGpuRenderTarget(e){}_ensureCanvas(e){let t=e.resource;(!t||!Qe.test(t))&&(t=Be.get().createCanvas(e.pixelWidth,e.pixelHeight),e.resource=t),(t.width!==e.pixelWidth||t.height!==e.pixelHeight)&&(t.width=e.pixelWidth,t.height=e.pixelHeight);const s=t.getContext("2d");return{canvas:t,context:s}}}class qe extends et{constructor(e){super(e),this.adaptor=new kt,this.adaptor.init(e,this)}}qe.extension={type:[R.CanvasSystem],name:"renderTarget"};class De{constructor(e){}init(){}initSource(e){}generateCanvas(e){const t=Be.get().createCanvas(),s=t.getContext("2d"),n=P.getCanvasSource(e);if(!n)return t;const o=e.frame,r=e.source._resolution??e.source.resolution??1,i=o.x*r,c=o.y*r,u=o.width*r,m=o.height*r;return t.width=Math.ceil(u),t.height=Math.ceil(m),s.drawImage(n,i,c,u,m,0,0,u,m),t}getPixels(e){const t=this.generateCanvas(e);return{pixels:t.getContext("2d",{willReadFrequently:!0}).getImageData(0,0,t.width,t.height).data,width:t.width,height:t.height}}destroy(){}}De.extension={type:[R.CanvasSystem],name:"texture"};const bt=[...tt,We,Fe,De,qe],_t=[st,nt,at,ot,rt,Ee,He,it],St=[lt,Ue],Le=[],Oe=[],Ne=[];re.handleByNamedList(R.CanvasSystem,Le);re.handleByNamedList(R.CanvasPipes,Oe);re.handleByNamedList(R.CanvasPipesAdaptor,Ne);re.add(...bt,..._t,...St);class At extends ze{constructor(){const e={name:"canvas",type:Ze.CANVAS,systems:Le,renderPipes:Oe,renderPipeAdaptors:Ne};super(e)}}export{At as CanvasRenderer};
@@ -0,0 +1 @@
1
+ import{v as n,x as o,q as u,o as f}from"./index-Cf0rVPz-.js";const s=class i extends n{constructor(e){e={...i.defaultOptions,...e},super(e),this.enabled=!0,this._state=o.for2d(),this.blendMode=e.blendMode,this.padding=e.padding,typeof e.antialias=="boolean"?this.antialias=e.antialias?"on":"off":this.antialias=e.antialias,this.resolution=e.resolution,this.blendRequired=e.blendRequired,this.clipToViewport=e.clipToViewport,this.addResource("uTexture",0,1),e.blendRequired&&this.addResource("uBackTexture",0,3)}apply(e,t,a,r){e.applyFilter(this,t,a,r)}get blendMode(){return this._state.blendMode}set blendMode(e){this._state.blendMode=e}static from(e){const{gpu:t,gl:a,...r}=e;let l,d;return t&&(l=u.from(t)),a&&(d=f.from(a)),new i({gpuProgram:l,glProgram:d,...r})}};s.defaultOptions={blendMode:"normal",resolution:1,padding:0,antialias:"off",blendRequired:!1,clipToViewport:!0};let b=s;export{b as F};