fcode 2.2.0__cp313-cp313-win_amd64.whl
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.
- fcode/__init__.py +3 -0
- fcode/_types.py +655 -0
- fcode/api.py +146 -0
- fcode/auth.py +49 -0
- fcode/cli.py +127 -0
- fcode/commands/__init__.py +0 -0
- fcode/commands/init.py +29 -0
- fcode/commands/ladder.py +74 -0
- fcode/commands/login.py +135 -0
- fcode/commands/logout.py +21 -0
- fcode/commands/map_editor.py +91 -0
- fcode/commands/match_detail.py +173 -0
- fcode/commands/match_group.py +163 -0
- fcode/commands/matches.py +127 -0
- fcode/commands/run.py +186 -0
- fcode/commands/starter.py +119 -0
- fcode/commands/status.py +112 -0
- fcode/commands/submission.py +260 -0
- fcode/commands/team_group.py +73 -0
- fcode/commands/teams.py +73 -0
- fcode/commands/test.py +51 -0
- fcode/commands/test_matches.py +59 -0
- fcode/commands/test_run.py +125 -0
- fcode/commands/watch.py +123 -0
- fcode/compat.py +36 -0
- fcode/config.py +47 -0
- fcode/data/__init__.py +0 -0
- fcode/data/docs/spec.md +290 -0
- fcode/data/maps/__init__.py +0 -0
- fcode/data/maps/atoll.map26 +0 -0
- fcode/data/maps/aurora.map26 +0 -0
- fcode/data/maps/crossfire.map26 +0 -0
- fcode/data/maps/duel.map26 +0 -0
- fcode/data/maps/fjord.map26 +0 -0
- fcode/data/maps/hive.map26 +0 -0
- fcode/data/maps/longship.map26 +0 -0
- fcode/data/maps/pinch.map26 +0 -0
- fcode/data/maps/quarry.map26 +0 -0
- fcode/data/maps/runestone.map26 +0 -0
- fcode/data/maps/skerry.map26 +0 -0
- fcode/data/maps/sprint.map26 +0 -0
- fcode/data/maps/strait.map26 +0 -0
- fcode/data/maps/twins.map26 +0 -0
- fcode/data/maps/vault.map26 +0 -0
- fcode/data/starter_bot.py +452 -0
- fcode/data/visualiser/.directory +9 -0
- fcode/data/visualiser/Builderbot_med.png +0 -0
- fcode/data/visualiser/armoured_conveyor_gold.png +0 -0
- fcode/data/visualiser/armoured_conveyor_silver.png +0 -0
- fcode/data/visualiser/assets/app-BiRa_5u6.css +1 -0
- fcode/data/visualiser/assets/app-CK52NxpR.js +86 -0
- fcode/data/visualiser/assets/main-COIx42iq.js +1 -0
- fcode/data/visualiser/assets/map-editor-BDLYjgel.js +1 -0
- fcode/data/visualiser/axionite_ore.png +0 -0
- fcode/data/visualiser/axionite_processed.png +0 -0
- fcode/data/visualiser/axionite_raw.png +0 -0
- fcode/data/visualiser/barrier_gold.png +0 -0
- fcode/data/visualiser/barrier_silver.png +0 -0
- fcode/data/visualiser/base_gold.png +0 -0
- fcode/data/visualiser/base_silver.png +0 -0
- fcode/data/visualiser/battlecodetitle-orange.webp +0 -0
- fcode/data/visualiser/bg-light.png +0 -0
- fcode/data/visualiser/bg.png +0 -0
- fcode/data/visualiser/breach_e_gold.png +0 -0
- fcode/data/visualiser/breach_e_silver.png +0 -0
- fcode/data/visualiser/breach_n_gold.png +0 -0
- fcode/data/visualiser/breach_n_silver.png +0 -0
- fcode/data/visualiser/breach_ne_gold.png +0 -0
- fcode/data/visualiser/breach_ne_silver.png +0 -0
- fcode/data/visualiser/breach_nw_gold.png +0 -0
- fcode/data/visualiser/breach_nw_silver.png +0 -0
- fcode/data/visualiser/breach_s_gold.png +0 -0
- fcode/data/visualiser/breach_s_silver.png +0 -0
- fcode/data/visualiser/breach_se_gold.png +0 -0
- fcode/data/visualiser/breach_se_silver.png +0 -0
- fcode/data/visualiser/breach_sw_gold.png +0 -0
- fcode/data/visualiser/breach_sw_silver.png +0 -0
- fcode/data/visualiser/bridge_gold.png +0 -0
- fcode/data/visualiser/bridge_silver.png +0 -0
- fcode/data/visualiser/bridge_stand_gold.png +0 -0
- fcode/data/visualiser/bridge_stand_silver.png +0 -0
- fcode/data/visualiser/builderbot_back_gold.png +0 -0
- fcode/data/visualiser/builderbot_back_silver.png +0 -0
- fcode/data/visualiser/builderbot_front_gold.png +0 -0
- fcode/data/visualiser/builderbot_front_silver.png +0 -0
- fcode/data/visualiser/builderbot_side_gold.png +0 -0
- fcode/data/visualiser/builderbot_side_silver.png +0 -0
- fcode/data/visualiser/conveyor_gold.png +0 -0
- fcode/data/visualiser/conveyor_silver.png +0 -0
- fcode/data/visualiser/dimetric/Dimetric_Tile_Cube.png +0 -0
- fcode/data/visualiser/dimetric/Dimetric_Tile_Floor_Footprint.png +0 -0
- fcode/data/visualiser/dimetric/barrier_team1.png +0 -0
- fcode/data/visualiser/dimetric/barrier_team2.png +0 -0
- fcode/data/visualiser/dimetric/base_team1.png +0 -0
- fcode/data/visualiser/dimetric/base_team2.png +0 -0
- fcode/data/visualiser/dimetric/bg.png +0 -0
- fcode/data/visualiser/dimetric/bridge_stand_team1.png +0 -0
- fcode/data/visualiser/dimetric/bridge_stand_team2.png +0 -0
- fcode/data/visualiser/dimetric/bridge_team1.png +0 -0
- fcode/data/visualiser/dimetric/bridge_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_e_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_e_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_n_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_n_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_ne_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_ne_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_nw_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_nw_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_s_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_s_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_se_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_se_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_sw_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_sw_team2.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_w_team1.png +0 -0
- fcode/data/visualiser/dimetric/builderbot_w_team2.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_ne_team1.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_ne_team2.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_nw_team1.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_nw_team2.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_se_team1.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_se_team2.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_sw_team1.png +0 -0
- fcode/data/visualiser/dimetric/conveyor_sw_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_e_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_e_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_n_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_n_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_ne_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_ne_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_nw_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_nw_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_s_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_s_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_se_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_se_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_sw_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_sw_team2.png +0 -0
- fcode/data/visualiser/dimetric/gunner_w_team1.png +0 -0
- fcode/data/visualiser/dimetric/gunner_w_team2.png +0 -0
- fcode/data/visualiser/dimetric/harvester_team1.png +0 -0
- fcode/data/visualiser/dimetric/harvester_team2.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team1_ne.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team1_nw.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team1_se.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team1_sw.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team2_ne.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team2_nw.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team2_se.png +0 -0
- fcode/data/visualiser/dimetric/launcher_team2_sw.png +0 -0
- fcode/data/visualiser/dimetric/natural_wall.png +0 -0
- fcode/data/visualiser/dimetric/natural_wall_ne.png +0 -0
- fcode/data/visualiser/dimetric/natural_wall_nw.png +0 -0
- fcode/data/visualiser/dimetric/natural_wall_se.png +0 -0
- fcode/data/visualiser/dimetric/natural_wall_sw.png +0 -0
- fcode/data/visualiser/dimetric/road_team1.png +0 -0
- fcode/data/visualiser/dimetric/road_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_e_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_e_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_n_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_n_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_ne_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_ne_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_nw_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_nw_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_s_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_s_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_se_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_se_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_sw_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_sw_team2.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_w_team1.png +0 -0
- fcode/data/visualiser/dimetric/sentinel_w_team2.png +0 -0
- fcode/data/visualiser/dimetric/splitter_ne_team1.png +0 -0
- fcode/data/visualiser/dimetric/splitter_ne_team2.png +0 -0
- fcode/data/visualiser/dimetric/splitter_nw_team1.png +0 -0
- fcode/data/visualiser/dimetric/splitter_nw_team2.png +0 -0
- fcode/data/visualiser/dimetric/splitter_se_team1.png +0 -0
- fcode/data/visualiser/dimetric/splitter_se_team2.png +0 -0
- fcode/data/visualiser/dimetric/splitter_sw_team1.png +0 -0
- fcode/data/visualiser/dimetric/splitter_sw_team2.png +0 -0
- fcode/data/visualiser/dimetric/titanium.png +0 -0
- fcode/data/visualiser/dimetric/titanium_ore.png +0 -0
- fcode/data/visualiser/fonts/HKGrotesk-Regular.otf +0 -0
- fcode/data/visualiser/foundry_gold.png +0 -0
- fcode/data/visualiser/foundry_silver.png +0 -0
- fcode/data/visualiser/gunner_n_gold.png +0 -0
- fcode/data/visualiser/gunner_n_silver.png +0 -0
- fcode/data/visualiser/gunner_ne_gold.png +0 -0
- fcode/data/visualiser/gunner_ne_silver.png +0 -0
- fcode/data/visualiser/gunner_nw_gold.png +0 -0
- fcode/data/visualiser/gunner_nw_silver.png +0 -0
- fcode/data/visualiser/gunner_s_gold.png +0 -0
- fcode/data/visualiser/gunner_s_silver.png +0 -0
- fcode/data/visualiser/gunner_se_gold.png +0 -0
- fcode/data/visualiser/gunner_se_silver.png +0 -0
- fcode/data/visualiser/gunner_sw_gold.png +0 -0
- fcode/data/visualiser/gunner_sw_silver.png +0 -0
- fcode/data/visualiser/gunner_w_gold.png +0 -0
- fcode/data/visualiser/gunner_w_silver.png +0 -0
- fcode/data/visualiser/harvester_gold.png +0 -0
- fcode/data/visualiser/harvester_silver.png +0 -0
- fcode/data/visualiser/index.html +20 -0
- fcode/data/visualiser/launcher_gold.png +0 -0
- fcode/data/visualiser/launcher_silver.png +0 -0
- fcode/data/visualiser/map-editor.html +20 -0
- fcode/data/visualiser/marker_gold.png +0 -0
- fcode/data/visualiser/marker_silver.png +0 -0
- fcode/data/visualiser/natural_wall.jpg +0 -0
- fcode/data/visualiser/road_gold.png +0 -0
- fcode/data/visualiser/road_silver.png +0 -0
- fcode/data/visualiser/sentinel_e_gold.png +0 -0
- fcode/data/visualiser/sentinel_e_silver.png +0 -0
- fcode/data/visualiser/sentinel_n_gold.png +0 -0
- fcode/data/visualiser/sentinel_n_silver.png +0 -0
- fcode/data/visualiser/sentinel_ne_gold.png +0 -0
- fcode/data/visualiser/sentinel_ne_silver.png +0 -0
- fcode/data/visualiser/sentinel_nw_gold.png +0 -0
- fcode/data/visualiser/sentinel_nw_silver.png +0 -0
- fcode/data/visualiser/sentinel_s_gold.png +0 -0
- fcode/data/visualiser/sentinel_s_silver.png +0 -0
- fcode/data/visualiser/sentinel_se_gold.png +0 -0
- fcode/data/visualiser/sentinel_se_silver.png +0 -0
- fcode/data/visualiser/sentinel_sw_gold.png +0 -0
- fcode/data/visualiser/sentinel_sw_silver.png +0 -0
- fcode/data/visualiser/splitter.png +0 -0
- fcode/data/visualiser/splitter_e_gold.png +0 -0
- fcode/data/visualiser/splitter_e_silver.png +0 -0
- fcode/data/visualiser/splitter_n_gold.png +0 -0
- fcode/data/visualiser/splitter_n_silver.png +0 -0
- fcode/data/visualiser/splitter_s_gold.png +0 -0
- fcode/data/visualiser/splitter_s_silver.png +0 -0
- fcode/data/visualiser/splitter_w_gold.png +0 -0
- fcode/data/visualiser/splitter_w_silver.png +0 -0
- fcode/data/visualiser/template02.png +0 -0
- fcode/data/visualiser/titanium.png +0 -0
- fcode/data/visualiser/titanium_ore.png +0 -0
- fcode/fcode_engine.cp313-win_amd64.pyd +0 -0
- fcode/py.typed +0 -0
- fcode/version_check.py +72 -0
- fcode-2.2.0.dist-info/METADATA +7 -0
- fcode-2.2.0.dist-info/RECORD +245 -0
- fcode-2.2.0.dist-info/WHEEL +4 -0
- fcode-2.2.0.dist-info/entry_points.txt +2 -0
- fcode-2.2.0.dist-info/sboms/fcode_engine.cyclonedx.json +1963 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{E as k,d as f,q as S,e as v,P as D,Q as ye,D as W,O as ke,A as ze,j as Xe,k as Ze,h as Ve,i as qe,f as Je,g as Qe,b as de,c as et,I as tt,v as Se,B as ve,u as we,w as Ee,G as Ce,y as Ne,K as Ae,x as Me,z as je,J as _e,a as he,F as Z,H as rt,Y as nt,s as st,C as ot,p as Te,T as H,n as Be,m as Oe,l as it,V as g,M as a,U as at,N as ue,L as ct,S as lt,r as dt}from"./app-CK52NxpR.js";const O=r=>r===S.A?"team2":"team1",ge=[{kind:k.BuilderBot,label:"Builder Bot",category:"Units",dirMode:"all8",thumb:r=>`dimetric/builderbot_se_${O(r)}.png`},{kind:k.Gunner,label:"Gunner",category:"Units",dirMode:"all8",thumb:r=>`dimetric/gunner_se_${O(r)}.png`},{kind:k.Sentinel,label:"Sentinel",category:"Units",dirMode:"all8",thumb:r=>`dimetric/sentinel_se_${O(r)}.png`},{kind:k.Launcher,label:"Launcher",category:"Units",dirMode:"none",thumb:r=>`dimetric/launcher_${O(r)}_se.png`},{kind:k.Conveyor,label:"Conveyor",category:"Logistics",dirMode:"cardinal4",thumb:r=>`dimetric/conveyor_se_${O(r)}.png`},{kind:k.Splitter,label:"Splitter",category:"Logistics",dirMode:"cardinal4",thumb:r=>`dimetric/splitter_se_${O(r)}.png`},{kind:k.Harvester,label:"Harvester",category:"Logistics",dirMode:"none",thumb:r=>`dimetric/harvester_${O(r)}.png`},{kind:k.Barrier,label:"Barrier",category:"Structures",dirMode:"none",thumb:r=>`dimetric/barrier_${O(r)}.png`},{kind:"road",label:"Road",category:"Structures",dirMode:"none",thumb:r=>`dimetric/road_${O(r)}.png`},{kind:k.Bridge,label:"Bridge",category:"Structures",dirMode:"none",thumb:r=>`dimetric/bridge_${O(r)}.png`}];function te(r){return ge.find(e=>e.kind===r)}const ht=[f.North,f.Northeast,f.East,f.Southeast,f.South,f.Southwest,f.West,f.Northwest],ut=[f.North,f.East,f.South,f.West];function ne(r){return r==="all8"?ht:r==="cardinal4"?ut:[f.Centre]}function $e(r){return r==="none"?f.Centre:ne(r)[0]}function mt(r,e,t){const n=ne(e);if(n.length<=1)return r;const o=n.indexOf(r);return n[((o===-1?0:o)+t+n.length)%n.length]}function Le(r,e){if(r===f.Centre)return r;const t=r-1;switch(e){case"rotational":return(t+4)%8+1;case"horizontal":return(8-t)%8+1;case"vertical":return(4-t+8)%8+1}}function be(r){return r===S.A?S.B:S.A}const Ue={[k.BuilderBot]:1,[k.Conveyor]:2,[k.Splitter]:3,[k.ArmouredConveyor]:4,[k.Bridge]:5,[k.Harvester]:6,[k.Foundry]:7,[k.Barrier]:8,[k.Gunner]:9,[k.Sentinel]:10,[k.Breach]:11,[k.Launcher]:12,road:13},pt=Object.fromEntries(Object.entries(Ue).map(([r,e])=>[e,r]));function ft(r){return Ue[r]}function xt(r){return pt[r]}const gt={[f.Centre]:"—",[f.North]:"N",[f.Northeast]:"NE",[f.East]:"E",[f.Southeast]:"SE",[f.South]:"S",[f.Southwest]:"SW",[f.West]:"W",[f.Northwest]:"NW"},A=128;v.Empty+"",v.Wall+"",v.OreTitanium+"";const me={[S.A]:16760640,[S.B]:7252735};function $(r,e,t){const n=[];for(let o=0;o<e;o++){const c=[];for(let s=0;s<r;s++)c.push(v.Empty);n.push(c)}return{width:r,height:e,environment:n,coreA:null,coreB:null,symmetry:t,decor:[]}}function F(r,e,t,n,o){switch(o){case"rotational":return{x:t-1-r,y:n-1-e};case"horizontal":return{x:t-1-r,y:e};case"vertical":return{x:r,y:n-1-e}}}function pe(r){return{width:r.width,height:r.height,environment:r.environment.map(e=>[...e]),coreA:r.coreA?{...r.coreA}:null,coreB:r.coreB?{...r.coreB}:null,symmetry:r.symmetry,decor:(r.decor??[]).map(e=>({...e}))}}function Re(r){switch(r){case f.North:case f.Northeast:case f.Northwest:return{facing:"back",flipX:!1};case f.East:return{facing:"side",flipX:!1};case f.West:return{facing:"side",flipX:!0};default:return{facing:"front",flipX:!1}}}const Ie=200;class bt extends D.Scene{mapState=$(20,20,"rotational");brush="wall";assetBrush=null;galleryMode=!1;galleryScrollY=null;undoStack=[];mapLayer;gridGraphics;entityLayer;ghostObjects=[];highlightGraphics;symmetryGraphics;projection=ye(W);ground=ke(W);dragStart=null;isPainting=!1;hoveredTile=null;static CLICK_THRESHOLD=8;onHoverChange;onMapChange;onUndoStackChange;constructor(){super({key:"MapEditorScene"})}preload(){for(const e of ze)this.load.image(e.key,e.file);this.load.spritesheet(Xe,Ze,{frameWidth:qe,frameHeight:Ve}),this.load.image(Je,Qe),this.load.image(de,et);for(const e of tt)this.load.image(e.key,e.file)}create(){this.mapLayer=this.add.container(0,0),this.gridGraphics=this.add.graphics(),this.entityLayer=this.add.container(0,0),this.symmetryGraphics=this.add.graphics(),this.highlightGraphics=this.add.graphics(),this.input.on("pointerdown",e=>{if(e.rightButtonDown()){this.dragStart={x:e.worldX,y:e.worldY};return}if(e.leftButtonDown()){if(this.galleryMode){this.dragStart={x:e.worldX,y:e.worldY};return}const t=this.worldToTile(e.worldX,e.worldY);t&&(this.pushUndo(),this.isPainting=!0,this.paintTile(t.x,t.y))}}),this.input.on("pointermove",e=>{if(this.dragStart&&(e.rightButtonDown()||this.galleryMode&&e.leftButtonDown())){const t=this.dragStart.x-e.worldX,n=this.dragStart.y-e.worldY;this.galleryMode?this.scrollGallery(n):(this.cameras.main.scrollX+=t,this.cameras.main.scrollY+=n)}if(this.isPainting&&e.leftButtonDown()){const t=this.worldToTile(e.worldX,e.worldY);t&&this.paintTile(t.x,t.y)}this.updateHover(e)}),this.input.on("pointerup",()=>{this.dragStart=null,this.isPainting=!1}),this.input.on("wheel",(e,t,n,o)=>{const c=this.cameras.main;if(this.galleryMode){this.scrollGallery(o/c.zoom);return}const s=D.Math.Clamp(c.zoom*(o>0?.9:1.1),.2,4);c.setZoom(s)}),this.scale.on("resize",()=>{this.galleryMode&&this.renderGallery()}),this.game.canvas.addEventListener("contextmenu",e=>e.preventDefault()),this.renderAll(),this.centerCamera()}getMapState(){return pe(this.mapState)}loadMap(e){this.pushUndo(),this.mapState={...e,decor:e.decor??[]},this.renderAll(),this.centerCamera(),this.notifyMapChange()}setBrush(e){this.brush=e,e!=="asset"&&(this.assetBrush=null),this.updateGhost()}setAssetBrush(e){this.brush="asset",this.assetBrush={...e},this.updateGhost()}setGalleryMode(e){e!==this.galleryMode&&(this.galleryMode=e,e||(this.galleryScrollY=null),this.renderAll(),e||this.centerCamera())}scrollGallery(e){if(!this.galleryScrollY)return;const t=this.cameras.main;t.scrollY=D.Math.Clamp(t.scrollY+e,this.galleryScrollY.min,this.galleryScrollY.max)}setMapSize(e,t){this.pushUndo();const{symmetry:n}=this.mapState;this.mapState=$(e,t,n),this.renderAll(),this.centerCamera(),this.notifyMapChange()}setSymmetry(e){this.pushUndo();const{width:t,height:n}=this.mapState;this.mapState=$(t,n,e),this.renderAll(),this.notifyMapChange()}clearMap(){this.pushUndo();const{width:e,height:t,symmetry:n}=this.mapState;this.mapState=$(e,t,n),this.renderAll(),this.notifyMapChange()}undo(){this.undoStack.length!==0&&(this.mapState=this.undoStack.pop(),this.renderAll(),this.notifyMapChange(),this.notifyUndoStackChange())}canUndo(){return this.undoStack.length>0}setOnHoverChange(e){this.onHoverChange=e}setOnMapChange(e){this.onMapChange=e}setOnUndoStackChange(e){this.onUndoStackChange=e}renderMode=W;setRenderMode(e){e===this.renderMode&&this.mapLayer||(this.renderMode=e,this.projection=ye(e),this.ground=ke(e),this.mapLayer&&(this.renderAll(),this.centerCamera()))}notifyMapChange(){this.onMapChange?.(pe(this.mapState))}pushUndo(){this.undoStack.push(pe(this.mapState)),this.undoStack.length>Ie&&this.undoStack.splice(0,this.undoStack.length-Ie),this.notifyUndoStackChange()}notifyUndoStackChange(){this.onUndoStackChange?.(this.undoStack.length>0)}paintTile(e,t){const{width:n,height:o,symmetry:c}=this.mapState,s=F(e,t,n,o,c);switch(this.brush){case"empty":this.setEnv(e,t,v.Empty),this.setEnv(s.x,s.y,v.Empty),this.clearCoreAt(e,t),this.clearCoreAt(s.x,s.y),this.removeDecorAt(e,t),this.removeDecorAt(s.x,s.y);break;case"wall":if(this.isCoreArea(e,t)||this.isCoreArea(s.x,s.y))return;this.setEnv(e,t,v.Wall),this.setEnv(s.x,s.y,v.Wall),this.removeDecorAt(e,t),this.removeDecorAt(s.x,s.y);break;case"titanium":if(this.isCoreArea(e,t)||this.isCoreArea(s.x,s.y))return;this.setEnv(e,t,v.OreTitanium),this.setEnv(s.x,s.y,v.OreTitanium);break;case"core_a":{if(e<0||t<0||e>=n-1||t>=o-1)return;const i=F(e+1,t+1,n,o,c),l=Math.min(s.x,i.x),d=Math.min(s.y,i.y);if(l<0||d<0||l>=n-1||d>=o-1||Math.abs(e-l)<=2&&Math.abs(t-d)<=2)return;this.clearAreaForCore(e,t),this.clearAreaForCore(l,d),this.mapState.coreA={x:e,y:t},this.mapState.coreB={x:l,y:d};break}case"eraser":this.setEnv(e,t,v.Empty),this.setEnv(s.x,s.y,v.Empty),this.clearCoreAt(e,t),this.clearCoreAt(s.x,s.y),this.removeDecorAt(e,t),this.removeDecorAt(s.x,s.y);break;case"asset":{const i=this.assetBrush;if(!i||!this.canPlaceDecor(e,t))return;this.stampDecor(e,t,i),(s.x!==e||s.y!==t)&&this.canPlaceDecor(s.x,s.y)&&this.stampDecor(s.x,s.y,{kind:i.kind,direction:Le(i.direction,c),team:be(i.team)});break}}this.renderAll(),this.notifyMapChange()}setEnv(e,t,n){e>=0&&t>=0&&e<this.mapState.width&&t<this.mapState.height&&(this.mapState.environment[t][e]=n)}canPlaceDecor(e,t){const{width:n,height:o,environment:c}=this.mapState;return!(e<0||t<0||e>=n||t>=o||c[t][e]===v.Wall||this.coreCovers(this.mapState.coreA,e,t)||this.coreCovers(this.mapState.coreB,e,t))}stampDecor(e,t,n){this.removeDecorAt(e,t),this.mapState.decor.push({x:e,y:t,kind:n.kind,direction:n.direction,team:n.team})}removeDecorAt(e,t){this.mapState.decor=this.mapState.decor.filter(n=>n.x!==e||n.y!==t)}coreCovers(e,t,n){if(!e)return!1;const o=t-e.x,c=n-e.y;return o>=0&&o<=1&&c>=0&&c<=1}coreMarginCovers(e,t,n){if(!e)return!1;const o=t-e.x,c=n-e.y;return o>=-1&&o<=2&&c>=-1&&c<=2}isCoreArea(e,t){return this.coreMarginCovers(this.mapState.coreA,e,t)||this.coreMarginCovers(this.mapState.coreB,e,t)}clearCoreAt(e,t){(this.coreCovers(this.mapState.coreA,e,t)||this.coreCovers(this.mapState.coreB,e,t))&&(this.mapState.coreA=null,this.mapState.coreB=null)}clearAreaForCore(e,t){for(let n=-1;n<=2;n++)for(let o=-1;o<=2;o++)this.setEnv(e+o,t+n,v.Empty),this.removeDecorAt(e+o,t+n)}worldToTile(e,t){return this.projection.toTile(e,t,this.mapState.width,this.mapState.height)}updateHover(e){if(this.galleryMode){this.hoveredTile&&(this.hoveredTile=null,this.highlightGraphics.clear(),this.onHoverChange?.(null));return}const t=this.worldToTile(e.worldX,e.worldY),n=this.hoveredTile;if(!(t?.x===n?.x&&t?.y===n?.y)){if(this.hoveredTile=t,t){const o=this.mapState.environment[t.y][t.x];let c=null;this.coreCovers(this.mapState.coreA,t.x,t.y)&&(c=S.A),this.coreCovers(this.mapState.coreB,t.x,t.y)&&(c=S.B);const s=this.mapState.decor.find(i=>i.x===t.x&&i.y===t.y)??null;this.onHoverChange?.({x:t.x,y:t.y,environment:o,hasCore:c,decor:s})}else this.onHoverChange?.(null);this.drawHighlights(),this.updateGhost()}}drawHighlights(){if(this.highlightGraphics.clear(),!this.hoveredTile)return;const{x:e,y:t}=this.hoveredTile,{width:n,height:o,symmetry:c}=this.mapState;if(this.brush==="core_a"){this.strokeTileOutline(e,t,2,me[S.A],.6,3);const s=F(e,t,n,o,c),i=F(e+1,t+1,n,o,c);this.strokeTileOutline(Math.min(s.x,i.x),Math.min(s.y,i.y),2,me[S.B],.6,3)}else{this.strokeTileOutline(e,t,1,16777215,.5,2);const s=F(e,t,n,o,c);this.strokeTileOutline(s.x,s.y,1,16777215,.3,2)}}strokeTileOutline(e,t,n,o,c,s){const i=this.highlightGraphics;if(i.lineStyle(s,o,c),this.renderMode==="iso"){const{x:l,y:d}=this.projection.center(e+(n-1)/2,t+(n-1)/2),h=Te/2*n,x=H/2*n;i.beginPath(),i.moveTo(l,d-x),i.lineTo(l+h,d),i.lineTo(l,d+x),i.lineTo(l-h,d),i.closePath(),i.strokePath()}else{const l=e*A,d=t*A;i.strokeRect(l+2,d+2,A*n-4,A*n-4)}}centerCamera(){const{width:e,height:t}=this.mapState,n=this.cameras.main,{cx:o,cy:c,bboxW:s,bboxH:i}=this.projection.cameraBbox(e,t),l=Math.min(n.width/s,n.height/i)*.9;n.setZoom(l),n.centerOn(o,c)}renderAll(){if(this.galleryMode){this.renderGallery(),this.updateGhost();return}this.renderMap(),this.renderEntities(),this.renderGrid(),this.renderSymmetryLine(),this.updateGhost()}buildGalleryItems(){const e=[],t=(s,i,l=1,d=1)=>{s&&e.push({key:s,label:i,span:l,scale:d})},n=[[S.A,"A"],[S.B,"B"]],o=f.East,c=f.Southeast;t(Be,"wall"),t(Oe,"ore"),t(it,"titanium");for(const[s,i]of n)t(Se(s),`core ${i}`,2,2/3);for(const[s,i]of n)t(ve(s),`harvester ${i}`),t(we(s),`barrier ${i}`),t(Ee(s),`bridge ${i}`),t(Ce(s),`launcher ${i}`);for(const[s,i]of n)t(Ne(o,s),`conv ${i}`);for(const[s,i]of n)t(Ae(o,s),`split ${i}`);for(const[s,i]of n)t(Me(c,s),`builder ${i}`);for(const[s,i]of n)t(je(c,s),`gunner ${i}`);for(const[s,i]of n)t(_e(c,s),`sentinel ${i}`);return e}renderGallery(){this.mapLayer.removeAll(!0),this.entityLayer.removeAll(!0),this.gridGraphics.clear(),this.symmetryGraphics.clear(),this.highlightGraphics.clear();const e=this.buildGalleryItems().sort((T,w)=>w.span-T.span),t=180,n=126,o=(1-he)*160,c=4*t,s=32;let i=0,l=0,d=0,h=0;for(const T of e){const w=T.span,I=w*t,U=w*n,_=(w-1)*(H/2)+o+40,j=s+U+_;i>0&&(i+I>c||w!==h)&&(i=0,l+=d,d=0),h=w,this.renderGalleryCell(i+I/2,l+s+U,T),i+=I,d=Math.max(d,j)}const x=l+d,b=this.cameras.main,y=t*.25,E=b.width/(c+y*2);b.setZoom(E);const M=b.height/E;b.centerOn(c/2,-s+M/2);const L=b.scrollY,R=Math.max(L,x+s-M/2-b.height/2);this.galleryScrollY={min:L,max:R}}renderGalleryCell(e,t,n){const o=n.span,c=[];for(let d=0;d<o;d++)for(let h=0;h<o;h++)c.push({ox:(h-d)*(Te/2),oy:(h+d-(o-1))*(H/2),order:h+d});if(c.sort((d,h)=>d.order-h.order),this.textures.exists(de))for(const d of c){const h=this.add.sprite(e+d.ox,t+d.oy,de);h.setOrigin(.5,he),this.entityLayer.add(h)}const s=!this.textures.exists(n.key);if(s){const d=this.add.rectangle(e,t-24*o,64*o,80*o,16711935,.2);d.setStrokeStyle(1,16711935),this.entityLayer.add(d)}else{const d=this.add.sprite(e,t,n.key);d.setOrigin(.5,Z),n.scale!==1&&d.setScale(n.scale),this.entityLayer.add(d)}const i=t+(o-1)*(H/2)+(1-he)*160+12,l=this.add.text(e,i,n.label,{fontSize:"13px",color:s?"#ff6b6b":"#e8e8e8",fontFamily:"monospace",backgroundColor:"#000000a0",padding:{x:4,y:1}});l.setOrigin(.5,0),this.entityLayer.add(l)}renderMap(){this.mapLayer.removeAll(!0),this.ground.draw({scene:this,mapLayer:this.mapLayer,map:this.mapState,theme:"dark"})}renderGrid(){this.gridGraphics.clear();const{width:e,height:t}=this.mapState,n=this.renderMode==="iso";this.gridGraphics.lineStyle(2,3813416,n?.25:.5);const o=(c,s,i,l)=>{if(n){const d=this.projection.center(c,s),h=this.projection.center(i,l);this.gridGraphics.lineBetween(d.x,d.y-H/2,h.x,h.y-H/2)}else this.gridGraphics.lineBetween(c*A,s*A,i*A,l*A)};for(let c=0;c<=e;c++)o(c,0,c,t);for(let c=0;c<=t;c++)o(0,c,e,c)}renderEntities(){this.entityLayer.removeAll(!0),this.renderMode==="iso"&&this.renderIsoEnvOverlays();for(const n of this.mapState.decor)n.x<0||n.y<0||n.x>=this.mapState.width||n.y>=this.mapState.height||this.addDecorSprite(n,null);const{coreA:e,coreB:t}=this.mapState;e&&this.renderCore(e.x,e.y,S.A),t&&this.renderCore(t.x,t.y,S.B),this.renderMode==="iso"&&this.entityLayer.sort("depth")}isoDecorKey(e){switch(e.kind){case k.BuilderBot:return Me(e.direction,e.team);case k.Gunner:return je(e.direction,e.team);case k.Sentinel:return _e(e.direction,e.team);case k.Conveyor:case k.ArmouredConveyor:return Ne(e.direction,e.team);case k.Splitter:return Ae(e.direction,e.team);case k.Harvester:return ve(e.team);case k.Barrier:return we(e.team);case k.Bridge:return Ee(e.team);case k.Launcher:return Ce(e.team);case"road":return rt(e.team);default:return null}}addDecorSprite(e,t){const{x:n,y:o}=this.projection.center(e.x,e.y),c=this.projection.depth(e.x,e.y);let s=null;if(this.renderMode==="iso"){const i=this.isoDecorKey(e);if(i&&this.textures.exists(i)){const l=this.add.sprite(n,o,i);l.setOrigin(.5,Z),s=l}}else{let i=e.kind==="road"?{key:`road_${e.team===S.A?"gold":"silver"}`,flipX:!1}:nt(e.kind,e.team,e.direction,e.kind===k.BuilderBot?Re(e.direction).facing:void 0);if(i.key&&this.textures.exists(i.key)){const l=this.add.sprite(n,o,i.key),d=Math.min(A/l.frame.width,A/l.frame.height);l.setScale(d);let h=i.flipX;if(e.kind===k.Conveyor||e.kind===k.ArmouredConveyor){const x=st(e.direction);l.setRotation(x.rotation),h=x.flipX}else e.kind===k.BuilderBot&&(h=Re(e.direction).flipX);l.setFlipX(h),s=l}}if(!s){const i=this.add.rectangle(n,o-24,64,80,16711935,.25);i.setStrokeStyle(1,16711935),s=i}s.setDepth(c),t&&(s.setAlpha(t.alpha),t.blocked&&(s instanceof D.GameObjects.Sprite?s.setTint(16733525):(s.setFillStyle(16729156,.3),s.setStrokeStyle(1,16729156))),this.ghostObjects.push(s)),this.entityLayer.add(s)}updateGhost(){if(!this.entityLayer)return;for(const d of this.ghostObjects)d.destroy();if(this.ghostObjects=[],this.galleryMode||this.brush!=="asset"||!this.assetBrush||!this.hoveredTile)return;const{x:e,y:t}=this.hoveredTile,{width:n,height:o,symmetry:c}=this.mapState,s=this.assetBrush,i=(d,h,x,b,y)=>this.mapState.decor.some(E=>E.x===d&&E.y===h&&E.kind===x&&E.direction===b&&E.team===y);i(e,t,s.kind,s.direction,s.team)||this.addDecorSprite({x:e,y:t,kind:s.kind,direction:s.direction,team:s.team},{alpha:.65,blocked:!this.canPlaceDecor(e,t)});const l=F(e,t,n,o,c);if(l.x!==e||l.y!==t){const d=Le(s.direction,c),h=be(s.team);i(l.x,l.y,s.kind,d,h)||this.addDecorSprite({x:l.x,y:l.y,kind:s.kind,direction:d,team:h},{alpha:.4,blocked:!this.canPlaceDecor(l.x,l.y)})}this.renderMode==="iso"&&this.entityLayer.sort("depth")}renderIsoEnvOverlays(){const{width:e,height:t,environment:n}=this.mapState;for(let o=0;o<t;o++)for(let c=0;c<e;c++){const s=n[o][c];let i=null;if(s===v.Wall?i=Be:s===v.OreTitanium&&(i=Oe),!i||!this.textures.exists(i))continue;const{x:l,y:d}=this.projection.center(c,o),h=this.add.sprite(l,d,i);h.setOrigin(.5,Z),h.setDepth(this.projection.depth(c,o)),this.entityLayer.add(h)}}renderCore(e,t,n){const o=n===S.A?"gold":"silver",c=this.renderMode==="iso",{x:s,y:i}=this.projection.center(e+.5,t+.5),l=this.projection.depth(e+1,t+1)+(c?ot:0),d=c?Se(n):null;if(d&&this.textures.exists(d)){const x=this.add.sprite(s,i,d);x.setScale(2/3),x.setOrigin(.5,Z),x.setDepth(l),this.entityLayer.add(x);return}const h=`base_${o}`;if(this.textures.exists(h)){const x=this.add.sprite(s,i,h),b=2*A,y=Math.min(b/x.frame.width,b/x.frame.height);x.setScale(y),x.setDepth(l),this.entityLayer.add(x)}else{const x=me[n],b=this.add.rectangle(s,i,2*A,2*A,x,.7);b.setStrokeStyle(2,x),b.setDepth(l),this.entityLayer.add(b);const y=this.add.text(s,i,n===S.A?"Core A":"Core B",{fontSize:"16px",color:"#ffffff",fontFamily:"monospace"});y.setOrigin(.5),y.setDepth(l),this.entityLayer.add(y)}}renderSymmetryLine(){this.symmetryGraphics.clear();const{width:e,height:t,symmetry:n}=this.mapState;switch(this.symmetryGraphics.lineStyle(3,16736352,.5),n){case"horizontal":{const o=this.projection.corner(e/2,0),c=this.projection.corner(e/2,t);this.symmetryGraphics.lineBetween(o.x,o.y,c.x,c.y);break}case"vertical":{const o=this.projection.corner(0,t/2),c=this.projection.corner(e,t/2);this.symmetryGraphics.lineBetween(o.x,o.y,c.x,c.y);break}case"rotational":{const o=this.projection.center(e/2-.5,t/2-.5);this.symmetryGraphics.fillStyle(16736352,.5),this.symmetryGraphics.fillCircle(o.x,o.y,8);break}}}}function yt(r,e){return{type:D.WEBGL,parent:r,backgroundColor:"#1d150f",scale:{mode:D.Scale.RESIZE,width:"100%",height:"100%"},render:{antialias:!0,antialiasGL:!0,mipmapFilter:"LINEAR_MIPMAP_LINEAR",roundPixels:!0,desynchronized:!1},audio:{noAudio:!0},loader:e?{baseURL:e.endsWith("/")?e:`${e}/`}:void 0,scene:[bt]}}const kt=g.forwardRef(function({assetBaseUrl:e,renderMode:t},n){const o=g.useRef(t),c=g.useRef(null),s=g.useRef(null),i=g.useRef(null),l=g.useRef([]);return g.useImperativeHandle(n,()=>({getScene(){return i.current},whenReady(d){i.current?d(i.current):l.current.push(d)}})),g.useEffect(()=>{if(!c.current||s.current)return;const d=yt(c.current,e),h=new D.Game(d);return s.current=h,h.events.on("ready",()=>{if(s.current!==h)return;const x=h.scene.getScene("MapEditorScene");i.current=x,x.setRenderMode(o.current??W);for(const b of l.current)b(x);l.current=[]}),()=>{s.current?.destroy(!0),s.current=null,i.current=null,l.current=[]}},[]),g.useEffect(()=>{o.current=t,i.current?.setRenderMode(t??W)},[t]),a.jsx("div",{ref:c,className:"h-full w-full"})}),St={rotational:0,horizontal:1,vertical:2},vt={0:"rotational",1:"horizontal",2:"vertical"},wt={nested:{battlecode:{nested:{Map:{fields:{width:{type:"int32",id:1},height:{type:"int32",id:2},rows:{rule:"repeated",type:"TileRow",id:3},cores:{rule:"repeated",type:"CorePosition",id:4},symmetry:{type:"int32",id:5},entities:{rule:"repeated",type:"MapEntity",id:6}}},MapEntity:{fields:{kind:{type:"int32",id:1},position:{type:"Pos",id:2},direction:{type:"int32",id:3},team:{type:"Team",id:4}}},TileRow:{fields:{tiles:{rule:"repeated",type:"Environment",id:1}}},Pos:{fields:{x:{type:"int32",id:1},y:{type:"int32",id:2}}},CorePosition:{fields:{id:{type:"int32",id:1},team:{type:"Team",id:2},position:{type:"Pos",id:3}}},Team:{values:{TEAM_A:0,TEAM_B:1}},Environment:{values:{ENV_EMPTY:0,ENV_WALL:1,ENV_ORE_TITANIUM:2,ENV_ORE_AXIONITE:3}}}}}};let fe=null;function He(){return fe||(fe=at.Root.fromJSON(wt).lookupType("battlecode.Map")),fe}function Et(r){const e=He(),t=[];for(let s=0;s<r.height;s++){const i=[];for(let l=0;l<r.width;l++)i.push(r.environment[s][l]);t.push({tiles:i})}const n=[];r.coreA&&n.push({id:1,team:S.A,position:{x:r.coreA.x,y:r.coreA.y}}),r.coreB&&n.push({id:2,team:S.B,position:{x:r.coreB.x,y:r.coreB.y}});const o=[];for(const s of r.decor??[]){const i=ft(s.kind);i!==void 0&&o.push({kind:i,position:{x:s.x,y:s.y},direction:s.direction,team:s.team})}const c=e.create({width:r.width,height:r.height,rows:t,cores:n,symmetry:St[r.symmetry]??0,entities:o});return e.encode(c).finish()}function Ct(r){const t=He().decode(new Uint8Array(r)),n=t.width,o=t.height,c=vt[t.symmetry]??"rotational",s=$(n,o,c);for(let l=0;l<o;l++){const d=t.rows[l];for(let h=0;h<n;h++)s.environment[l][h]=d?.tiles[h]??0}for(const l of t.cores||[]){const d=l.team,h={x:l.position.x,y:l.position.y};d===S.A?s.coreA=h:s.coreB=h}const i=[];for(const l of t.entities||[]){const d=xt(l.kind);if(d===void 0||!l.position)continue;const h=l.position.x??0,x=l.position.y??0;if(h<0||x<0||h>=n||x>=o)continue;let b=l.direction>=f.Centre&&l.direction<=f.Northwest?l.direction:f.Centre;const y=te(d);y&&(y.dirMode==="none"?b=f.Centre:ne(y.dirMode).includes(b)||(b=$e(y.dirMode)));const E=l.team===S.B?S.B:S.A;i.push({x:h,y:x,kind:d,direction:b,team:E})}return s.decor=i,s}const V=8,q=30,se=[{id:"empty",label:"Empty",hex:"#000000"},{id:"wall",label:"Wall",hex:"#44465E"},{id:"titanium",label:"Titanium Ore",hex:"#5AD4FF"},{id:"core_a",label:"Core (Team A)",hex:"#FFBF40"},{id:"core_b",label:"Core (Team B)",hex:"#6EAAFF"}],Nt=new Map(se.map(r=>[Ut(r.hex),r.id])),At=new Map(se.map(r=>[r.id,Ye(r.hex)])),Mt=["rotational","horizontal","vertical"];async function jt(r){Fe(r.width,r.height);const e=Tt(r),t=re(e,"core_a"),n=re(e,"core_b");if(Math.abs(t.x-n.x)<=2&&Math.abs(t.y-n.y)<=2)throw new Error("Core footprints are too close together (need a 1-tile clear margin).");We(e);const o=document.createElement("canvas");o.width=r.width,o.height=r.height;const c=o.getContext("2d");if(!c)throw new Error("Could not create a canvas context to write the PNG.");const s=c.createImageData(r.width,r.height);return Bt(s.data,e,r.width,r.height),c.putImageData(s,0,0),Ht(o)}async function _t(r){const e=await createImageBitmap(r,{imageOrientation:"none",premultiplyAlpha:"none",colorSpaceConversion:"none"});try{const t=e.width,n=e.height;Fe(t,n);const o=document.createElement("canvas");o.width=t,o.height=n;const c=o.getContext("2d",{willReadFrequently:!0});if(!c)throw new Error("Could not create a canvas context to read the PNG.");c.imageSmoothingEnabled=!1,c.drawImage(e,0,0);const s=c.getImageData(0,0,t,n),i=Ot(s.data,t,n),l=re(i,"core_a"),d=re(i,"core_b");if(Math.abs(l.x-d.x)<=1&&Math.abs(l.y-d.y)<=1)throw new Error("Core footprints are too close together.");const h=We(i),x=$(t,n,h);for(let b=0;b<n;b++)for(let y=0;y<t;y++)x.environment[b][y]=Pt(i[b][y]);return x.coreA=l,x.coreB=d,x}finally{e.close()}}function Fe(r,e){if(r<V||e<V||r>q||e>q)throw new Error(`PNG map size must be between ${V}x${V} and ${q}x${q}; got ${r}x${e}.`)}function Tt(r){if(!r.coreA||!r.coreB)throw new Error("Both teams must have a core before exporting a PNG.");const e=r.environment.map(t=>t.map(Dt));return Ge(e,r.coreA.x,r.coreA.y,"core_a"),Ge(e,r.coreB.x,r.coreB.y,"core_b"),e}function Ge(r,e,t,n){if(e<0||t<0||e+1>=r[0].length||t+1>=r.length)throw new Error(`${ee(n)} must fit fully inside the map bounds.`);for(let o=t;o<=t+1;o++)for(let c=e;c<=e+1;c++)r[o][c]=n}function Bt(r,e,t,n){for(let o=0;o<n;o++)for(let c=0;c<t;c++){const s=At.get(e[o][c]);if(!s)throw new Error(`Unsupported PNG tile at (${c}, ${o}).`);const i=(o*t+c)*4;r[i]=s[0],r[i+1]=s[1],r[i+2]=s[2],r[i+3]=s[3]}}function Ot(r,e,t){const n=[];for(let o=0;o<t;o++){const c=[];for(let s=0;s<e;s++){const i=(o*e+s)*4,l=r[i],d=r[i+1],h=r[i+2],x=r[i+3];if(x!==255)throw new Error(`PNG pixels must be fully opaque; found alpha ${x} at (${s}, ${o}).`);const b=Nt.get(`${l},${d},${h},${x}`);if(!b)throw new Error(`Unsupported PNG colour ${Ft(l,d,h)} at (${s}, ${o}). Use one of the six documented palette colours.`);c.push(b)}n.push(c)}return n}function re(r,e){const t=[];for(let d=0;d<r.length;d++)for(let h=0;h<r[0].length;h++)r[d][h]===e&&t.push({x:h,y:d});if(t.length!==4)throw new Error(`${ee(e)} must be a single solid 2x2 block; found ${t.length} matching pixels.`);const n=t.map(d=>d.x),o=t.map(d=>d.y),c=Math.min(...n),s=Math.max(...n),i=Math.min(...o),l=Math.max(...o);if(s-c!==1||l-i!==1)throw new Error(`${ee(e)} must occupy a contiguous 2x2 block.`);for(let d=i;d<=l;d++)for(let h=c;h<=s;h++)if(r[d][h]!==e)throw new Error(`${ee(e)} must occupy a contiguous 2x2 block.`);return{x:c,y:i}}function We(r){const e=r[0].length,t=r.length,n=Mt.filter(o=>Lt(r,e,t,o));if(n.length===0)throw new Error("PNG map must be rotationally, horizontally, or vertically symmetric.");if(n.length>1)throw new Error(`PNG map matches multiple symmetries (${n.map($t).join(", ")}). Make it unambiguous before importing.`);return n[0]}function Lt(r,e,t,n){for(let o=0;o<t;o++)for(let c=0;c<e;c++){const s=Rt(c,o,e,t,n);if(!It(r[o][c],r[s.y][s.x]))return!1}return!0}function Rt(r,e,t,n,o){switch(o){case"rotational":return{x:t-1-r,y:n-1-e};case"horizontal":return{x:t-1-r,y:e};case"vertical":return{x:r,y:n-1-e}}}function It(r,e){return r===e?!Gt(r):r==="core_a"&&e==="core_b"||r==="core_b"&&e==="core_a"}function Gt(r){return r==="core_a"||r==="core_b"}function Pt(r){switch(r){case"empty":case"core_a":case"core_b":return v.Empty;case"wall":return v.Wall;case"titanium":return v.OreTitanium}}function Dt(r){switch(r){case v.Empty:return"empty";case v.Wall:return"wall";case v.OreTitanium:return"titanium";case v.OreAxionite:throw new Error("axionite ore is disabled — cannot export to PNG")}}function ee(r){return se.find(e=>e.id===r)?.label??r}function $t(r){switch(r){case"rotational":return"rotational";case"horizontal":return"horizontal reflection";case"vertical":return"vertical reflection"}}function Ut(r){return Ye(r).join(",")}function Ye(r){const e=/^#([0-9a-f]{6})$/i.exec(r);if(!e)throw new Error(`Invalid hex colour: ${r}`);const t=e[1];return[parseInt(t.slice(0,2),16),parseInt(t.slice(2,4),16),parseInt(t.slice(4,6),16),255]}function Ht(r){return new Promise((e,t)=>{r.toBlob(n=>{if(n){e(n);return}t(new Error("Failed to encode PNG data."))},"image/png")})}function Ft(r,e,t){return`#${[r,e,t].map(n=>n.toString(16).padStart(2,"0").toUpperCase()).join("")}`}function Wt(r,e){return r?`${r.replace(/\/+$/,"")}/${e}`:`/${e}`}const Yt=[f.Northwest,f.North,f.Northeast,f.West,null,f.East,f.Southwest,f.South,f.Southeast],Kt={[f.North]:"↑",[f.Northeast]:"↗",[f.East]:"→",[f.Southeast]:"↘",[f.South]:"↓",[f.Southwest]:"↙",[f.West]:"←",[f.Northwest]:"↖"},zt=["Units","Logistics","Structures"],J=8,Q=30,Xt=[{id:"wall",label:"Wall",colour:"#44465e",key:"1"},{id:"titanium",label:"Titanium Ore",colour:"#5ad4ff",key:"2"},{id:"core_a",label:"Core (Team A)",colour:"#ffbf40",key:"3"},{id:"eraser",label:"Eraser",colour:"#888888",key:"4"}],Zt=[{id:"rotational",label:"Rotational (180°)"},{id:"horizontal",label:"Horizontal Reflection"},{id:"vertical",label:"Vertical Reflection"}];function Vt(r){return r.replace(/\.(?:map26|pb|png)$/i,"")}function Pe(r){return r.trim()||"custom_map"}function De(r,e){const t=URL.createObjectURL(r),n=document.createElement("a");n.href=t,n.download=e,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(t)}function qt({mapState:r,currentBrush:e,canUndo:t,onBrushChange:n,onMapSizeChange:o,onSymmetryChange:c,onImport:s,onClear:i,onUndo:l,showAssetPalette:d=!1,assetBaseUrl:h,assetTeam:x,assetBrush:b,onAssetSelect:y,onAssetDirectionChange:E,onAssetTeamChange:M}){const[L,R]=g.useState(r.width.toString()),[T,w]=g.useState(r.height.toString()),[I,U]=g.useState(new Set);g.useEffect(()=>{R(r.width.toString()),w(r.height.toString())},[r.width,r.height]);const[_,j]=g.useState("custom_map"),z=g.useRef(null),Y=g.useCallback(()=>{const m=parseInt(L,10),u=parseInt(T,10);isNaN(m)||isNaN(u)||m<J||u<J||m>Q||u>Q||o(m,u)},[L,T,o]),K=g.useCallback(()=>{const m=Et(r),u=new Blob([m.slice().buffer],{type:"application/octet-stream"});De(u,`${Pe(_)}.map26`)},[r,_]),oe=g.useCallback(()=>{(async()=>{try{const m=await jt(r);De(m,`${Pe(_)}.png`)}catch(m){ue.error("Failed to export PNG map:",m),alert(m instanceof Error?m.message:"Failed to export PNG map. Make sure the map uses a single valid symmetry and both cores are placed.")}})()},[r,_]),ie=g.useCallback(()=>{z.current?.click()},[]),ae=g.useCallback(m=>{const u=m.target,p=u.files?.[0];if(!p)return;const C=p.name.toLowerCase(),N=C.endsWith(".map26")||C.endsWith(".pb"),B=C.endsWith(".png")||p.type==="image/png";if(!N&&!B){alert(`Invalid file: expected a .map26, .pb, or .png file, got "${p.name}".`),u.value="";return}const X=Vt(p.name)||"custom_map";if(u.value="",B){(async()=>{try{const P=await _t(p);s(P),j(X)}catch(P){ue.error("Failed to import PNG map:",P),alert(P instanceof Error?P.message:"Failed to import PNG map. Make sure it uses the documented palette and core layout.")}})();return}const ce=new FileReader;ce.addEventListener("load",()=>{const P=ce.result;try{const le=Ct(P);s(le),j(X)}catch(le){ue.error("Failed to import map:",le),alert("Failed to import map file. Make sure it's a valid .map26 or .pb map file.")}}),ce.readAsArrayBuffer(p)},[s]),G=r.coreA===null&&r.coreB===null&&r.decor.length===0&&r.environment.every(m=>m.every(u=>u===0));return a.jsxs("aside",{className:"flex h-full w-64 flex-shrink-0 flex-col gap-4 overflow-y-auto p-4",children:[a.jsxs("section",{children:[a.jsx("h2",{className:"mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:"Map Size"}),a.jsxs("div",{className:"rounded-xl border border-border bg-card p-3 dark:bg-[#111111]",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsxs("label",{className:"flex flex-col gap-1 text-[11px] text-muted-foreground",children:["Width",a.jsx("input",{type:"number","aria-label":"Width",min:J,max:Q,value:L,onChange:m=>R(m.target.value),disabled:!G,className:"w-16 rounded bg-muted px-2 py-1 text-xs text-foreground outline-none ring-1 ring-black/10 focus:ring-[#ffbf40] disabled:opacity-40 dark:bg-[#1c1c1c] dark:ring-white/15 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"})]}),a.jsx("span",{className:"mt-4 text-muted-foreground",children:"x"}),a.jsxs("label",{className:"flex flex-col gap-1 text-[11px] text-muted-foreground",children:["Height",a.jsx("input",{type:"number","aria-label":"Height",min:J,max:Q,value:T,onChange:m=>w(m.target.value),disabled:!G,className:"w-16 rounded bg-muted px-2 py-1 text-xs text-foreground outline-none ring-1 ring-black/10 focus:ring-[#ffbf40] disabled:opacity-40 dark:bg-[#1c1c1c] dark:ring-white/15 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"})]})]}),a.jsx("button",{className:"mt-2 w-full rounded-lg bg-muted px-3 py-1.5 text-xs font-medium text-muted-foreground transition-all hover:bg-muted/70 hover:text-foreground disabled:opacity-40 dark:bg-[#1c1c1c] dark:hover:bg-[#262626]",onClick:Y,disabled:!G,children:"Apply Size"}),a.jsx("button",{className:"mt-1.5 w-full rounded-lg bg-red-100 px-3 py-1.5 text-xs font-medium text-red-500 transition-all hover:bg-red-200 hover:text-red-600 disabled:opacity-40 dark:bg-[#3a1520] dark:text-[#ff6b6b] dark:hover:bg-[#4a1a28] dark:hover:text-[#ff8888]",onClick:i,disabled:G,children:"Clear Map"}),a.jsxs("button",{className:"mt-1.5 w-full rounded-lg bg-muted px-3 py-1.5 text-xs font-medium text-muted-foreground transition-all hover:bg-muted/70 hover:text-foreground disabled:opacity-40 dark:bg-[#1c1c1c] dark:hover:bg-[#262626]",onClick:l,disabled:!t,children:["Undo",a.jsx("kbd",{className:"ml-2 rounded bg-gray-200 px-1.5 py-0.5 text-[10px] text-muted-foreground dark:bg-[#0a0a0a] dark:text-[#484848]",children:"Ctrl+Z"})]})]})]}),a.jsxs("section",{children:[a.jsx("h2",{className:"mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:"Symmetry"}),a.jsx("div",{className:"rounded-xl border border-border bg-card p-3 dark:bg-[#111111]",children:a.jsx("div",{className:"flex flex-col gap-1.5",children:Zt.map(m=>a.jsxs("button",{type:"button",onClick:()=>c(m.id),disabled:!G,className:`flex items-center gap-2 rounded-lg px-2 py-1.5 text-xs text-left transition-all select-none ${r.symmetry===m.id?"bg-muted text-[#ffbf40] ring-1 ring-[#ffbf40]/30 dark:bg-[#1c1c1c]":"text-muted-foreground hover:bg-muted/50 dark:hover:bg-[#1c1c1c]/50"} disabled:opacity-40 disabled:pointer-events-none`,children:[a.jsx("span",{className:`inline-block h-3 w-3 rounded-full border-2 ${r.symmetry===m.id?"border-[#ffbf40] bg-[#ffbf40]":"border-[#7a6a50] bg-transparent"}`}),m.label]},m.id))})})]}),a.jsxs("section",{children:[a.jsx("h2",{className:"mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:"Brush Tool"}),a.jsxs("div",{className:"rounded-xl border border-border bg-card p-3 dark:bg-[#111111]",children:[a.jsx("div",{className:"flex flex-col gap-1",children:Xt.map(m=>a.jsxs("button",{className:`flex items-center gap-2 rounded-lg px-2 py-1.5 text-left text-xs transition-all ${e===m.id?"bg-muted text-foreground ring-1 ring-[#ffbf40]/40 dark:bg-[#1c1c1c]":"text-muted-foreground hover:bg-muted/50 hover:text-foreground dark:hover:bg-[#1c1c1c]/50"}`,onClick:()=>n(m.id),children:[a.jsx("span",{className:"inline-block h-3 w-3 rounded-sm",style:{backgroundColor:m.colour}}),a.jsx("span",{className:"flex-1",children:m.label}),a.jsx("kbd",{className:"rounded bg-gray-200 px-1.5 py-0.5 text-[10px] text-muted-foreground dark:bg-[#0a0a0a] dark:text-[#484848]",children:m.key})]},m.id))}),a.jsx("p",{className:"mt-2 text-[10px] text-muted-foreground/60 dark:text-[#484848]",children:"Left click to paint. Right click to pan."})]})]}),d&&a.jsxs("section",{children:[a.jsx("h2",{className:"mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:"Assets"}),a.jsxs("div",{className:"rounded-xl border border-border bg-card p-3 dark:bg-[#111111]",children:[a.jsx("div",{className:"mb-2 flex gap-0.5 rounded-lg bg-muted p-0.5 dark:bg-[#1c1c1c]",children:[[S.A,"Gold","#ffbf40"],[S.B,"Silver","#6eaaff"]].map(([m,u,p])=>a.jsxs("button",{type:"button",onClick:()=>M(m),className:`flex-1 rounded-md px-2 py-1 text-[11px] font-medium transition-colors ${x===m?"bg-card text-foreground shadow-sm dark:bg-[#2a2a2a]":"text-muted-foreground hover:text-foreground"}`,children:[a.jsx("span",{className:"mr-1.5 inline-block h-2 w-2 rounded-full",style:{backgroundColor:p}}),u]},u))}),zt.map(m=>{const u=ge.filter(p=>p.category===m);return u.length===0?null:a.jsxs("div",{className:"mb-2",children:[a.jsx("div",{className:"mb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/60 dark:text-[#484848]",children:m}),a.jsx("div",{className:"grid grid-cols-4 gap-1",children:u.map(p=>{const C=e==="asset"&&b?.kind===p.kind,N=Wt(h,p.thumb(x));return a.jsx("button",{type:"button",title:p.label,onClick:()=>y(p.kind),className:`flex aspect-square items-center justify-center overflow-hidden rounded-lg p-1 transition-all ${C?"bg-muted ring-2 ring-[#ffbf40]/70 dark:bg-[#1c1c1c]":"bg-muted/40 hover:bg-muted dark:bg-[#1c1c1c]/40 dark:hover:bg-[#1c1c1c]"}`,children:I.has(N)?a.jsx("span",{className:"text-[9px] leading-tight text-muted-foreground",children:p.label}):a.jsx("img",{src:N,alt:p.label,className:"max-h-full max-w-full object-contain",draggable:!1,onError:()=>U(B=>new Set(B).add(N))})},p.kind)})})]},m)}),e==="asset"&&b&&(()=>{const m=ge.find(p=>p.kind===b.kind);if(!m||m.dirMode==="none")return null;const u=m.dirMode==="cardinal4";return a.jsxs("div",{className:"mt-2 border-t border-border pt-2",children:[a.jsxs("div",{className:"mb-1 flex items-center justify-between",children:[a.jsx("span",{className:"text-[10px] font-medium uppercase tracking-wider text-muted-foreground/60 dark:text-[#484848]",children:"Facing"}),a.jsxs("span",{className:"text-[10px] text-muted-foreground/60 dark:text-[#484848]",children:[a.jsx("kbd",{className:"rounded bg-gray-200 px-1 py-0.5 text-[9px] dark:bg-[#0a0a0a]",children:"R"})," ","rotate"]})]}),a.jsx("div",{className:"mx-auto grid w-fit grid-cols-3 gap-0.5",children:Yt.map((p,C)=>{if(p===null)return a.jsx("span",{className:"flex h-7 w-7 items-center justify-center text-[10px] text-muted-foreground/40",children:"·"},C);const N=p%2===0,B=u&&N,X=b.direction===p;return a.jsx("button",{type:"button",disabled:B,onClick:()=>E(p),className:`flex h-7 w-7 items-center justify-center rounded text-sm transition-colors ${X?"bg-[#ffbf40] text-black":B?"text-muted-foreground/20":"bg-muted/40 text-muted-foreground hover:bg-muted hover:text-foreground dark:bg-[#1c1c1c]/40 dark:hover:bg-[#1c1c1c]"}`,children:Kt[p]},C)})})]})})(),a.jsx("p",{className:"mt-2 text-[10px] leading-4 text-muted-foreground/60 dark:text-[#484848]",children:"Painted assets mirror with swapped team + reflected facing. They're saved in .map26 exports (the engine ignores them) but not in PNG exports."})]})]}),a.jsxs("section",{children:[a.jsx("h2",{className:"mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:"File"}),a.jsxs("div",{className:"flex flex-col gap-2",children:[a.jsx("button",{className:"w-full rounded-xl border border-border bg-card px-3 py-2.5 text-xs font-medium text-muted-foreground transition-all hover:border-[#ffbf40]/30 hover:bg-muted hover:text-foreground dark:bg-[#111111] dark:hover:bg-[#1c1c1c]",onClick:ie,children:"Import Map File"}),a.jsx("input",{ref:z,type:"file",accept:".map26,.pb,.png,image/png,application/x-protobuf,application/octet-stream","aria-label":"Import map file",className:"hidden",onChange:ae}),a.jsx("p",{className:"text-[10px] text-muted-foreground/60 dark:text-[#484848]",children:"Accepts .map26, .pb, and .png files."}),a.jsxs("div",{className:"flex items-center gap-1",children:[a.jsx("input",{type:"text","aria-label":"File name",value:_,onChange:m=>j(m.target.value),placeholder:"filename",className:"min-w-0 flex-1 rounded-lg border border-border bg-card px-2 py-2 text-xs text-foreground outline-none focus:border-[#ffbf40]/50 dark:bg-[#111111]"}),a.jsx("span",{className:"flex-shrink-0 text-xs text-muted-foreground/60 dark:text-[#484848]",children:"base name"})]}),(r.coreA===null||r.coreB===null)&&a.jsx("p",{className:"text-[10px] text-[#ff6b6b]",children:"Place a core (brush 4) to enable export. Cores are 2x2 with a 1-tile clear margin — walls and ore can't sit against them."}),a.jsx("button",{className:"w-full rounded-xl border border-[#ffbf40]/30 bg-amber-50 px-3 py-2.5 text-xs font-medium text-[#ffbf40] transition-all hover:bg-amber-100 hover:text-[#ffa800] disabled:opacity-40 dark:bg-[#0d0d0d] dark:hover:bg-[#1c1c1c]",onClick:K,disabled:r.coreA===null||r.coreB===null,title:r.coreA===null||r.coreB===null?"Both teams must have a core to export":void 0,children:"Export Map (.map26)"}),a.jsx("button",{className:"w-full rounded-xl border border-[#6eaaff]/30 bg-blue-50 px-3 py-2.5 text-xs font-medium text-[#6eaaff] transition-all hover:bg-blue-100 hover:text-[#8ec2ff] disabled:opacity-40 dark:bg-[#182032] dark:hover:bg-[#1d2740]",onClick:oe,disabled:r.coreA===null||r.coreB===null,title:r.coreA===null||r.coreB===null?"Both teams must have a core to export":"Exports a 1 pixel per tile PNG using the import palette",children:"Export Map (.png)"})]})]}),a.jsxs("section",{children:[a.jsx("h2",{className:"mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground",children:"PNG Palette"}),a.jsxs("div",{className:"rounded-xl border border-border bg-card p-3 dark:bg-[#111111]",children:[a.jsx("p",{className:"text-[10px] leading-4 text-muted-foreground/60 dark:text-[#484848]",children:"PNG imports and exports use 1 pixel = 1 tile. Team A and Team B cores must each be a solid 2x2 block, and the map must have exactly one valid symmetry."}),a.jsx("div",{className:"mt-2 flex flex-col gap-1.5",children:se.map(m=>a.jsxs("div",{className:"flex items-center gap-2 rounded-lg bg-muted/50 px-2 py-1.5 text-xs text-muted-foreground dark:bg-[#1c1c1c]/50",children:[a.jsx("span",{className:"inline-block h-3 w-3 flex-shrink-0 rounded-sm border border-black/20 dark:border-white/20",style:{backgroundColor:m.hex}}),a.jsx("span",{className:"min-w-0 flex-1",children:m.label}),a.jsx("code",{className:"text-[10px] text-muted-foreground/60 dark:text-[#484848]",children:m.hex})]},m.id))})]})]})]})}const Jt={[v.Empty]:"Empty",[v.Wall]:"Wall",[v.OreTitanium]:"Titanium Ore",[v.OreAxionite]:"Axionite Ore"},xe={[S.A]:{label:"Team Gold (A)",colour:"#ffbf40"},[S.B]:{label:"Team Silver (B)",colour:"#6eaaff"}};function Qt({hoveredTile:r,showAssetShortcuts:e=!1}){return a.jsxs("aside",{className:"flex h-full w-64 flex-shrink-0 flex-col gap-4 overflow-y-auto p-4",children:[a.jsxs("section",{className:"rounded-xl border border-border bg-card p-3 dark:bg-[#111111]",children:[a.jsx("h3",{className:"mb-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground",children:"Hovered Tile"}),r?a.jsx("div",{className:"flex flex-col gap-1.5 text-xs",children:a.jsxs("div",{className:"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-[11px]",children:[a.jsx("span",{className:"text-muted-foreground",children:"Position"}),a.jsxs("span",{className:"text-muted-foreground",children:["(",r.x,", ",r.y,")"]}),a.jsx("span",{className:"text-muted-foreground",children:"Terrain"}),a.jsx("span",{className:"text-muted-foreground",children:Jt[r.environment]??"Unknown"}),r.hasCore!==null&&a.jsxs(a.Fragment,{children:[a.jsx("span",{className:"text-muted-foreground",children:"Core"}),a.jsx("span",{style:{color:xe[r.hasCore].colour},children:xe[r.hasCore].label})]}),r.decor&&a.jsxs(a.Fragment,{children:[a.jsx("span",{className:"text-muted-foreground",children:"Asset"}),a.jsxs("span",{style:{color:xe[r.decor.team].colour},children:[te(r.decor.kind)?.label??r.decor.kind,r.decor.direction!==f.Centre&&` (${gt[r.decor.direction]})`]})]})]})}):a.jsx("div",{className:"text-xs text-muted-foreground/60 italic dark:text-[#484848]",children:"Hover over a tile to see info"})]}),a.jsxs("section",{className:"rounded-xl border border-border bg-card p-3 dark:bg-[#111111]",children:[a.jsx("h3",{className:"mb-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground",children:"Keyboard Shortcuts"}),a.jsxs("div",{className:"flex flex-col gap-1 text-[11px]",children:[[["1","Wall brush"],["2","Titanium ore brush"],["3","Core brush"],["4","Eraser"],...e?[["R","Rotate asset facing"],["T","Swap asset team"]]:[]].map(([t,n])=>a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("kbd",{className:"rounded bg-gray-200 px-1.5 py-0.5 text-[10px] text-muted-foreground dark:bg-[#0a0a0a] dark:text-[#484848]",children:t}),a.jsx("span",{className:"text-muted-foreground",children:n})]},t)),a.jsxs("div",{className:"mt-1 border-t border-border pt-1",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("kbd",{className:"rounded bg-gray-200 px-1.5 py-0.5 text-[10px] text-muted-foreground dark:bg-[#0a0a0a] dark:text-[#484848]",children:"Ctrl+Z"}),a.jsx("span",{className:"text-muted-foreground",children:"Undo"})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("kbd",{className:"rounded bg-gray-200 px-1.5 py-0.5 text-[10px] text-muted-foreground dark:bg-[#0a0a0a] dark:text-[#484848]",children:"Right drag"}),a.jsx("span",{className:"text-muted-foreground",children:"Pan camera"})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("kbd",{className:"rounded bg-gray-200 px-1.5 py-0.5 text-[10px] text-muted-foreground dark:bg-[#0a0a0a] dark:text-[#484848]",children:"Scroll"}),a.jsx("span",{className:"text-muted-foreground",children:"Zoom"})]})]})]})]})]})}const er={1:"wall",2:"titanium",3:"core_a",4:"eraser"};function tr({assetBaseUrl:r,showHeader:e=!0,renderMode:t,isAdmin:n=!1}={}){const o=g.useRef(null),[c,s]=g.useState(()=>$(20,20,"rotational")),[i,l]=g.useState("wall"),[d,h]=g.useState(null),[x,b]=g.useState(!1),[y,E]=g.useState(null),[M,L]=g.useState(S.A),[R,T]=g.useState(t??W),[w,I]=g.useState(!1),U=g.useCallback(()=>{const u=!w;I(u),o.current?.getScene()?.setGalleryMode(u)},[w]);g.useEffect(()=>{o.current?.whenReady(u=>{u.setOnHoverChange(h),u.setOnMapChange(s),u.setOnUndoStackChange(b),s(u.getMapState()),b(u.canUndo())})},[]);const _=g.useCallback(u=>{l(u),o.current?.getScene()?.setBrush(u)},[]),j=g.useCallback((u,p)=>{l("asset"),o.current?.getScene()?.setAssetBrush({...u,team:p})},[]),z=g.useCallback(u=>{const p=te(u);if(!p)return;const C=ne(p.dirMode),N=y&&C.includes(y.direction)?y.direction:$e(p.dirMode),B={kind:u,direction:N};E(B),j(B,M)},[y,M,j]),Y=g.useCallback(u=>{if(!y)return;const p={...y,direction:u};E(p),j(p,M)},[y,M,j]),K=g.useCallback(u=>{L(u),y&&i==="asset"&&j(y,u)},[y,i,j]),oe=g.useCallback((u,p)=>{o.current?.getScene()?.setMapSize(u,p)},[]),ie=g.useCallback(u=>{o.current?.getScene()?.setSymmetry(u)},[]),ae=g.useCallback(u=>{o.current?.getScene()?.loadMap(u)},[]),G=g.useCallback(()=>{o.current?.getScene()?.clearMap()},[]),m=g.useCallback(()=>{o.current?.getScene()?.undo()},[]);return g.useEffect(()=>{const u=p=>{if(p.target instanceof HTMLInputElement||p.target instanceof HTMLTextAreaElement)return;if((p.ctrlKey||p.metaKey)&&p.key==="z"){p.preventDefault(),m();return}if(i==="asset"&&y&&(p.key==="r"||p.key==="R")){const N=te(y.kind);N&&N.dirMode!=="none"&&(p.preventDefault(),Y(mt(y.direction,N.dirMode,p.shiftKey?-1:1)));return}if(i==="asset"&&y&&(p.key==="t"||p.key==="T")){p.preventDefault(),K(be(M));return}const C=er[p.key];C&&_(C)};return window.addEventListener("keydown",u),()=>window.removeEventListener("keydown",u)},[_,m,i,y,M,Y,K]),a.jsxs("div",{className:"flex h-screen w-screen flex-col bg-background",children:[e&&a.jsx("header",{className:"flex flex-shrink-0 items-center justify-between px-6 py-4",children:a.jsxs("div",{className:"flex items-center gap-4",children:[a.jsx(ct,{}),a.jsx("span",{className:"rounded-lg bg-muted px-3 py-1 text-sm font-semibold text-[#ffbf40] dark:bg-[#1c1c1c]",children:"Map Editor"})]})}),a.jsxs("main",{className:"flex min-h-0 flex-1 gap-2 px-4 pb-4",children:[a.jsx(qt,{mapState:c,currentBrush:i,canUndo:x,onBrushChange:_,onMapSizeChange:oe,onSymmetryChange:ie,onImport:ae,onClear:G,onUndo:m,showAssetPalette:n,assetBaseUrl:r,assetTeam:M,assetBrush:y,onAssetSelect:z,onAssetDirectionChange:Y,onAssetTeamChange:K}),a.jsx("div",{className:"flex min-w-0 flex-1 flex-col gap-2",children:a.jsxs("div",{className:"relative min-h-0 flex-1 overflow-hidden rounded-2xl border border-border",children:[a.jsx(kt,{ref:o,assetBaseUrl:r,renderMode:R}),n&&a.jsx("button",{type:"button",onClick:U,title:"Admin: browse every asset sprite at once",className:`absolute left-3 top-3 rounded-md px-2.5 py-1 text-xs font-medium backdrop-blur transition-colors ${w?"bg-[#ffbf40] text-black":"bg-black/40 text-white/70 hover:text-white"}`,children:w?"Exit Gallery":"Asset Gallery"}),!w&&a.jsx("div",{className:"absolute right-3 top-3 flex gap-0.5 rounded-md bg-black/40 p-0.5 backdrop-blur",children:["iso","square"].map(u=>a.jsx("button",{type:"button",onClick:()=>T(u),className:`rounded px-2.5 py-1 text-xs font-medium capitalize transition-colors ${R===u?"bg-[#ffbf40] text-black":"text-white/70 hover:text-white"}`,children:u},u))})]})}),a.jsx(Qt,{hoveredTile:d,showAssetShortcuts:n})]})]})}const Ke=new URLSearchParams(window.location.search),rr=Ke.get("assetBaseUrl")??void 0,nr=lt(Ke.get("render"));dt.createRoot(document.getElementById("root")).render(a.jsx(g.StrictMode,{children:a.jsx(tr,{assetBaseUrl:rr,renderMode:nr})}));
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Florent Code League Replay Viewer</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
background: #000000;
|
|
11
|
+
}
|
|
12
|
+
</style>
|
|
13
|
+
<script type="module" crossorigin src="/assets/main-COIx42iq.js"></script>
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/app-CK52NxpR.js">
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/app-BiRa_5u6.css">
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<div id="root"></div>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Florent Code League Map Editor</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
background: #000000;
|
|
11
|
+
}
|
|
12
|
+
</style>
|
|
13
|
+
<script type="module" crossorigin src="/assets/map-editor-BDLYjgel.js"></script>
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/app-CK52NxpR.js">
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/app-BiRa_5u6.css">
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<div id="root"></div>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|