diff --git a/res/ui/building_icons/virtual_processor.png b/res/ui/building_icons/virtual_processor.png new file mode 100644 index 00000000..f5471999 Binary files /dev/null and b/res/ui/building_icons/virtual_processor.png differ diff --git a/res_built/atlas/atlas0_hq.json b/res_built/atlas/atlas0_hq.json index 2aa01927..886f57c6 100644 --- a/res_built/atlas/atlas0_hq.json +++ b/res_built/atlas/atlas0_hq.json @@ -1,1308 +1,1388 @@ -{"frames": { - -"sprites/belt/built/forward_0.png": -{ - "frame": {"x":440,"y":742,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_1.png": -{ - "frame": {"x":1925,"y":1008,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_2.png": -{ - "frame": {"x":1540,"y":1139,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_3.png": -{ - "frame": {"x":1803,"y":1118,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_4.png": -{ - "frame": {"x":1923,"y":1156,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_5.png": -{ - "frame": {"x":1801,"y":1266,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_6.png": -{ - "frame": {"x":1921,"y":1304,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_7.png": -{ - "frame": {"x":432,"y":1334,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_8.png": -{ - "frame": {"x":430,"y":1482,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_9.png": -{ - "frame": {"x":141,"y":1877,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_10.png": -{ - "frame": {"x":438,"y":890,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_11.png": -{ - "frame": {"x":438,"y":1038,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_12.png": -{ - "frame": {"x":1542,"y":991,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/forward_13.png": -{ - "frame": {"x":437,"y":1186,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_0.png": -{ - "frame": {"x":145,"y":1475,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_1.png": -{ - "frame": {"x":3,"y":1575,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_2.png": -{ - "frame": {"x":279,"y":1493,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_3.png": -{ - "frame": {"x":137,"y":1609,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_4.png": -{ - "frame": {"x":3,"y":1709,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_5.png": -{ - "frame": {"x":271,"y":1627,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_6.png": -{ - "frame": {"x":137,"y":1743,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_7.png": -{ - "frame": {"x":3,"y":1843,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_8.png": -{ - "frame": {"x":1379,"y":1274,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_9.png": -{ - "frame": {"x":1513,"y":1287,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_10.png": -{ - "frame": {"x":1076,"y":1288,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_11.png": -{ - "frame": {"x":927,"y":1295,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_12.png": -{ - "frame": {"x":786,"y":1363,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/left_13.png": -{ - "frame": {"x":552,"y":1416,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_0.png": -{ - "frame": {"x":1647,"y":1294,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_1.png": -{ - "frame": {"x":1781,"y":1414,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_2.png": -{ - "frame": {"x":1344,"y":1408,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_3.png": -{ - "frame": {"x":1195,"y":1520,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_4.png": -{ - "frame": {"x":1054,"y":1556,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_5.png": -{ - "frame": {"x":1478,"y":1421,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_6.png": -{ - "frame": {"x":1329,"y":1542,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_7.png": -{ - "frame": {"x":1188,"y":1654,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_8.png": -{ - "frame": {"x":1612,"y":1428,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_9.png": -{ - "frame": {"x":1463,"y":1555,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_10.png": -{ - "frame": {"x":1915,"y":1452,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_11.png": -{ - "frame": {"x":1210,"y":1386,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_12.png": -{ - "frame": {"x":1061,"y":1422,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/belt/built/right_13.png": -{ - "frame": {"x":920,"y":1429,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":1322,"y":1676,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":1746,"y":1548,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":261,"y":1877,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/constant_signal.png": -{ - "frame": {"x":1937,"y":759,"w":105,"h":127}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":105,"h":127}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":151,"w":548,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":548,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":847,"y":298,"w":256,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/display.png": -{ - "frame": {"x":1597,"y":1562,"w":128,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":8,"w":128,"h":136}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/filter.png": -{ - "frame": {"x":1107,"y":556,"w":268,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":16,"y":0,"w":268,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/lever.png": -{ - "frame": {"x":1823,"y":732,"w":110,"h":116}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":17,"w":110,"h":116}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/logic_gate-not.png": -{ - "frame": {"x":1545,"y":843,"w":123,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":123,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/logic_gate-or.png": -{ - "frame": {"x":560,"y":888,"w":144,"h":123}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":123}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/logic_gate-transistor.png": -{ - "frame": {"x":1820,"y":970,"w":101,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":101,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/logic_gate-xor.png": -{ - "frame": {"x":1101,"y":852,"w":144,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/logic_gate.png": -{ - "frame": {"x":824,"y":885,"w":144,"h":133}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":133}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":150,"y":1035,"w":136,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":150,"y":1182,"w":136,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":1676,"y":584,"w":261,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":1683,"y":3,"w":288,"h":287}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":555,"y":298,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":3,"y":3,"w":560,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":3,"y":299,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":3,"y":1035,"w":143,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":1396,"y":979,"w":142,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":142,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":290,"y":1060,"w":143,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":1249,"y":988,"w":142,"h":138}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":1094,"y":1146,"w":139,"h":138}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":295,"y":299,"w":256,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":295,"y":594,"w":261,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":847,"y":593,"w":250,"h":288}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":21,"y":0,"w":250,"h":288}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":292,"y":742,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":3,"y":1330,"w":138,"h":125}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":3,"y":1459,"w":138,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":558,"y":1185,"w":139,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":1237,"y":1270,"w":138,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire-cross.png": -{ - "frame": {"x":3,"y":887,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire-split.png": -{ - "frame": {"x":801,"y":1022,"w":144,"h":82}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":62,"w":144,"h":82}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire-turn.png": -{ - "frame": {"x":706,"y":1036,"w":82,"h":82}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":62,"y":62,"w":82,"h":82}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire.png": -{ - "frame": {"x":1107,"y":151,"w":20,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":62,"y":0,"w":20,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_tunnel-coating.png": -{ - "frame": {"x":255,"y":677,"w":33,"h":135}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":55,"y":4,"w":33,"h":135}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_tunnel.png": -{ - "frame": {"x":290,"y":1208,"w":138,"h":135}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":138,"h":135}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":145,"y":1475,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":1647,"y":1294,"w":130,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":440,"y":742,"w":116,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/constant_signal.png": -{ - "frame": {"x":1941,"y":628,"w":104,"h":127}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":104,"h":127}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":555,"y":151,"w":548,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":548,"h":143}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":847,"y":446,"w":256,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/display.png": -{ - "frame": {"x":1545,"y":704,"w":126,"h":135}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":126,"h":135}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/filter.png": -{ - "frame": {"x":1379,"y":556,"w":267,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":267,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":1131,"y":3,"w":548,"h":549}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":16,"w":548,"h":549}, - "sourceSize": {"w":576,"h":576} -}, -"sprites/buildings/lever.png": -{ - "frame": {"x":1823,"y":852,"w":109,"h":114}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":18,"y":18,"w":109,"h":114}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/logic_gate-not.png": -{ - "frame": {"x":972,"y":885,"w":122,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":12,"y":0,"w":122,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/logic_gate-or.png": -{ - "frame": {"x":1396,"y":852,"w":143,"h":123}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":123}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/logic_gate-transistor.png": -{ - "frame": {"x":151,"y":887,"w":100,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":100,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/logic_gate-xor.png": -{ - "frame": {"x":3,"y":1183,"w":143,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/logic_gate.png": -{ - "frame": {"x":1249,"y":852,"w":143,"h":132}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":132}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":150,"y":1329,"w":136,"h":142}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":290,"y":1347,"w":136,"h":142}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":560,"y":594,"w":260,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":1683,"y":294,"w":288,"h":286}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":555,"y":446,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":567,"y":3,"w":560,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":3,"y":447,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":1098,"y":999,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":949,"y":1033,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":1395,"y":1127,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":1243,"y":1130,"w":141,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":792,"y":1108,"w":139,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":295,"y":447,"w":256,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":560,"y":741,"w":260,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":3,"y":595,"w":248,"h":288}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":22,"y":0,"w":248,"h":288}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":1101,"y":704,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":1660,"y":1166,"w":137,"h":124}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":935,"y":1180,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":786,"y":1248,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":557,"y":1301,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire-cross.png": -{ - "frame": {"x":1249,"y":704,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire-split.png": -{ - "frame": {"x":290,"y":890,"w":144,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire-turn.png": -{ - "frame": {"x":706,"y":1122,"w":81,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire.png": -{ - "frame": {"x":2027,"y":184,"w":18,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_tunnel-coating.png": -{ - "frame": {"x":255,"y":816,"w":31,"h":134}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":56,"y":5,"w":31,"h":134}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_tunnel.png": -{ - "frame": {"x":1662,"y":1028,"w":137,"h":134}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":137,"h":134}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":1107,"y":447,"w":12,"h":12}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, - "sourceSize": {"w":12,"h":12} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":1107,"y":463,"w":12,"h":12}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, - "sourceSize": {"w":12,"h":12} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":1975,"y":184,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":255,"y":638,"w":35,"h":35}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":35,"h":35}, - "sourceSize": {"w":39,"h":39} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":255,"y":595,"w":35,"h":39}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":35,"h":39}, - "sourceSize": {"w":39,"h":39} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":708,"y":988,"w":89,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, - "sourceSize": {"w":90,"h":45} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":48,"y":1977,"w":38,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/boolean_false.png": -{ - "frame": {"x":255,"y":954,"w":31,"h":41}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":5,"w":31,"h":41}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/boolean_true.png": -{ - "frame": {"x":1650,"y":556,"w":22,"h":41}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":5,"w":22,"h":41}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/display/blue.png": -{ - "frame": {"x":1975,"y":288,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, - "sourceSize": {"w":49,"h":49} -}, -"sprites/wires/display/cyan.png": -{ - "frame": {"x":1975,"y":339,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, - "sourceSize": {"w":49,"h":49} -}, -"sprites/wires/display/green.png": -{ - "frame": {"x":1975,"y":390,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, - "sourceSize": {"w":49,"h":49} -}, -"sprites/wires/display/purple.png": -{ - "frame": {"x":1975,"y":441,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, - "sourceSize": {"w":49,"h":49} -}, -"sprites/wires/display/red.png": -{ - "frame": {"x":1975,"y":492,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, - "sourceSize": {"w":49,"h":49} -}, -"sprites/wires/display/white.png": -{ - "frame": {"x":1975,"y":543,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, - "sourceSize": {"w":49,"h":49} -}, -"sprites/wires/display/yellow.png": -{ - "frame": {"x":90,"y":1977,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, - "sourceSize": {"w":49,"h":49} -}, -"sprites/wires/lever_on.png": -{ - "frame": {"x":1936,"y":890,"w":109,"h":114}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":18,"y":18,"w":109,"h":114}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/logical_acceptor.png": -{ - "frame": {"x":1975,"y":3,"w":62,"h":106}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":43,"y":0,"w":62,"h":106}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/logical_ejector.png": -{ - "frame": {"x":1975,"y":113,"w":60,"h":67}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":44,"y":0,"w":60,"h":67}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/network_conflict.png": -{ - "frame": {"x":271,"y":1810,"w":47,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":2,"w":47,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/network_empty.png": -{ - "frame": {"x":3,"y":1977,"w":41,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":41,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/overlay_tile.png": -{ - "frame": {"x":708,"y":888,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/color_cross.png": -{ - "frame": {"x":1397,"y":704,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/color_forward.png": -{ - "frame": {"x":2026,"y":332,"w":18,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/color_split.png": -{ - "frame": {"x":290,"y":975,"w":144,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/color_turn.png": -{ - "frame": {"x":701,"y":1207,"w":81,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/conflict_cross.png": -{ - "frame": {"x":1675,"y":732,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/conflict_forward.png": -{ - "frame": {"x":2026,"y":480,"w":18,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/conflict_split.png": -{ - "frame": {"x":558,"y":1015,"w":144,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/conflict_turn.png": -{ - "frame": {"x":701,"y":1292,"w":81,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/regular_cross.png": -{ - "frame": {"x":1249,"y":704,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/regular_forward.png": -{ - "frame": {"x":2027,"y":184,"w":18,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/regular_split.png": -{ - "frame": {"x":290,"y":890,"w":144,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/regular_turn.png": -{ - "frame": {"x":706,"y":1122,"w":81,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/shape_cross.png": -{ - "frame": {"x":1672,"y":880,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/shape_forward.png": -{ - "frame": {"x":1107,"y":299,"w":18,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/shape_split.png": -{ - "frame": {"x":558,"y":1100,"w":144,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/sets/shape_turn.png": -{ - "frame": {"x":698,"y":1377,"w":81,"h":81}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/wires/wires_preview.png": -{ - "frame": {"x":1975,"y":236,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_hq.png", - "format": "RGBA8888", - "size": {"w":2048,"h":2048}, - "scale": "0.75", - "smartupdate": "$TexturePacker:SmartUpdate:876f0711b44fa7bbab8d2539e9651766:ff01f850e086ef31c114b036c3a32e6d:908b89f5ca8ff73e331a35a3b14d0604$" -} -} +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":440,"y":742,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":1545,"y":991,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":828,"y":1285,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":426,"y":1482,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":418,"y":1630,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":820,"y":1433,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":411,"y":1778,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":814,"y":1581,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":806,"y":1729,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":799,"y":1877,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":1545,"y":1139,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":433,"y":1038,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":427,"y":1186,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":426,"y":1334,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":151,"y":1035,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":151,"y":1169,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":3,"y":1601,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":686,"y":1431,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":546,"y":1542,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":277,"y":1685,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":137,"y":1718,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":3,"y":1735,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":948,"y":1317,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":680,"y":1565,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":1527,"y":1427,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":151,"y":1303,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":284,"y":1551,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":143,"y":1584,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":538,"y":1676,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":271,"y":1819,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":672,"y":1699,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":531,"y":1810,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":1216,"y":1398,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":1074,"y":1493,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":934,"y":1585,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":1350,"y":1449,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":1208,"y":1532,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":1068,"y":1627,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":137,"y":1852,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":3,"y":1869,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":1082,"y":1359,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":940,"y":1451,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":934,"y":1719,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":665,"y":1833,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":919,"y":1877,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":1937,"y":759,"w":105,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":105,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":3,"y":151,"w":548,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":548,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":847,"y":298,"w":256,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":1533,"y":1287,"w":128,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":8,"w":128,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":1107,"y":556,"w":268,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":16,"y":0,"w":268,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":1823,"y":732,"w":110,"h":116}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":17,"w":110,"h":116}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":1545,"y":843,"w":123,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":123,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":1249,"y":989,"w":144,"h":123}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":123}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":1820,"y":970,"w":101,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":101,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":290,"y":890,"w":144,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":1249,"y":852,"w":144,"h":133}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":133}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":144,"y":1437,"w":136,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":3,"y":1454,"w":136,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":1676,"y":584,"w":261,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":1683,"y":3,"w":288,"h":287}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":555,"y":298,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":560,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":3,"y":299,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":1665,"y":1198,"w":143,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":948,"y":1169,"w":142,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":142,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":1899,"y":1156,"w":143,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":1242,"y":1116,"w":142,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":1384,"y":1307,"w":139,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":295,"y":299,"w":256,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":295,"y":594,"w":261,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":847,"y":593,"w":250,"h":288}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":21,"y":0,"w":250,"h":288}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":292,"y":742,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":559,"y":1036,"w":138,"h":125}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":285,"y":1182,"w":138,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":1661,"y":1493,"w":139,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":553,"y":1165,"w":138,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-analyzer.png": +{ + "frame": {"x":3,"y":887,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-rotater.png": +{ + "frame": {"x":1925,"y":1008,"w":118,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":118,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-shapecompare.png": +{ + "frame": {"x":1397,"y":852,"w":144,"h":133}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":133}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-unstacker.png": +{ + "frame": {"x":1101,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor.png": +{ + "frame": {"x":285,"y":1037,"w":144,"h":141}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":3,"w":144,"h":141}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":1249,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":1397,"y":989,"w":144,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":62,"w":144,"h":82}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":1813,"y":1118,"w":82,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":62,"y":62,"w":82,"h":82}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":1107,"y":151,"w":20,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":62,"y":0,"w":20,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":255,"y":677,"w":33,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":55,"y":4,"w":33,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":1855,"y":1591,"w":138,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":138,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":151,"y":1035,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":538,"y":1676,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":440,"y":742,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":1941,"y":628,"w":104,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":104,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":555,"y":151,"w":548,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":548,"h":143}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":847,"y":446,"w":256,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":1545,"y":704,"w":126,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":126,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":1379,"y":556,"w":267,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":267,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":1131,"y":3,"w":548,"h":549}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":16,"w":548,"h":549}, + "sourceSize": {"w":576,"h":576} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":1823,"y":852,"w":109,"h":114}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":18,"w":109,"h":114}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":972,"y":885,"w":122,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":0,"w":122,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":1095,"y":1085,"w":143,"h":123}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":123}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":151,"y":887,"w":100,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":100,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":1897,"y":1304,"w":143,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":948,"y":1033,"w":143,"h":132}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":132}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":688,"y":1285,"w":136,"h":142}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":546,"y":1396,"w":136,"h":142}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":560,"y":594,"w":260,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":1683,"y":294,"w":288,"h":286}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":555,"y":446,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":567,"y":3,"w":560,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":3,"y":447,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":1094,"y":1212,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":1388,"y":1160,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":1665,"y":1346,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":1239,"y":1258,"w":141,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":1895,"y":1451,"w":139,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":295,"y":447,"w":256,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":560,"y":741,"w":260,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":3,"y":595,"w":248,"h":288}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":22,"y":0,"w":248,"h":288}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":1397,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":3,"y":1326,"w":137,"h":124}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":695,"y":1170,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":547,"y":1281,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":285,"y":1436,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-analyzer.png": +{ + "frame": {"x":1675,"y":732,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-rotater.png": +{ + "frame": {"x":438,"y":890,"w":117,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":117,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-shapecompare.png": +{ + "frame": {"x":801,"y":1033,"w":143,"h":133}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":133}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-unstacker.png": +{ + "frame": {"x":3,"y":1035,"w":144,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":144,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor.png": +{ + "frame": {"x":3,"y":1182,"w":144,"h":140}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":144,"h":140}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":1672,"y":880,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":1098,"y":1000,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":1812,"y":1204,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":2027,"y":184,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":255,"y":816,"w":31,"h":134}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":56,"y":5,"w":31,"h":134}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":285,"y":1298,"w":137,"h":134}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":137,"h":134}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":1107,"y":447,"w":12,"h":12}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, + "sourceSize": {"w":12,"h":12} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":1107,"y":463,"w":12,"h":12}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, + "sourceSize": {"w":12,"h":12} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":1975,"y":184,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":255,"y":638,"w":35,"h":35}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":35,"h":35}, + "sourceSize": {"w":39,"h":39} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":255,"y":595,"w":35,"h":39}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":35,"h":39}, + "sourceSize": {"w":39,"h":39} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":708,"y":988,"w":89,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, + "sourceSize": {"w":90,"h":45} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":1997,"y":1643,"w":38,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":255,"y":954,"w":31,"h":41}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":5,"w":31,"h":41}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":1650,"y":556,"w":22,"h":41}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":5,"w":22,"h":41}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":1975,"y":288,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":1975,"y":339,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":1975,"y":390,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":1975,"y":441,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":1975,"y":492,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":1975,"y":543,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":1804,"y":1544,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":1936,"y":890,"w":109,"h":114}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":18,"w":109,"h":114}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":1975,"y":3,"w":62,"h":106}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":43,"y":0,"w":62,"h":106}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":1975,"y":113,"w":60,"h":67}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":44,"y":0,"w":60,"h":67}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":1804,"y":1595,"w":47,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":2,"w":47,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":1997,"y":1591,"w":41,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":41,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":708,"y":888,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":1101,"y":852,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":2026,"y":332,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":1397,"y":1075,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":1812,"y":1289,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":824,"y":885,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":2026,"y":480,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":1665,"y":1028,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":1810,"y":1374,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":1672,"y":880,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":2027,"y":184,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":1098,"y":1000,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":1812,"y":1204,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":560,"y":888,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":1107,"y":299,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":1665,"y":1113,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":1810,"y":1459,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":1975,"y":236,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_hq.png", + "format": "RGBA8888", + "size": {"w":2048,"h":2048}, + "scale": "0.75", + "smartupdate": "$TexturePacker:SmartUpdate:2b3d82298ef871f8c3ae06176af3dcd1:a4ea5a77f537770c7508bf6fd6c71ae8:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_hq.png b/res_built/atlas/atlas0_hq.png index ef9ab78b..991ba8a7 100644 Binary files a/res_built/atlas/atlas0_hq.png and b/res_built/atlas/atlas0_hq.png differ diff --git a/res_built/atlas/atlas0_lq.json b/res_built/atlas/atlas0_lq.json index 3896c6fd..e7f1e66d 100644 --- a/res_built/atlas/atlas0_lq.json +++ b/res_built/atlas/atlas0_lq.json @@ -1,1308 +1,1388 @@ -{"frames": { - -"sprites/belt/built/forward_0.png": -{ - "frame": {"x":415,"y":463,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_1.png": -{ - "frame": {"x":195,"y":828,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_2.png": -{ - "frame": {"x":3,"y":959,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_3.png": -{ - "frame": {"x":448,"y":705,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_4.png": -{ - "frame": {"x":394,"y":752,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_5.png": -{ - "frame": {"x":342,"y":762,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_6.png": -{ - "frame": {"x":289,"y":795,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_7.png": -{ - "frame": {"x":239,"y":836,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_8.png": -{ - "frame": {"x":191,"y":880,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_9.png": -{ - "frame": {"x":143,"y":883,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_10.png": -{ - "frame": {"x":147,"y":831,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_11.png": -{ - "frame": {"x":99,"y":862,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_12.png": -{ - "frame": {"x":51,"y":870,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/forward_13.png": -{ - "frame": {"x":3,"y":907,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_0.png": -{ - "frame": {"x":3,"y":667,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_1.png": -{ - "frame": {"x":208,"y":636,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_2.png": -{ - "frame": {"x":256,"y":640,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_3.png": -{ - "frame": {"x":202,"y":684,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_4.png": -{ - "frame": {"x":150,"y":687,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_5.png": -{ - "frame": {"x":99,"y":718,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_6.png": -{ - "frame": {"x":51,"y":726,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_7.png": -{ - "frame": {"x":3,"y":763,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_8.png": -{ - "frame": {"x":304,"y":651,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_9.png": -{ - "frame": {"x":250,"y":688,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_10.png": -{ - "frame": {"x":154,"y":639,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_11.png": -{ - "frame": {"x":102,"y":670,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_12.png": -{ - "frame": {"x":51,"y":678,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/left_13.png": -{ - "frame": {"x":3,"y":715,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_0.png": -{ - "frame": {"x":198,"y":732,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_1.png": -{ - "frame": {"x":147,"y":735,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_2.png": -{ - "frame": {"x":298,"y":699,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_3.png": -{ - "frame": {"x":246,"y":736,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_4.png": -{ - "frame": {"x":195,"y":780,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_5.png": -{ - "frame": {"x":147,"y":783,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_6.png": -{ - "frame": {"x":99,"y":814,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_7.png": -{ - "frame": {"x":51,"y":822,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_8.png": -{ - "frame": {"x":3,"y":859,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_9.png": -{ - "frame": {"x":400,"y":704,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_10.png": -{ - "frame": {"x":99,"y":766,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_11.png": -{ - "frame": {"x":51,"y":774,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_12.png": -{ - "frame": {"x":3,"y":811,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/belt/built/right_13.png": -{ - "frame": {"x":352,"y":666,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":346,"y":714,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":294,"y":747,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":95,"y":914,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/constant_signal.png": -{ - "frame": {"x":329,"y":390,"w":36,"h":43}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":191,"y":55,"w":184,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":187,"y":315,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/display.png": -{ - "frame": {"x":106,"y":620,"w":44,"h":46}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/filter.png": -{ - "frame": {"x":3,"y":244,"w":91,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":91,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/lever.png": -{ - "frame": {"x":470,"y":257,"w":38,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/logic_gate-not.png": -{ - "frame": {"x":243,"y":784,"w":42,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/logic_gate-or.png": -{ - "frame": {"x":55,"y":500,"w":48,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/logic_gate-transistor.png": -{ - "frame": {"x":144,"y":448,"w":35,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/logic_gate-xor.png": -{ - "frame": {"x":291,"y":159,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/logic_gate.png": -{ - "frame": {"x":384,"y":566,"w":48,"h":45}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":462,"y":345,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":211,"y":584,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":98,"y":244,"w":89,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":387,"y":3,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":191,"y":159,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":3,"y":3,"w":188,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":375,"y":203,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":291,"y":211,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":285,"y":263,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":460,"y":397,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":183,"y":367,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":364,"y":615,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":278,"y":338,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":369,"y":307,"w":89,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":94,"y":348,"w":85,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":277,"y":390,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":3,"y":500,"w":48,"h":43}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":159,"y":523,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":211,"y":542,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":263,"y":546,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire-cross.png": -{ - "frame": {"x":183,"y":419,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire-split.png": -{ - "frame": {"x":315,"y":567,"w":48,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire-turn.png": -{ - "frame": {"x":479,"y":129,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire.png": -{ - "frame": {"x":357,"y":286,"w":8,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_tunnel-coating.png": -{ - "frame": {"x":235,"y":458,"w":13,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":13,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_tunnel.png": -{ - "frame": {"x":384,"y":515,"w":48,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":3,"y":667,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":198,"y":732,"w":44,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":415,"y":463,"w":40,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/constant_signal.png": -{ - "frame": {"x":235,"y":411,"w":36,"h":43}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":191,"y":107,"w":184,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":369,"y":359,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/display.png": -{ - "frame": {"x":54,"y":628,"w":44,"h":46}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/filter.png": -{ - "frame": {"x":191,"y":263,"w":90,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":90,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":55,"w":184,"h":185}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/lever.png": -{ - "frame": {"x":470,"y":301,"w":38,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/logic_gate-not.png": -{ - "frame": {"x":466,"y":653,"w":43,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":43,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/logic_gate-or.png": -{ - "frame": {"x":107,"y":500,"w":48,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/logic_gate-transistor.png": -{ - "frame": {"x":421,"y":411,"w":35,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/logic_gate-xor.png": -{ - "frame": {"x":92,"y":448,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/logic_gate.png": -{ - "frame": {"x":436,"y":604,"w":48,"h":45}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":262,"y":588,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":313,"y":599,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":3,"y":296,"w":88,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":379,"y":103,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":191,"y":211,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":195,"y":3,"w":188,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":370,"y":255,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":369,"y":411,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":460,"y":449,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":275,"y":442,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":436,"y":553,"w":48,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":415,"y":653,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":3,"y":348,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":95,"y":296,"w":88,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":3,"y":400,"w":85,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":183,"y":471,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":3,"y":579,"w":47,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":3,"y":625,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":106,"y":578,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":157,"y":597,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire-cross.png": -{ - "frame": {"x":268,"y":494,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire-split.png": -{ - "frame": {"x":55,"y":546,"w":48,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire-turn.png": -{ - "frame": {"x":479,"y":161,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire.png": -{ - "frame": {"x":327,"y":457,"w":8,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_tunnel-coating.png": -{ - "frame": {"x":252,"y":492,"w":12,"h":46}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":18,"y":1,"w":12,"h":46}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_tunnel.png": -{ - "frame": {"x":55,"y":578,"w":47,"h":46}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":47,"h":46}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":379,"y":55,"w":4,"h":4}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, - "sourceSize": {"w":4,"h":4} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":379,"y":63,"w":4,"h":4}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, - "sourceSize": {"w":4,"h":4} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":487,"y":30,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":252,"y":458,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":252,"y":475,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":479,"y":110,"w":30,"h":15}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":30,"h":15}, - "sourceSize": {"w":30,"h":15} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":349,"y":437,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/boolean_false.png": -{ - "frame": {"x":235,"y":509,"w":12,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":1,"w":12,"h":15}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/boolean_true.png": -{ - "frame": {"x":357,"y":267,"w":9,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":1,"w":9,"h":15}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/display/blue.png": -{ - "frame": {"x":487,"y":50,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/display/cyan.png": -{ - "frame": {"x":487,"y":70,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/display/green.png": -{ - "frame": {"x":487,"y":90,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/display/purple.png": -{ - "frame": {"x":337,"y":267,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/display/red.png": -{ - "frame": {"x":337,"y":287,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/display/white.png": -{ - "frame": {"x":337,"y":307,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/display/yellow.png": -{ - "frame": {"x":278,"y":315,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/lever_on.png": -{ - "frame": {"x":235,"y":367,"w":38,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/logical_acceptor.png": -{ - "frame": {"x":343,"y":227,"w":23,"h":36}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":23,"h":36}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/logical_ejector.png": -{ - "frame": {"x":487,"y":3,"w":22,"h":23}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":22,"h":23}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/network_conflict.png": -{ - "frame": {"x":298,"y":315,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/network_empty.png": -{ - "frame": {"x":318,"y":315,"w":15,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":15,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/overlay_tile.png": -{ - "frame": {"x":343,"y":159,"w":32,"h":32}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/sets/color_cross.png": -{ - "frame": {"x":363,"y":463,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/color_forward.png": -{ - "frame": {"x":339,"y":457,"w":8,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/color_split.png": -{ - "frame": {"x":3,"y":547,"w":48,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/color_turn.png": -{ - "frame": {"x":479,"y":193,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/conflict_cross.png": -{ - "frame": {"x":459,"y":501,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/conflict_forward.png": -{ - "frame": {"x":351,"y":457,"w":8,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/conflict_split.png": -{ - "frame": {"x":107,"y":546,"w":48,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/conflict_turn.png": -{ - "frame": {"x":343,"y":195,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/regular_cross.png": -{ - "frame": {"x":268,"y":494,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/regular_forward.png": -{ - "frame": {"x":327,"y":457,"w":8,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/regular_split.png": -{ - "frame": {"x":55,"y":546,"w":48,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/regular_turn.png": -{ - "frame": {"x":479,"y":161,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/shape_cross.png": -{ - "frame": {"x":332,"y":515,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/shape_forward.png": -{ - "frame": {"x":320,"y":509,"w":8,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/shape_split.png": -{ - "frame": {"x":159,"y":565,"w":48,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/sets/shape_turn.png": -{ - "frame": {"x":475,"y":225,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/wires_preview.png": -{ - "frame": {"x":329,"y":437,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_lq.png", - "format": "RGBA8888", - "size": {"w":512,"h":1024}, - "scale": "0.25", - "smartupdate": "$TexturePacker:SmartUpdate:876f0711b44fa7bbab8d2539e9651766:ff01f850e086ef31c114b036c3a32e6d:908b89f5ca8ff73e331a35a3b14d0604$" -} -} +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":96,"y":970,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":140,"y":970,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":229,"y":863,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":272,"y":915,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":272,"y":967,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":273,"y":835,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":405,"y":750,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":353,"y":760,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":449,"y":750,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":397,"y":802,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":141,"y":917,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":184,"y":969,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":185,"y":891,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":228,"y":943,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":3,"y":725,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":3,"y":773,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":154,"y":747,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":102,"y":773,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":51,"y":774,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":3,"y":821,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":413,"y":654,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":361,"y":664,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":309,"y":710,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":257,"y":739,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":365,"y":616,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":313,"y":662,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":261,"y":691,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":209,"y":719,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":461,"y":654,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":202,"y":767,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":409,"y":702,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":357,"y":712,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":305,"y":758,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":250,"y":787,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":198,"y":815,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":147,"y":843,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":99,"y":869,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":51,"y":870,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":150,"y":795,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":99,"y":821,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":51,"y":822,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":3,"y":869,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":3,"y":917,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":457,"y":702,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":441,"y":802,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":329,"y":390,"w":36,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":191,"y":55,"w":184,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":187,"y":315,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":106,"y":723,"w":44,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":3,"y":244,"w":91,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":91,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":470,"y":257,"w":38,"h":40}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":50,"y":965,"w":42,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":107,"y":552,"w":48,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":144,"y":448,"w":35,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":291,"y":159,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":315,"y":567,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":462,"y":345,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":263,"y":597,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":98,"y":244,"w":89,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":387,"y":3,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":191,"y":159,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":188,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":375,"y":203,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":291,"y":211,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":285,"y":263,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":460,"y":397,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":183,"y":367,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":107,"y":672,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":278,"y":338,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":369,"y":307,"w":89,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":94,"y":348,"w":85,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":277,"y":390,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":55,"y":552,"w":48,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":107,"y":598,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":55,"y":599,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":3,"y":601,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-analyzer.png": +{ + "frame": {"x":183,"y":419,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-rotater.png": +{ + "frame": {"x":415,"y":463,"w":41,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":41,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-shapecompare.png": +{ + "frame": {"x":367,"y":567,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-unstacker.png": +{ + "frame": {"x":92,"y":448,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor.png": +{ + "frame": {"x":369,"y":411,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":460,"y":449,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":211,"y":593,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":479,"y":129,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":357,"y":286,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":235,"y":458,"w":13,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":13,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":211,"y":542,"w":48,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":3,"y":725,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":461,"y":654,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":96,"y":970,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":235,"y":411,"w":36,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":191,"y":107,"w":184,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":369,"y":359,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":54,"y":724,"w":44,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":191,"y":263,"w":90,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":90,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":3,"y":55,"w":184,"h":185}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":470,"y":301,"w":38,"h":40}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":3,"y":965,"w":43,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":43,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":159,"y":575,"w":48,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":421,"y":411,"w":35,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":275,"y":442,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":419,"y":605,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":211,"y":625,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":159,"y":653,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":3,"y":296,"w":88,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":379,"y":103,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":191,"y":211,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":195,"y":3,"w":188,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":370,"y":255,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":183,"y":471,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":268,"y":494,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":363,"y":463,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":263,"y":546,"w":48,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":55,"y":673,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":3,"y":348,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":95,"y":296,"w":88,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":3,"y":400,"w":85,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":460,"y":501,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":314,"y":616,"w":47,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":262,"y":649,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":210,"y":677,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":158,"y":705,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-analyzer.png": +{ + "frame": {"x":332,"y":515,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-rotater.png": +{ + "frame": {"x":96,"y":918,"w":41,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":41,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-shapecompare.png": +{ + "frame": {"x":3,"y":552,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-unstacker.png": +{ + "frame": {"x":384,"y":515,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor.png": +{ + "frame": {"x":436,"y":553,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":3,"y":500,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":159,"y":621,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":479,"y":161,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":327,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":252,"y":492,"w":12,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":1,"w":12,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":3,"y":675,"w":47,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":379,"y":55,"w":4,"h":4}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, + "sourceSize": {"w":4,"h":4} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":379,"y":63,"w":4,"h":4}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, + "sourceSize": {"w":4,"h":4} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":487,"y":30,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":252,"y":458,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":252,"y":475,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":479,"y":110,"w":30,"h":15}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":15}, + "sourceSize": {"w":30,"h":15} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":349,"y":437,"w":14,"h":16}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":235,"y":509,"w":12,"h":15}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":1,"w":12,"h":15}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":357,"y":267,"w":9,"h":15}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":9,"h":15}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":487,"y":50,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":487,"y":70,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":487,"y":90,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":337,"y":267,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":337,"y":287,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":337,"y":307,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":278,"y":315,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":235,"y":367,"w":38,"h":40}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":343,"y":227,"w":23,"h":36}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":23,"h":36}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":487,"y":3,"w":22,"h":23}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":22,"h":23}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":298,"y":315,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":318,"y":315,"w":15,"h":16}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":15,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":343,"y":159,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":55,"y":500,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":339,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":107,"y":640,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":479,"y":193,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":107,"y":500,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":351,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":55,"y":641,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":343,"y":195,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":3,"y":500,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":327,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":159,"y":621,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":479,"y":161,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":159,"y":523,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":320,"y":509,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":3,"y":643,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":475,"y":225,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":329,"y":437,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_lq.png", + "format": "RGBA8888", + "size": {"w":512,"h":1024}, + "scale": "0.25", + "smartupdate": "$TexturePacker:SmartUpdate:2b3d82298ef871f8c3ae06176af3dcd1:a4ea5a77f537770c7508bf6fd6c71ae8:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_lq.png b/res_built/atlas/atlas0_lq.png index c6b4be55..88e42984 100644 Binary files a/res_built/atlas/atlas0_lq.png and b/res_built/atlas/atlas0_lq.png differ diff --git a/res_built/atlas/atlas0_mq.json b/res_built/atlas/atlas0_mq.json index 89809854..5f33f6fd 100644 --- a/res_built/atlas/atlas0_mq.json +++ b/res_built/atlas/atlas0_mq.json @@ -1,1308 +1,1388 @@ -{"frames": { - -"sprites/belt/built/forward_0.png": -{ - "frame": {"x":943,"y":816,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_1.png": -{ - "frame": {"x":439,"y":803,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_2.png": -{ - "frame": {"x":850,"y":1402,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_3.png": -{ - "frame": {"x":932,"y":1402,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_4.png": -{ - "frame": {"x":751,"y":1431,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_5.png": -{ - "frame": {"x":650,"y":1480,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_6.png": -{ - "frame": {"x":551,"y":1494,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_7.png": -{ - "frame": {"x":454,"y":1522,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_8.png": -{ - "frame": {"x":358,"y":1553,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_9.png": -{ - "frame": {"x":267,"y":1554,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_10.png": -{ - "frame": {"x":276,"y":1454,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_11.png": -{ - "frame": {"x":185,"y":1499,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_12.png": -{ - "frame": {"x":94,"y":1514,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/forward_13.png": -{ - "frame": {"x":3,"y":1585,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_0.png": -{ - "frame": {"x":196,"y":1135,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_1.png": -{ - "frame": {"x":99,"y":1150,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_2.png": -{ - "frame": {"x":287,"y":1181,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_3.png": -{ - "frame": {"x":190,"y":1226,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_4.png": -{ - "frame": {"x":94,"y":1241,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_5.png": -{ - "frame": {"x":3,"y":1312,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_6.png": -{ - "frame": {"x":674,"y":1207,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_7.png": -{ - "frame": {"x":577,"y":1217,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_8.png": -{ - "frame": {"x":478,"y":1246,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_9.png": -{ - "frame": {"x":378,"y":1271,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_10.png": -{ - "frame": {"x":3,"y":1221,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_11.png": -{ - "frame": {"x":583,"y":1126,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_12.png": -{ - "frame": {"x":486,"y":1155,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/left_13.png": -{ - "frame": {"x":387,"y":1180,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_0.png": -{ - "frame": {"x":281,"y":1272,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_1.png": -{ - "frame": {"x":185,"y":1317,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_2.png": -{ - "frame": {"x":569,"y":1308,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_3.png": -{ - "frame": {"x":469,"y":1337,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_4.png": -{ - "frame": {"x":372,"y":1362,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_5.png": -{ - "frame": {"x":276,"y":1363,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_6.png": -{ - "frame": {"x":185,"y":1408,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_7.png": -{ - "frame": {"x":94,"y":1423,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_8.png": -{ - "frame": {"x":3,"y":1494,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_9.png": -{ - "frame": {"x":856,"y":1311,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_10.png": -{ - "frame": {"x":94,"y":1332,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_11.png": -{ - "frame": {"x":3,"y":1403,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_12.png": -{ - "frame": {"x":765,"y":1249,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/belt/built/right_13.png": -{ - "frame": {"x":668,"y":1298,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":759,"y":1340,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":660,"y":1389,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":176,"y":1599,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/constant_signal.png": -{ - "frame": {"x":949,"y":396,"w":71,"h":85}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":71,"h":85}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":373,"y":103,"w":366,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":745,"y":594,"w":172,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/display.png": -{ - "frame": {"x":560,"y":1399,"w":86,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":86,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/filter.png": -{ - "frame": {"x":569,"y":303,"w":180,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":10,"y":0,"w":180,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/lever.png": -{ - "frame": {"x":946,"y":734,"w":74,"h":78}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":74,"h":78}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/logic_gate-not.png": -{ - "frame": {"x":367,"y":1453,"w":83,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":83,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/logic_gate-or.png": -{ - "frame": {"x":521,"y":991,"w":96,"h":82}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":82}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/logic_gate-transistor.png": -{ - "frame": {"x":449,"y":703,"w":68,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/logic_gate-xor.png": -{ - "frame": {"x":3,"y":674,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/logic_gate.png": -{ - "frame": {"x":335,"y":902,"w":96,"h":89}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":929,"y":916,"w":92,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":100,"y":1050,"w":92,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":3,"y":474,"w":175,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":759,"y":3,"w":192,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":373,"y":303,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":3,"y":3,"w":374,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":753,"y":394,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":103,"y":674,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":921,"y":1016,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":203,"y":674,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":820,"y":1152,"w":95,"h":93}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":101,"y":874,"w":93,"h":93}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":3,"y":574,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":182,"y":474,"w":175,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":528,"y":603,"w":167,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":349,"y":703,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":198,"y":969,"w":93,"h":84}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":100,"y":971,"w":93,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":3,"y":874,"w":94,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":3,"y":1048,"w":93,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire-cross.png": -{ - "frame": {"x":521,"y":799,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire-split.png": -{ - "frame": {"x":721,"y":990,"w":96,"h":55}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":41,"w":96,"h":55}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire-turn.png": -{ - "frame": {"x":955,"y":105,"w":55,"h":55}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":41,"y":41,"w":55,"h":55}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire.png": -{ - "frame": {"x":699,"y":603,"w":14,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":41,"y":0,"w":14,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_tunnel-coating.png": -{ - "frame": {"x":921,"y":594,"w":23,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":36,"y":2,"w":23,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_tunnel.png": -{ - "frame": {"x":3,"y":953,"w":93,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":93,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":196,"y":1135,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":281,"y":1272,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":943,"y":816,"w":78,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/constant_signal.png": -{ - "frame": {"x":949,"y":485,"w":70,"h":85}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":70,"h":85}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":373,"y":203,"w":366,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":178,"y":574,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/display.png": -{ - "frame": {"x":463,"y":1428,"w":84,"h":90}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":84,"h":90}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/filter.png": -{ - "frame": {"x":569,"y":403,"w":179,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":179,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":103,"w":366,"h":367}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":10,"w":366,"h":367}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/lever.png": -{ - "frame": {"x":948,"y":574,"w":73,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":12,"y":12,"w":73,"h":76}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/logic_gate-not.png": -{ - "frame": {"x":435,"y":903,"w":82,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":82,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/logic_gate-or.png": -{ - "frame": {"x":621,"y":923,"w":96,"h":83}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":83}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/logic_gate-transistor.png": -{ - "frame": {"x":621,"y":799,"w":68,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/logic_gate-xor.png": -{ - "frame": {"x":339,"y":803,"w":96,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":95}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/logic_gate.png": -{ - "frame": {"x":521,"y":899,"w":96,"h":88}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":88}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":391,"y":1081,"w":91,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":292,"y":1082,"w":91,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":361,"y":503,"w":174,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":759,"y":199,"w":192,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":373,"y":403,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":381,"y":3,"w":374,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":752,"y":494,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":821,"y":1052,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":721,"y":1107,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":920,"y":1116,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":919,"y":1216,"w":94,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":198,"y":874,"w":93,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":353,"y":603,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":539,"y":503,"w":174,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":736,"y":694,"w":166,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":729,"y":890,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":295,"y":995,"w":92,"h":83}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":196,"y":1057,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":391,"y":1003,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":487,"y":1077,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire-cross.png": -{ - "frame": {"x":829,"y":894,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire-split.png": -{ - "frame": {"x":621,"y":1010,"w":96,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire-turn.png": -{ - "frame": {"x":955,"y":164,"w":54,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire.png": -{ - "frame": {"x":743,"y":103,"w":12,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_tunnel-coating.png": -{ - "frame": {"x":921,"y":689,"w":21,"h":90}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":37,"y":3,"w":21,"h":90}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_tunnel.png": -{ - "frame": {"x":3,"y":1127,"w":92,"h":90}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":3,"w":92,"h":90}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":1013,"y":164,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":1013,"y":176,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":693,"y":851,"w":32,"h":32}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":717,"y":605,"w":24,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":24,"h":24}, - "sourceSize": {"w":26,"h":26} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":717,"y":575,"w":24,"h":26}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":24,"h":26}, - "sourceSize": {"w":26,"h":26} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":955,"y":71,"w":60,"h":30}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":60,"h":30}, - "sourceSize": {"w":60,"h":30} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":717,"y":539,"w":26,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/boolean_false.png": -{ - "frame": {"x":717,"y":633,"w":21,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":3,"w":21,"h":28}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/boolean_true.png": -{ - "frame": {"x":717,"y":665,"w":15,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":3,"w":15,"h":28}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/display/blue.png": -{ - "frame": {"x":699,"y":703,"w":33,"h":33}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, - "sourceSize": {"w":33,"h":33} -}, -"sprites/wires/display/cyan.png": -{ - "frame": {"x":699,"y":740,"w":33,"h":33}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, - "sourceSize": {"w":33,"h":33} -}, -"sprites/wires/display/green.png": -{ - "frame": {"x":699,"y":777,"w":33,"h":33}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, - "sourceSize": {"w":33,"h":33} -}, -"sprites/wires/display/purple.png": -{ - "frame": {"x":906,"y":783,"w":33,"h":33}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, - "sourceSize": {"w":33,"h":33} -}, -"sprites/wires/display/red.png": -{ - "frame": {"x":906,"y":820,"w":33,"h":33}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, - "sourceSize": {"w":33,"h":33} -}, -"sprites/wires/display/white.png": -{ - "frame": {"x":906,"y":857,"w":33,"h":33}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, - "sourceSize": {"w":33,"h":33} -}, -"sprites/wires/display/yellow.png": -{ - "frame": {"x":693,"y":814,"w":33,"h":33}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, - "sourceSize": {"w":33,"h":33} -}, -"sprites/wires/lever_on.png": -{ - "frame": {"x":948,"y":654,"w":73,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":12,"y":12,"w":73,"h":76}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/logical_acceptor.png": -{ - "frame": {"x":303,"y":674,"w":42,"h":71}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":28,"y":0,"w":42,"h":71}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/logical_ejector.png": -{ - "frame": {"x":303,"y":749,"w":41,"h":45}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":29,"y":0,"w":41,"h":45}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/network_conflict.png": -{ - "frame": {"x":303,"y":798,"w":32,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":32,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/network_empty.png": -{ - "frame": {"x":717,"y":503,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/overlay_tile.png": -{ - "frame": {"x":955,"y":3,"w":64,"h":64}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/sets/color_cross.png": -{ - "frame": {"x":3,"y":774,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/color_forward.png": -{ - "frame": {"x":743,"y":203,"w":12,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/color_split.png": -{ - "frame": {"x":821,"y":994,"w":96,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/color_turn.png": -{ - "frame": {"x":955,"y":222,"w":54,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/conflict_cross.png": -{ - "frame": {"x":103,"y":774,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/conflict_forward.png": -{ - "frame": {"x":303,"y":832,"w":12,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/conflict_split.png": -{ - "frame": {"x":721,"y":1049,"w":96,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/conflict_turn.png": -{ - "frame": {"x":955,"y":280,"w":54,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/regular_cross.png": -{ - "frame": {"x":829,"y":894,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/regular_forward.png": -{ - "frame": {"x":743,"y":103,"w":12,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/regular_split.png": -{ - "frame": {"x":621,"y":1010,"w":96,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/regular_turn.png": -{ - "frame": {"x":955,"y":164,"w":54,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/shape_cross.png": -{ - "frame": {"x":203,"y":774,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/shape_forward.png": -{ - "frame": {"x":319,"y":832,"w":12,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/shape_split.png": -{ - "frame": {"x":621,"y":1068,"w":96,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/sets/shape_turn.png": -{ - "frame": {"x":955,"y":338,"w":54,"h":54}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/wires_preview.png": -{ - "frame": {"x":693,"y":887,"w":32,"h":32}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, - "sourceSize": {"w":32,"h":32} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_mq.png", - "format": "RGBA8888", - "size": {"w":1024,"h":2048}, - "scale": "0.5", - "smartupdate": "$TexturePacker:SmartUpdate:876f0711b44fa7bbab8d2539e9651766:ff01f850e086ef31c114b036c3a32e6d:908b89f5ca8ff73e331a35a3b14d0604$" -} -} +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":943,"y":816,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":439,"y":803,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":177,"y":1647,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":259,"y":1647,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":341,"y":1654,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":85,"y":1656,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":3,"y":1665,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":167,"y":1747,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":85,"y":1756,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":3,"y":1765,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":3,"y":1565,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":268,"y":1547,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":350,"y":1554,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":432,"y":1633,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":787,"y":1185,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":685,"y":1261,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":867,"y":1292,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":771,"y":1367,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":862,"y":1383,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":198,"y":1274,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":100,"y":1283,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":3,"y":1292,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":289,"y":1274,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":380,"y":1277,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":589,"y":1293,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":878,"y":1201,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":776,"y":1276,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":680,"y":1352,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":471,"y":1357,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":562,"y":1384,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":3,"y":1383,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":282,"y":1365,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":373,"y":1368,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":464,"y":1448,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":555,"y":1475,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":646,"y":1534,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":185,"y":1456,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":94,"y":1465,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":653,"y":1443,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":744,"y":1458,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":191,"y":1365,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":94,"y":1374,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":3,"y":1474,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":276,"y":1456,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":249,"y":1747,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":949,"y":396,"w":71,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":71,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":373,"y":103,"w":366,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":745,"y":594,"w":172,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":367,"y":1459,"w":86,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":86,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":569,"y":303,"w":180,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":10,"y":0,"w":180,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":946,"y":734,"w":74,"h":78}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":11,"w":74,"h":78}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":545,"y":1566,"w":83,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":7,"y":0,"w":83,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":3,"y":874,"w":96,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":82}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":449,"y":703,"w":68,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":3,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":521,"y":999,"w":96,"h":89}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":929,"y":916,"w":92,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":398,"y":1177,"w":92,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":3,"y":474,"w":175,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":759,"y":3,"w":192,"h":192}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":373,"y":303,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":374,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":753,"y":394,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":103,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":203,"y":990,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":203,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":202,"y":1090,"w":95,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":101,"y":1186,"w":93,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":3,"y":574,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":182,"y":474,"w":175,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":528,"y":603,"w":167,"h":192}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":349,"y":703,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":498,"y":1092,"w":93,"h":84}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":401,"y":1098,"w":93,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":3,"y":1118,"w":94,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":301,"y":1101,"w":93,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-analyzer.png": +{ + "frame": {"x":521,"y":799,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-rotater.png": +{ + "frame": {"x":185,"y":1547,"w":79,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":79,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-shapecompare.png": +{ + "frame": {"x":621,"y":1023,"w":96,"h":89}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-unstacker.png": +{ + "frame": {"x":729,"y":890,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor.png": +{ + "frame": {"x":921,"y":1016,"w":96,"h":94}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":96,"h":94}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":829,"y":894,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":103,"y":874,"w":96,"h":55}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":41,"w":96,"h":55}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":955,"y":105,"w":55,"h":55}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":41,"y":41,"w":55,"h":55}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":699,"y":603,"w":14,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":41,"y":0,"w":14,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":921,"y":594,"w":23,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":36,"y":2,"w":23,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":3,"y":1197,"w":93,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":93,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":787,"y":1185,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":471,"y":1357,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":943,"y":816,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":949,"y":485,"w":70,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":70,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":373,"y":203,"w":366,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":178,"y":574,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":457,"y":1539,"w":84,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":84,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":569,"y":403,"w":179,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":179,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":3,"y":103,"w":366,"h":367}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":10,"w":366,"h":367}, + "sourceSize": {"w":384,"h":384} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":948,"y":574,"w":73,"h":76}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":12,"w":73,"h":76}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":435,"y":903,"w":82,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":82,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":921,"y":1114,"w":96,"h":83}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":83}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":621,"y":799,"w":68,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":821,"y":994,"w":96,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":821,"y":1093,"w":96,"h":88}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":88}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":590,"y":1194,"w":91,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":494,"y":1258,"w":91,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":361,"y":503,"w":174,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":759,"y":199,"w":192,"h":191}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":373,"y":403,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":381,"y":3,"w":374,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":752,"y":494,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":103,"y":991,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":3,"y":1018,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":302,"y":1001,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":102,"y":1091,"w":94,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":401,"y":1003,"w":93,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":353,"y":603,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":539,"y":503,"w":174,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":736,"y":694,"w":166,"h":192}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":3,"y":774,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":198,"y":1187,"w":92,"h":83}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":595,"y":1116,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":494,"y":1180,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":691,"y":1183,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-analyzer.png": +{ + "frame": {"x":103,"y":774,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-rotater.png": +{ + "frame": {"x":94,"y":1556,"w":79,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":79,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-shapecompare.png": +{ + "frame": {"x":721,"y":1090,"w":96,"h":89}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-unstacker.png": +{ + "frame": {"x":203,"y":774,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor.png": +{ + "frame": {"x":335,"y":903,"w":96,"h":94}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":96,"h":94}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":339,"y":803,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":203,"y":874,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":955,"y":164,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":743,"y":103,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":921,"y":689,"w":21,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":37,"y":3,"w":21,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":301,"y":1180,"w":92,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":3,"w":92,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":1013,"y":164,"w":8,"h":8}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, + "sourceSize": {"w":8,"h":8} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":1013,"y":176,"w":8,"h":8}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, + "sourceSize": {"w":8,"h":8} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":693,"y":851,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":717,"y":605,"w":24,"h":24}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":24,"h":24}, + "sourceSize": {"w":26,"h":26} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":717,"y":575,"w":24,"h":26}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":24,"h":26}, + "sourceSize": {"w":26,"h":26} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":955,"y":71,"w":60,"h":30}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":30}, + "sourceSize": {"w":60,"h":30} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":717,"y":539,"w":26,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":717,"y":633,"w":21,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":3,"w":21,"h":28}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":717,"y":665,"w":15,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":7,"y":3,"w":15,"h":28}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":699,"y":703,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":699,"y":740,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":699,"y":777,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":906,"y":783,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":906,"y":820,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":906,"y":857,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":693,"y":814,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":948,"y":654,"w":73,"h":76}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":12,"w":73,"h":76}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":303,"y":674,"w":42,"h":71}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":28,"y":0,"w":42,"h":71}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":303,"y":749,"w":41,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":29,"y":0,"w":41,"h":45}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":303,"y":798,"w":32,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":32,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":717,"y":503,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":955,"y":3,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":521,"y":899,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":743,"y":203,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":203,"y":932,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":955,"y":222,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":621,"y":923,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":303,"y":832,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":103,"y":933,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":955,"y":280,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":339,"y":803,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":743,"y":103,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":203,"y":874,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":955,"y":164,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":721,"y":990,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":319,"y":832,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":3,"y":960,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":955,"y":338,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":693,"y":887,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_mq.png", + "format": "RGBA8888", + "size": {"w":1024,"h":2048}, + "scale": "0.5", + "smartupdate": "$TexturePacker:SmartUpdate:2b3d82298ef871f8c3ae06176af3dcd1:a4ea5a77f537770c7508bf6fd6c71ae8:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_mq.png b/res_built/atlas/atlas0_mq.png index e05b73e3..e787fa6c 100644 Binary files a/res_built/atlas/atlas0_mq.png and b/res_built/atlas/atlas0_mq.png differ diff --git a/res_raw/atlas.tps b/res_raw/atlas.tps index 28809d93..95fe82bf 100644 --- a/res_raw/atlas.tps +++ b/res_raw/atlas.tps @@ -277,6 +277,7 @@ sprites/blueprints/underground_belt_entry.png sprites/blueprints/underground_belt_exit-tier2.png sprites/blueprints/underground_belt_exit.png + sprites/blueprints/wire_tunnel-coating.png sprites/blueprints/wire_tunnel.png sprites/buildings/constant_signal.png sprites/buildings/display.png @@ -295,6 +296,7 @@ sprites/buildings/underground_belt_entry.png sprites/buildings/underground_belt_exit-tier2.png sprites/buildings/underground_belt_exit.png + sprites/buildings/wire_tunnel-coating.png sprites/buildings/wire_tunnel.png sprites/wires/lever_on.png sprites/wires/sets/color_cross.png @@ -533,6 +535,8 @@ sprites/wires/boolean_false.png sprites/wires/boolean_true.png + sprites/wires/network_conflict.png + sprites/wires/network_empty.png sprites/wires/wires_preview.png pivotPoint diff --git a/res_raw/sprites/blueprints/virtual_processor-analyzer.png b/res_raw/sprites/blueprints/virtual_processor-analyzer.png new file mode 100644 index 00000000..9aa5d298 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-analyzer.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-rotater.png b/res_raw/sprites/blueprints/virtual_processor-rotater.png new file mode 100644 index 00000000..d50da022 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-rotater.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-shapecompare.png b/res_raw/sprites/blueprints/virtual_processor-shapecompare.png new file mode 100644 index 00000000..6fe8abfb Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-shapecompare.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-unstacker.png b/res_raw/sprites/blueprints/virtual_processor-unstacker.png new file mode 100644 index 00000000..a9ce56dd Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-unstacker.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor.png b/res_raw/sprites/blueprints/virtual_processor.png new file mode 100644 index 00000000..230c4a23 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-analyzer.png b/res_raw/sprites/buildings/virtual_processor-analyzer.png new file mode 100644 index 00000000..f30c8d3b Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-analyzer.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-rotater.png b/res_raw/sprites/buildings/virtual_processor-rotater.png new file mode 100644 index 00000000..8c9dcbdc Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-rotater.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-shapecompare.png b/res_raw/sprites/buildings/virtual_processor-shapecompare.png new file mode 100644 index 00000000..dad1e4bf Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-shapecompare.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-unstacker.png b/res_raw/sprites/buildings/virtual_processor-unstacker.png new file mode 100644 index 00000000..a51edf6d Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-unstacker.png differ diff --git a/res_raw/sprites/buildings/virtual_processor.png b/res_raw/sprites/buildings/virtual_processor.png new file mode 100644 index 00000000..87093df4 Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor.png differ diff --git a/src/css/icons.scss b/src/css/icons.scss index 38c32fd5..85054264 100644 --- a/src/css/icons.scss +++ b/src/css/icons.scss @@ -1,38 +1,38 @@ -$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire, - constant_signal, logic_gate, lever, filter, wire_tunnel, display; - -@each $building in $buildings { - [data-icon="building_icons/#{$building}.png"] { - background-image: uiResource("res/ui/building_icons/#{$building}.png") !important; - } -} - -$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt, - underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl, - stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage; -@each $building in $buildingsAndVariants { - [data-icon="building_tutorials/#{$building}.png"] { - background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important; - } -} - -// Special case -[data-icon="building_tutorials/painter-mirrored.png"] { - background-image: uiResource("res/ui/building_tutorials/painter.png") !important; -} - -$icons: notification_saved, notification_success, notification_upgrade; -@each $icon in $icons { - [data-icon="icons/#{$icon}.png"] { - background-image: uiResource("res/ui/icons/#{$icon}.png") !important; - } -} - -$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi, - th, hu, pl, ja, kor, no, pt-PT; - -@each $language in $languages { - [data-languageicon="#{$language}"] { - background-image: uiResource("languages/#{$language}.svg") !important; - } -} +$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire, + constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor; + +@each $building in $buildings { + [data-icon="building_icons/#{$building}.png"] { + background-image: uiResource("res/ui/building_icons/#{$building}.png") !important; + } +} + +$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt, + underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl, + stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage; +@each $building in $buildingsAndVariants { + [data-icon="building_tutorials/#{$building}.png"] { + background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important; + } +} + +// Special case +[data-icon="building_tutorials/painter-mirrored.png"] { + background-image: uiResource("res/ui/building_tutorials/painter.png") !important; +} + +$icons: notification_saved, notification_success, notification_upgrade; +@each $icon in $icons { + [data-icon="icons/#{$icon}.png"] { + background-image: uiResource("res/ui/icons/#{$icon}.png") !important; + } +} + +$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi, + th, hu, pl, ja, kor, no, pt-PT; + +@each $language in $languages { + [data-languageicon="#{$language}"] { + background-image: uiResource("languages/#{$language}.svg") !important; + } +} diff --git a/src/js/core/buffer_maintainer.js b/src/js/core/buffer_maintainer.js index c28c0ee5..3d466f14 100644 --- a/src/js/core/buffer_maintainer.js +++ b/src/js/core/buffer_maintainer.js @@ -13,7 +13,7 @@ import { round1Digit } from "./utils"; const logger = createLogger("buffers"); -const bufferGcDurationSeconds = 10; +const bufferGcDurationSeconds = 5; export class BufferMaintainer { /** @@ -27,6 +27,31 @@ export class BufferMaintainer { this.iterationIndex = 1; this.lastIteration = 0; + + this.root.signals.gameFrameStarted.add(this.update, this); + } + + /** + * Returns the buffer stats + */ + getStats() { + let stats = { + rootKeys: 0, + subKeys: 0, + vramBytes: 0, + }; + this.cache.forEach((subCache, key) => { + ++stats.rootKeys; + + subCache.forEach((cacheEntry, subKey) => { + ++stats.subKeys; + + const canvas = cacheEntry.canvas; + stats.vramBytes += canvas.width * canvas.height * 4; + }); + }); + + return stats; } /** diff --git a/src/js/core/config.js b/src/js/core/config.js index 3f6362c1..8d30aebb 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -53,6 +53,8 @@ export const globalConfig = { beltSpeedItemsPerSecond: 2, minerSpeedItemsPerSecond: 0, // COMPUTED + defaultItemDiameter: 20, + itemSpacingOnBelts: 0.63, wiresSpeedItemsPerSecond: 6, diff --git a/src/js/core/config.local.js b/src/js/core/config.local.js index 7bf9a002..ec62d3c1 100644 --- a/src/js/core/config.local.js +++ b/src/js/core/config.local.js @@ -95,5 +95,14 @@ export default { // Whether to items / s instead of items / m in stats // detailedStatistics: true, // ----------------------------------------------------------------------------------- + // Shows detailed information about which atlas is used + // showAtlasInfo: true, + // ----------------------------------------------------------------------------------- + // Renders the rotation of all wires + // renderWireRotations: true, + // ----------------------------------------------------------------------------------- + // Renders information about wire networks + // renderWireNetworkInfos: true, + // ----------------------------------------------------------------------------------- /* dev:end */ }; diff --git a/src/js/core/rectangle.js b/src/js/core/rectangle.js index 1cbfdc27..f17825ca 100644 --- a/src/js/core/rectangle.js +++ b/src/js/core/rectangle.js @@ -53,27 +53,6 @@ export class Rectangle { return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom; } - /** - * Returns a rectangle arround a rotated point - * @param {Array} points - * @param {number} angle - * @returns {Rectangle} - */ - static getAroundPointsRotated(points, angle) { - let minX = 1e10; - let minY = 1e10; - let maxX = -1e10; - let maxY = -1e10; - for (let i = 0; i < points.length; ++i) { - const rotated = points[i].rotated(angle); - minX = Math.min(minX, rotated.x); - minY = Math.min(minY, rotated.y); - maxX = Math.max(maxX, rotated.x); - maxY = Math.max(maxY, rotated.y); - } - return new Rectangle(minX, minY, maxX - minX, maxY - minY); - } - /** * Copies this instance * @returns {Rectangle} @@ -82,28 +61,6 @@ export class Rectangle { return new Rectangle(this.x, this.y, this.w, this.h); } - /** - * Ensures the rectangle contains the given square - * @param {number} centerX - * @param {number} centerY - * @param {number} halfWidth - * @param {number} halfHeight - */ - extendBySquare(centerX, centerY, halfWidth, halfHeight) { - if (this.isEmpty()) { - // Just assign values since this rectangle is empty - this.x = centerX - halfWidth; - this.y = centerY - halfHeight; - this.w = halfWidth * 2; - this.h = halfHeight * 2; - } else { - this.setLeft(Math.min(this.x, centerX - halfWidth)); - this.setRight(Math.max(this.right(), centerX + halfWidth)); - this.setTop(Math.min(this.y, centerY - halfHeight)); - this.setBottom(Math.max(this.bottom(), centerY + halfHeight)); - } - } - /** * Returns if this rectangle is empty * @returns {boolean} @@ -259,14 +216,6 @@ export class Rectangle { return new Rectangle(this.x - amount, this.y - amount, this.w + 2 * amount, this.h + 2 * amount); } - /** - * Helper for computing a culling area. Returns the top left tile - * @returns {Vector} - */ - getMinStartTile() { - return new Vector(this.x, this.y).snapWorldToTile(); - } - /** * Returns if the given rectangle is contained * @param {Rectangle} rect @@ -394,7 +343,7 @@ export class Rectangle { } /** - * Returns a new recangle in tile space which includes all tiles which are visible in this rect + * Returns a new rectangle in tile space which includes all tiles which are visible in this rect * @returns {Rectangle} */ toTileCullRectangle() { diff --git a/src/js/game/base_item.js b/src/js/game/base_item.js index 61dc3f34..cbd89e7f 100644 --- a/src/js/game/base_item.js +++ b/src/js/game/base_item.js @@ -1,3 +1,4 @@ +import { globalConfig } from "../core/config"; import { DrawParameters } from "../core/draw_parameters"; import { BasicSerializableObject } from "../savegame/serialization"; @@ -57,7 +58,22 @@ export class BaseItem extends BasicSerializableObject { * @param {DrawParameters} parameters * @param {number=} diameter */ - drawCentered(x, y, parameters, diameter) {} + drawItemCenteredClipped(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { + if (parameters.visibleRect.containsCircle(x, y, diameter / 2)) { + this.drawItemCenteredImpl(x, y, parameters, diameter); + } + } + + /** + * INTERNAL + * @param {number} x + * @param {number} y + * @param {DrawParameters} parameters + * @param {number=} diameter + */ + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { + abstract; + } getBackgroundColorAsResource() { abstract; diff --git a/src/js/game/belt_path.js b/src/js/game/belt_path.js index 9e665487..0e4b7b79 100644 --- a/src/js/game/belt_path.js +++ b/src/js/game/belt_path.js @@ -1194,9 +1194,13 @@ export class BeltPath extends BasicSerializableObject { const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile(); const distanceAndItem = this.items[currentItemIndex]; - if (parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, 10)) { - distanceAndItem[_item].drawCentered(worldPos.x, worldPos.y, parameters); - } + + distanceAndItem[_item].drawItemCenteredClipped( + worldPos.x, + worldPos.y, + parameters, + globalConfig.defaultItemDiameter + ); // Check for the next item currentItemPos += distanceAndItem[_nextDistance]; diff --git a/src/js/game/blueprint.js b/src/js/game/blueprint.js index dc30554d..ccbbc248 100644 --- a/src/js/game/blueprint.js +++ b/src/js/game/blueprint.js @@ -92,7 +92,7 @@ export class Blueprint { parameters.context.globalAlpha = 1; } - staticComp.drawSpriteOnFullEntityBounds(parameters, staticComp.getBlueprintSprite(), 0, newPos); + staticComp.drawSpriteOnBoundsClipped(parameters, staticComp.getBlueprintSprite(), 0, newPos); } parameters.context.globalAlpha = 1; } diff --git a/src/js/game/buildings/virtual_processor.js b/src/js/game/buildings/virtual_processor.js new file mode 100644 index 00000000..dba8978a --- /dev/null +++ b/src/js/game/buildings/virtual_processor.js @@ -0,0 +1,151 @@ +import { Vector, enumDirection } from "../../core/vector"; +import { LogicGateComponent, enumLogicGateType } from "../components/logic_gate"; +import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; + +/** @enum {string} */ +export const enumVirtualProcessorVariants = { + analyzer: "analyzer", + rotater: "rotater", + unstacker: "unstacker", + shapecompare: "shapecompare", +}; + +/** @enum {string} */ +export const enumVariantToGate = { + [defaultBuildingVariant]: enumLogicGateType.cutter, + [enumVirtualProcessorVariants.analyzer]: enumLogicGateType.analyzer, + [enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater, + [enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker, + [enumVirtualProcessorVariants.shapecompare]: enumLogicGateType.shapecompare, +}; + +export class MetaVirtualProcessorBuilding extends MetaBuilding { + constructor() { + super("virtual_processor"); + } + + getSilhouetteColor() { + return "#823cab"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [ + defaultBuildingVariant, + enumVirtualProcessorVariants.rotater, + enumVirtualProcessorVariants.unstacker, + enumVirtualProcessorVariants.analyzer, + enumVirtualProcessorVariants.shapecompare, + ]; + } + + getRenderPins() { + // We already have it included + return false; + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant, variant) { + const gateType = enumVariantToGate[variant]; + entity.components.LogicGate.type = gateType; + const pinComp = entity.components.WiredPins; + switch (gateType) { + case enumLogicGateType.cutter: + case enumLogicGateType.analyzer: + case enumLogicGateType.unstacker: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + case enumLogicGateType.rotater: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + case enumLogicGateType.shapecompare: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + default: + assertAlways("unknown logic gate type: " + gateType); + } + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [], + }) + ); + + entity.addComponent(new LogicGateComponent({})); + } +} diff --git a/src/js/game/components/logic_gate.js b/src/js/game/components/logic_gate.js index bf3f3477..fe151184 100644 --- a/src/js/game/components/logic_gate.js +++ b/src/js/game/components/logic_gate.js @@ -1,30 +1,36 @@ -import { Component } from "../component"; - -/** @enum {string} */ -export const enumLogicGateType = { - and: "and", - not: "not", - xor: "xor", - or: "or", - transistor: "transistor", -}; - -export class LogicGateComponent extends Component { - static getId() { - return "LogicGate"; - } - - duplicateWithoutContents() { - return new LogicGateComponent({ type: this.type }); - } - - /** - * - * @param {object} param0 - * @param {enumLogicGateType=} param0.type - */ - constructor({ type = enumLogicGateType.and }) { - super(); - this.type = type; - } -} +import { Component } from "../component"; + +/** @enum {string} */ +export const enumLogicGateType = { + and: "and", + not: "not", + xor: "xor", + or: "or", + transistor: "transistor", + + analyzer: "analyzer", + rotater: "rotater", + unstacker: "unstacker", + cutter: "cutter", + shapecompare: "shapecompare", +}; + +export class LogicGateComponent extends Component { + static getId() { + return "LogicGate"; + } + + duplicateWithoutContents() { + return new LogicGateComponent({ type: this.type }); + } + + /** + * + * @param {object} param0 + * @param {enumLogicGateType=} param0.type + */ + constructor({ type = enumLogicGateType.and }) { + super(); + this.type = type; + } +} diff --git a/src/js/game/components/static_map_entity.js b/src/js/game/components/static_map_entity.js index db4c834e..3d138e42 100644 --- a/src/js/game/components/static_map_entity.js +++ b/src/js/game/components/static_map_entity.js @@ -162,8 +162,9 @@ export class StaticMapEntityComponent extends Component { * @returns {Vector} */ localTileToWorld(localTile) { - const result = this.applyRotationToVector(localTile); - result.addInplace(this.origin); + const result = localTile.rotateFastMultipleOf90(this.rotation); + result.x += this.origin.x; + result.y += this.origin.y; return result; } @@ -235,7 +236,7 @@ export class StaticMapEntityComponent extends Component { * @param {number=} extrudePixels How many pixels to extrude the sprite * @param {Vector=} overridePosition Whether to drwa the entity at a different location */ - drawSpriteOnFullEntityBounds(parameters, sprite, extrudePixels = 0, overridePosition = null) { + drawSpriteOnBoundsClipped(parameters, sprite, extrudePixels = 0, overridePosition = null) { if (!this.shouldBeDrawn(parameters) && !overridePosition) { return; } diff --git a/src/js/game/components/wired_pins.js b/src/js/game/components/wired_pins.js index 2822ab57..9a19c2b0 100644 --- a/src/js/game/components/wired_pins.js +++ b/src/js/game/components/wired_pins.js @@ -1,6 +1,8 @@ import { enumDirection, Vector } from "../../core/vector"; import { BaseItem } from "../base_item"; import { Component } from "../component"; +import { types } from "../../savegame/serialization"; +import { typeItemSingleton } from "../item_resolver"; /** @enum {string} */ export const enumPinSlotType = { @@ -27,6 +29,16 @@ export class WiredPinsComponent extends Component { return "WiredPins"; } + static getSchema() { + return { + slots: types.array( + types.structured({ + value: types.nullable(typeItemSingleton), + }) + ), + }; + } + /** * * @param {object} param0 diff --git a/src/js/game/core.js b/src/js/game/core.js index 70d69c2c..3ca70bb6 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -9,7 +9,7 @@ import { DrawParameters } from "../core/draw_parameters"; import { gMetaBuildingRegistry } from "../core/global_registries"; import { createLogger } from "../core/logging"; import { Rectangle } from "../core/rectangle"; -import { randomInt, round2Digits } from "../core/utils"; +import { randomInt, round2Digits, round3Digits } from "../core/utils"; import { Vector } from "../core/vector"; import { Savegame } from "../savegame/savegame"; import { SavegameSerializer } from "../savegame/savegame_serializer"; @@ -329,8 +329,7 @@ export class GameCore { return; } - // Update buffers as the very first - root.buffers.update(); + this.root.signals.gameFrameStarted.dispatch(); root.queue.requireRedraw = false; @@ -390,33 +389,24 @@ export class GameCore { // Map overview root.map.drawOverlay(params); } else { + // Background (grid, resources, etc) root.map.drawBackground(params); // Belt items systems.belt.drawBeltItems(params); - // Items being ejected / accepted currently (animations) - systems.itemEjector.draw(params); - systems.itemAcceptor.draw(params); - - // Miner & Static map entities + // Miner & Static map entities etc. root.map.drawForeground(params); // HUB Overlay systems.hub.draw(params); - // Storage items - systems.storage.draw(params); - // Green wires overlay root.hud.parts.wiresOverlay.draw(params); if (this.root.currentLayer === "wires") { // Static map entities root.map.drawWiresForegroundLayer(params); - - // pins - systems.wiredPins.draw(params); } } @@ -464,7 +454,7 @@ export class GameCore { if (G_IS_DEV && globalConfig.debug.showAtlasInfo) { context.font = "13px GameFont"; - context.fillStyle = "yellow"; + context.fillStyle = "blue"; context.fillText( "Atlas: " + desiredAtlasScale + @@ -472,8 +462,22 @@ export class GameCore { round2Digits(zoomLevel) + " / Effective Zoom: " + round2Digits(effectiveZoomLevel), - 200, - 20 + 20, + 600 + ); + + const stats = this.root.buffers.getStats(); + context.fillText( + "Buffers: " + + stats.rootKeys + + " root keys, " + + stats.subKeys + + " sub keys / buffers / VRAM: " + + round2Digits(stats.vramBytes / (1024 * 1024)) + + " MB", + + 20, + 620 ); } diff --git a/src/js/game/game_system_with_filter.js b/src/js/game/game_system_with_filter.js index ef6dfd52..7b1ffbf0 100644 --- a/src/js/game/game_system_with_filter.js +++ b/src/js/game/game_system_with_filter.js @@ -6,8 +6,7 @@ import { Entity } from "./entity"; import { GameRoot } from "./root"; import { GameSystem } from "./game_system"; import { arrayDelete, arrayDeleteValue } from "../core/utils"; -import { DrawParameters } from "../core/draw_parameters"; -import { globalConfig } from "../core/config"; + export class GameSystemWithFilter extends GameSystem { /** * Constructs a new game system with the given component filter. It will process @@ -35,80 +34,6 @@ export class GameSystemWithFilter extends GameSystem { this.root.signals.bulkOperationFinished.add(this.refreshCaches, this); } - /** - * Calls a function for each matching entity on the screen, useful for drawing them - * @param {DrawParameters} parameters - * @param {function} callback - */ - forEachMatchingEntityOnScreen(parameters, callback) { - const cullRange = parameters.visibleRect.toTileCullRectangle(); - if (this.allEntities.length < 100) { - // So, its much quicker to simply perform per-entity checking - - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - if (cullRange.containsRect(entity.components.StaticMapEntity.getTileSpaceBounds())) { - callback(parameters, entity); - } - } - return; - } - - const top = cullRange.top(); - const right = cullRange.right(); - const bottom = cullRange.bottom(); - const left = cullRange.left(); - - const border = 1; - const minY = top - border; - const maxY = bottom + border; - const minX = left - border; - const maxX = right + border - 1; - - const map = this.root.map; - - let seenUids = new Set(); - - const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize); - const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize); - - const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize); - const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize); - - const requiredComponents = this.requiredComponentIds; - - // Render y from top down for proper blending - for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) { - for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) { - const chunk = map.getChunk(chunkX, chunkY, false); - if (!chunk) { - continue; - } - - // BIG TODO: CULLING ON AN ENTITY BASIS - - const entities = chunk.containedEntities; - entityLoop: for (let i = 0; i < entities.length; ++i) { - const entity = entities[i]; - - // Avoid drawing twice - if (seenUids.has(entity.uid)) { - continue; - } - - seenUids.add(entity.uid); - - for (let i = 0; i < requiredComponents.length; ++i) { - if (!entity.components[requiredComponents[i]]) { - continue entityLoop; - } - } - callback(parameters, entity); - } - } - } - } - /** * @param {Entity} entity */ diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index 013fcde4..461a3431 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -374,7 +374,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { // HACK to draw the entity sprite const previewSprite = metaBuilding.getBlueprintSprite(rotationVariant, this.currentVariant.get()); staticComp.origin = worldPos.divideScalar(globalConfig.tileSize).subScalars(0.5, 0.5); - staticComp.drawSpriteOnFullEntityBounds(parameters, previewSprite); + staticComp.drawSpriteOnBoundsClipped(parameters, previewSprite); staticComp.origin = mouseTile; // Draw ejectors diff --git a/src/js/game/hud/parts/sandbox_controller.js b/src/js/game/hud/parts/sandbox_controller.js index 04773019..dd521655 100644 --- a/src/js/game/hud/parts/sandbox_controller.js +++ b/src/js/game/hud/parts/sandbox_controller.js @@ -78,7 +78,7 @@ export class HUDSandboxController extends BaseHUDPart { if (!this.root.hubGoals.storedShapes[blueprintShape]) { this.root.hubGoals.storedShapes[blueprintShape] = 0; } - this.root.hubGoals.storedShapes[blueprintShape] += 1e4; + this.root.hubGoals.storedShapes[blueprintShape] += 1e9; } maxOutAll() { diff --git a/src/js/game/hud/parts/wire_info.js b/src/js/game/hud/parts/wire_info.js index f73d53d7..9394dcc2 100644 --- a/src/js/game/hud/parts/wire_info.js +++ b/src/js/game/hud/parts/wire_info.js @@ -64,11 +64,16 @@ export class HUDWireInfo extends BaseHUDPart { const network = networks[0]; if (network.valueConflict) { - this.spriteConflict.draw(parameters.context, mousePos.x + 10, mousePos.y - 10, 40, 40); + this.spriteConflict.draw(parameters.context, mousePos.x + 15, mousePos.y - 10, 60, 60); } else if (!network.currentValue) { - this.spriteEmpty.draw(parameters.context, mousePos.x + 10, mousePos.y - 10, 40, 40); + this.spriteEmpty.draw(parameters.context, mousePos.x + 15, mousePos.y - 10, 60, 60); } else { - network.currentValue.drawCentered(mousePos.x + 20, mousePos.y, parameters, 40); + network.currentValue.drawItemCenteredClipped( + mousePos.x + 40, + mousePos.y + 10, + parameters, + 60 + ); } } } diff --git a/src/js/game/hud/parts/wires_toolbar.js b/src/js/game/hud/parts/wires_toolbar.js index 542218e2..af5a31dd 100644 --- a/src/js/game/hud/parts/wires_toolbar.js +++ b/src/js/game/hud/parts/wires_toolbar.js @@ -1,25 +1,27 @@ -import { HUDBaseToolbar } from "./base_toolbar"; -import { MetaWireBuilding } from "../../buildings/wire"; -import { MetaConstantSignalBuilding } from "../../buildings/constant_signal"; -import { MetaLogicGateBuilding } from "../../buildings/logic_gate"; -import { MetaLeverBuilding } from "../../buildings/lever"; -import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel"; - -const supportedBuildings = [ - MetaWireBuilding, - MetaWireTunnelBuilding, - MetaConstantSignalBuilding, - MetaLogicGateBuilding, - MetaLeverBuilding, -]; - -export class HUDWiresToolbar extends HUDBaseToolbar { - constructor(root) { - super(root, { - supportedBuildings, - visibilityCondition: () => - !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires", - htmlElementId: "ingame_HUD_wires_toolbar", - }); - } -} +import { HUDBaseToolbar } from "./base_toolbar"; +import { MetaWireBuilding } from "../../buildings/wire"; +import { MetaConstantSignalBuilding } from "../../buildings/constant_signal"; +import { MetaLogicGateBuilding } from "../../buildings/logic_gate"; +import { MetaLeverBuilding } from "../../buildings/lever"; +import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel"; +import { MetaVirtualProcessorBuilding } from "../../buildings/virtual_processor"; + +const supportedBuildings = [ + MetaWireBuilding, + MetaWireTunnelBuilding, + MetaConstantSignalBuilding, + MetaLogicGateBuilding, + MetaLeverBuilding, + MetaVirtualProcessorBuilding, +]; + +export class HUDWiresToolbar extends HUDBaseToolbar { + constructor(root) { + super(root, { + supportedBuildings, + visibilityCondition: () => + !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires", + htmlElementId: "ingame_HUD_wires_toolbar", + }); + } +} diff --git a/src/js/game/items/boolean_item.js b/src/js/game/items/boolean_item.js index 57342bde..38422398 100644 --- a/src/js/game/items/boolean_item.js +++ b/src/js/game/items/boolean_item.js @@ -2,6 +2,7 @@ import { DrawParameters } from "../../core/draw_parameters"; import { Loader } from "../../core/loader"; import { types } from "../../savegame/serialization"; import { BaseItem } from "../base_item"; +import { globalConfig } from "../../core/config"; export class BooleanItem extends BaseItem { static getId() { @@ -46,7 +47,7 @@ export class BooleanItem extends BaseItem { * @param {number} diameter * @param {DrawParameters} parameters */ - drawCentered(x, y, parameters, diameter = 12) { + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { let sprite; if (this.value) { sprite = Loader.getSprite("sprites/wires/boolean_true.png"); diff --git a/src/js/game/items/color_item.js b/src/js/game/items/color_item.js index 76a1e1d0..19d26286 100644 --- a/src/js/game/items/color_item.js +++ b/src/js/game/items/color_item.js @@ -5,6 +5,7 @@ import { types } from "../../savegame/serialization"; import { BaseItem } from "../base_item"; import { enumColors, enumColorsToHexCode } from "../colors"; import { THEME } from "../theme"; +import { drawSpriteClipped } from "../../core/draw_utils"; export class ColorItem extends BaseItem { static getId() { @@ -54,23 +55,33 @@ export class ColorItem extends BaseItem { * @param {number} diameter * @param {DrawParameters} parameters */ - drawCentered(x, y, parameters, diameter = 12) { + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { if (!this.bufferGenerator) { this.bufferGenerator = this.internalGenerateColorBuffer.bind(this); } + const realDiameter = diameter * 0.6; const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); - - const key = diameter + "/" + dpi; + const key = realDiameter + "/" + dpi + "/" + this.color; const canvas = parameters.root.buffers.getForKey({ - key, - subKey: this.color, - w: diameter, - h: diameter, + key: "coloritem", + subKey: key, + w: realDiameter, + h: realDiameter, dpi, redrawMethod: this.bufferGenerator, }); - parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter); + + drawSpriteClipped({ + parameters, + sprite: canvas, + x: x - realDiameter / 2, + y: y - realDiameter / 2, + w: realDiameter, + h: realDiameter, + originalW: realDiameter * dpi, + originalH: realDiameter * dpi, + }); } /** * diff --git a/src/js/game/items/shape_item.js b/src/js/game/items/shape_item.js index 44081cab..d99a7251 100644 --- a/src/js/game/items/shape_item.js +++ b/src/js/game/items/shape_item.js @@ -3,6 +3,7 @@ import { types } from "../../savegame/serialization"; import { BaseItem } from "../base_item"; import { ShapeDefinition } from "../shape_definition"; import { THEME } from "../theme"; +import { globalConfig } from "../../core/config"; export class ShapeItem extends BaseItem { static getId() { @@ -55,7 +56,7 @@ export class ShapeItem extends BaseItem { * @param {DrawParameters} parameters * @param {number=} diameter */ - drawCentered(x, y, parameters, diameter) { + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { this.definition.drawCentered(x, y, parameters, diameter); } } diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index f88e5a22..099e2b21 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -1,456 +1,457 @@ -/* typehints:start */ -import { GameRoot } from "./root"; -import { InputReceiver } from "../core/input_receiver"; -import { Application } from "../application"; -/* typehints:end */ - -import { Signal, STOP_PROPAGATION } from "../core/signal"; -import { IS_MOBILE } from "../core/config"; -import { T } from "../translations"; -function key(str) { - return str.toUpperCase().charCodeAt(0); -} - -export const KEYMAPPINGS = { - general: { - confirm: { keyCode: 13 }, // enter - back: { keyCode: 27, builtin: true }, // escape - }, - - ingame: { - menuOpenShop: { keyCode: key("F") }, - menuOpenStats: { keyCode: key("G") }, - menuClose: { keyCode: key("Q") }, - - toggleHud: { keyCode: 113 }, // F2 - exportScreenshot: { keyCode: 114 }, // F3PS - toggleFPSInfo: { keyCode: 115 }, // F4 - - switchLayers: { keyCode: key("Y") }, - }, - - navigation: { - mapMoveUp: { keyCode: key("W") }, - mapMoveRight: { keyCode: key("D") }, - mapMoveDown: { keyCode: key("S") }, - mapMoveLeft: { keyCode: key("A") }, - mapMoveFaster: { keyCode: 16 }, //shift - - centerMap: { keyCode: 32 }, // SPACE - mapZoomIn: { keyCode: 187, repeated: true }, // "+" - mapZoomOut: { keyCode: 189, repeated: true }, // "-" - - createMarker: { keyCode: key("M") }, - }, - - buildings: { - belt: { keyCode: key("1") }, - splitter: { keyCode: key("2") }, - underground_belt: { keyCode: key("3") }, - miner: { keyCode: key("4") }, - cutter: { keyCode: key("5") }, - rotater: { keyCode: key("6") }, - stacker: { keyCode: key("7") }, - mixer: { keyCode: key("8") }, - painter: { keyCode: key("9") }, - trash: { keyCode: key("0") }, - - lever: { keyCode: key("L") }, - filter: { keyCode: key("B") }, - display: { keyCode: key("N") }, - - wire: { keyCode: key("1") }, - wire_tunnel: { keyCode: key("2") }, - constant_signal: { keyCode: key("3") }, - logic_gate: { keyCode: key("4") }, - }, - - placement: { - pipette: { keyCode: key("Q") }, - rotateWhilePlacing: { keyCode: key("R") }, - rotateInverseModifier: { keyCode: 16 }, // SHIFT - cycleBuildingVariants: { keyCode: key("T") }, - cycleBuildings: { keyCode: 9 }, // TAB - switchDirectionLockSide: { keyCode: key("R") }, - }, - - massSelect: { - massSelectStart: { keyCode: 17 }, // CTRL - massSelectSelectMultiple: { keyCode: 16 }, // SHIFT - massSelectCopy: { keyCode: key("C") }, - massSelectCut: { keyCode: key("X") }, - confirmMassDelete: { keyCode: 46 }, // DEL - pasteLastBlueprint: { keyCode: key("V") }, - }, - - placementModifiers: { - lockBeltDirection: { keyCode: 16 }, // SHIFT - placementDisableAutoOrientation: { keyCode: 17 }, // CTRL - placeMultiple: { keyCode: 16 }, // SHIFT - placeInverse: { keyCode: 18 }, // ALT - }, -}; - -// Assign ids -for (const categoryId in KEYMAPPINGS) { - for (const mappingId in KEYMAPPINGS[categoryId]) { - KEYMAPPINGS[categoryId][mappingId].id = mappingId; - } -} - -export const KEYCODE_LMB = 1; -export const KEYCODE_MMB = 2; -export const KEYCODE_RMB = 3; - -/** - * Returns a keycode -> string - * @param {number} code - * @returns {string} - */ -export function getStringForKeyCode(code) { - switch (code) { - case KEYCODE_LMB: - return "LMB"; - case KEYCODE_MMB: - return "MMB"; - case KEYCODE_RMB: - return "RMB"; - case 4: - return "MB4"; - case 5: - return "MB5"; - case 8: - return "⌫"; - case 9: - return T.global.keys.tab; - case 13: - return "⏎"; - case 16: - return "⇪"; - case 17: - return T.global.keys.control; - case 18: - return T.global.keys.alt; - case 19: - return "PAUSE"; - case 20: - return "CAPS"; - case 27: - return T.global.keys.escape; - case 32: - return T.global.keys.space; - case 33: - return "PGUP"; - case 34: - return "PGDOWN"; - case 35: - return "END"; - case 36: - return "HOME"; - case 37: - return "⬅"; - case 38: - return "⬆"; - case 39: - return "➡"; - case 40: - return "⬇"; - case 44: - return "PRNT"; - case 45: - return "INS"; - case 46: - return "DEL"; - case 93: - return "SEL"; - case 96: - return "NUM 0"; - case 97: - return "NUM 1"; - case 98: - return "NUM 2"; - case 99: - return "NUM 3"; - case 100: - return "NUM 4"; - case 101: - return "NUM 5"; - case 102: - return "NUM 6"; - case 103: - return "NUM 7"; - case 104: - return "NUM 8"; - case 105: - return "NUM 9"; - case 106: - return "*"; - case 107: - return "+"; - case 109: - return "-"; - case 110: - return "."; - case 111: - return "/"; - case 112: - return "F1"; - case 113: - return "F2"; - case 114: - return "F3"; - case 115: - return "F4"; - case 116: - return "F4"; - case 117: - return "F5"; - case 118: - return "F6"; - case 119: - return "F7"; - case 120: - return "F8"; - case 121: - return "F9"; - case 122: - return "F10"; - case 123: - return "F11"; - case 124: - return "F12"; - - case 144: - return "NUMLOCK"; - case 145: - return "SCRLOCK"; - case 182: - return "COMP"; - case 183: - return "CALC"; - case 186: - return ";"; - case 187: - return "+"; - case 188: - return ","; - case 189: - return "-"; - case 191: - return "/"; - case 219: - return "["; - case 220: - return "\\"; - case 221: - return "]"; - case 222: - return "'"; - } - - return String.fromCharCode(code); -} - -export class Keybinding { - /** - * - * @param {KeyActionMapper} keyMapper - * @param {Application} app - * @param {object} param0 - * @param {number} param0.keyCode - * @param {boolean=} param0.builtin - * @param {boolean=} param0.repeated - */ - constructor(keyMapper, app, { keyCode, builtin = false, repeated = false }) { - assert(keyCode && Number.isInteger(keyCode), "Invalid key code: " + keyCode); - this.keyMapper = keyMapper; - this.app = app; - this.keyCode = keyCode; - this.builtin = builtin; - this.repeated = repeated; - - this.signal = new Signal(); - this.toggled = new Signal(); - } - - /** - * Returns whether this binding is currently pressed - * @returns {boolean} - */ - get pressed() { - // Check if the key is down - if (this.app.inputMgr.keysDown.has(this.keyCode)) { - // Check if it is the top reciever - const reciever = this.keyMapper.inputReceiver; - return this.app.inputMgr.getTopReciever() === reciever; - } - return false; - } - - /** - * Adds an event listener - * @param {function() : void} receiver - * @param {object=} scope - */ - add(receiver, scope = null) { - this.signal.add(receiver, scope); - } - - /** - * @param {Element} elem - * @returns {HTMLElement} the created element, or null if the keybindings are not shown - * */ - appendLabelToElement(elem) { - if (IS_MOBILE) { - return null; - } - const spacer = document.createElement("code"); - spacer.classList.add("keybinding"); - spacer.innerHTML = getStringForKeyCode(this.keyCode); - elem.appendChild(spacer); - return spacer; - } - - /** - * Returns the key code as a nice string - */ - getKeyCodeString() { - return getStringForKeyCode(this.keyCode); - } - - /** - * Remvoes all signal receivers - */ - clearSignalReceivers() { - this.signal.removeAll(); - } -} - -export class KeyActionMapper { - /** - * - * @param {GameRoot} root - * @param {InputReceiver} inputReciever - */ - constructor(root, inputReciever) { - this.root = root; - this.inputReceiver = inputReciever; - - inputReciever.keydown.add(this.handleKeydown, this); - inputReciever.keyup.add(this.handleKeyup, this); - - /** @type {Object.} */ - this.keybindings = {}; - - const overrides = root.app.settings.getKeybindingOverrides(); - - for (const category in KEYMAPPINGS) { - for (const key in KEYMAPPINGS[category]) { - let payload = Object.assign({}, KEYMAPPINGS[category][key]); - if (overrides[key]) { - payload.keyCode = overrides[key]; - } - - this.keybindings[key] = new Keybinding(this, this.root.app, payload); - } - } - - inputReciever.pageBlur.add(this.onPageBlur, this); - inputReciever.destroyed.add(this.cleanup, this); - } - - /** - * Returns all keybindings starting with the given id - * @param {string} pattern - * @returns {Array} - */ - getKeybindingsStartingWith(pattern) { - let result = []; - for (const key in this.keybindings) { - if (key.startsWith(pattern)) { - result.push(this.keybindings[key]); - } - } - return result; - } - - /** - * Forwards the given events to the other mapper (used in tooltips) - * @param {KeyActionMapper} receiver - * @param {Array} bindings - */ - forward(receiver, bindings) { - for (let i = 0; i < bindings.length; ++i) { - const key = bindings[i]; - this.keybindings[key].signal.add((...args) => receiver.keybindings[key].signal.dispatch(...args)); - } - } - - cleanup() { - for (const key in this.keybindings) { - this.keybindings[key].signal.removeAll(); - } - } - - onPageBlur() { - // Reset all down states - // Find mapping - for (const key in this.keybindings) { - /** @type {Keybinding} */ - const binding = this.keybindings[key]; - } - } - - /** - * Internal keydown handler - * @param {object} param0 - * @param {number} param0.keyCode - * @param {boolean} param0.shift - * @param {boolean} param0.alt - * @param {boolean=} param0.initial - */ - handleKeydown({ keyCode, shift, alt, initial }) { - let stop = false; - - // Find mapping - for (const key in this.keybindings) { - /** @type {Keybinding} */ - const binding = this.keybindings[key]; - if (binding.keyCode === keyCode && (initial || binding.repeated)) { - /** @type {Signal} */ - const signal = this.keybindings[key].signal; - if (signal.dispatch() === STOP_PROPAGATION) { - return; - } - } - } - - if (stop) { - return STOP_PROPAGATION; - } - } - - /** - * Internal keyup handler - * @param {object} param0 - * @param {number} param0.keyCode - * @param {boolean} param0.shift - * @param {boolean} param0.alt - */ - handleKeyup({ keyCode, shift, alt }) { - // Empty - } - - /** - * Returns a given keybinding - * @param {{ keyCode: number }} binding - * @returns {Keybinding} - */ - getBinding(binding) { - // @ts-ignore - const id = binding.id; - assert(id, "Not a valid keybinding: " + JSON.stringify(binding)); - assert(this.keybindings[id], "Keybinding " + id + " not known!"); - return this.keybindings[id]; - } -} +/* typehints:start */ +import { GameRoot } from "./root"; +import { InputReceiver } from "../core/input_receiver"; +import { Application } from "../application"; +/* typehints:end */ + +import { Signal, STOP_PROPAGATION } from "../core/signal"; +import { IS_MOBILE } from "../core/config"; +import { T } from "../translations"; +function key(str) { + return str.toUpperCase().charCodeAt(0); +} + +export const KEYMAPPINGS = { + general: { + confirm: { keyCode: 13 }, // enter + back: { keyCode: 27, builtin: true }, // escape + }, + + ingame: { + menuOpenShop: { keyCode: key("F") }, + menuOpenStats: { keyCode: key("G") }, + menuClose: { keyCode: key("Q") }, + + toggleHud: { keyCode: 113 }, // F2 + exportScreenshot: { keyCode: 114 }, // F3PS + toggleFPSInfo: { keyCode: 115 }, // F4 + + switchLayers: { keyCode: key("Y") }, + }, + + navigation: { + mapMoveUp: { keyCode: key("W") }, + mapMoveRight: { keyCode: key("D") }, + mapMoveDown: { keyCode: key("S") }, + mapMoveLeft: { keyCode: key("A") }, + mapMoveFaster: { keyCode: 16 }, //shift + + centerMap: { keyCode: 32 }, // SPACE + mapZoomIn: { keyCode: 187, repeated: true }, // "+" + mapZoomOut: { keyCode: 189, repeated: true }, // "-" + + createMarker: { keyCode: key("M") }, + }, + + buildings: { + belt: { keyCode: key("1") }, + splitter: { keyCode: key("2") }, + underground_belt: { keyCode: key("3") }, + miner: { keyCode: key("4") }, + cutter: { keyCode: key("5") }, + rotater: { keyCode: key("6") }, + stacker: { keyCode: key("7") }, + mixer: { keyCode: key("8") }, + painter: { keyCode: key("9") }, + trash: { keyCode: key("0") }, + + lever: { keyCode: key("L") }, + filter: { keyCode: key("B") }, + display: { keyCode: key("N") }, + + wire: { keyCode: key("1") }, + wire_tunnel: { keyCode: key("2") }, + constant_signal: { keyCode: key("3") }, + logic_gate: { keyCode: key("4") }, + virtual_processor: { keyCode: key("5") }, + }, + + placement: { + pipette: { keyCode: key("Q") }, + rotateWhilePlacing: { keyCode: key("R") }, + rotateInverseModifier: { keyCode: 16 }, // SHIFT + cycleBuildingVariants: { keyCode: key("T") }, + cycleBuildings: { keyCode: 9 }, // TAB + switchDirectionLockSide: { keyCode: key("R") }, + }, + + massSelect: { + massSelectStart: { keyCode: 17 }, // CTRL + massSelectSelectMultiple: { keyCode: 16 }, // SHIFT + massSelectCopy: { keyCode: key("C") }, + massSelectCut: { keyCode: key("X") }, + confirmMassDelete: { keyCode: 46 }, // DEL + pasteLastBlueprint: { keyCode: key("V") }, + }, + + placementModifiers: { + lockBeltDirection: { keyCode: 16 }, // SHIFT + placementDisableAutoOrientation: { keyCode: 17 }, // CTRL + placeMultiple: { keyCode: 16 }, // SHIFT + placeInverse: { keyCode: 18 }, // ALT + }, +}; + +// Assign ids +for (const categoryId in KEYMAPPINGS) { + for (const mappingId in KEYMAPPINGS[categoryId]) { + KEYMAPPINGS[categoryId][mappingId].id = mappingId; + } +} + +export const KEYCODE_LMB = 1; +export const KEYCODE_MMB = 2; +export const KEYCODE_RMB = 3; + +/** + * Returns a keycode -> string + * @param {number} code + * @returns {string} + */ +export function getStringForKeyCode(code) { + switch (code) { + case KEYCODE_LMB: + return "LMB"; + case KEYCODE_MMB: + return "MMB"; + case KEYCODE_RMB: + return "RMB"; + case 4: + return "MB4"; + case 5: + return "MB5"; + case 8: + return "⌫"; + case 9: + return T.global.keys.tab; + case 13: + return "⏎"; + case 16: + return "⇪"; + case 17: + return T.global.keys.control; + case 18: + return T.global.keys.alt; + case 19: + return "PAUSE"; + case 20: + return "CAPS"; + case 27: + return T.global.keys.escape; + case 32: + return T.global.keys.space; + case 33: + return "PGUP"; + case 34: + return "PGDOWN"; + case 35: + return "END"; + case 36: + return "HOME"; + case 37: + return "⬅"; + case 38: + return "⬆"; + case 39: + return "➡"; + case 40: + return "⬇"; + case 44: + return "PRNT"; + case 45: + return "INS"; + case 46: + return "DEL"; + case 93: + return "SEL"; + case 96: + return "NUM 0"; + case 97: + return "NUM 1"; + case 98: + return "NUM 2"; + case 99: + return "NUM 3"; + case 100: + return "NUM 4"; + case 101: + return "NUM 5"; + case 102: + return "NUM 6"; + case 103: + return "NUM 7"; + case 104: + return "NUM 8"; + case 105: + return "NUM 9"; + case 106: + return "*"; + case 107: + return "+"; + case 109: + return "-"; + case 110: + return "."; + case 111: + return "/"; + case 112: + return "F1"; + case 113: + return "F2"; + case 114: + return "F3"; + case 115: + return "F4"; + case 116: + return "F4"; + case 117: + return "F5"; + case 118: + return "F6"; + case 119: + return "F7"; + case 120: + return "F8"; + case 121: + return "F9"; + case 122: + return "F10"; + case 123: + return "F11"; + case 124: + return "F12"; + + case 144: + return "NUMLOCK"; + case 145: + return "SCRLOCK"; + case 182: + return "COMP"; + case 183: + return "CALC"; + case 186: + return ";"; + case 187: + return "+"; + case 188: + return ","; + case 189: + return "-"; + case 191: + return "/"; + case 219: + return "["; + case 220: + return "\\"; + case 221: + return "]"; + case 222: + return "'"; + } + + return String.fromCharCode(code); +} + +export class Keybinding { + /** + * + * @param {KeyActionMapper} keyMapper + * @param {Application} app + * @param {object} param0 + * @param {number} param0.keyCode + * @param {boolean=} param0.builtin + * @param {boolean=} param0.repeated + */ + constructor(keyMapper, app, { keyCode, builtin = false, repeated = false }) { + assert(keyCode && Number.isInteger(keyCode), "Invalid key code: " + keyCode); + this.keyMapper = keyMapper; + this.app = app; + this.keyCode = keyCode; + this.builtin = builtin; + this.repeated = repeated; + + this.signal = new Signal(); + this.toggled = new Signal(); + } + + /** + * Returns whether this binding is currently pressed + * @returns {boolean} + */ + get pressed() { + // Check if the key is down + if (this.app.inputMgr.keysDown.has(this.keyCode)) { + // Check if it is the top reciever + const reciever = this.keyMapper.inputReceiver; + return this.app.inputMgr.getTopReciever() === reciever; + } + return false; + } + + /** + * Adds an event listener + * @param {function() : void} receiver + * @param {object=} scope + */ + add(receiver, scope = null) { + this.signal.add(receiver, scope); + } + + /** + * @param {Element} elem + * @returns {HTMLElement} the created element, or null if the keybindings are not shown + * */ + appendLabelToElement(elem) { + if (IS_MOBILE) { + return null; + } + const spacer = document.createElement("code"); + spacer.classList.add("keybinding"); + spacer.innerHTML = getStringForKeyCode(this.keyCode); + elem.appendChild(spacer); + return spacer; + } + + /** + * Returns the key code as a nice string + */ + getKeyCodeString() { + return getStringForKeyCode(this.keyCode); + } + + /** + * Remvoes all signal receivers + */ + clearSignalReceivers() { + this.signal.removeAll(); + } +} + +export class KeyActionMapper { + /** + * + * @param {GameRoot} root + * @param {InputReceiver} inputReciever + */ + constructor(root, inputReciever) { + this.root = root; + this.inputReceiver = inputReciever; + + inputReciever.keydown.add(this.handleKeydown, this); + inputReciever.keyup.add(this.handleKeyup, this); + + /** @type {Object.} */ + this.keybindings = {}; + + const overrides = root.app.settings.getKeybindingOverrides(); + + for (const category in KEYMAPPINGS) { + for (const key in KEYMAPPINGS[category]) { + let payload = Object.assign({}, KEYMAPPINGS[category][key]); + if (overrides[key]) { + payload.keyCode = overrides[key]; + } + + this.keybindings[key] = new Keybinding(this, this.root.app, payload); + } + } + + inputReciever.pageBlur.add(this.onPageBlur, this); + inputReciever.destroyed.add(this.cleanup, this); + } + + /** + * Returns all keybindings starting with the given id + * @param {string} pattern + * @returns {Array} + */ + getKeybindingsStartingWith(pattern) { + let result = []; + for (const key in this.keybindings) { + if (key.startsWith(pattern)) { + result.push(this.keybindings[key]); + } + } + return result; + } + + /** + * Forwards the given events to the other mapper (used in tooltips) + * @param {KeyActionMapper} receiver + * @param {Array} bindings + */ + forward(receiver, bindings) { + for (let i = 0; i < bindings.length; ++i) { + const key = bindings[i]; + this.keybindings[key].signal.add((...args) => receiver.keybindings[key].signal.dispatch(...args)); + } + } + + cleanup() { + for (const key in this.keybindings) { + this.keybindings[key].signal.removeAll(); + } + } + + onPageBlur() { + // Reset all down states + // Find mapping + for (const key in this.keybindings) { + /** @type {Keybinding} */ + const binding = this.keybindings[key]; + } + } + + /** + * Internal keydown handler + * @param {object} param0 + * @param {number} param0.keyCode + * @param {boolean} param0.shift + * @param {boolean} param0.alt + * @param {boolean=} param0.initial + */ + handleKeydown({ keyCode, shift, alt, initial }) { + let stop = false; + + // Find mapping + for (const key in this.keybindings) { + /** @type {Keybinding} */ + const binding = this.keybindings[key]; + if (binding.keyCode === keyCode && (initial || binding.repeated)) { + /** @type {Signal} */ + const signal = this.keybindings[key].signal; + if (signal.dispatch() === STOP_PROPAGATION) { + return; + } + } + } + + if (stop) { + return STOP_PROPAGATION; + } + } + + /** + * Internal keyup handler + * @param {object} param0 + * @param {number} param0.keyCode + * @param {boolean} param0.shift + * @param {boolean} param0.alt + */ + handleKeyup({ keyCode, shift, alt }) { + // Empty + } + + /** + * Returns a given keybinding + * @param {{ keyCode: number }} binding + * @returns {Keybinding} + */ + getBinding(binding) { + // @ts-ignore + const id = binding.id; + assert(id, "Not a valid keybinding: " + JSON.stringify(binding)); + assert(this.keybindings[id], "Keybinding " + id + " not known!"); + return this.keybindings[id]; + } +} diff --git a/src/js/game/map_chunk_view.js b/src/js/game/map_chunk_view.js index c62a3401..0918e7af 100644 --- a/src/js/game/map_chunk_view.js +++ b/src/js/game/map_chunk_view.js @@ -52,10 +52,16 @@ export class MapChunkView extends MapChunk { */ drawForegroundLayer(parameters) { const systems = this.root.systemMgr.systems; + + systems.itemEjector.drawChunk(parameters, this); + systems.itemAcceptor.drawChunk(parameters, this); + systems.miner.drawChunk(parameters, this); + systems.staticMapEntities.drawChunk(parameters, this); systems.lever.drawChunk(parameters, this); systems.display.drawChunk(parameters, this); + systems.storage.drawChunk(parameters, this); } /** @@ -97,11 +103,9 @@ export class MapChunkView extends MapChunk { const destX = this.x * dims + patch.pos.x * globalConfig.tileSize; const destY = this.y * dims + patch.pos.y * globalConfig.tileSize; - const destSize = Math.min(80, 30 / parameters.zoomLevel); + const diameter = Math.min(80, 30 / parameters.zoomLevel); - if (parameters.visibleRect.containsCircle(destX, destY, destSize)) { - patch.item.drawCentered(destX, destY, parameters, destSize); - } + patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter); } } } @@ -265,5 +269,6 @@ export class MapChunkView extends MapChunk { const systems = this.root.systemMgr.systems; systems.wire.drawChunk(parameters, this); systems.staticMapEntities.drawWiresChunk(parameters, this); + systems.wiredPins.drawChunk(parameters, this); } } diff --git a/src/js/game/meta_building_registry.js b/src/js/game/meta_building_registry.js index 7bf3b097..8e98a54d 100644 --- a/src/js/game/meta_building_registry.js +++ b/src/js/game/meta_building_registry.js @@ -1,162 +1,171 @@ -import { gMetaBuildingRegistry } from "../core/global_registries"; -import { createLogger } from "../core/logging"; -import { MetaBeltBuilding } from "./buildings/belt"; -import { MetaBeltBaseBuilding } from "./buildings/belt_base"; -import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter"; -import { MetaHubBuilding } from "./buildings/hub"; -import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner"; -import { MetaMixerBuilding } from "./buildings/mixer"; -import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter"; -import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater"; -import { enumSplitterVariants, MetaSplitterBuilding } from "./buildings/splitter"; -import { MetaStackerBuilding } from "./buildings/stacker"; -import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash"; -import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; -import { MetaWireBuilding } from "./buildings/wire"; -import { gBuildingVariants, registerBuildingVariant } from "./building_codes"; -import { defaultBuildingVariant } from "./meta_building"; -import { MetaConstantSignalBuilding } from "./buildings/constant_signal"; -import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate"; -import { MetaLeverBuilding } from "./buildings/lever"; -import { MetaFilterBuilding } from "./buildings/filter"; -import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire_tunnel"; -import { MetaDisplayBuilding } from "./buildings/display"; - -const logger = createLogger("building_registry"); - -export function initMetaBuildingRegistry() { - gMetaBuildingRegistry.register(MetaSplitterBuilding); - gMetaBuildingRegistry.register(MetaMinerBuilding); - gMetaBuildingRegistry.register(MetaCutterBuilding); - gMetaBuildingRegistry.register(MetaRotaterBuilding); - gMetaBuildingRegistry.register(MetaStackerBuilding); - gMetaBuildingRegistry.register(MetaMixerBuilding); - gMetaBuildingRegistry.register(MetaPainterBuilding); - gMetaBuildingRegistry.register(MetaTrashBuilding); - gMetaBuildingRegistry.register(MetaBeltBuilding); - gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding); - gMetaBuildingRegistry.register(MetaHubBuilding); - gMetaBuildingRegistry.register(MetaWireBuilding); - gMetaBuildingRegistry.register(MetaConstantSignalBuilding); - gMetaBuildingRegistry.register(MetaLogicGateBuilding); - gMetaBuildingRegistry.register(MetaLeverBuilding); - gMetaBuildingRegistry.register(MetaFilterBuilding); - gMetaBuildingRegistry.register(MetaWireTunnelBuilding); - gMetaBuildingRegistry.register(MetaDisplayBuilding); - - // Belt - registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0); - registerBuildingVariant(2, MetaBeltBaseBuilding, defaultBuildingVariant, 1); - registerBuildingVariant(3, MetaBeltBaseBuilding, defaultBuildingVariant, 2); - - // Splitter - registerBuildingVariant(4, MetaSplitterBuilding); - registerBuildingVariant(5, MetaSplitterBuilding, enumSplitterVariants.compact); - registerBuildingVariant(6, MetaSplitterBuilding, enumSplitterVariants.compactInverse); - - // Miner - registerBuildingVariant(7, MetaMinerBuilding); - registerBuildingVariant(8, MetaMinerBuilding, enumMinerVariants.chainable); - - // Cutter - registerBuildingVariant(9, MetaCutterBuilding); - registerBuildingVariant(10, MetaCutterBuilding, enumCutterVariants.quad); - - // Rotater - registerBuildingVariant(11, MetaRotaterBuilding); - registerBuildingVariant(12, MetaRotaterBuilding, enumRotaterVariants.ccw); - registerBuildingVariant(13, MetaRotaterBuilding, enumRotaterVariants.fl); - - // Stacker - registerBuildingVariant(14, MetaStackerBuilding); - - // Mixer - registerBuildingVariant(15, MetaMixerBuilding); - - // Painter - registerBuildingVariant(16, MetaPainterBuilding); - registerBuildingVariant(17, MetaPainterBuilding, enumPainterVariants.mirrored); - registerBuildingVariant(18, MetaPainterBuilding, enumPainterVariants.double); - registerBuildingVariant(19, MetaPainterBuilding, enumPainterVariants.quad); - - // Trash - registerBuildingVariant(20, MetaTrashBuilding); - registerBuildingVariant(21, MetaTrashBuilding, enumTrashVariants.storage); - - // Underground belt - registerBuildingVariant(22, MetaUndergroundBeltBuilding, defaultBuildingVariant, 0); - registerBuildingVariant(23, MetaUndergroundBeltBuilding, defaultBuildingVariant, 1); - registerBuildingVariant(24, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 0); - registerBuildingVariant(25, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 1); - - // Hub - registerBuildingVariant(26, MetaHubBuilding); - - // Wire - registerBuildingVariant(27, MetaWireBuilding, defaultBuildingVariant, 0); - registerBuildingVariant(28, MetaWireBuilding, defaultBuildingVariant, 1); - registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2); - registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3); - - // Constant signal - registerBuildingVariant(31, MetaConstantSignalBuilding); - - // Logic gate - registerBuildingVariant(32, MetaLogicGateBuilding); - registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not); - registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor); - registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or); - registerBuildingVariant(38, MetaLogicGateBuilding, enumLogicGateVariants.transistor); - - // Lever - registerBuildingVariant(33, MetaLeverBuilding); - - // Filter - registerBuildingVariant(37, MetaFilterBuilding); - - // Wire tunnel - registerBuildingVariant(39, MetaWireTunnelBuilding); - registerBuildingVariant(41, MetaWireTunnelBuilding, enumWireTunnelVariants.coating); - - // Display - registerBuildingVariant(40, MetaDisplayBuilding); - - // Propagate instances - for (const key in gBuildingVariants) { - gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass( - gBuildingVariants[key].metaClass - ); - } - - for (const key in gBuildingVariants) { - const variant = gBuildingVariants[key]; - assert(variant.metaClass, "Variant has no meta: " + key); - - if (typeof variant.rotationVariant === "undefined") { - variant.rotationVariant = 0; - } - if (typeof variant.variant === "undefined") { - variant.variant = defaultBuildingVariant; - } - } - - logger.log("Registered", gMetaBuildingRegistry.getNumEntries(), "buildings"); - logger.log("Registered", Object.keys(gBuildingVariants).length, "building codes"); -} - -/** - * Once all sprites are loaded, propagates the cache - */ -export function initBuildingCodesAfterResourcesLoaded() { - logger.log("Propagating sprite cache"); - for (const key in gBuildingVariants) { - const variant = gBuildingVariants[key]; - - variant.sprite = variant.metaInstance.getSprite(variant.rotationVariant, variant.variant); - variant.blueprintSprite = variant.metaInstance.getBlueprintSprite( - variant.rotationVariant, - variant.variant - ); - variant.silhouetteColor = variant.metaInstance.getSilhouetteColor(); - } -} +import { gMetaBuildingRegistry } from "../core/global_registries"; +import { createLogger } from "../core/logging"; +import { MetaBeltBuilding } from "./buildings/belt"; +import { MetaBeltBaseBuilding } from "./buildings/belt_base"; +import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter"; +import { MetaHubBuilding } from "./buildings/hub"; +import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner"; +import { MetaMixerBuilding } from "./buildings/mixer"; +import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter"; +import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater"; +import { enumSplitterVariants, MetaSplitterBuilding } from "./buildings/splitter"; +import { MetaStackerBuilding } from "./buildings/stacker"; +import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash"; +import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; +import { MetaWireBuilding } from "./buildings/wire"; +import { gBuildingVariants, registerBuildingVariant } from "./building_codes"; +import { defaultBuildingVariant } from "./meta_building"; +import { MetaConstantSignalBuilding } from "./buildings/constant_signal"; +import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate"; +import { MetaLeverBuilding } from "./buildings/lever"; +import { MetaFilterBuilding } from "./buildings/filter"; +import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire_tunnel"; +import { MetaDisplayBuilding } from "./buildings/display"; +import { MetaVirtualProcessorBuilding, enumVirtualProcessorVariants } from "./buildings/virtual_processor"; + +const logger = createLogger("building_registry"); + +export function initMetaBuildingRegistry() { + gMetaBuildingRegistry.register(MetaSplitterBuilding); + gMetaBuildingRegistry.register(MetaMinerBuilding); + gMetaBuildingRegistry.register(MetaCutterBuilding); + gMetaBuildingRegistry.register(MetaRotaterBuilding); + gMetaBuildingRegistry.register(MetaStackerBuilding); + gMetaBuildingRegistry.register(MetaMixerBuilding); + gMetaBuildingRegistry.register(MetaPainterBuilding); + gMetaBuildingRegistry.register(MetaTrashBuilding); + gMetaBuildingRegistry.register(MetaBeltBuilding); + gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding); + gMetaBuildingRegistry.register(MetaHubBuilding); + gMetaBuildingRegistry.register(MetaWireBuilding); + gMetaBuildingRegistry.register(MetaConstantSignalBuilding); + gMetaBuildingRegistry.register(MetaLogicGateBuilding); + gMetaBuildingRegistry.register(MetaLeverBuilding); + gMetaBuildingRegistry.register(MetaFilterBuilding); + gMetaBuildingRegistry.register(MetaWireTunnelBuilding); + gMetaBuildingRegistry.register(MetaDisplayBuilding); + gMetaBuildingRegistry.register(MetaVirtualProcessorBuilding); + + // Belt + registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(2, MetaBeltBaseBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(3, MetaBeltBaseBuilding, defaultBuildingVariant, 2); + + // Splitter + registerBuildingVariant(4, MetaSplitterBuilding); + registerBuildingVariant(5, MetaSplitterBuilding, enumSplitterVariants.compact); + registerBuildingVariant(6, MetaSplitterBuilding, enumSplitterVariants.compactInverse); + + // Miner + registerBuildingVariant(7, MetaMinerBuilding); + registerBuildingVariant(8, MetaMinerBuilding, enumMinerVariants.chainable); + + // Cutter + registerBuildingVariant(9, MetaCutterBuilding); + registerBuildingVariant(10, MetaCutterBuilding, enumCutterVariants.quad); + + // Rotater + registerBuildingVariant(11, MetaRotaterBuilding); + registerBuildingVariant(12, MetaRotaterBuilding, enumRotaterVariants.ccw); + registerBuildingVariant(13, MetaRotaterBuilding, enumRotaterVariants.fl); + + // Stacker + registerBuildingVariant(14, MetaStackerBuilding); + + // Mixer + registerBuildingVariant(15, MetaMixerBuilding); + + // Painter + registerBuildingVariant(16, MetaPainterBuilding); + registerBuildingVariant(17, MetaPainterBuilding, enumPainterVariants.mirrored); + registerBuildingVariant(18, MetaPainterBuilding, enumPainterVariants.double); + registerBuildingVariant(19, MetaPainterBuilding, enumPainterVariants.quad); + + // Trash + registerBuildingVariant(20, MetaTrashBuilding); + registerBuildingVariant(21, MetaTrashBuilding, enumTrashVariants.storage); + + // Underground belt + registerBuildingVariant(22, MetaUndergroundBeltBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(23, MetaUndergroundBeltBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(24, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 0); + registerBuildingVariant(25, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 1); + + // Hub + registerBuildingVariant(26, MetaHubBuilding); + + // Wire + registerBuildingVariant(27, MetaWireBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(28, MetaWireBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2); + registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3); + + // Constant signal + registerBuildingVariant(31, MetaConstantSignalBuilding); + + // Logic gate + registerBuildingVariant(32, MetaLogicGateBuilding); + registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not); + registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor); + registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or); + registerBuildingVariant(38, MetaLogicGateBuilding, enumLogicGateVariants.transistor); + + // Lever + registerBuildingVariant(33, MetaLeverBuilding); + + // Filter + registerBuildingVariant(37, MetaFilterBuilding); + + // Wire tunnel + registerBuildingVariant(39, MetaWireTunnelBuilding); + registerBuildingVariant(41, MetaWireTunnelBuilding, enumWireTunnelVariants.coating); + + // Display + registerBuildingVariant(40, MetaDisplayBuilding); + + // Virtual Processor + registerBuildingVariant(42, MetaVirtualProcessorBuilding); + registerBuildingVariant(43, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.analyzer); + registerBuildingVariant(44, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.rotater); + registerBuildingVariant(45, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.unstacker); + registerBuildingVariant(46, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.shapecompare); + + // Propagate instances + for (const key in gBuildingVariants) { + gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass( + gBuildingVariants[key].metaClass + ); + } + + for (const key in gBuildingVariants) { + const variant = gBuildingVariants[key]; + assert(variant.metaClass, "Variant has no meta: " + key); + + if (typeof variant.rotationVariant === "undefined") { + variant.rotationVariant = 0; + } + if (typeof variant.variant === "undefined") { + variant.variant = defaultBuildingVariant; + } + } + + logger.log("Registered", gMetaBuildingRegistry.getNumEntries(), "buildings"); + logger.log("Registered", Object.keys(gBuildingVariants).length, "building codes"); +} + +/** + * Once all sprites are loaded, propagates the cache + */ +export function initBuildingCodesAfterResourcesLoaded() { + logger.log("Propagating sprite cache"); + for (const key in gBuildingVariants) { + const variant = gBuildingVariants[key]; + + variant.sprite = variant.metaInstance.getSprite(variant.rotationVariant, variant.variant); + variant.blueprintSprite = variant.metaInstance.getBlueprintSprite( + variant.rotationVariant, + variant.variant + ); + variant.silhouetteColor = variant.metaInstance.getSilhouetteColor(); + } +} diff --git a/src/js/game/root.js b/src/js/game/root.js index dfb8025a..dd224dd8 100644 --- a/src/js/game/root.js +++ b/src/js/game/root.js @@ -149,6 +149,8 @@ export class GameRoot { gameSaved: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got saved gameRestored: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got restored + gameFrameStarted: /** @type {TypedSignal<[]>} */ (new Signal()), // New frame + storyGoalCompleted: /** @type {TypedSignal<[number, string]>} */ (new Signal()), upgradePurchased: /** @type {TypedSignal<[string]>} */ (new Signal()), diff --git a/src/js/game/shape_definition.js b/src/js/game/shape_definition.js index 4279c9fa..6ffb14a3 100644 --- a/src/js/game/shape_definition.js +++ b/src/js/game/shape_definition.js @@ -1,614 +1,610 @@ -import { makeOffscreenBuffer } from "../core/buffer_utils"; -import { globalConfig } from "../core/config"; -import { smoothenDpi } from "../core/dpi_manager"; -import { DrawParameters } from "../core/draw_parameters"; -import { createLogger } from "../core/logging"; -import { Vector } from "../core/vector"; -import { BasicSerializableObject, types } from "../savegame/serialization"; -import { enumColors, enumColorsToHexCode, enumColorToShortcode, enumShortcodeToColor } from "./colors"; -import { THEME } from "./theme"; - -const rusha = require("rusha"); - -const logger = createLogger("shape_definition"); - -/** - * @typedef {{ - * subShape: enumSubShape, - * color: enumColors, - * }} ShapeLayerItem - */ - -/** - * Order is Q1 (tr), Q2(br), Q3(bl), Q4(tl) - * @typedef {[ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?]} ShapeLayer - */ - -const arrayQuadrantIndexToOffset = [ - new Vector(1, -1), // tr - new Vector(1, 1), // br - new Vector(-1, 1), // bl - new Vector(-1, -1), // tl -]; - -/** @enum {string} */ -export const enumSubShape = { - rect: "rect", - circle: "circle", - star: "star", - windmill: "windmill", -}; - -/** @enum {string} */ -export const enumSubShapeToShortcode = { - [enumSubShape.rect]: "R", - [enumSubShape.circle]: "C", - [enumSubShape.star]: "S", - [enumSubShape.windmill]: "W", -}; - -/** @enum {enumSubShape} */ -export const enumShortcodeToSubShape = {}; -for (const key in enumSubShapeToShortcode) { - enumShortcodeToSubShape[enumSubShapeToShortcode[key]] = key; -} - -/** - * Converts the given parameters to a valid shape definition - * @param {*} layers - * @returns {Array} - */ -export function createSimpleShape(layers) { - layers.forEach(layer => { - layer.forEach(item => { - if (item) { - item.color = item.color || enumColors.uncolored; - } - }); - }); - return layers; -} - -/** - * Cache which shapes are valid short keys and which not - * @type {Map} - */ -const SHORT_KEY_CACHE = new Map(); - -export class ShapeDefinition extends BasicSerializableObject { - static getId() { - return "ShapeDefinition"; - } - - static getSchema() { - return {}; - } - - deserialize(data) { - const errorCode = super.deserialize(data); - if (errorCode) { - return errorCode; - } - const definition = ShapeDefinition.fromShortKey(data); - this.layers = definition.layers; - } - - serialize() { - return this.getHash(); - } - - /** - * - * @param {object} param0 - * @param {Array=} param0.layers - */ - constructor({ layers = [] }) { - super(); - - /** - * The layers from bottom to top - * @type {Array} */ - this.layers = layers; - - /** @type {string} */ - this.cachedHash = null; - - // Set on demand - this.bufferGenerator = null; - } - - /** - * Generates the definition from the given short key - * @param {string} key - * @returns {ShapeDefinition} - */ - static fromShortKey(key) { - const sourceLayers = key.split(":"); - let layers = []; - for (let i = 0; i < sourceLayers.length; ++i) { - const text = sourceLayers[i]; - assert(text.length === 8, "Invalid shape short key: " + key); - - /** @type {ShapeLayer} */ - const quads = [null, null, null, null]; - for (let quad = 0; quad < 4; ++quad) { - const shapeText = text[quad * 2 + 0]; - const subShape = enumShortcodeToSubShape[shapeText]; - const color = enumShortcodeToColor[text[quad * 2 + 1]]; - if (subShape) { - assert(color, "Invalid shape short key:", key); - quads[quad] = { - subShape, - color, - }; - } else if (shapeText !== "-") { - assert(false, "Invalid shape key: " + shapeText); - } - } - layers.push(quads); - } - - const definition = new ShapeDefinition({ layers }); - // We know the hash so save some work - definition.cachedHash = key; - return definition; - } - - /** - * Checks if a given string is a valid short key - * @param {string} key - * @returns {boolean} - */ - static isValidShortKey(key) { - if (SHORT_KEY_CACHE.has(key)) { - return SHORT_KEY_CACHE.get(key); - } - - const result = ShapeDefinition.isValidShortKeyInternal(key); - SHORT_KEY_CACHE.set(key, result); - return result; - } - - /** - * INTERNAL - * Checks if a given string is a valid short key - * @param {string} key - * @returns {boolean} - */ - static isValidShortKeyInternal(key) { - const sourceLayers = key.split(":"); - let layers = []; - for (let i = 0; i < sourceLayers.length; ++i) { - const text = sourceLayers[i]; - if (text.length !== 8) { - return false; - } - - /** @type {ShapeLayer} */ - const quads = [null, null, null, null]; - let anyFilled = false; - for (let quad = 0; quad < 4; ++quad) { - const shapeText = text[quad * 2 + 0]; - const colorText = text[quad * 2 + 1]; - const subShape = enumShortcodeToSubShape[shapeText]; - const color = enumShortcodeToColor[colorText]; - - // Valid shape - if (subShape) { - if (!color) { - // Invalid color - return false; - } - quads[quad] = { - subShape, - color, - }; - anyFilled = true; - } else if (shapeText === "-") { - // Make sure color is empty then, too - if (colorText !== "-") { - return false; - } - } else { - // Invalid shape key - return false; - } - } - - if (!anyFilled) { - // Empty layer - return false; - } - layers.push(quads); - } - - if (layers.length === 0 || layers.length > 4) { - return false; - } - - return true; - } - - /** - * Internal method to clone the shape definition - * @returns {Array} - */ - internalCloneLayers() { - return JSON.parse(JSON.stringify(this.layers)); - } - - /** - * Returns if the definition is entirely empty^ - * @returns {boolean} - */ - isEntirelyEmpty() { - return this.layers.length === 0; - } - - /** - * Returns a unique id for this shape - * @returns {string} - */ - getHash() { - if (this.cachedHash) { - return this.cachedHash; - } - - let id = ""; - for (let layerIndex = 0; layerIndex < this.layers.length; ++layerIndex) { - const layer = this.layers[layerIndex]; - - for (let quadrant = 0; quadrant < layer.length; ++quadrant) { - const item = layer[quadrant]; - if (item) { - id += enumSubShapeToShortcode[item.subShape] + enumColorToShortcode[item.color]; - } else { - id += "--"; - } - } - - if (layerIndex < this.layers.length - 1) { - id += ":"; - } - } - this.cachedHash = id; - return id; - } - - /** - * Draws the shape definition - * @param {number} x - * @param {number} y - * @param {DrawParameters} parameters - * @param {number=} diameter - */ - drawCentered(x, y, parameters, diameter = 20) { - const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); - - if (!this.bufferGenerator) { - this.bufferGenerator = this.internalGenerateShapeBuffer.bind(this); - } - - const key = diameter + "/" + dpi; - const canvas = parameters.root.buffers.getForKey({ - key, - subKey: this.cachedHash, - w: diameter, - h: diameter, - dpi, - redrawMethod: this.bufferGenerator, - }); - parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter); - } - - /** - * Generates this shape as a canvas - * @param {number} size - */ - generateAsCanvas(size = 120) { - const [canvas, context] = makeOffscreenBuffer(size, size, { - smooth: true, - label: "definition-canvas-cache-" + this.getHash(), - reusable: false, - }); - - this.internalGenerateShapeBuffer(canvas, context, size, size, 1); - return canvas; - } - - /** - * - * @param {HTMLCanvasElement} canvas - * @param {CanvasRenderingContext2D} context - * @param {number} w - * @param {number} h - * @param {number} dpi - */ - internalGenerateShapeBuffer(canvas, context, w, h, dpi) { - context.translate((w * dpi) / 2, (h * dpi) / 2); - context.scale((dpi * w) / 23, (dpi * h) / 23); - - context.fillStyle = "#e9ecf7"; - - const quadrantSize = 10; - const quadrantHalfSize = quadrantSize / 2; - - context.fillStyle = THEME.items.circleBackground; - context.beginCircle(0, 0, quadrantSize * 1.15); - context.fill(); - - for (let layerIndex = 0; layerIndex < this.layers.length; ++layerIndex) { - const quadrants = this.layers[layerIndex]; - - const layerScale = Math.max(0.1, 0.9 - layerIndex * 0.22); - - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - if (!quadrants[quadrantIndex]) { - continue; - } - const { subShape, color } = quadrants[quadrantIndex]; - - const quadrantPos = arrayQuadrantIndexToOffset[quadrantIndex]; - const centerQuadrantX = quadrantPos.x * quadrantHalfSize; - const centerQuadrantY = quadrantPos.y * quadrantHalfSize; - - const rotation = Math.radians(quadrantIndex * 90); - - context.translate(centerQuadrantX, centerQuadrantY); - context.rotate(rotation); - - context.fillStyle = enumColorsToHexCode[color]; - context.strokeStyle = THEME.items.outline; - context.lineWidth = THEME.items.outlineWidth; - - const insetPadding = 0.0; - - switch (subShape) { - case enumSubShape.rect: { - context.beginPath(); - const dims = quadrantSize * layerScale; - context.rect( - insetPadding + -quadrantHalfSize, - -insetPadding + quadrantHalfSize - dims, - dims, - dims - ); - - break; - } - case enumSubShape.star: { - context.beginPath(); - const dims = quadrantSize * layerScale; - - let originX = insetPadding - quadrantHalfSize; - let originY = -insetPadding + quadrantHalfSize - dims; - - const moveInwards = dims * 0.4; - context.moveTo(originX, originY + moveInwards); - context.lineTo(originX + dims, originY); - context.lineTo(originX + dims - moveInwards, originY + dims); - context.lineTo(originX, originY + dims); - context.closePath(); - break; - } - - case enumSubShape.windmill: { - context.beginPath(); - const dims = quadrantSize * layerScale; - - let originX = insetPadding - quadrantHalfSize; - let originY = -insetPadding + quadrantHalfSize - dims; - const moveInwards = dims * 0.4; - context.moveTo(originX, originY + moveInwards); - context.lineTo(originX + dims, originY); - context.lineTo(originX + dims, originY + dims); - context.lineTo(originX, originY + dims); - context.closePath(); - break; - } - - case enumSubShape.circle: { - context.beginPath(); - context.moveTo(insetPadding + -quadrantHalfSize, -insetPadding + quadrantHalfSize); - context.arc( - insetPadding + -quadrantHalfSize, - -insetPadding + quadrantHalfSize, - quadrantSize * layerScale, - -Math.PI * 0.5, - 0 - ); - context.closePath(); - break; - } - - default: { - assertAlways(false, "Unkown sub shape: " + subShape); - } - } - - context.fill(); - context.stroke(); - - context.rotate(-rotation); - context.translate(-centerQuadrantX, -centerQuadrantY); - } - } - } - - /** - * Returns a definition with only the given quadrants - * @param {Array} includeQuadrants - * @returns {ShapeDefinition} - */ - cloneFilteredByQuadrants(includeQuadrants) { - const newLayers = this.internalCloneLayers(); - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - let anyContents = false; - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - if (includeQuadrants.indexOf(quadrantIndex) < 0) { - quadrants[quadrantIndex] = null; - } else if (quadrants[quadrantIndex]) { - anyContents = true; - } - } - - // Check if the layer is entirely empty - if (!anyContents) { - newLayers.splice(layerIndex, 1); - layerIndex -= 1; - } - } - return new ShapeDefinition({ layers: newLayers }); - } - - /** - * Returns a definition which was rotated clockwise - * @returns {ShapeDefinition} - */ - cloneRotateCW() { - const newLayers = this.internalCloneLayers(); - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - quadrants.unshift(quadrants[3]); - quadrants.pop(); - } - return new ShapeDefinition({ layers: newLayers }); - } - - /** - * Returns a definition which was rotated counter clockwise - * @returns {ShapeDefinition} - */ - cloneRotateCCW() { - const newLayers = this.internalCloneLayers(); - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - quadrants.push(quadrants[0]); - quadrants.shift(); - } - return new ShapeDefinition({ layers: newLayers }); - } - - /** - * Returns a definition which was rotated 180 degrees (flipped) - * @returns {ShapeDefinition} - */ - cloneRotateFL() { - const newLayers = this.internalCloneLayers(); - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - quadrants.push(quadrants.shift(), quadrants.shift()); - } - return new ShapeDefinition({ layers: newLayers }); - } - - /** - * Stacks the given shape definition on top. - * @param {ShapeDefinition} definition - */ - cloneAndStackWith(definition) { - if (this.isEntirelyEmpty() || definition.isEntirelyEmpty()) { - assert(false, "Can not stack entirely empty definition"); - } - - const bottomShapeLayers = this.layers; - const bottomShapeHighestLayerByQuad = [-1, -1, -1, -1]; - - for (let layer = bottomShapeLayers.length - 1; layer >= 0; --layer) { - const shapeLayer = bottomShapeLayers[layer]; - for (let quad = 0; quad < 4; ++quad) { - const shapeQuad = shapeLayer[quad]; - if (shapeQuad !== null && bottomShapeHighestLayerByQuad[quad] < layer) { - bottomShapeHighestLayerByQuad[quad] = layer; - } - } - } - - const topShapeLayers = definition.layers; - const topShapeLowestLayerByQuad = [4, 4, 4, 4]; - - for (let layer = 0; layer < topShapeLayers.length; ++layer) { - const shapeLayer = topShapeLayers[layer]; - for (let quad = 0; quad < 4; ++quad) { - const shapeQuad = shapeLayer[quad]; - if (shapeQuad !== null && topShapeLowestLayerByQuad[quad] > layer) { - topShapeLowestLayerByQuad[quad] = layer; - } - } - } - - /** - * We want to find the number `layerToMergeAt` such that when the top shape is placed at that - * layer, the smallest gap between shapes is only 1. Instead of doing a guess-and-check method to - * find the appropriate layer, we just calculate all the gaps assuming a merge at layer 0, even - * though they go negative, and calculating the number to add to it so the minimum gap is 1 (ends - * up being 1 - minimum). - */ - const gapsBetweenShapes = []; - for (let quad = 0; quad < 4; ++quad) { - gapsBetweenShapes.push(topShapeLowestLayerByQuad[quad] - bottomShapeHighestLayerByQuad[quad]); - } - const smallestGapBetweenShapes = Math.min(...gapsBetweenShapes); - // Can't merge at a layer lower than 0 - const layerToMergeAt = Math.max(1 - smallestGapBetweenShapes, 0); - - const mergedLayers = this.internalCloneLayers(); - for (let layer = mergedLayers.length; layer < layerToMergeAt + topShapeLayers.length; ++layer) { - mergedLayers.push([null, null, null, null]); - } - - for (let layer = 0; layer < topShapeLayers.length; ++layer) { - const layerMergingAt = layerToMergeAt + layer; - const bottomShapeLayer = mergedLayers[layerMergingAt]; - const topShapeLayer = topShapeLayers[layer]; - for (let quad = 0; quad < 4; quad++) { - assert(!(bottomShapeLayer[quad] && topShapeLayer[quad]), "Shape merge: Sub shape got lost"); - bottomShapeLayer[quad] = bottomShapeLayer[quad] || topShapeLayer[quad]; - } - } - - // Limit to 4 layers at max - mergedLayers.splice(4); - - return new ShapeDefinition({ layers: mergedLayers }); - } - - /** - * Clones the shape and colors everything in the given color - * @param {enumColors} color - */ - cloneAndPaintWith(color) { - const newLayers = this.internalCloneLayers(); - - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - const item = quadrants[quadrantIndex]; - if (item) { - item.color = color; - } - } - } - return new ShapeDefinition({ layers: newLayers }); - } - - /** - * Clones the shape and colors everything in the given colors - * @param {[enumColors, enumColors, enumColors, enumColors]} colors - */ - cloneAndPaintWith4Colors(colors) { - const newLayers = this.internalCloneLayers(); - - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - const item = quadrants[quadrantIndex]; - if (item) { - item.color = colors[quadrantIndex]; - } - } - } - return new ShapeDefinition({ layers: newLayers }); - } -} +import { makeOffscreenBuffer } from "../core/buffer_utils"; +import { globalConfig } from "../core/config"; +import { smoothenDpi } from "../core/dpi_manager"; +import { DrawParameters } from "../core/draw_parameters"; +import { Vector } from "../core/vector"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +import { enumColors, enumColorsToHexCode, enumColorToShortcode, enumShortcodeToColor } from "./colors"; +import { THEME } from "./theme"; + +/** + * @typedef {{ + * subShape: enumSubShape, + * color: enumColors, + * }} ShapeLayerItem + */ + +/** + * Order is Q1 (tr), Q2(br), Q3(bl), Q4(tl) + * @typedef {[ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?]} ShapeLayer + */ + +const arrayQuadrantIndexToOffset = [ + new Vector(1, -1), // tr + new Vector(1, 1), // br + new Vector(-1, 1), // bl + new Vector(-1, -1), // tl +]; + +/** @enum {string} */ +export const enumSubShape = { + rect: "rect", + circle: "circle", + star: "star", + windmill: "windmill", +}; + +/** @enum {string} */ +export const enumSubShapeToShortcode = { + [enumSubShape.rect]: "R", + [enumSubShape.circle]: "C", + [enumSubShape.star]: "S", + [enumSubShape.windmill]: "W", +}; + +/** @enum {enumSubShape} */ +export const enumShortcodeToSubShape = {}; +for (const key in enumSubShapeToShortcode) { + enumShortcodeToSubShape[enumSubShapeToShortcode[key]] = key; +} + +/** + * Converts the given parameters to a valid shape definition + * @param {*} layers + * @returns {Array} + */ +export function createSimpleShape(layers) { + layers.forEach(layer => { + layer.forEach(item => { + if (item) { + item.color = item.color || enumColors.uncolored; + } + }); + }); + return layers; +} + +/** + * Cache which shapes are valid short keys and which not + * @type {Map} + */ +const SHORT_KEY_CACHE = new Map(); + +export class ShapeDefinition extends BasicSerializableObject { + static getId() { + return "ShapeDefinition"; + } + + static getSchema() { + return {}; + } + + deserialize(data) { + const errorCode = super.deserialize(data); + if (errorCode) { + return errorCode; + } + const definition = ShapeDefinition.fromShortKey(data); + this.layers = /** @type {Array} */ (definition.layers); + } + + serialize() { + return this.getHash(); + } + + /** + * + * @param {object} param0 + * @param {Array=} param0.layers + */ + constructor({ layers = [] }) { + super(); + + /** + * The layers from bottom to top + * @type {Array} + */ + this.layers = layers; + + /** @type {string} */ + this.cachedHash = null; + + // Set on demand + this.bufferGenerator = null; + } + + /** + * Generates the definition from the given short key + * @param {string} key + * @returns {ShapeDefinition} + */ + static fromShortKey(key) { + const sourceLayers = key.split(":"); + let layers = []; + for (let i = 0; i < sourceLayers.length; ++i) { + const text = sourceLayers[i]; + assert(text.length === 8, "Invalid shape short key: " + key); + + /** @type {ShapeLayer} */ + const quads = [null, null, null, null]; + for (let quad = 0; quad < 4; ++quad) { + const shapeText = text[quad * 2 + 0]; + const subShape = enumShortcodeToSubShape[shapeText]; + const color = enumShortcodeToColor[text[quad * 2 + 1]]; + if (subShape) { + assert(color, "Invalid shape short key:", key); + quads[quad] = { + subShape, + color, + }; + } else if (shapeText !== "-") { + assert(false, "Invalid shape key: " + shapeText); + } + } + layers.push(quads); + } + + const definition = new ShapeDefinition({ layers }); + // We know the hash so save some work + definition.cachedHash = key; + return definition; + } + + /** + * Checks if a given string is a valid short key + * @param {string} key + * @returns {boolean} + */ + static isValidShortKey(key) { + if (SHORT_KEY_CACHE.has(key)) { + return SHORT_KEY_CACHE.get(key); + } + + const result = ShapeDefinition.isValidShortKeyInternal(key); + SHORT_KEY_CACHE.set(key, result); + return result; + } + + /** + * INTERNAL + * Checks if a given string is a valid short key + * @param {string} key + * @returns {boolean} + */ + static isValidShortKeyInternal(key) { + const sourceLayers = key.split(":"); + let layers = []; + for (let i = 0; i < sourceLayers.length; ++i) { + const text = sourceLayers[i]; + if (text.length !== 8) { + return false; + } + + /** @type {ShapeLayer} */ + const quads = [null, null, null, null]; + let anyFilled = false; + for (let quad = 0; quad < 4; ++quad) { + const shapeText = text[quad * 2 + 0]; + const colorText = text[quad * 2 + 1]; + const subShape = enumShortcodeToSubShape[shapeText]; + const color = enumShortcodeToColor[colorText]; + + // Valid shape + if (subShape) { + if (!color) { + // Invalid color + return false; + } + quads[quad] = { + subShape, + color, + }; + anyFilled = true; + } else if (shapeText === "-") { + // Make sure color is empty then, too + if (colorText !== "-") { + return false; + } + } else { + // Invalid shape key + return false; + } + } + + if (!anyFilled) { + // Empty layer + return false; + } + layers.push(quads); + } + + if (layers.length === 0 || layers.length > 4) { + return false; + } + + return true; + } + + /** + * Internal method to clone the shape definition + * @returns {Array} + */ + internalCloneLayers() { + return JSON.parse(JSON.stringify(this.layers)); + } + + /** + * Returns if the definition is entirely empty^ + * @returns {boolean} + */ + isEntirelyEmpty() { + return this.layers.length === 0; + } + + /** + * Returns a unique id for this shape + * @returns {string} + */ + getHash() { + if (this.cachedHash) { + return this.cachedHash; + } + + let id = ""; + for (let layerIndex = 0; layerIndex < this.layers.length; ++layerIndex) { + const layer = this.layers[layerIndex]; + + for (let quadrant = 0; quadrant < layer.length; ++quadrant) { + const item = layer[quadrant]; + if (item) { + id += enumSubShapeToShortcode[item.subShape] + enumColorToShortcode[item.color]; + } else { + id += "--"; + } + } + + if (layerIndex < this.layers.length - 1) { + id += ":"; + } + } + this.cachedHash = id; + return id; + } + + /** + * Draws the shape definition + * @param {number} x + * @param {number} y + * @param {DrawParameters} parameters + * @param {number=} diameter + */ + drawCentered(x, y, parameters, diameter = 20) { + const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); + + if (!this.bufferGenerator) { + this.bufferGenerator = this.internalGenerateShapeBuffer.bind(this); + } + + const key = diameter + "/" + dpi + "/" + this.cachedHash; + const canvas = parameters.root.buffers.getForKey({ + key: "shapedef", + subKey: key, + w: diameter, + h: diameter, + dpi, + redrawMethod: this.bufferGenerator, + }); + parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter); + } + + /** + * Generates this shape as a canvas + * @param {number} size + */ + generateAsCanvas(size = 120) { + const [canvas, context] = makeOffscreenBuffer(size, size, { + smooth: true, + label: "definition-canvas-cache-" + this.getHash(), + reusable: false, + }); + + this.internalGenerateShapeBuffer(canvas, context, size, size, 1); + return canvas; + } + + /** + * + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi + */ + internalGenerateShapeBuffer(canvas, context, w, h, dpi) { + context.translate((w * dpi) / 2, (h * dpi) / 2); + context.scale((dpi * w) / 23, (dpi * h) / 23); + + context.fillStyle = "#e9ecf7"; + + const quadrantSize = 10; + const quadrantHalfSize = quadrantSize / 2; + + context.fillStyle = THEME.items.circleBackground; + context.beginCircle(0, 0, quadrantSize * 1.15); + context.fill(); + + for (let layerIndex = 0; layerIndex < this.layers.length; ++layerIndex) { + const quadrants = this.layers[layerIndex]; + + const layerScale = Math.max(0.1, 0.9 - layerIndex * 0.22); + + for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { + if (!quadrants[quadrantIndex]) { + continue; + } + const { subShape, color } = quadrants[quadrantIndex]; + + const quadrantPos = arrayQuadrantIndexToOffset[quadrantIndex]; + const centerQuadrantX = quadrantPos.x * quadrantHalfSize; + const centerQuadrantY = quadrantPos.y * quadrantHalfSize; + + const rotation = Math.radians(quadrantIndex * 90); + + context.translate(centerQuadrantX, centerQuadrantY); + context.rotate(rotation); + + context.fillStyle = enumColorsToHexCode[color]; + context.strokeStyle = THEME.items.outline; + context.lineWidth = THEME.items.outlineWidth; + + const insetPadding = 0.0; + + switch (subShape) { + case enumSubShape.rect: { + context.beginPath(); + const dims = quadrantSize * layerScale; + context.rect( + insetPadding + -quadrantHalfSize, + -insetPadding + quadrantHalfSize - dims, + dims, + dims + ); + + break; + } + case enumSubShape.star: { + context.beginPath(); + const dims = quadrantSize * layerScale; + + let originX = insetPadding - quadrantHalfSize; + let originY = -insetPadding + quadrantHalfSize - dims; + + const moveInwards = dims * 0.4; + context.moveTo(originX, originY + moveInwards); + context.lineTo(originX + dims, originY); + context.lineTo(originX + dims - moveInwards, originY + dims); + context.lineTo(originX, originY + dims); + context.closePath(); + break; + } + + case enumSubShape.windmill: { + context.beginPath(); + const dims = quadrantSize * layerScale; + + let originX = insetPadding - quadrantHalfSize; + let originY = -insetPadding + quadrantHalfSize - dims; + const moveInwards = dims * 0.4; + context.moveTo(originX, originY + moveInwards); + context.lineTo(originX + dims, originY); + context.lineTo(originX + dims, originY + dims); + context.lineTo(originX, originY + dims); + context.closePath(); + break; + } + + case enumSubShape.circle: { + context.beginPath(); + context.moveTo(insetPadding + -quadrantHalfSize, -insetPadding + quadrantHalfSize); + context.arc( + insetPadding + -quadrantHalfSize, + -insetPadding + quadrantHalfSize, + quadrantSize * layerScale, + -Math.PI * 0.5, + 0 + ); + context.closePath(); + break; + } + + default: { + assertAlways(false, "Unkown sub shape: " + subShape); + } + } + + context.fill(); + context.stroke(); + + context.rotate(-rotation); + context.translate(-centerQuadrantX, -centerQuadrantY); + } + } + } + + /** + * Returns a definition with only the given quadrants + * @param {Array} includeQuadrants + * @returns {ShapeDefinition} + */ + cloneFilteredByQuadrants(includeQuadrants) { + const newLayers = this.internalCloneLayers(); + for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { + const quadrants = newLayers[layerIndex]; + let anyContents = false; + for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { + if (includeQuadrants.indexOf(quadrantIndex) < 0) { + quadrants[quadrantIndex] = null; + } else if (quadrants[quadrantIndex]) { + anyContents = true; + } + } + + // Check if the layer is entirely empty + if (!anyContents) { + newLayers.splice(layerIndex, 1); + layerIndex -= 1; + } + } + return new ShapeDefinition({ layers: newLayers }); + } + + /** + * Returns a definition which was rotated clockwise + * @returns {ShapeDefinition} + */ + cloneRotateCW() { + const newLayers = this.internalCloneLayers(); + for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { + const quadrants = newLayers[layerIndex]; + quadrants.unshift(quadrants[3]); + quadrants.pop(); + } + return new ShapeDefinition({ layers: newLayers }); + } + + /** + * Returns a definition which was rotated counter clockwise + * @returns {ShapeDefinition} + */ + cloneRotateCCW() { + const newLayers = this.internalCloneLayers(); + for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { + const quadrants = newLayers[layerIndex]; + quadrants.push(quadrants[0]); + quadrants.shift(); + } + return new ShapeDefinition({ layers: newLayers }); + } + + /** + * Returns a definition which was rotated 180 degrees (flipped) + * @returns {ShapeDefinition} + */ + cloneRotateFL() { + const newLayers = this.internalCloneLayers(); + for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { + const quadrants = newLayers[layerIndex]; + quadrants.push(quadrants.shift(), quadrants.shift()); + } + return new ShapeDefinition({ layers: newLayers }); + } + + /** + * Stacks the given shape definition on top. + * @param {ShapeDefinition} definition + */ + cloneAndStackWith(definition) { + if (this.isEntirelyEmpty() || definition.isEntirelyEmpty()) { + assert(false, "Can not stack entirely empty definition"); + } + + const bottomShapeLayers = this.layers; + const bottomShapeHighestLayerByQuad = [-1, -1, -1, -1]; + + for (let layer = bottomShapeLayers.length - 1; layer >= 0; --layer) { + const shapeLayer = bottomShapeLayers[layer]; + for (let quad = 0; quad < 4; ++quad) { + const shapeQuad = shapeLayer[quad]; + if (shapeQuad !== null && bottomShapeHighestLayerByQuad[quad] < layer) { + bottomShapeHighestLayerByQuad[quad] = layer; + } + } + } + + const topShapeLayers = definition.layers; + const topShapeLowestLayerByQuad = [4, 4, 4, 4]; + + for (let layer = 0; layer < topShapeLayers.length; ++layer) { + const shapeLayer = topShapeLayers[layer]; + for (let quad = 0; quad < 4; ++quad) { + const shapeQuad = shapeLayer[quad]; + if (shapeQuad !== null && topShapeLowestLayerByQuad[quad] > layer) { + topShapeLowestLayerByQuad[quad] = layer; + } + } + } + + /** + * We want to find the number `layerToMergeAt` such that when the top shape is placed at that + * layer, the smallest gap between shapes is only 1. Instead of doing a guess-and-check method to + * find the appropriate layer, we just calculate all the gaps assuming a merge at layer 0, even + * though they go negative, and calculating the number to add to it so the minimum gap is 1 (ends + * up being 1 - minimum). + */ + const gapsBetweenShapes = []; + for (let quad = 0; quad < 4; ++quad) { + gapsBetweenShapes.push(topShapeLowestLayerByQuad[quad] - bottomShapeHighestLayerByQuad[quad]); + } + const smallestGapBetweenShapes = Math.min(...gapsBetweenShapes); + // Can't merge at a layer lower than 0 + const layerToMergeAt = Math.max(1 - smallestGapBetweenShapes, 0); + + const mergedLayers = this.internalCloneLayers(); + for (let layer = mergedLayers.length; layer < layerToMergeAt + topShapeLayers.length; ++layer) { + mergedLayers.push([null, null, null, null]); + } + + for (let layer = 0; layer < topShapeLayers.length; ++layer) { + const layerMergingAt = layerToMergeAt + layer; + const bottomShapeLayer = mergedLayers[layerMergingAt]; + const topShapeLayer = topShapeLayers[layer]; + for (let quad = 0; quad < 4; quad++) { + assert(!(bottomShapeLayer[quad] && topShapeLayer[quad]), "Shape merge: Sub shape got lost"); + bottomShapeLayer[quad] = bottomShapeLayer[quad] || topShapeLayer[quad]; + } + } + + // Limit to 4 layers at max + mergedLayers.splice(4); + + return new ShapeDefinition({ layers: mergedLayers }); + } + + /** + * Clones the shape and colors everything in the given color + * @param {enumColors} color + */ + cloneAndPaintWith(color) { + const newLayers = this.internalCloneLayers(); + + for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { + const quadrants = newLayers[layerIndex]; + for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { + const item = quadrants[quadrantIndex]; + if (item) { + item.color = color; + } + } + } + return new ShapeDefinition({ layers: newLayers }); + } + + /** + * Clones the shape and colors everything in the given colors + * @param {[enumColors, enumColors, enumColors, enumColors]} colors + */ + cloneAndPaintWith4Colors(colors) { + const newLayers = this.internalCloneLayers(); + + for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { + const quadrants = newLayers[layerIndex]; + for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { + const item = quadrants[quadrantIndex]; + if (item) { + item.color = colors[quadrantIndex]; + } + } + } + return new ShapeDefinition({ layers: newLayers }); + } +} diff --git a/src/js/game/systems/belt.js b/src/js/game/systems/belt.js index 420e0604..4d8151f6 100644 --- a/src/js/game/systems/belt.js +++ b/src/js/game/systems/belt.js @@ -14,7 +14,6 @@ import { GameSystemWithFilter } from "../game_system_with_filter"; import { MapChunkView } from "../map_chunk_view"; import { defaultBuildingVariant } from "../meta_building"; import { getCodeFromBuildingData } from "../building_codes"; -import { enumLayer } from "../root"; export const BELT_ANIM_COUNT = 14; @@ -496,13 +495,15 @@ export class BeltSystem extends GameSystemWithFilter { ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * globalConfig.itemSpacingOnBelts ); - const contents = chunk.containedEntitiesByLayer[enumLayer.regular]; + const contents = chunk.containedEntitiesByLayer.regular; for (let i = 0; i < contents.length; ++i) { const entity = contents[i]; if (entity.components.Belt) { const direction = entity.components.Belt.direction; const sprite = this.beltAnimations[direction][animationIndex % BELT_ANIM_COUNT]; - entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds(parameters, sprite, 0); + + // Culling happens within the static map entity component + entity.components.StaticMapEntity.drawSpriteOnBoundsClipped(parameters, sprite, 0); } } } diff --git a/src/js/game/systems/belt_underlays.js b/src/js/game/systems/belt_underlays.js index c20801f0..5bdf2331 100644 --- a/src/js/game/systems/belt_underlays.js +++ b/src/js/game/systems/belt_underlays.js @@ -7,7 +7,6 @@ import { GameSystemWithFilter } from "../game_system_with_filter"; import { BELT_ANIM_COUNT } from "./belt"; import { MapChunkView } from "../map_chunk_view"; import { DrawParameters } from "../../core/draw_parameters"; -import { enumLayer } from "../root"; export class BeltUnderlaysSystem extends GameSystemWithFilter { constructor(root) { @@ -29,38 +28,56 @@ export class BeltUnderlaysSystem extends GameSystemWithFilter { // Limit speed to avoid belts going backwards const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10); - const contents = chunk.containedEntitiesByLayer[enumLayer.regular]; + const contents = chunk.containedEntitiesByLayer.regular; for (let i = 0; i < contents.length; ++i) { const entity = contents[i]; const underlayComp = entity.components.BeltUnderlays; - if (underlayComp) { - const staticComp = entity.components.StaticMapEntity; - const underlays = underlayComp.underlays; - for (let i = 0; i < underlays.length; ++i) { - const { pos, direction } = underlays[i]; - const transformedPos = staticComp.localTileToWorld(pos); + if (!underlayComp) { + continue; + } - if (!chunk.tileSpaceRectangle.containsPoint(transformedPos.x, transformedPos.y)) { - continue; - } + const staticComp = entity.components.StaticMapEntity; + const underlays = underlayComp.underlays; + for (let i = 0; i < underlays.length; ++i) { + const { pos, direction } = underlays[i]; + const transformedPos = staticComp.localTileToWorld(pos); - const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)]; - - // SYNC with systems/belt.js:drawSingleEntity! - const animationIndex = Math.floor( - ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * - globalConfig.itemSpacingOnBelts - ); - - drawRotatedSprite({ - parameters, - sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length], - x: (transformedPos.x + 0.5) * globalConfig.tileSize, - y: (transformedPos.y + 0.5) * globalConfig.tileSize, - angle: Math.radians(angle), - size: globalConfig.tileSize, - }); + // Culling + if (!chunk.tileSpaceRectangle.containsPoint(transformedPos.x, transformedPos.y)) { + continue; } + + const destX = transformedPos.x * globalConfig.tileSize; + const destY = transformedPos.y * globalConfig.tileSize; + + // Culling, #2 + if ( + !parameters.visibleRect.containsRect4Params( + destX, + destY, + globalConfig.tileSize, + globalConfig.tileSize + ) + ) { + continue; + } + + const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)]; + + // SYNC with systems/belt.js:drawSingleEntity! + const animationIndex = Math.floor( + ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * + globalConfig.itemSpacingOnBelts + ); + + drawRotatedSprite({ + parameters, + sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length], + x: destX + globalConfig.halfTileSize, + y: destY + globalConfig.halfTileSize, + angle: Math.radians(angle), + size: globalConfig.tileSize, + }); } } } diff --git a/src/js/game/systems/display.js b/src/js/game/systems/display.js index 6cdb8622..b1bd9e69 100644 --- a/src/js/game/systems/display.js +++ b/src/js/game/systems/display.js @@ -66,9 +66,11 @@ export class DisplaySystem extends GameSystemWithFilter { if (entity && entity.components.Display) { const pinsComp = entity.components.WiredPins; const network = pinsComp.slots[0].linkedNetwork; + if (!network || !network.currentValue) { continue; } + const value = this.getDisplayItem(network.currentValue); if (!value) { @@ -84,7 +86,7 @@ export class DisplaySystem extends GameSystemWithFilter { globalConfig.tileSize ); } else if (value.getItemType() === "shape") { - value.draw( + value.drawItemCenteredClipped( (origin.x + 0.5) * globalConfig.tileSize, (origin.y + 0.5) * globalConfig.tileSize, parameters, diff --git a/src/js/game/systems/hub.js b/src/js/game/systems/hub.js index 3641d9d6..2270f941 100644 --- a/src/js/game/systems/hub.js +++ b/src/js/game/systems/hub.js @@ -5,6 +5,14 @@ import { T } from "../../translations"; import { HubComponent } from "../components/hub"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; +import { globalConfig } from "../../core/config"; +import { smoothenDpi } from "../../core/dpi_manager"; +import { drawSpriteClipped } from "../../core/draw_utils"; +import { Rectangle } from "../../core/rectangle"; +import { ORIGINAL_SPRITE_SCALE } from "../../core/sprites"; + +const HUB_SIZE_TILES = 4; +const HUB_SIZE_PIXELS = HUB_SIZE_TILES * globalConfig.tileSize; export class HubSystem extends GameSystemWithFilter { constructor(root) { @@ -13,8 +21,13 @@ export class HubSystem extends GameSystemWithFilter { this.hubSprite = Loader.getSprite("sprites/buildings/hub.png"); } + /** + * @param {DrawParameters} parameters + */ draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); + for (let i = 0; i < this.allEntities.length; ++i) { + this.drawEntity(parameters, this.allEntities[i]); + } } update() { @@ -27,35 +40,42 @@ export class HubSystem extends GameSystemWithFilter { ); } } - /** - * @param {DrawParameters} parameters - * @param {Entity} entity + * + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; + redrawHubBaseTexture(canvas, context, w, h, dpi) { + // This method is quite ugly, please ignore it! - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } + context.scale(dpi, dpi); - const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); + const parameters = new DrawParameters({ + context, + visibleRect: new Rectangle(0, 0, w, h), + desiredAtlasScale: ORIGINAL_SPRITE_SCALE, + zoomLevel: dpi * 0.75, + root: this.root, + }); - // Background - staticComp.drawSpriteOnFullEntityBounds(parameters, this.hubSprite, 2.2); + context.clearRect(0, 0, w, h); + + this.hubSprite.draw(context, 0, 0, w, h); const definition = this.root.hubGoals.currentGoal.definition; - - definition.drawCentered(pos.x - 25, pos.y - 10, parameters, 40); + definition.drawCentered(45, 58, parameters, 36); const goals = this.root.hubGoals.currentGoal; - const textOffsetX = 2; - const textOffsetY = -6; + const textOffsetX = 70; + const textOffsetY = 61; // Deliver count const delivered = this.root.hubGoals.getCurrentGoalDelivered(); + const deliveredText = "" + formatBigNumber(delivered); if (delivered > 9999) { context.font = "bold 16px GameFont"; @@ -66,52 +86,87 @@ export class HubSystem extends GameSystemWithFilter { } context.fillStyle = "#64666e"; context.textAlign = "left"; - context.fillText("" + formatBigNumber(delivered), pos.x + textOffsetX, pos.y + textOffsetY); + context.fillText(deliveredText, textOffsetX, textOffsetY); // Required context.font = "13px GameFont"; context.fillStyle = "#a4a6b0"; - context.fillText( - "/ " + formatBigNumber(goals.required), - pos.x + textOffsetX, - pos.y + textOffsetY + 13 - ); + context.fillText("/ " + formatBigNumber(goals.required), textOffsetX, textOffsetY + 13); // Reward const rewardText = T.storyRewards[goals.reward].title.toUpperCase(); if (rewardText.length > 12) { - context.font = "bold 9px GameFont"; + context.font = "bold 8px GameFont"; } else { - context.font = "bold 11px GameFont"; + context.font = "bold 10px GameFont"; } context.fillStyle = "#fd0752"; context.textAlign = "center"; - context.fillText(rewardText, pos.x, pos.y + 46); + context.fillText(rewardText, HUB_SIZE_PIXELS / 2, 105); - // Level - context.font = "bold 11px GameFont"; + // Level "8" + context.font = "bold 10px GameFont"; context.fillStyle = "#fff"; - context.fillText("" + this.root.hubGoals.level, pos.x - 42, pos.y - 36); + context.fillText("" + this.root.hubGoals.level, 27, 32); - // Texts + // "LVL" context.textAlign = "center"; context.fillStyle = "#fff"; - context.font = "bold 7px GameFont"; - context.fillText(T.buildings.hub.levelShortcut, pos.x - 42, pos.y - 47); + context.font = "bold 6px GameFont"; + context.fillText(T.buildings.hub.levelShortcut, 27, 22); + // "Deliver" context.fillStyle = "#64666e"; - context.font = "bold 11px GameFont"; - context.fillText(T.buildings.hub.deliver.toUpperCase(), pos.x, pos.y - 40); + context.font = "bold 10px GameFont"; + context.fillText(T.buildings.hub.deliver.toUpperCase(), HUB_SIZE_PIXELS / 2, 30); + // "To unlock" const unlockText = T.buildings.hub.toUnlock.toUpperCase(); if (unlockText.length > 15) { context.font = "bold 8px GameFont"; } else { - context.font = "bold 11px GameFont"; + context.font = "bold 10px GameFont"; } - context.fillText(T.buildings.hub.toUnlock.toUpperCase(), pos.x, pos.y + 30); + context.fillText(T.buildings.hub.toUnlock.toUpperCase(), HUB_SIZE_PIXELS / 2, 92); context.textAlign = "left"; } + + /** + * @param {DrawParameters} parameters + * @param {Entity} entity + */ + drawEntity(parameters, entity) { + const staticComp = entity.components.StaticMapEntity; + if (!staticComp.shouldBeDrawn(parameters)) { + return; + } + + // Deliver count + const delivered = this.root.hubGoals.getCurrentGoalDelivered(); + const deliveredText = "" + formatBigNumber(delivered); + + const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); + const canvas = parameters.root.buffers.getForKey({ + key: "hub", + subKey: dpi + "/" + this.root.hubGoals.level + "/" + deliveredText, + w: globalConfig.tileSize * 4, + h: globalConfig.tileSize * 4, + dpi, + redrawMethod: this.redrawHubBaseTexture.bind(this), + }); + + const extrude = 8; + drawSpriteClipped({ + parameters, + sprite: canvas, + x: staticComp.origin.x * globalConfig.tileSize - extrude, + y: staticComp.origin.y * globalConfig.tileSize - extrude, + w: HUB_SIZE_PIXELS + 2 * extrude, + h: HUB_SIZE_PIXELS + 2 * extrude, + originalW: HUB_SIZE_PIXELS * dpi, + originalH: HUB_SIZE_PIXELS * dpi, + }); + } } diff --git a/src/js/game/systems/item_acceptor.js b/src/js/game/systems/item_acceptor.js index b67bd867..745da4bf 100644 --- a/src/js/game/systems/item_acceptor.js +++ b/src/js/game/systems/item_acceptor.js @@ -3,8 +3,8 @@ import { DrawParameters } from "../../core/draw_parameters"; import { fastArrayDelete } from "../../core/utils"; import { enumDirectionToVector } from "../../core/vector"; import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; export class ItemAcceptorSystem extends GameSystemWithFilter { constructor(root) { @@ -38,43 +38,45 @@ export class ItemAcceptorSystem extends GameSystemWithFilter { } /** - * Draws the acceptor items * @param {DrawParameters} parameters + * @param {MapChunkView} chunk */ - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntityRegularLayer.bind(this)); - } + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const acceptorComp = entity.components.ItemAcceptor; + if (!acceptorComp) { + continue; + } - /** - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntityRegularLayer(parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const acceptorComp = entity.components.ItemAcceptor; + const staticComp = entity.components.StaticMapEntity; + for (let animIndex = 0; animIndex < acceptorComp.itemConsumptionAnimations.length; ++animIndex) { + const { item, slotIndex, animProgress, direction } = acceptorComp.itemConsumptionAnimations[ + animIndex + ]; - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } + const slotData = acceptorComp.slots[slotIndex]; + const realSlotPos = staticComp.localTileToWorld(slotData.pos); - for (let animIndex = 0; animIndex < acceptorComp.itemConsumptionAnimations.length; ++animIndex) { - const { item, slotIndex, animProgress, direction } = acceptorComp.itemConsumptionAnimations[ - animIndex - ]; + if (!chunk.tileSpaceRectangle.containsPoint(realSlotPos.x, realSlotPos.y)) { + // Not within this chunk + continue; + } - const slotData = acceptorComp.slots[slotIndex]; + const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)]; + const finalTile = realSlotPos.subScalars( + fadeOutDirection.x * (animProgress / 2 - 0.5), + fadeOutDirection.y * (animProgress / 2 - 0.5) + ); - const slotWorldPos = staticComp.applyRotationToVector(slotData.pos).add(staticComp.origin); - const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)]; - const finalTile = slotWorldPos.subScalars( - fadeOutDirection.x * (animProgress / 2 - 0.5), - fadeOutDirection.y * (animProgress / 2 - 0.5) - ); - item.drawCentered( - (finalTile.x + 0.5) * globalConfig.tileSize, - (finalTile.y + 0.5) * globalConfig.tileSize, - parameters - ); + item.drawItemCenteredClipped( + (finalTile.x + 0.5) * globalConfig.tileSize, + (finalTile.y + 0.5) * globalConfig.tileSize, + parameters, + globalConfig.defaultItemDiameter + ); + } } } } diff --git a/src/js/game/systems/item_ejector.js b/src/js/game/systems/item_ejector.js index 130c87f0..6804925d 100644 --- a/src/js/game/systems/item_ejector.js +++ b/src/js/game/systems/item_ejector.js @@ -8,6 +8,7 @@ import { ItemEjectorComponent } from "../components/item_ejector"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { enumItemProcessorTypes } from "../components/item_processor"; +import { MapChunkView } from "../map_chunk_view"; const logger = createLogger("systems/ejector"); @@ -336,50 +337,52 @@ export class ItemEjectorSystem extends GameSystemWithFilter { } /** - * Draws everything * @param {DrawParameters} parameters + * @param {MapChunkView} chunk */ - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this)); - } + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; - /** - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawSingleEntity(parameters, entity) { - const ejectorComp = entity.components.ItemEjector; - const staticComp = entity.components.StaticMapEntity; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - for (let i = 0; i < ejectorComp.slots.length; ++i) { - const slot = ejectorComp.slots[i]; - const ejectedItem = slot.item; - - if (!ejectedItem) { - // No item + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const ejectorComp = entity.components.ItemEjector; + if (!ejectorComp) { continue; } - const realPosition = slot.pos.rotateFastMultipleOf90(staticComp.rotation); - const realDirection = Vector.transformDirectionFromMultipleOf90( - slot.direction, - staticComp.rotation - ); - const realDirectionVector = enumDirectionToVector[realDirection]; + const staticComp = entity.components.StaticMapEntity; - const tileX = - staticComp.origin.x + realPosition.x + 0.5 + realDirectionVector.x * 0.5 * slot.progress; - const tileY = - staticComp.origin.y + realPosition.y + 0.5 + realDirectionVector.y * 0.5 * slot.progress; + for (let i = 0; i < ejectorComp.slots.length; ++i) { + const slot = ejectorComp.slots[i]; + const ejectedItem = slot.item; - const worldX = tileX * globalConfig.tileSize; - const worldY = tileY * globalConfig.tileSize; + if (!ejectedItem) { + // No item + continue; + } - ejectedItem.drawCentered(worldX, worldY, parameters); + const realPosition = staticComp.localTileToWorld(slot.pos); + if (!chunk.tileSpaceRectangle.containsPoint(realPosition.x, realPosition.y)) { + // Not within this chunk + continue; + } + + const realDirection = staticComp.localDirectionToWorld(slot.direction); + const realDirectionVector = enumDirectionToVector[realDirection]; + + const tileX = realPosition.x + 0.5 + realDirectionVector.x * 0.5 * slot.progress; + const tileY = realPosition.y + 0.5 + realDirectionVector.y * 0.5 * slot.progress; + + const worldX = tileX * globalConfig.tileSize; + const worldY = tileY * globalConfig.tileSize; + + ejectedItem.drawItemCenteredClipped( + worldX, + worldY, + parameters, + globalConfig.defaultItemDiameter + ); + } } } } diff --git a/src/js/game/systems/lever.js b/src/js/game/systems/lever.js index fa727535..0d538afc 100644 --- a/src/js/game/systems/lever.js +++ b/src/js/game/systems/lever.js @@ -34,8 +34,9 @@ export class LeverSystem extends GameSystemWithFilter { const contents = chunk.containedEntitiesByLayer.regular; for (let i = 0; i < contents.length; ++i) { const entity = contents[i]; - if (entity && entity.components.Lever) { - const sprite = entity.components.Lever.toggled ? this.spriteOn : this.spriteOff; + const leverComp = entity.components.Lever; + if (leverComp) { + const sprite = leverComp.toggled ? this.spriteOn : this.spriteOff; const origin = entity.components.StaticMapEntity.origin; sprite.drawCached( parameters, diff --git a/src/js/game/systems/logic_gate.js b/src/js/game/systems/logic_gate.js index 9fe41250..6914410e 100644 --- a/src/js/game/systems/logic_gate.js +++ b/src/js/game/systems/logic_gate.js @@ -1,180 +1,326 @@ -import { LogicGateComponent, enumLogicGateType } from "../components/logic_gate"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { BaseItem } from "../base_item"; -import { enumPinSlotType } from "../components/wired_pins"; -import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON, BooleanItem } from "../items/boolean_item"; -import { enumItemProcessorTypes } from "../components/item_processor"; - -export class LogicGateSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [LogicGateComponent]); - - this.boundOperations = { - [enumLogicGateType.and]: this.compute_AND.bind(this), - [enumLogicGateType.not]: this.compute_NOT.bind(this), - [enumLogicGateType.xor]: this.compute_XOR.bind(this), - [enumLogicGateType.or]: this.compute_OR.bind(this), - [enumLogicGateType.transistor]: this.compute_IF.bind(this), - }; - } - - update() { - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const logicComp = entity.components.LogicGate; - const slotComp = entity.components.WiredPins; - - const slotValues = []; - - for (let i = 0; i < slotComp.slots.length; ++i) { - const slot = slotComp.slots[i]; - if (slot.type !== enumPinSlotType.logicalAcceptor) { - continue; - } - if (slot.linkedNetwork) { - slotValues.push(slot.linkedNetwork.currentValue); - } else { - slotValues.push(null); - } - } - - const result = this.boundOperations[logicComp.type](slotValues); - - // @TODO: For now we hardcode the value to always be slot 0 - assert( - slotValues.length === slotComp.slots.length - 1, - "Bad slot config, should have N acceptor slots and 1 ejector" - ); - assert(slotComp.slots[0].type === enumPinSlotType.logicalEjector, "Slot 0 should be ejector"); - - slotComp.slots[0].value = result; - } - } - - /** - * @param {Array} parameters - * @returns {BaseItem} - */ - compute_AND(parameters) { - assert(parameters.length === 2, "bad parameter count for AND"); - - const param1 = parameters[0]; - const param2 = parameters[1]; - if (!param1 || !param2) { - // Not enough params - return BOOL_FALSE_SINGLETON; - } - - const itemType = param1.getItemType(); - - if (itemType !== param2.getItemType()) { - // Differing type - return BOOL_FALSE_SINGLETON; - } - - if (itemType === "boolean") { - return /** @type {BooleanItem} */ (param1).value && /** @type {BooleanItem} */ (param2).value - ? BOOL_TRUE_SINGLETON - : BOOL_FALSE_SINGLETON; - } - - return BOOL_FALSE_SINGLETON; - } - - /** - * @param {Array} parameters - * @returns {BaseItem} - */ - compute_NOT(parameters) { - const item = parameters[0]; - if (!item) { - return BOOL_TRUE_SINGLETON; - } - - if (item.getItemType() !== "boolean") { - // Not a boolean actually - return BOOL_FALSE_SINGLETON; - } - - const value = /** @type {BooleanItem} */ (item).value; - return value ? BOOL_FALSE_SINGLETON : BOOL_TRUE_SINGLETON; - } - - /** - * @param {Array} parameters - * @returns {BaseItem} - */ - compute_XOR(parameters) { - assert(parameters.length === 2, "bad parameter count for XOR"); - - const param1 = parameters[0]; - const param2 = parameters[1]; - if (!param1 && !param2) { - // Not enough params - return BOOL_FALSE_SINGLETON; - } - - // Check for the right types - if (param1 && param1.getItemType() !== "boolean") { - return BOOL_FALSE_SINGLETON; - } - - if (param2 && param2.getItemType() !== "boolean") { - return BOOL_FALSE_SINGLETON; - } - - const valueParam1 = param1 ? /** @type {BooleanItem} */ (param1).value : 0; - const valueParam2 = param2 ? /** @type {BooleanItem} */ (param2).value : 0; - - return valueParam1 ^ valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; - } - - /** - * @param {Array} parameters - * @returns {BaseItem} - */ - compute_OR(parameters) { - assert(parameters.length === 2, "bad parameter count for OR"); - - const param1 = parameters[0]; - const param2 = parameters[1]; - if (!param1 && !param2) { - // Not enough params - return BOOL_FALSE_SINGLETON; - } - - const valueParam1 = - param1 && param1.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param1).value : 0; - const valueParam2 = - param2 && param2.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param2).value : 0; - - return valueParam1 || valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; - } - - /** - * @param {Array} parameters - * @returns {BaseItem} - */ - compute_IF(parameters) { - assert(parameters.length === 2, "bad parameter count for IF"); - - const flag = parameters[0]; - const value = parameters[1]; - if (!flag || !value) { - // Not enough params - return null; - } - - if (flag.getItemType() !== "boolean") { - // Flag is not a boolean - return null; - } - - // pass through item - if (/** @type {BooleanItem} */ (flag).value) { - return value; - } - - return null; - } -} +import { BaseItem } from "../base_item"; +import { enumColors } from "../colors"; +import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; +import { enumPinSlotType } from "../components/wired_pins"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON, BooleanItem } from "../items/boolean_item"; +import { COLOR_ITEM_SINGLETONS } from "../items/color_item"; +import { ShapeDefinition } from "../shape_definition"; +import { ShapeItem } from "../items/shape_item"; + +export class LogicGateSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [LogicGateComponent]); + + this.boundOperations = { + [enumLogicGateType.and]: this.compute_AND.bind(this), + [enumLogicGateType.not]: this.compute_NOT.bind(this), + [enumLogicGateType.xor]: this.compute_XOR.bind(this), + [enumLogicGateType.or]: this.compute_OR.bind(this), + [enumLogicGateType.transistor]: this.compute_IF.bind(this), + + [enumLogicGateType.rotater]: this.compute_ROTATE.bind(this), + [enumLogicGateType.analyzer]: this.compute_ANALYZE.bind(this), + [enumLogicGateType.cutter]: this.compute_CUT.bind(this), + [enumLogicGateType.unstacker]: this.compute_UNSTACK.bind(this), + [enumLogicGateType.shapecompare]: this.compute_SHAPECOMPARE.bind(this), + }; + } + + update() { + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const logicComp = entity.components.LogicGate; + const slotComp = entity.components.WiredPins; + + const slotValues = []; + + for (let i = 0; i < slotComp.slots.length; ++i) { + const slot = slotComp.slots[i]; + if (slot.type !== enumPinSlotType.logicalAcceptor) { + continue; + } + if (slot.linkedNetwork) { + slotValues.push(slot.linkedNetwork.currentValue); + } else { + slotValues.push(null); + } + } + + const result = this.boundOperations[logicComp.type](slotValues); + + if (Array.isArray(result)) { + let resultIndex = 0; + for (let i = 0; i < slotComp.slots.length; ++i) { + const slot = slotComp.slots[i]; + if (slot.type !== enumPinSlotType.logicalEjector) { + continue; + } + slot.value = result[resultIndex++]; + } + } else { + // @TODO: For now we hardcode the value to always be slot 0 + assert( + slotValues.length === slotComp.slots.length - 1, + "Bad slot config, should have N acceptor slots and 1 ejector" + ); + assert(slotComp.slots[0].type === enumPinSlotType.logicalEjector, "Slot 0 should be ejector"); + slotComp.slots[0].value = result; + } + } + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_AND(parameters) { + assert(parameters.length === 2, "bad parameter count for AND"); + + const param1 = parameters[0]; + const param2 = parameters[1]; + if (!param1 || !param2) { + // Not enough params + return BOOL_FALSE_SINGLETON; + } + + const itemType = param1.getItemType(); + + if (itemType !== param2.getItemType()) { + // Differing type + return BOOL_FALSE_SINGLETON; + } + + if (itemType === "boolean") { + return /** @type {BooleanItem} */ (param1).value && /** @type {BooleanItem} */ (param2).value + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + + return BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_NOT(parameters) { + const item = parameters[0]; + if (!item) { + return BOOL_TRUE_SINGLETON; + } + + if (item.getItemType() !== "boolean") { + // Not a boolean actually + return BOOL_FALSE_SINGLETON; + } + + const value = /** @type {BooleanItem} */ (item).value; + return value ? BOOL_FALSE_SINGLETON : BOOL_TRUE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_XOR(parameters) { + assert(parameters.length === 2, "bad parameter count for XOR"); + + const param1 = parameters[0]; + const param2 = parameters[1]; + if (!param1 && !param2) { + // Not enough params + return BOOL_FALSE_SINGLETON; + } + + // Check for the right types + if (param1 && param1.getItemType() !== "boolean") { + return BOOL_FALSE_SINGLETON; + } + + if (param2 && param2.getItemType() !== "boolean") { + return BOOL_FALSE_SINGLETON; + } + + const valueParam1 = param1 ? /** @type {BooleanItem} */ (param1).value : 0; + const valueParam2 = param2 ? /** @type {BooleanItem} */ (param2).value : 0; + + return valueParam1 ^ valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_OR(parameters) { + assert(parameters.length === 2, "bad parameter count for OR"); + + const param1 = parameters[0]; + const param2 = parameters[1]; + if (!param1 && !param2) { + // Not enough params + return BOOL_FALSE_SINGLETON; + } + + const valueParam1 = + param1 && param1.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param1).value : 0; + const valueParam2 = + param2 && param2.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param2).value : 0; + + return valueParam1 || valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_IF(parameters) { + assert(parameters.length === 2, "bad parameter count for IF"); + + const flag = parameters[0]; + const value = parameters[1]; + if (!flag || !value) { + // Not enough params + return null; + } + + if (flag.getItemType() !== "boolean") { + // Flag is not a boolean + return null; + } + + // pass through item + if (/** @type {BooleanItem} */ (flag).value) { + return value; + } + + return null; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_ROTATE(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return null; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(definition); + return this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition); + } + + /** + * @param {Array} parameters + * @returns {[BaseItem, BaseItem]} + */ + compute_ANALYZE(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return [null, null]; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const lowerLayer = /** @type {import("../shape_definition").ShapeLayer} */ (definition.layers[0]); + if (!lowerLayer) { + return [null, null]; + } + + const topRightContent = lowerLayer[0]; + + if (!topRightContent || topRightContent.subShape === null) { + return [null, null]; + } + + const newDefinition = new ShapeDefinition({ + layers: [ + [ + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + ], + ], + }); + + return [ + COLOR_ITEM_SINGLETONS[topRightContent.color], + this.root.shapeDefinitionMgr.getShapeItemFromDefinition(newDefinition), + ]; + } + + /** + * @param {Array} parameters + * @returns {[BaseItem, BaseItem]} + */ + compute_CUT(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return [null, null]; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const result = this.root.shapeDefinitionMgr.shapeActionCutHalf(definition); + return [ + result[0].isEntirelyEmpty() + ? null + : this.root.shapeDefinitionMgr.getShapeItemFromDefinition(result[0]), + result[1].isEntirelyEmpty() + ? null + : this.root.shapeDefinitionMgr.getShapeItemFromDefinition(result[1]), + ]; + } + + /** + * @param {Array} parameters + * @returns {[BaseItem, BaseItem]} + */ + compute_UNSTACK(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return [null, null]; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const layers = /** @type {Array} */ (definition.layers); + + const upperLayerDefinition = new ShapeDefinition({ + layers: [layers[layers.length - 1]], + }); + + const lowerLayers = layers.slice(0, layers.length - 1); + const lowerLayerDefinition = + lowerLayers.length > 0 ? new ShapeDefinition({ layers: lowerLayers }) : null; + + return [ + lowerLayerDefinition + ? this.root.shapeDefinitionMgr.getShapeItemFromDefinition(lowerLayerDefinition) + : null, + this.root.shapeDefinitionMgr.getShapeItemFromDefinition(upperLayerDefinition), + ]; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_SHAPECOMPARE(parameters) { + const itemA = parameters[0]; + const itemB = parameters[1]; + + return itemA && + itemB && + itemA.getItemType() === "shape" && + itemB.getItemType() === "shape" && + /** @type {ShapeItem} */ (itemA).definition.getHash() === + /** @type {ShapeItem} */ (itemB).definition.getHash() + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } +} diff --git a/src/js/game/systems/map_resources.js b/src/js/game/systems/map_resources.js index 8a005a21..eb3d0d2f 100644 --- a/src/js/game/systems/map_resources.js +++ b/src/js/game/systems/map_resources.js @@ -13,7 +13,7 @@ export class MapResourcesSystem extends GameSystem { */ drawChunk(parameters, chunk) { const basicChunkBackground = this.root.buffers.getForKey({ - key: "chunkres", + key: "mapresourcebg", subKey: chunk.renderKey, w: globalConfig.mapChunkSize, h: globalConfig.mapChunkSize, @@ -42,10 +42,9 @@ export class MapResourcesSystem extends GameSystem { const patch = chunk.patches[i]; const destX = chunk.x * globalConfig.mapChunkWorldSize + patch.pos.x * globalConfig.tileSize; const destY = chunk.y * globalConfig.mapChunkWorldSize + patch.pos.y * globalConfig.tileSize; - const destSize = Math.min(80, 40 / parameters.zoomLevel); - if (parameters.visibleRect.containsCircle(destX, destY, destSize / 2)) { - patch.item.drawCentered(destX, destY, parameters, destSize); - } + const diameter = Math.min(80, 40 / parameters.zoomLevel); + + patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter); } } else { // HIGH QUALITY: Draw all items @@ -61,9 +60,12 @@ export class MapResourcesSystem extends GameSystem { const destX = worldX + globalConfig.halfTileSize; const destY = worldY + globalConfig.halfTileSize; - if (parameters.visibleRect.containsCircle(destX, destY, globalConfig.tileSize / 2)) { - lowerItem.drawCentered(destX, destY, parameters); - } + lowerItem.drawItemCenteredClipped( + destX, + destY, + parameters, + globalConfig.defaultItemDiameter + ); } } } diff --git a/src/js/game/systems/miner.js b/src/js/game/systems/miner.js index 0f1fbc45..deff1557 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -102,41 +102,39 @@ export class MinerSystem extends GameSystemWithFilter { * @param {MapChunkView} chunk */ drawChunk(parameters, chunk) { - const contents = chunk.contents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; + const contents = chunk.containedEntitiesByLayer.regular; - if (entity && entity.components.Miner) { - const staticComp = entity.components.StaticMapEntity; - const minerComp = entity.components.Miner; - if (!staticComp.shouldBeDrawn(parameters)) { - continue; - } - if (!minerComp.cachedMinedItem) { - continue; - } - - if (minerComp.cachedMinedItem) { - const padding = 3; - parameters.context.fillStyle = minerComp.cachedMinedItem.getBackgroundColorAsResource(); - parameters.context.fillRect( - staticComp.origin.x * globalConfig.tileSize + padding, - staticComp.origin.y * globalConfig.tileSize + padding, - globalConfig.tileSize - 2 * padding, - globalConfig.tileSize - 2 * padding - ); - } - - if (minerComp.cachedMinedItem) { - minerComp.cachedMinedItem.drawCentered( - (0.5 + staticComp.origin.x) * globalConfig.tileSize, - (0.5 + staticComp.origin.y) * globalConfig.tileSize, - parameters - ); - } - } + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const minerComp = entity.components.Miner; + if (!minerComp) { + continue; } + + const staticComp = entity.components.StaticMapEntity; + if (!minerComp.cachedMinedItem) { + continue; + } + + // Draw the item background - this is to hide the ejected item animation from + // the item ejecto + + const padding = 3; + const destX = staticComp.origin.x * globalConfig.tileSize + padding; + const destY = staticComp.origin.y * globalConfig.tileSize + padding; + const dimensions = globalConfig.tileSize - 2 * padding; + + if (parameters.visibleRect.containsRect4Params(destX, destY, dimensions, dimensions)) { + parameters.context.fillStyle = minerComp.cachedMinedItem.getBackgroundColorAsResource(); + parameters.context.fillRect(destX, destY, dimensions, dimensions); + } + + minerComp.cachedMinedItem.drawItemCenteredClipped( + (0.5 + staticComp.origin.x) * globalConfig.tileSize, + (0.5 + staticComp.origin.y) * globalConfig.tileSize, + parameters, + globalConfig.defaultItemDiameter + ); } } } diff --git a/src/js/game/systems/static_map_entity.js b/src/js/game/systems/static_map_entity.js index 00de6b5a..da6575a5 100644 --- a/src/js/game/systems/static_map_entity.js +++ b/src/js/game/systems/static_map_entity.js @@ -6,6 +6,18 @@ import { MapChunkView } from "../map_chunk_view"; export class StaticMapEntitySystem extends GameSystem { constructor(root) { super(root); + + /** @type {Set} */ + this.drawnUids = new Set(); + + this.root.signals.gameFrameStarted.add(this.clearUidList, this); + } + + /** + * Clears the uid list when a new frame started + */ + clearUidList() { + this.drawnUids.clear(); } /** @@ -18,25 +30,21 @@ export class StaticMapEntitySystem extends GameSystem { return; } - const drawnUids = new Set(); + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; - const contents = chunk.contents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; - - if (entity) { - if (drawnUids.has(entity.uid)) { - continue; - } - drawnUids.add(entity.uid); - const staticComp = entity.components.StaticMapEntity; - - const sprite = staticComp.getSprite(); - if (sprite) { - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2); - } + const staticComp = entity.components.StaticMapEntity; + const sprite = staticComp.getSprite(); + if (sprite) { + // Avoid drawing an entity twice which has been drawn for + // another chunk already + if (this.drawnUids.has(entity.uid)) { + continue; } + + this.drawnUids.add(entity.uid); + staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 2); } } } @@ -65,7 +73,7 @@ export class StaticMapEntitySystem extends GameSystem { const sprite = staticComp.getSprite(); if (sprite) { - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2); + staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 2); } } } diff --git a/src/js/game/systems/storage.js b/src/js/game/systems/storage.js index 5da8c9a4..5a2b57bb 100644 --- a/src/js/game/systems/storage.js +++ b/src/js/game/systems/storage.js @@ -1,16 +1,28 @@ import { GameSystemWithFilter } from "../game_system_with_filter"; import { StorageComponent } from "../components/storage"; -import { Entity } from "../entity"; import { DrawParameters } from "../../core/draw_parameters"; import { formatBigNumber, lerp } from "../../core/utils"; import { Loader } from "../../core/loader"; import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item"; +import { MapChunkView } from "../map_chunk_view"; export class StorageSystem extends GameSystemWithFilter { constructor(root) { super(root, [StorageComponent]); this.storageOverlaySprite = Loader.getSprite("sprites/misc/storage_overlay.png"); + + /** + * Stores which uids were already drawn to avoid drawing entities twice + * @type {Set} + */ + this.drawnUids = new Set(); + + this.root.signals.gameFrameStarted.add(this.clearDrawnUids, this); + } + + clearDrawnUids() { + this.drawnUids.clear(); } update() { @@ -43,38 +55,46 @@ export class StorageSystem extends GameSystemWithFilter { } } - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); - } - /** * @param {DrawParameters} parameters - * @param {Entity} entity + * @param {MapChunkView} chunk */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const storageComp = entity.components.Storage; + if (!storageComp) { + continue; + } - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } + const storedItem = storageComp.storedItem; + if (!storedItem) { + continue; + } - const storageComp = entity.components.Storage; + if (this.drawnUids.has(entity.uid)) { + continue; + } - const storedItem = storageComp.storedItem; - if (storedItem !== null) { + this.drawnUids.add(entity.uid); + + const staticComp = entity.components.StaticMapEntity; + + const context = parameters.context; context.globalAlpha = storageComp.overlayOpacity; const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); - storedItem.drawCentered(center.x, center.y, parameters, 30); + storedItem.drawItemCenteredClipped(center.x, center.y, parameters, 30); this.storageOverlaySprite.drawCached(parameters, center.x - 15, center.y + 15, 30, 15); - context.font = "bold 10px GameFont"; - context.textAlign = "center"; - context.fillStyle = "#64666e"; - context.fillText(formatBigNumber(storageComp.storedCount), center.x, center.y + 25.5); - - context.textAlign = "left"; + if (parameters.visibleRect.containsCircle(center.x, center.y + 25, 20)) { + context.font = "bold 10px GameFont"; + context.textAlign = "center"; + context.fillStyle = "#64666e"; + context.fillText(formatBigNumber(storageComp.storedCount), center.x, center.y + 25.5); + context.textAlign = "left"; + } context.globalAlpha = 1; } } diff --git a/src/js/game/systems/wire.js b/src/js/game/systems/wire.js index 19a2d8be..b8d8031e 100644 --- a/src/js/game/systems/wire.js +++ b/src/js/game/systems/wire.js @@ -317,7 +317,9 @@ export class WireSystem extends GameSystemWithFilter { if ( currentNetwork.providers.length > 0 && - (currentNetwork.wires.length > 0 || currentNetwork.receivers.length > 0) + (currentNetwork.wires.length > 0 || + currentNetwork.receivers.length > 0 || + currentNetwork.tunnels.length > 0) ) { this.networks.push(currentNetwork); VERBOSE_WIRES && logger.log("Attached new network with uid", currentNetwork); @@ -624,7 +626,7 @@ export class WireSystem extends GameSystemWithFilter { assert(sprite, "Unknown wire type: " + wireType); const staticComp = entity.components.StaticMapEntity; parameters.context.globalAlpha = opacity; - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0); + staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 0); parameters.context.globalAlpha = 1; if (G_IS_DEV && globalConfig.debug.renderWireRotations) { diff --git a/src/js/game/systems/wired_pins.js b/src/js/game/systems/wired_pins.js index 02e84372..43771b49 100644 --- a/src/js/game/systems/wired_pins.js +++ b/src/js/game/systems/wired_pins.js @@ -1,13 +1,13 @@ import { globalConfig } from "../../core/config"; import { DrawParameters } from "../../core/draw_parameters"; +import { drawRotatedSprite } from "../../core/draw_utils"; import { Loader } from "../../core/loader"; -import { Vector, enumDirectionToAngle } from "../../core/vector"; +import { STOP_PROPAGATION } from "../../core/signal"; +import { enumDirectionToAngle, Vector } from "../../core/vector"; import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { STOP_PROPAGATION } from "../../core/signal"; -import { drawRotatedSprite } from "../../core/draw_utils"; -import { GLOBAL_APP } from "../../core/globals"; +import { MapChunkView } from "../map_chunk_view"; export class WiredPinsSystem extends GameSystemWithFilter { constructor(root) { @@ -146,65 +146,84 @@ export class WiredPinsSystem extends GameSystemWithFilter { // TODO } - /** - * Draws the pins - * @param {DrawParameters} parameters - */ - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this)); - } - /** * Draws a given entity * @param {DrawParameters} parameters - * @param {Entity} entity + * @param {MapChunkView} chunk */ - drawSingleEntity(parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const slots = entity.components.WiredPins.slots; + drawChunk(parameters, chunk) { + const contents = chunk.containedEntities; - for (let i = 0; i < slots.length; ++i) { - const slot = slots[i]; - const tile = staticComp.localTileToWorld(slot.pos); - - const worldPos = tile.toWorldSpaceCenterOfTile(); - const effectiveRotation = Math.radians( - staticComp.rotation + enumDirectionToAngle[slot.direction] - ); - - if (staticComp.getMetaBuilding().getRenderPins()) { - drawRotatedSprite({ - parameters, - sprite: this.pinSprites[slot.type], - x: worldPos.x, - y: worldPos.y, - angle: effectiveRotation, - size: globalConfig.tileSize + 2, - offsetX: 0, - offsetY: 0, - }); + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const pinsComp = entity.components.WiredPins; + if (!pinsComp) { + continue; } - // Draw contained item to visualize whats emitted - const value = slot.value; - if (value) { - const offset = new Vector(0, -9).rotated(effectiveRotation); - value.drawCentered(worldPos.x + offset.x, worldPos.y + offset.y, parameters, 9); - } + const staticComp = entity.components.StaticMapEntity; + const slots = pinsComp.slots; - // Debug view - if (G_IS_DEV && globalConfig.debug.renderWireNetworkInfos) { - const offset = new Vector(0, -10).rotated(effectiveRotation); - const network = slot.linkedNetwork; - parameters.context.fillStyle = "blue"; - parameters.context.font = "5px Tahoma"; - parameters.context.textAlign = "center"; - parameters.context.fillText( - network ? "S" + network.uid : "???", - (tile.x + 0.5) * globalConfig.tileSize + offset.x, - (tile.y + 0.5) * globalConfig.tileSize + offset.y + for (let j = 0; j < slots.length; ++j) { + const slot = slots[j]; + const tile = staticComp.localTileToWorld(slot.pos); + + if (!chunk.tileSpaceRectangle.containsPoint(tile.x, tile.y)) { + // Doesn't belong to this chunk + continue; + } + const worldPos = tile.toWorldSpaceCenterOfTile(); + + // Culling + if ( + !parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, globalConfig.halfTileSize) + ) { + continue; + } + + const effectiveRotation = Math.radians( + staticComp.rotation + enumDirectionToAngle[slot.direction] ); - parameters.context.textAlign = "left"; + + if (staticComp.getMetaBuilding().getRenderPins()) { + drawRotatedSprite({ + parameters, + sprite: this.pinSprites[slot.type], + x: worldPos.x, + y: worldPos.y, + angle: effectiveRotation, + size: globalConfig.tileSize + 2, + offsetX: 0, + offsetY: 0, + }); + } + + // Draw contained item to visualize whats emitted + const value = slot.value; + if (value) { + const offset = new Vector(0, -9).rotated(effectiveRotation); + value.drawItemCenteredClipped( + worldPos.x + offset.x, + worldPos.y + offset.y, + parameters, + 9 + ); + } + + // Debug view + if (G_IS_DEV && globalConfig.debug.renderWireNetworkInfos) { + const offset = new Vector(0, -10).rotated(effectiveRotation); + const network = slot.linkedNetwork; + parameters.context.fillStyle = "blue"; + parameters.context.font = "5px Tahoma"; + parameters.context.textAlign = "center"; + parameters.context.fillText( + network ? "S" + network.uid : "???", + (tile.x + 0.5) * globalConfig.tileSize + offset.x, + (tile.y + 0.5) * globalConfig.tileSize + offset.y + ); + parameters.context.textAlign = "left"; + } } } } diff --git a/translations/base-de.yaml b/translations/base-de.yaml index 29713620..251fbab2 100644 --- a/translations/base-de.yaml +++ b/translations/base-de.yaml @@ -44,6 +44,7 @@ steamPage: Nutze dein gesammeltes Wissen über die Maschinen und lasse deine Fabriken die gewünschten Formen der 18 verschiedenen Level abliefern. Schalte mit jedem Level neue Arbeitsschritte oder Gebäude frei. Das sollte dich schon für Stunden beschäftigt halten! Danach werden im Freispielmodus zufällige Formen generiert, die du ebenfalls abliefern kannst. Ich füge regelmäßig neue Funktionen hinzu und davon sind eine ganze Menge geplant! + Wenn du das Spiel erwirbst, erhälst du Zugriff auf die zusätzlichen Features der Standalone-Version. Das bedeutet, du kannst unter anderem die neuesten Updates zuerst spielen! [b]Vorteile der Standalone[/b] @@ -296,6 +297,7 @@ ingame: copySelection: Kopieren clearSelection: Auswahl aufheben pipette: Pipette + switchLayers: Ebenen wechseln # Names of the colors, used for the color blind mode @@ -832,7 +834,6 @@ keybindings: Modifikator: stattdessen gegen den UZS rotieren cycleBuildingVariants: Variante wählen confirmMassDelete: Massenlöschung bestätigen - pasteLastBlueprint: Letzte Blaupause einfügen cycleBuildings: Gebäude rotieren lockBeltDirection: Bandplaner aktivieren switchDirectionLockSide: >- @@ -846,8 +847,10 @@ keybindings: placementDisableAutoOrientation: Automatische Orientierung deaktivieren placeMultiple: Im Platziermodus bleiben placeInverse: Automatische Förderbandorientierung invertieren - advanced_processor: Farbnivertierer + pasteLastBlueprint: Letzte Blaupause einfügen + advanced_processor: Farbinvertierer energy_generator: Energiegenerator + wire: Energiekabel about: title: Über dieses Spiel diff --git a/translations/base-en.yaml b/translations/base-en.yaml index edc304b9..8703a14e 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -1,932 +1,953 @@ -# -# GAME TRANSLATIONS -# -# Contributing: -# -# If you want to contribute, please make a pull request on this respository -# and I will have a look. -# -# Placeholders: -# -# Do *not* replace placeholders! Placeholders have a special syntax like -# `Hotkey: `. They are encapsulated within angle brackets. The correct -# translation for this one in German for example would be: `Taste: ` (notice -# how the placeholder stayed '' and was not replaced!) -# -# Adding a new language: -# -# If you want to add a new language, ask me in the Discord and I will setup -# the basic structure so the game also detects it. -# - ---- -steamPage: - # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - - # This is the text shown above the Discord link - discordLink: Official Discord - Chat with me! - - # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. - # NOTICE: - # - Do not translate the first line (This is the gif image at the start of the store) - # - Please keep the markup (Stuff like [b], [list] etc) in the same format - longText: >- - [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - - Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. - - As the demand for shapes increases, you'll have to scale up your factory to meet the demand - Don't forget about resources though, you'll have to expand across the [b]infinite map[/b]! - - Soon you'll have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with them to satisfy the demand. - - This game features 18 progressive levels (Which should already keep you busy for hours!) but I'm constantly adding new content - There's a lot planned! - - Purchasing the game gives you access to the standalone version which has additional features, and you'll also receive access to newly developed features. - - [b]Standalone Advantages[/b] - - [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ - [/list] - - [b]Future Updates[/b] - - I am updating the game often and trying to push an update at least once every week! - - [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! - [/list] - - [b]This game is open source![/b] - - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! - - [b]Links[/b] - - [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] - [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] - [/list] - -global: - loading: Loading - error: Error - - # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," - - # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" - decimalSeparator: "." - - # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. - suffix: - thousands: k - millions: M - billions: B - trillions: T - - # Shown for infinitely big numbers - infinite: inf - - time: - # Used for formatting past time dates - oneSecondAgo: one second ago - xSecondsAgo: seconds ago - oneMinuteAgo: one minute ago - xMinutesAgo: minutes ago - oneHourAgo: one hour ago - xHoursAgo: hours ago - oneDayAgo: one day ago - xDaysAgo: days ago - - # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h m - - xMinutes: minutes - - keys: - tab: TAB - control: CTRL - alt: ALT - escape: ESC - shift: SHIFT - space: SPACE - -demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: Demo Version - intro: >- - Get the standalone to unlock all features! - -mainMenu: - play: Play - continue: Continue - newGame: New Game - changelog: Changelog - subreddit: Reddit - importSavegame: Import - openSourceHint: This game is open source! - discordLink: Official Discord Server - helpTranslate: Help translate! - madeBy: Made by - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. - - savegameLevel: Level - savegameLevelUnknown: Unknown Level - -dialogs: - buttons: - ok: OK - delete: Delete - cancel: Cancel - later: Later - restart: Restart - reset: Reset - getStandalone: Get Standalone - deleteGame: I know what I am doing - viewUpdate: View Update - showUpgrades: Show Upgrades - showKeybindings: Show Keybindings - - importSavegameError: - title: Import Error - text: >- - Failed to import your savegame: - - importSavegameSuccess: - title: Savegame Imported - text: >- - Your savegame has been successfully imported. - - gameLoadFailure: - title: Game is broken - text: >- - Failed to load your savegame: - - confirmSavegameDelete: - title: Confirm deletion - text: >- - Are you sure you want to delete the game? - - savegameDeletionError: - title: Failed to delete - text: >- - Failed to delete the savegame: - - restartRequired: - title: Restart required - text: >- - You need to restart the game to apply the settings. - - editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. - - resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. - - keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! - - featureRestriction: - title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider getting the standalone version for the full experience! - - oneSavegameLimit: - title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone version! - - updateSummary: - title: New update! - desc: >- - Here are the changes since you last played: - - upgradesIntroduction: - title: Unlock Upgrades - desc: >- - All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! - The upgrades tab can be found on the top right corner of the screen. - - massDeleteConfirm: - title: Confirm delete - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - - massCutConfirm: - title: Confirm cut - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? - - massCutInsufficientConfirm: - title: Confirm cut - desc: >- - You can not afford to paste this area! Are you sure you want to cut it? - - blueprintsNotUnlocked: - title: Not unlocked yet - desc: >- - Complete level 12 to unlock Blueprints! - - keybindingsIntroduction: - title: Useful keybindings - desc: >- - This game has a lot of keybindings which make it easier to build big factories. - Here are a few, but be sure to check out the keybindings!

- CTRL + Drag: Select an area.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
- - createMarker: - title: New Marker - titleEdit: Edit Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - - markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! - - exportScreenshotWarning: - title: Export screenshot - desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! - -ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation - keybindingsOverlay: - moveMap: Move - selectBuildings: Select area - stopPlacement: Stop placement - rotateBuilding: Rotate building - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto-orientation - toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create marker - delete: Delete - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear selection - pipette: Pipette - switchLayers: Switch layers - - # Names of the colors, used for the color blind mode - colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - black: Black - uncolored: Gray - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) - buildingPlacement: - # Buildings can have different variants which are unlocked at later levels, - # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Press to cycle variants. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - - infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s - itemsPerSecondDouble: (x2) - - tiles: tiles - - # The notification when completing a level - levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level - - # Notifications on the lower right - notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. - - # The "Upgrades" window - shop: - title: Upgrades - buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window - statistics: - title: Statistics - dataSources: - stored: - title: Stored - description: Displaying amount of stored shapes in your central building. - produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. - delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" - settingsMenu: - playtime: Playtime - - buildingsPlaced: Buildings - beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints - tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close - - # When placing a blueprint - blueprintPlacer: - cost: Cost - - # Map markers - waypoints: - waypoints: Markers - hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. - - # Shape viewer - shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key - - # Interactive tutorial - interactiveTutorial: - title: Tutorial - hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! - - 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. - -# All shop upgrades -shopUpgrades: - belt: - name: Belts, Distributor & Tunnels - description: Speed x → x - miner: - name: Extraction - description: Speed x → x - processors: - name: Cutting, Rotating & Stacking - description: Speed x → x - painting: - name: Mixing & Painting - description: Speed x → x - -# Buildings and their name / description -buildings: - hub: - deliver: Deliver - toUnlock: to unlock - levelShortcut: LVL - - belt: - default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - - # Internal name for the Extractor - miner: - default: - name: &miner Extractor - description: Place over a shape or color to extract it. - - chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. - - # Internal name for the Tunnel - underground_belt: - default: - name: &underground_belt Tunnel - description: Allows you to tunnel resources under buildings and belts. - - tier2: - name: Tunnel Tier II - description: Allows you to tunnel resources under buildings and belts. - - # Internal name for the Balancer - splitter: - default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. - - compact: - name: Merger (compact) - description: Merges two conveyor belts into one. - - compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. - - cutter: - default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halves. If you use only one part, be sure to destroy the other part or it will stall! - quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! - - rotater: - default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. - ccw: - name: Rotate (CCW) - description: Rotates shapes counter-clockwise by 90 degrees. - fl: - name: Rotate (180) - description: Rotates shapes by 180 degrees. - - stacker: - default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. - - mixer: - default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. - - painter: - default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the top input. - - mirrored: - name: *painter - description: *painter_desc - - double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. - - quad: - name: Painter (Quad) - description: Allows you to color each quadrant of the shape with a different color. - - trash: - default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. - - storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. - - wire: - default: - name: &wire Wire - description: &wire_desc Allows to connect logical components and can transfer items, colors or boolean signals. - - wire_tunnel: - default: - name: &wire_tunnel Wire Tunnel - description: Allows to cross two wires without connecting them. - - coating: - name: Wire Insulation - description: Allows to pass through signals without connecting to other wires on the sides. - - constant_signal: - default: - name: &constant_signal Constant Signal - description: Emits a constant signal (shape, color or boolean). - - lever: - default: - name: &lever Button - description: Can be toggled to emit 1 / 0 - - logic_gate: - default: - name: &logic_gate AND Gate - description: Emits a truthy boolean signal if both inputs are truthy. - not: - name: NOT - description: Inverts the given signal. - xor: - name: XOR - description: Emits a truthy signal if one of the inputs is truthy, but not both. - or: - name: OR - description: Emits a truthy signal if one of the inputs is truthy. - - transistor: - name: Gate - description: Only forwards the bottom input if the left input is true. - - filter: - default: - name: &filter Filter - # TEMP - description: Only leaves through items who match exactly the provided shape / color. If you put in a boolean 1, it leaves everything through, if you put in a 0 it will leave nothing through. - - display: - default: - name: &display Display - # TEMP - description: Can be connected on the wires layer to show a color or shape. When inputting a boolean item, the display will be white if the value is 1. - -storyRewards: - # Those are the rewards gained from completing the store - reward_cutter_and_trash: - title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! - - reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - - reward_painter: - title: Painting - desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a colorblind mode in the settings! - - reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! - - reward_stacker: - title: Combiner - desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! - - reward_splitter: - title: Splitter/Merger - desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

- - reward_tunnel: - title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! - - reward_rotater_ccw: - title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows you to rotate shapes counter-clockwise! To build it, select the rotater and press 'T' to cycle through its variants! - - reward_miner_chainable: - title: Chaining Extractor - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! - - reward_underground_belt_tier_2: - title: Tunnel Tier II - desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! - - reward_splitter_compact: - title: Compact Balancer - desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one belt! - - reward_cutter_quad: - title: Quad Cutting - desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! - - reward_painter_double: - title: Double Painting - desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! - - reward_painter_quad: - title: Quad Painting - desc: You have unlocked a variant of the painter - It allows you to paint each part of the shape individually! - - reward_storage: - title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows you to store items up to a given capacity! - - reward_freeplay: - title: Freeplay - desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) - - reward_blueprints: - title: Blueprints - desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). - - # Special reward, which is shown when there is no reward actually - no_reward: - title: Next level - desc: >- - This level gave you no reward, but the next one will!

PS: Better not destroy your existing factory - You'll need all those shapes later to unlock upgrades! - - no_reward_freeplay: - title: Next level - desc: >- - Congratulations! By the way, more content is planned for the standalone! - -settings: - title: Settings - categories: - general: General - userInterface: User Interface - advanced: Advanced - performance: Performance - - versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built - - labels: - uiScale: - title: Interface scale - description: >- - Changes the size of the user interface. The interface will still scale based on your device's resolution, but this setting controls the amount of scaling. - scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge - - autosaveInterval: - title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it entirely here. - - intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - ten_minutes: 10 Minutes - twenty_minutes: 20 Minutes - disabled: Disabled - - scrollWheelSensitivity: - title: Zoom sensitivity - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). - sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast - - movementSpeed: - title: Movement speed - description: >- - Changes how fast the view moves when using the keyboard. - speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast - - language: - title: Language - description: >- - Change the language. All translations are user-contributed and might be incomplete! - - enableColorBlindHelper: - title: Color Blind Mode - description: >- - Enables various tools which allow you to play the game if you are color blind. - - fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - - soundsMuted: - title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - - musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. - - theme: - title: Game theme - description: >- - Choose the game theme (light / dark). - themes: - dark: Dark - light: Light - - refreshRate: - title: Tick Rate - description: >- - The game will automatically adjust the tickrate to be between this target tickrate and half of it. For example, with a tickrate of 60hz, the game will try to stay at 60hz, and if your computer can't handle it it will go down until it eventually reaches 30hz. - - alwaysMultiplace: - title: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - - offerHints: - title: Hints & Tutorials - description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements up to a given level to make it easier to get into the game. - - enableTunnelSmartplace: - title: Smart Tunnels - description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. - - vignette: - title: Vignette - description: >- - Enables the vignette, which darkens the screen corners and makes text easier to read. - - rotationByBuilding: - title: Rotation by building type - description: >- - Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. - - compactBuildingInfo: - title: Compact Building Infos - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. - - disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings - description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. - - lowQualityMapResources: - title: Low Quality Map Resources - description: >- - Simplifies the rendering of resources on the map when zoomed in to improve performance. - It even looks cleaner, so be sure to try it out! - - disableTileGrid: - title: Disable Grid - description: >- - Disabling the tile grid can help with the performance. This also makes the game look cleaner! - - lowQualityTextures: - title: Low quality textures (Ugly) - description: >- - Uses low quality textures to save performance. This will make the game look very ugly! - -keybindings: - title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - - resetKeybindings: Reset Keybindings - - categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers - - mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - mapMoveFaster: Move Faster - centerMap: Center Map - - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker - - menuOpenShop: Upgrades - menuOpenStats: Statistics - menuClose: Close Menu - - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info - switchLayers: Switch layers - exportScreenshot: Export whole Base as Image - - # --- Do not translate the values in this section - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - wire: *wire - constant_signal: *constant_signal - logic_gate: *logic_gate - lever: *lever - filter: *filter - wire_tunnel: *wire_tunnel - display: *display - # --- - - pipette: Pipette - rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Delete area - pasteLastBlueprint: Paste last blueprint - cycleBuildings: Cycle Buildings - lockBeltDirection: Enable belt planner - switchDirectionLockSide: >- - Planner: Switch side - - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area - massSelectCut: Cut area - - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation - -about: - title: About this Game - body: >- - This game is open source and developed by Tobias Springer (this is me).

- - If you want to contribute, check out shapez.io on GitHub.

- - This game wouldn't have been possible without the great Discord community around my games - You should really join the Discord server!

- - The soundtrack was made by Peppsen - He's awesome.

- - Finally, huge thanks to my best friend Niklas - Without our Factorio sessions, this game would never have existed. - -changelog: - title: Changelog - -demo: - features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image - - settingNotAvailable: Not available in the demo. +# +# GAME TRANSLATIONS +# +# Contributing: +# +# If you want to contribute, please make a pull request on this respository +# and I will have a look. +# +# Placeholders: +# +# Do *not* replace placeholders! Placeholders have a special syntax like +# `Hotkey: `. They are encapsulated within angle brackets. The correct +# translation for this one in German for example would be: `Taste: ` (notice +# how the placeholder stayed '' and was not replaced!) +# +# Adding a new language: +# +# If you want to add a new language, ask me in the Discord and I will setup +# the basic structure so the game also detects it. +# + +--- +steamPage: + # This is the short text appearing on the steam page + shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + + # This is the text shown above the Discord link + discordLink: Official Discord - Chat with me! + + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. + # NOTICE: + # - Do not translate the first line (This is the gif image at the start of the store) + # - Please keep the markup (Stuff like [b], [list] etc) in the same format + longText: >- + [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + + shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + + Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. + + As the demand for shapes increases, you'll have to scale up your factory to meet the demand - Don't forget about resources though, you'll have to expand across the [b]infinite map[/b]! + + Soon you'll have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with them to satisfy the demand. + + This game features 18 progressive levels (Which should already keep you busy for hours!) but I'm constantly adding new content - There's a lot planned! + + Purchasing the game gives you access to the standalone version which has additional features, and you'll also receive access to newly developed features. + + [b]Standalone Advantages[/b] + + [list] + [*] Dark Mode + [*] Unlimited Waypoints + [*] Unlimited Savegames + [*] Additional settings + [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. + [*] Coming soon: More Levels + [*] Allows me to further develop shapez.io ❤️ + [/list] + + [b]Future Updates[/b] + + I am updating the game often and trying to push an update at least once every week! + + [list] + [*] Different maps and challenges (e.g. maps with obstacles) + [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) + [*] A story mode where buildings have a cost + [*] Configurable map generator (Configure resource/shape size/density, seed and more) + [*] Additional types of shapes + [*] Performance improvements (The game already runs pretty well!) + [*] And much more! + [/list] + + [b]This game is open source![/b] + + Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. + Be sure to check out my trello board for the full roadmap! + + [b]Links[/b] + + [list] + [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] + [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [/list] + +global: + loading: Loading + error: Error + + # How big numbers are rendered, e.g. "10,000" + thousandsDivider: "," + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. + suffix: + thousands: k + millions: M + billions: B + trillions: T + + # Shown for infinitely big numbers + infinite: inf + + time: + # Used for formatting past time dates + oneSecondAgo: one second ago + xSecondsAgo: seconds ago + oneMinuteAgo: one minute ago + xMinutesAgo: minutes ago + oneHourAgo: one hour ago + xHoursAgo: hours ago + oneDayAgo: one day ago + xDaysAgo: days ago + + # Short formats for times, e.g. '5h 23m' + secondsShort: s + minutesAndSecondsShort: m s + hoursAndMinutesShort: h m + + xMinutes: minutes + + keys: + tab: TAB + control: CTRL + alt: ALT + escape: ESC + shift: SHIFT + space: SPACE + +demoBanners: + # This is the "advertisement" shown in the main menu and other various places + title: Demo Version + intro: >- + Get the standalone to unlock all features! + +mainMenu: + play: Play + continue: Continue + newGame: New Game + changelog: Changelog + subreddit: Reddit + importSavegame: Import + openSourceHint: This game is open source! + discordLink: Official Discord Server + helpTranslate: Help translate! + madeBy: Made by + + # This is shown when using firefox and other browsers which are not supported. + browserWarning: >- + Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. + + savegameLevel: Level + savegameLevelUnknown: Unknown Level + +dialogs: + buttons: + ok: OK + delete: Delete + cancel: Cancel + later: Later + restart: Restart + reset: Reset + getStandalone: Get Standalone + deleteGame: I know what I am doing + viewUpdate: View Update + showUpgrades: Show Upgrades + showKeybindings: Show Keybindings + + importSavegameError: + title: Import Error + text: >- + Failed to import your savegame: + + importSavegameSuccess: + title: Savegame Imported + text: >- + Your savegame has been successfully imported. + + gameLoadFailure: + title: Game is broken + text: >- + Failed to load your savegame: + + confirmSavegameDelete: + title: Confirm deletion + text: >- + Are you sure you want to delete the game? + + savegameDeletionError: + title: Failed to delete + text: >- + Failed to delete the savegame: + + restartRequired: + title: Restart required + text: >- + You need to restart the game to apply the settings. + + editKeybinding: + title: Change Keybinding + desc: Press the key or mouse button you want to assign, or escape to cancel. + + resetKeybindingsConfirmation: + title: Reset keybindings + desc: This will reset all keybindings to their default values. Please confirm. + + keybindingsResetOk: + title: Keybindings reset + desc: The keybindings have been reset to their respective defaults! + + featureRestriction: + title: Demo Version + desc: You tried to access a feature () which is not available in the demo. Consider getting the standalone version for the full experience! + + oneSavegameLimit: + title: Limited savegames + desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone version! + + updateSummary: + title: New update! + desc: >- + Here are the changes since you last played: + + upgradesIntroduction: + title: Unlock Upgrades + desc: >- + All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! + The upgrades tab can be found on the top right corner of the screen. + + massDeleteConfirm: + title: Confirm delete + desc: >- + You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + + massCutConfirm: + title: Confirm cut + desc: >- + You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? + + massCutInsufficientConfirm: + title: Confirm cut + desc: >- + You can not afford to paste this area! Are you sure you want to cut it? + + blueprintsNotUnlocked: + title: Not unlocked yet + desc: >- + Complete level 12 to unlock Blueprints! + + keybindingsIntroduction: + title: Useful keybindings + desc: >- + This game has a lot of keybindings which make it easier to build big factories. + Here are a few, but be sure to check out the keybindings!

+ CTRL + Drag: Select an area.
+ SHIFT: Hold to place multiple of one building.
+ ALT: Invert orientation of placed belts.
+ + createMarker: + title: New Marker + titleEdit: Edit Marker + desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) + + markerDemoLimit: + desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + + exportScreenshotWarning: + title: Export screenshot + desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! + +ingame: + # This is shown in the top left corner and displays useful keybindings in + # every situation + keybindingsOverlay: + moveMap: Move + selectBuildings: Select area + stopPlacement: Stop placement + rotateBuilding: Rotate building + placeMultiple: Place multiple + reverseOrientation: Reverse orientation + disableAutoOrientation: Disable auto-orientation + toggleHud: Toggle HUD + placeBuilding: Place building + createMarker: Create marker + delete: Delete + pasteLastBlueprint: Paste last blueprint + lockBeltDirection: Enable belt planner + plannerSwitchSide: Flip planner side + cutSelection: Cut + copySelection: Copy + clearSelection: Clear selection + pipette: Pipette + switchLayers: Switch layers + + # Names of the colors, used for the color blind mode + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + black: Black + uncolored: Gray + + # Everything related to placing buildings (I.e. as soon as you selected a building + # from the toolbar) + buildingPlacement: + # Buildings can have different variants which are unlocked at later levels, + # and this is the hint shown when there are multiple variants available. + cycleBuildingVariants: Press to cycle variants. + + # Shows the hotkey in the ui, e.g. "Hotkey: Q" + hotkeyLabel: >- + Hotkey: + + infoTexts: + speed: Speed + range: Range + storage: Storage + oneItemPerSecond: 1 item / second + itemsPerSecond: items / s + itemsPerSecondDouble: (x2) + + tiles: tiles + + # The notification when completing a level + levelCompleteNotification: + # is replaced by the actual level, so this gets 'Level 03' for example. + levelTitle: Level + completed: Completed + unlockText: Unlocked ! + buttonNextLevel: Next Level + + # Notifications on the lower right + notifications: + newUpgrade: A new upgrade is available! + gameSaved: Your game has been saved. + + # The "Upgrades" window + shop: + title: Upgrades + buttonUnlock: Upgrade + + # Gets replaced to e.g. "Tier IX" + tier: Tier + + # The roman number for each tier + tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] + + maximumLevel: MAXIMUM LEVEL (Speed x) + + # The "Statistics" window + statistics: + title: Statistics + dataSources: + stored: + title: Stored + description: Displaying amount of stored shapes in your central building. + produced: + title: Produced + description: Displaying all shapes your whole factory produces, including intermediate products. + delivered: + title: Delivered + description: Displaying shapes which are delivered to your central building. + noShapesProduced: No shapes have been produced so far. + + # Displays the shapes per minute, e.g. '523 / m' + shapesPerMinute: / m + + # Settings menu, when you press "ESC" + settingsMenu: + playtime: Playtime + + buildingsPlaced: Buildings + beltsPlaced: Belts + + buttons: + continue: Continue + settings: Settings + menu: Return to menu + + # Bottom left tutorial hints + tutorialHints: + title: Need help? + showHint: Show hint + hideHint: Close + + # When placing a blueprint + blueprintPlacer: + cost: Cost + + # Map markers + waypoints: + waypoints: Markers + hub: HUB + description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. + creationSuccessNotification: Marker has been created. + + # Shape viewer + shapeViewer: + title: Layers + empty: Empty + copyKey: Copy Key + + # Interactive tutorial + interactiveTutorial: + title: Tutorial + hints: + 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_2_conveyor: >- + Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + + 1_3_expand: >- + This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + +# All shop upgrades +shopUpgrades: + belt: + name: Belts, Distributor & Tunnels + description: Speed x → x + miner: + name: Extraction + description: Speed x → x + processors: + name: Cutting, Rotating & Stacking + description: Speed x → x + painting: + name: Mixing & Painting + description: Speed x → x + +# Buildings and their name / description +buildings: + hub: + deliver: Deliver + toUnlock: to unlock + levelShortcut: LVL + + belt: + default: + name: &belt Conveyor Belt + description: Transports items, hold and drag to place multiple. + + # Internal name for the Extractor + miner: + default: + name: &miner Extractor + description: Place over a shape or color to extract it. + + chainable: + name: Extractor (Chain) + description: Place over a shape or color to extract it. Can be chained. + + # Internal name for the Tunnel + underground_belt: + default: + name: &underground_belt Tunnel + description: Allows you to tunnel resources under buildings and belts. + + tier2: + name: Tunnel Tier II + description: Allows you to tunnel resources under buildings and belts. + + # Internal name for the Balancer + splitter: + default: + name: &splitter Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. + + compact: + name: Merger (compact) + description: Merges two conveyor belts into one. + + compact-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + + cutter: + default: + name: &cutter Cutter + description: Cuts shapes from top to bottom and outputs both halves. If you use only one part, be sure to destroy the other part or it will stall! + quad: + name: Cutter (Quad) + description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! + + rotater: + default: + name: &rotater Rotate + description: Rotates shapes clockwise by 90 degrees. + ccw: + name: Rotate (CCW) + description: Rotates shapes counter-clockwise by 90 degrees. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. + + stacker: + default: + name: &stacker Stacker + description: Stacks both items. If they can not be merged, the right item is placed above the left item. + + mixer: + default: + name: &mixer Color Mixer + description: Mixes two colors using additive blending. + + painter: + default: + name: &painter Painter + description: &painter_desc Colors the whole shape on the left input with the color from the top input. + + mirrored: + name: *painter + description: *painter_desc + + double: + name: Painter (Double) + description: Colors the shapes on the left inputs with the color from the top input. + + quad: + name: Painter (Quad) + description: Allows you to color each quadrant of the shape with a different color. + + trash: + default: + name: &trash Trash + description: Accepts inputs from all sides and destroys them. Forever. + + storage: + name: Storage + description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + + wire: + default: + name: &wire Wire + description: &wire_desc Allows to connect logical components and can transfer items, colors or boolean signals. + + wire_tunnel: + default: + name: &wire_tunnel Wire Tunnel + description: Allows to cross two wires without connecting them. + + coating: + name: Wire Insulation + description: Allows to pass through signals without connecting to other wires on the sides. + + constant_signal: + default: + name: &constant_signal Constant Signal + description: Emits a constant signal (shape, color or boolean). + + lever: + default: + name: &lever Button + description: Can be toggled to emit 1 / 0 + + logic_gate: + default: + name: &logic_gate AND Gate + description: Emits a truthy boolean signal if both inputs are truthy. + not: + name: NOT + description: Inverts the given signal. + xor: + name: XOR + description: Emits a truthy signal if one of the inputs is truthy, but not both. + or: + name: OR + description: Emits a truthy signal if one of the inputs is truthy. + + transistor: + name: Gate + description: Only forwards the bottom input if the left input is true. + + filter: + default: + name: &filter Filter + # TEMP + description: Only leaves through items who match exactly the provided shape / color. If you put in a boolean 1, it leaves everything through, if you put in a 0 it will leave nothing through. + + display: + default: + name: &display Display + # TEMP + description: Can be connected on the wires layer to show a color or shape. When inputting a boolean item, the display will be white if the value is 1. + + virtual_processor: + default: + name: &virtual_processor Virtual Cutter + description: Virtually cuts the shape input from top to bottom and returns both halfs. + + analyzer: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape and returns its shape and color + + rotater: + name: Virtual Rotater + description: Virtually rotates the shape by 90 degrees clockwise. + + unstacker: + name: Virtual Unstacker + description: Returns the topmost layer to the right, and the remaining ones on the left. + + shapecompare: + name: Compare Shapes + description: Returns true if both shapes are exactly equal + +storyRewards: + # Those are the rewards gained from completing the store + reward_cutter_and_trash: + title: Cutting Shapes + desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + + reward_rotater: + title: Rotating + desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + + reward_painter: + title: Painting + desc: >- + The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a colorblind mode in the settings! + + reward_mixer: + title: Color Mixing + desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + + reward_stacker: + title: Combiner + desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + + reward_splitter: + title: Splitter/Merger + desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ + reward_tunnel: + title: Tunnel + desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! + + reward_rotater_ccw: + title: CCW Rotating + desc: You have unlocked a variant of the rotater - It allows you to rotate shapes counter-clockwise! To build it, select the rotater and press 'T' to cycle through its variants! + + reward_miner_chainable: + title: Chaining Extractor + desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + + reward_underground_belt_tier_2: + title: Tunnel Tier II + desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + + reward_splitter_compact: + title: Compact Balancer + desc: >- + You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one belt! + + reward_cutter_quad: + title: Quad Cutting + desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + + reward_painter_double: + title: Double Painting + desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + + reward_painter_quad: + title: Quad Painting + desc: You have unlocked a variant of the painter - It allows you to paint each part of the shape individually! + + reward_storage: + title: Storage Buffer + desc: You have unlocked a variant of the trash - It allows you to store items up to a given capacity! + + reward_freeplay: + title: Freeplay + desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + + reward_blueprints: + title: Blueprints + desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + + # Special reward, which is shown when there is no reward actually + no_reward: + title: Next level + desc: >- + This level gave you no reward, but the next one will!

PS: Better not destroy your existing factory - You'll need all those shapes later to unlock upgrades! + + no_reward_freeplay: + title: Next level + desc: >- + Congratulations! By the way, more content is planned for the standalone! + +settings: + title: Settings + categories: + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance + + versionBadges: + dev: Development + staging: Staging + prod: Production + buildDate: Built + + labels: + uiScale: + title: Interface scale + description: >- + Changes the size of the user interface. The interface will still scale based on your device's resolution, but this setting controls the amount of scaling. + scales: + super_small: Super small + small: Small + regular: Regular + large: Large + huge: Huge + + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it entirely here. + + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + + scrollWheelSensitivity: + title: Zoom sensitivity + description: >- + Changes how sensitive the zoom is (Either mouse wheel or trackpad). + sensitivity: + super_slow: Super slow + slow: Slow + regular: Regular + fast: Fast + super_fast: Super fast + + movementSpeed: + title: Movement speed + description: >- + Changes how fast the view moves when using the keyboard. + speeds: + super_slow: Super slow + slow: Slow + regular: Regular + fast: Fast + super_fast: Super Fast + extremely_fast: Extremely Fast + + language: + title: Language + description: >- + Change the language. All translations are user-contributed and might be incomplete! + + enableColorBlindHelper: + title: Color Blind Mode + description: >- + Enables various tools which allow you to play the game if you are color blind. + + fullscreen: + title: Fullscreen + description: >- + It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + + soundsMuted: + title: Mute Sounds + description: >- + If enabled, mutes all sound effects. + + musicMuted: + title: Mute Music + description: >- + If enabled, mutes all music. + + theme: + title: Game theme + description: >- + Choose the game theme (light / dark). + themes: + dark: Dark + light: Light + + refreshRate: + title: Tick Rate + description: >- + The game will automatically adjust the tickrate to be between this target tickrate and half of it. For example, with a tickrate of 60hz, the game will try to stay at 60hz, and if your computer can't handle it it will go down until it eventually reaches 30hz. + + alwaysMultiplace: + title: Multiplace + description: >- + If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + + offerHints: + title: Hints & Tutorials + description: >- + Whether to offer hints and tutorials while playing. Also hides certain UI elements up to a given level to make it easier to get into the game. + + enableTunnelSmartplace: + title: Smart Tunnels + description: >- + When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. + + vignette: + title: Vignette + description: >- + Enables the vignette, which darkens the screen corners and makes text easier to read. + + rotationByBuilding: + title: Rotation by building type + description: >- + Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + + compactBuildingInfo: + title: Compact Building Infos + description: >- + Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: >- + Disables the warning dialogs brought up when cutting/deleting more than 100 entities. + + lowQualityMapResources: + title: Low Quality Map Resources + description: >- + Simplifies the rendering of resources on the map when zoomed in to improve performance. + It even looks cleaner, so be sure to try it out! + + disableTileGrid: + title: Disable Grid + description: >- + Disabling the tile grid can help with the performance. This also makes the game look cleaner! + + lowQualityTextures: + title: Low quality textures (Ugly) + description: >- + Uses low quality textures to save performance. This will make the game look very ugly! + +keybindings: + title: Keybindings + hint: >- + Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + + resetKeybindings: Reset Keybindings + + categoryLabels: + general: Application + ingame: Game + navigation: Navigating + placement: Placement + massSelect: Mass Select + buildings: Building Shortcuts + placementModifiers: Placement Modifiers + + mappings: + confirm: Confirm + back: Back + mapMoveUp: Move Up + mapMoveRight: Move Right + mapMoveDown: Move Down + mapMoveLeft: Move Left + mapMoveFaster: Move Faster + centerMap: Center Map + + mapZoomIn: Zoom in + mapZoomOut: Zoom out + createMarker: Create Marker + + menuOpenShop: Upgrades + menuOpenStats: Statistics + menuClose: Close Menu + + toggleHud: Toggle HUD + toggleFPSInfo: Toggle FPS and Debug Info + switchLayers: Switch layers + exportScreenshot: Export whole Base as Image + + # --- Do not translate the values in this section + belt: *belt + splitter: *splitter + underground_belt: *underground_belt + miner: *miner + cutter: *cutter + rotater: *rotater + stacker: *stacker + mixer: *mixer + painter: *painter + trash: *trash + wire: *wire + constant_signal: *constant_signal + logic_gate: *logic_gate + lever: *lever + filter: *filter + wire_tunnel: *wire_tunnel + display: *display + # --- + + pipette: Pipette + rotateWhilePlacing: Rotate + rotateInverseModifier: >- + Modifier: Rotate CCW instead + cycleBuildingVariants: Cycle Variants + confirmMassDelete: Delete area + pasteLastBlueprint: Paste last blueprint + cycleBuildings: Cycle Buildings + lockBeltDirection: Enable belt planner + switchDirectionLockSide: >- + Planner: Switch side + + massSelectStart: Hold and drag to start + massSelectSelectMultiple: Select multiple areas + massSelectCopy: Copy area + massSelectCut: Cut area + + placementDisableAutoOrientation: Disable automatic orientation + placeMultiple: Stay in placement mode + placeInverse: Invert automatic belt orientation + +about: + title: About this Game + body: >- + This game is open source and developed by Tobias Springer (this is me).

+ + If you want to contribute, check out shapez.io on GitHub.

+ + This game wouldn't have been possible without the great Discord community around my games - You should really join the Discord server!

+ + The soundtrack was made by Peppsen - He's awesome.

+ + Finally, huge thanks to my best friend Niklas - Without our Factorio sessions, this game would never have existed. + +changelog: + title: Changelog + +demo: + features: + restoringGames: Restoring savegames + importingGames: Importing savegames + oneGameLimit: Limited to one savegame + customizeKeybindings: Customizing Keybindings + exportingBase: Exporting whole Base as Image + + settingNotAvailable: Not available in the demo.