Implement wire networks, add levers
BIN
res/ui/building_icons/lever.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
@ -42,7 +42,7 @@
|
||||
},
|
||||
"sprites/belt/forward_5.png":
|
||||
{
|
||||
"frame": {"x":425,"y":48,"w":13,"h":13},
|
||||
"frame": {"x":419,"y":110,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -50,7 +50,7 @@
|
||||
},
|
||||
"sprites/belt/forward_6.png":
|
||||
{
|
||||
"frame": {"x":450,"y":23,"w":13,"h":13},
|
||||
"frame": {"x":436,"y":110,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -58,7 +58,7 @@
|
||||
},
|
||||
"sprites/belt/forward_7.png":
|
||||
{
|
||||
"frame": {"x":465,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":425,"y":48,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -66,7 +66,7 @@
|
||||
},
|
||||
"sprites/belt/forward_8.png":
|
||||
{
|
||||
"frame": {"x":419,"y":106,"w":13,"h":13},
|
||||
"frame": {"x":465,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -74,7 +74,7 @@
|
||||
},
|
||||
"sprites/belt/forward_9.png":
|
||||
{
|
||||
"frame": {"x":436,"y":106,"w":13,"h":13},
|
||||
"frame": {"x":442,"y":65,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -226,7 +226,7 @@
|
||||
},
|
||||
"sprites/belt/left_0.png":
|
||||
{
|
||||
"frame": {"x":442,"y":85,"w":13,"h":13},
|
||||
"frame": {"x":459,"y":65,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -234,7 +234,7 @@
|
||||
},
|
||||
"sprites/belt/left_1.png":
|
||||
{
|
||||
"frame": {"x":446,"y":65,"w":13,"h":13},
|
||||
"frame": {"x":465,"y":43,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -242,7 +242,7 @@
|
||||
},
|
||||
"sprites/belt/left_2.png":
|
||||
{
|
||||
"frame": {"x":482,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":504,"y":111,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -250,7 +250,7 @@
|
||||
},
|
||||
"sprites/belt/left_3.png":
|
||||
{
|
||||
"frame": {"x":510,"y":71,"w":13,"h":13},
|
||||
"frame": {"x":533,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -258,7 +258,7 @@
|
||||
},
|
||||
"sprites/belt/left_4.png":
|
||||
{
|
||||
"frame": {"x":514,"y":54,"w":13,"h":13},
|
||||
"frame": {"x":510,"y":88,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -266,7 +266,7 @@
|
||||
},
|
||||
"sprites/belt/left_5.png":
|
||||
{
|
||||
"frame": {"x":516,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":514,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -274,7 +274,7 @@
|
||||
},
|
||||
"sprites/belt/left_6.png":
|
||||
{
|
||||
"frame": {"x":518,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":527,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -282,7 +282,7 @@
|
||||
},
|
||||
"sprites/belt/left_7.png":
|
||||
{
|
||||
"frame": {"x":533,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":533,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -290,7 +290,7 @@
|
||||
},
|
||||
"sprites/belt/left_8.png":
|
||||
{
|
||||
"frame": {"x":511,"y":108,"w":13,"h":13},
|
||||
"frame": {"x":541,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -298,7 +298,7 @@
|
||||
},
|
||||
"sprites/belt/left_9.png":
|
||||
{
|
||||
"frame": {"x":521,"y":88,"w":13,"h":13},
|
||||
"frame": {"x":550,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -306,7 +306,7 @@
|
||||
},
|
||||
"sprites/belt/left_10.png":
|
||||
{
|
||||
"frame": {"x":453,"y":102,"w":13,"h":13},
|
||||
"frame": {"x":473,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -314,7 +314,7 @@
|
||||
},
|
||||
"sprites/belt/left_11.png":
|
||||
{
|
||||
"frame": {"x":459,"y":82,"w":13,"h":13},
|
||||
"frame": {"x":482,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -322,7 +322,7 @@
|
||||
},
|
||||
"sprites/belt/left_12.png":
|
||||
{
|
||||
"frame": {"x":463,"y":65,"w":13,"h":13},
|
||||
"frame": {"x":463,"y":82,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -330,7 +330,7 @@
|
||||
},
|
||||
"sprites/belt/left_13.png":
|
||||
{
|
||||
"frame": {"x":465,"y":40,"w":13,"h":13},
|
||||
"frame": {"x":476,"y":60,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -338,7 +338,7 @@
|
||||
},
|
||||
"sprites/belt/left_14.png":
|
||||
{
|
||||
"frame": {"x":467,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":482,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -346,7 +346,7 @@
|
||||
},
|
||||
"sprites/belt/left_15.png":
|
||||
{
|
||||
"frame": {"x":482,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":490,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -354,7 +354,7 @@
|
||||
},
|
||||
"sprites/belt/left_16.png":
|
||||
{
|
||||
"frame": {"x":470,"y":99,"w":13,"h":13},
|
||||
"frame": {"x":499,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -362,7 +362,7 @@
|
||||
},
|
||||
"sprites/belt/left_17.png":
|
||||
{
|
||||
"frame": {"x":476,"y":82,"w":13,"h":13},
|
||||
"frame": {"x":476,"y":99,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -370,7 +370,7 @@
|
||||
},
|
||||
"sprites/belt/left_18.png":
|
||||
{
|
||||
"frame": {"x":487,"y":99,"w":13,"h":13},
|
||||
"frame": {"x":480,"y":77,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -378,7 +378,7 @@
|
||||
},
|
||||
"sprites/belt/left_19.png":
|
||||
{
|
||||
"frame": {"x":480,"y":57,"w":13,"h":13},
|
||||
"frame": {"x":493,"y":94,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -386,7 +386,7 @@
|
||||
},
|
||||
"sprites/belt/left_20.png":
|
||||
{
|
||||
"frame": {"x":484,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":493,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -394,7 +394,7 @@
|
||||
},
|
||||
"sprites/belt/left_21.png":
|
||||
{
|
||||
"frame": {"x":499,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":499,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -402,7 +402,7 @@
|
||||
},
|
||||
"sprites/belt/left_22.png":
|
||||
{
|
||||
"frame": {"x":493,"y":74,"w":13,"h":13},
|
||||
"frame": {"x":507,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -410,7 +410,7 @@
|
||||
},
|
||||
"sprites/belt/left_23.png":
|
||||
{
|
||||
"frame": {"x":497,"y":54,"w":13,"h":13},
|
||||
"frame": {"x":516,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -418,7 +418,7 @@
|
||||
},
|
||||
"sprites/belt/left_24.png":
|
||||
{
|
||||
"frame": {"x":499,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":497,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -426,7 +426,7 @@
|
||||
},
|
||||
"sprites/belt/left_25.png":
|
||||
{
|
||||
"frame": {"x":501,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":510,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -434,7 +434,7 @@
|
||||
},
|
||||
"sprites/belt/left_26.png":
|
||||
{
|
||||
"frame": {"x":516,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":516,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -442,7 +442,7 @@
|
||||
},
|
||||
"sprites/belt/left_27.png":
|
||||
{
|
||||
"frame": {"x":504,"y":91,"w":13,"h":13},
|
||||
"frame": {"x":524,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -450,7 +450,7 @@
|
||||
},
|
||||
"sprites/belt/right_0.png":
|
||||
{
|
||||
"frame": {"x":527,"y":71,"w":13,"h":13},
|
||||
"frame": {"x":521,"y":105,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -458,7 +458,7 @@
|
||||
},
|
||||
"sprites/belt/right_1.png":
|
||||
{
|
||||
"frame": {"x":531,"y":54,"w":13,"h":13},
|
||||
"frame": {"x":527,"y":88,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -466,7 +466,7 @@
|
||||
},
|
||||
"sprites/belt/right_2.png":
|
||||
{
|
||||
"frame": {"x":545,"y":105,"w":13,"h":13},
|
||||
"frame": {"x":575,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -474,7 +474,7 @@
|
||||
},
|
||||
"sprites/belt/right_3.png":
|
||||
{
|
||||
"frame": {"x":578,"y":71,"w":13,"h":13},
|
||||
"frame": {"x":572,"y":105,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -482,7 +482,7 @@
|
||||
},
|
||||
"sprites/belt/right_4.png":
|
||||
{
|
||||
"frame": {"x":582,"y":54,"w":13,"h":13},
|
||||
"frame": {"x":578,"y":88,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -490,7 +490,7 @@
|
||||
},
|
||||
"sprites/belt/right_5.png":
|
||||
{
|
||||
"frame": {"x":584,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":582,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -498,7 +498,7 @@
|
||||
},
|
||||
"sprites/belt/right_6.png":
|
||||
{
|
||||
"frame": {"x":586,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":595,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -506,7 +506,7 @@
|
||||
},
|
||||
"sprites/belt/right_7.png":
|
||||
{
|
||||
"frame": {"x":601,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":601,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -514,7 +514,7 @@
|
||||
},
|
||||
"sprites/belt/right_8.png":
|
||||
{
|
||||
"frame": {"x":579,"y":105,"w":13,"h":13},
|
||||
"frame": {"x":609,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -522,7 +522,7 @@
|
||||
},
|
||||
"sprites/belt/right_9.png":
|
||||
{
|
||||
"frame": {"x":589,"y":88,"w":13,"h":13},
|
||||
"frame": {"x":618,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -530,7 +530,7 @@
|
||||
},
|
||||
"sprites/belt/right_10.png":
|
||||
{
|
||||
"frame": {"x":533,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":531,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -538,7 +538,7 @@
|
||||
},
|
||||
"sprites/belt/right_11.png":
|
||||
{
|
||||
"frame": {"x":535,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":544,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -546,7 +546,7 @@
|
||||
},
|
||||
"sprites/belt/right_12.png":
|
||||
{
|
||||
"frame": {"x":550,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":550,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -554,7 +554,7 @@
|
||||
},
|
||||
"sprites/belt/right_13.png":
|
||||
{
|
||||
"frame": {"x":528,"y":105,"w":13,"h":13},
|
||||
"frame": {"x":558,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -562,7 +562,7 @@
|
||||
},
|
||||
"sprites/belt/right_14.png":
|
||||
{
|
||||
"frame": {"x":538,"y":88,"w":13,"h":13},
|
||||
"frame": {"x":567,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -570,7 +570,7 @@
|
||||
},
|
||||
"sprites/belt/right_15.png":
|
||||
{
|
||||
"frame": {"x":544,"y":71,"w":13,"h":13},
|
||||
"frame": {"x":538,"y":105,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -578,7 +578,7 @@
|
||||
},
|
||||
"sprites/belt/right_16.png":
|
||||
{
|
||||
"frame": {"x":548,"y":54,"w":13,"h":13},
|
||||
"frame": {"x":544,"y":88,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -586,7 +586,7 @@
|
||||
},
|
||||
"sprites/belt/right_17.png":
|
||||
{
|
||||
"frame": {"x":550,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":548,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -594,7 +594,7 @@
|
||||
},
|
||||
"sprites/belt/right_18.png":
|
||||
{
|
||||
"frame": {"x":552,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":561,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -602,7 +602,7 @@
|
||||
},
|
||||
"sprites/belt/right_19.png":
|
||||
{
|
||||
"frame": {"x":567,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":567,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -610,7 +610,7 @@
|
||||
},
|
||||
"sprites/belt/right_20.png":
|
||||
{
|
||||
"frame": {"x":555,"y":88,"w":13,"h":13},
|
||||
"frame": {"x":584,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -618,7 +618,7 @@
|
||||
},
|
||||
"sprites/belt/right_21.png":
|
||||
{
|
||||
"frame": {"x":561,"y":71,"w":13,"h":13},
|
||||
"frame": {"x":555,"y":105,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -626,7 +626,7 @@
|
||||
},
|
||||
"sprites/belt/right_22.png":
|
||||
{
|
||||
"frame": {"x":565,"y":54,"w":13,"h":13},
|
||||
"frame": {"x":561,"y":88,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -634,7 +634,7 @@
|
||||
},
|
||||
"sprites/belt/right_23.png":
|
||||
{
|
||||
"frame": {"x":567,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":565,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -642,7 +642,7 @@
|
||||
},
|
||||
"sprites/belt/right_24.png":
|
||||
{
|
||||
"frame": {"x":569,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":578,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -650,7 +650,7 @@
|
||||
},
|
||||
"sprites/belt/right_25.png":
|
||||
{
|
||||
"frame": {"x":584,"y":3,"w":13,"h":13},
|
||||
"frame": {"x":584,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -658,7 +658,7 @@
|
||||
},
|
||||
"sprites/belt/right_26.png":
|
||||
{
|
||||
"frame": {"x":562,"y":105,"w":13,"h":13},
|
||||
"frame": {"x":592,"y":20,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -666,7 +666,7 @@
|
||||
},
|
||||
"sprites/belt/right_27.png":
|
||||
{
|
||||
"frame": {"x":572,"y":88,"w":13,"h":13},
|
||||
"frame": {"x":601,"y":3,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -674,7 +674,7 @@
|
||||
},
|
||||
"sprites/blueprints/belt_left.png":
|
||||
{
|
||||
"frame": {"x":595,"y":71,"w":13,"h":13},
|
||||
"frame": {"x":589,"y":105,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -682,7 +682,7 @@
|
||||
},
|
||||
"sprites/blueprints/belt_right.png":
|
||||
{
|
||||
"frame": {"x":599,"y":54,"w":13,"h":13},
|
||||
"frame": {"x":595,"y":88,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -690,7 +690,7 @@
|
||||
},
|
||||
"sprites/blueprints/belt_top.png":
|
||||
{
|
||||
"frame": {"x":601,"y":37,"w":13,"h":13},
|
||||
"frame": {"x":599,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -720,6 +720,14 @@
|
||||
"spriteSourceSize": {"x":1,"y":0,"w":36,"h":19},
|
||||
"sourceSize": {"w":38,"h":19}
|
||||
},
|
||||
"sprites/blueprints/lever.png":
|
||||
{
|
||||
"frame": {"x":398,"y":88,"w":17,"h":18},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":1,"y":1,"w":17,"h":18},
|
||||
"sourceSize": {"w":19,"h":19}
|
||||
},
|
||||
"sprites/blueprints/logic_gate.png":
|
||||
{
|
||||
"frame": {"x":354,"y":89,"w":19,"h":18},
|
||||
@ -866,7 +874,7 @@
|
||||
},
|
||||
"sprites/blueprints/underground_belt_entry.png":
|
||||
{
|
||||
"frame": {"x":400,"y":66,"w":19,"h":16},
|
||||
"frame": {"x":440,"y":87,"w":19,"h":16},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":0,"y":3,"w":19,"h":16},
|
||||
@ -874,7 +882,7 @@
|
||||
},
|
||||
"sprites/blueprints/underground_belt_exit-tier2.png":
|
||||
{
|
||||
"frame": {"x":419,"y":86,"w":19,"h":16},
|
||||
"frame": {"x":453,"y":107,"w":19,"h":16},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":16},
|
||||
@ -882,7 +890,7 @@
|
||||
},
|
||||
"sprites/blueprints/underground_belt_exit.png":
|
||||
{
|
||||
"frame": {"x":423,"y":65,"w":19,"h":16},
|
||||
"frame": {"x":427,"y":25,"w":19,"h":16},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":16},
|
||||
@ -890,7 +898,7 @@
|
||||
},
|
||||
"sprites/blueprints/wire-cross.png":
|
||||
{
|
||||
"frame": {"x":603,"y":20,"w":13,"h":13},
|
||||
"frame": {"x":612,"y":54,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -906,7 +914,7 @@
|
||||
},
|
||||
"sprites/blueprints/wire-turn.png":
|
||||
{
|
||||
"frame": {"x":485,"y":116,"w":9,"h":9},
|
||||
"frame": {"x":491,"y":116,"w":9,"h":9},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":4,"y":4,"w":9,"h":9},
|
||||
@ -914,7 +922,7 @@
|
||||
},
|
||||
"sprites/blueprints/wire.png":
|
||||
{
|
||||
"frame": {"x":618,"y":3,"w":5,"h":13},
|
||||
"frame": {"x":626,"y":20,"w":5,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":4,"y":0,"w":5,"h":13},
|
||||
@ -922,7 +930,7 @@
|
||||
},
|
||||
"sprites/buildings/belt_left.png":
|
||||
{
|
||||
"frame": {"x":596,"y":105,"w":13,"h":13},
|
||||
"frame": {"x":618,"y":37,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -930,7 +938,7 @@
|
||||
},
|
||||
"sprites/buildings/belt_right.png":
|
||||
{
|
||||
"frame": {"x":606,"y":88,"w":13,"h":13},
|
||||
"frame": {"x":606,"y":105,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -946,7 +954,7 @@
|
||||
},
|
||||
"sprites/buildings/constant_signal.png":
|
||||
{
|
||||
"frame": {"x":398,"y":88,"w":17,"h":18},
|
||||
"frame": {"x":400,"y":66,"w":17,"h":18},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":1,"y":1,"w":17,"h":18},
|
||||
@ -976,6 +984,14 @@
|
||||
"spriteSourceSize": {"x":1,"y":1,"w":75,"h":76},
|
||||
"sourceSize": {"w":77,"h":77}
|
||||
},
|
||||
"sprites/buildings/lever.png":
|
||||
{
|
||||
"frame": {"x":419,"y":88,"w":17,"h":18},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":1,"y":1,"w":17,"h":18},
|
||||
"sourceSize": {"w":19,"h":19}
|
||||
},
|
||||
"sprites/buildings/logic_gate.png":
|
||||
{
|
||||
"frame": {"x":404,"y":26,"w":19,"h":18},
|
||||
@ -1122,7 +1138,7 @@
|
||||
},
|
||||
"sprites/buildings/underground_belt_entry.png":
|
||||
{
|
||||
"frame": {"x":427,"y":25,"w":19,"h":16},
|
||||
"frame": {"x":442,"y":3,"w":19,"h":16},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":0,"y":3,"w":19,"h":16},
|
||||
@ -1138,7 +1154,7 @@
|
||||
},
|
||||
"sprites/buildings/underground_belt_exit.png":
|
||||
{
|
||||
"frame": {"x":442,"y":3,"w":19,"h":16},
|
||||
"frame": {"x":450,"y":23,"w":19,"h":16},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":16},
|
||||
@ -1146,7 +1162,7 @@
|
||||
},
|
||||
"sprites/buildings/wire-cross.png":
|
||||
{
|
||||
"frame": {"x":612,"y":71,"w":13,"h":13},
|
||||
"frame": {"x":612,"y":88,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -1162,7 +1178,7 @@
|
||||
},
|
||||
"sprites/buildings/wire-turn.png":
|
||||
{
|
||||
"frame": {"x":498,"y":116,"w":9,"h":9},
|
||||
"frame": {"x":623,"y":105,"w":9,"h":9},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":4,"y":4,"w":9,"h":9},
|
||||
@ -1170,7 +1186,7 @@
|
||||
},
|
||||
"sprites/buildings/wire.png":
|
||||
{
|
||||
"frame": {"x":616,"y":54,"w":5,"h":13},
|
||||
"frame": {"x":629,"y":54,"w":5,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":4,"y":0,"w":5,"h":13},
|
||||
@ -1256,6 +1272,14 @@
|
||||
"spriteSourceSize": {"x":1,"y":0,"w":4,"h":6},
|
||||
"sourceSize": {"w":6,"h":6}
|
||||
},
|
||||
"sprites/wires/lever_on.png":
|
||||
{
|
||||
"frame": {"x":421,"y":65,"w":17,"h":18},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":1,"y":1,"w":17,"h":18},
|
||||
"sourceSize": {"w":19,"h":19}
|
||||
},
|
||||
"sprites/wires/logical_acceptor.png":
|
||||
{
|
||||
"frame": {"x":120,"y":72,"w":7,"h":3},
|
||||
@ -1266,7 +1290,7 @@
|
||||
},
|
||||
"sprites/wires/logical_ejector.png":
|
||||
{
|
||||
"frame": {"x":470,"y":116,"w":11,"h":9},
|
||||
"frame": {"x":476,"y":116,"w":11,"h":9},
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": {"x":1,"y":0,"w":11,"h":9},
|
||||
@ -1274,7 +1298,7 @@
|
||||
},
|
||||
"sprites/wires/overlay_tile.png":
|
||||
{
|
||||
"frame": {"x":613,"y":105,"w":13,"h":13},
|
||||
"frame": {"x":616,"y":71,"w":13,"h":13},
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
|
||||
@ -1285,8 +1309,8 @@
|
||||
"version": "1.0",
|
||||
"image": "atlas0_10.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {"w":629,"h":128},
|
||||
"size": {"w":637,"h":128},
|
||||
"scale": "0.1",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:4ffd589da27497135028c29f7b9b26e4:f71ff2b46aa491f7d9c066b5013b58f3:f159918d23e5952766c6d23ab52278c6$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:e7b9a04c4837403c3b74aa5fde7c34d7:e9ca7594f22ec25258261277e04c5fe2:f159918d23e5952766c6d23ab52278c6$"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 213 KiB |
Before Width: | Height: | Size: 499 KiB After Width: | Height: | Size: 504 KiB |
Before Width: | Height: | Size: 1001 KiB After Width: | Height: | Size: 994 KiB |
@ -255,9 +255,9 @@
|
||||
<key type="filename">sprites/buildings/miner.png</key>
|
||||
<key type="filename">sprites/buildings/rotater.png</key>
|
||||
<key type="filename">sprites/buildings/trash.png</key>
|
||||
<key type="filename">sprites/misc/wires_overlay_tile.png</key>
|
||||
<key type="filename">sprites/wires/logical_acceptor.png</key>
|
||||
<key type="filename">sprites/wires/logical_ejector.png</key>
|
||||
<key type="filename">sprites/wires/overlay_tile.png</key>
|
||||
<struct type="IndividualSpriteSettings">
|
||||
<key>pivotPoint</key>
|
||||
<point_f>0.5,0.5</point_f>
|
||||
@ -382,6 +382,7 @@
|
||||
<false/>
|
||||
</struct>
|
||||
<key type="filename">sprites/blueprints/constant_signal.png</key>
|
||||
<key type="filename">sprites/blueprints/logic_gate.png</key>
|
||||
<key type="filename">sprites/blueprints/miner-chainable.png</key>
|
||||
<key type="filename">sprites/blueprints/miner.png</key>
|
||||
<key type="filename">sprites/blueprints/rotater-ccw.png</key>
|
||||
@ -395,6 +396,7 @@
|
||||
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
|
||||
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
||||
<key type="filename">sprites/buildings/constant_signal.png</key>
|
||||
<key type="filename">sprites/buildings/logic_gate.png</key>
|
||||
<key type="filename">sprites/buildings/miner-chainable.png</key>
|
||||
<key type="filename">sprites/buildings/rotater-ccw.png</key>
|
||||
<key type="filename">sprites/buildings/rotater-fl.png</key>
|
||||
|
BIN
res_raw/sprites/blueprints/lever.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 38 KiB |
BIN
res_raw/sprites/buildings/lever.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
res_raw/sprites/wires/lever_on.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
@ -1,5 +1,5 @@
|
||||
$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire,
|
||||
constant_signal, logic_gate;
|
||||
constant_signal, logic_gate, lever;
|
||||
|
||||
@each $building in $buildings {
|
||||
[data-icon="building_icons/#{$building}.png"] {
|
||||
|
@ -13,7 +13,7 @@ export class DrawParameters {
|
||||
/** @type {Rectangle} */
|
||||
this.visibleRect = visibleRect;
|
||||
|
||||
/** @type {number} */
|
||||
/** @type {string} */
|
||||
this.desiredAtlasScale = desiredAtlasScale;
|
||||
|
||||
/** @type {number} */
|
||||
|
@ -43,6 +43,14 @@ export const enumAngleToDirection = {
|
||||
270: enumDirection.left,
|
||||
};
|
||||
|
||||
/** @type {Array<enumDirection>} */
|
||||
export const arrayAllDirections = [
|
||||
enumDirection.top,
|
||||
enumDirection.right,
|
||||
enumDirection.bottom,
|
||||
enumDirection.left,
|
||||
];
|
||||
|
||||
export class Vector {
|
||||
/**
|
||||
*
|
||||
|
@ -31,6 +31,29 @@ export class BaseItem extends BasicSerializableObject {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the item equals the other itme
|
||||
* @param {BaseItem} other
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
if (this.getItemType() !== other.getItemType()) {
|
||||
return false;
|
||||
}
|
||||
return this.equalsImpl(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for custom comparison
|
||||
* @abstract
|
||||
* @param {BaseItem} other
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equalsImpl(other) {
|
||||
abstract;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the item at the given position
|
||||
* @param {number} x
|
||||
|
57
src/js/game/buildings/lever.js
Normal file
@ -0,0 +1,57 @@
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||
import { Entity } from "../entity";
|
||||
import { MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { LeverComponent } from "../components/lever";
|
||||
|
||||
export class MetaLeverBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("lever");
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
// @todo: Render differently based on if its activated or not
|
||||
return "#1a678b";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getIsUnlocked(root) {
|
||||
// @todo
|
||||
return true;
|
||||
}
|
||||
|
||||
isRotateable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
|
||||
getSprite() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
setupEntityComponents(entity) {
|
||||
entity.addComponent(
|
||||
new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.top,
|
||||
type: enumPinSlotType.logicalEjector,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(new LeverComponent({}));
|
||||
}
|
||||
}
|
@ -1,8 +1,17 @@
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||
import { Entity } from "../entity";
|
||||
import { MetaBuilding } from "../meta_building";
|
||||
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
|
||||
import { enumLayer, GameRoot } from "../root";
|
||||
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumLogicGateVariants = {};
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumVariantToGate = {
|
||||
[defaultBuildingVariant]: enumLogicGateType.and,
|
||||
};
|
||||
|
||||
export class MetaLogicGateBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
@ -29,6 +38,15 @@ export class MetaLogicGateBuilding extends MetaBuilding {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Entity} entity
|
||||
* @param {number} rotationVariant
|
||||
*/
|
||||
updateVariants(entity, rotationVariant, variant) {
|
||||
entity.components.LogicGate.type = enumVariantToGate[variant];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
* @param {Entity} entity
|
||||
@ -55,5 +73,7 @@ export class MetaLogicGateBuilding extends MetaBuilding {
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(new LogicGateComponent({}));
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import { WiredPinsComponent } from "./components/wired_pins";
|
||||
import { BeltUnderlaysComponent } from "./components/belt_underlays";
|
||||
import { WireComponent } from "./components/wire";
|
||||
import { ConstantSignalComponent } from "./components/constant_signal";
|
||||
import { LogicGateComponent } from "./components/logic_gate";
|
||||
import { LeverComponent } from "./components/lever";
|
||||
|
||||
export function initComponentRegistry() {
|
||||
gComponentRegistry.register(StaticMapEntityComponent);
|
||||
@ -27,6 +29,8 @@ export function initComponentRegistry() {
|
||||
gComponentRegistry.register(BeltUnderlaysComponent);
|
||||
gComponentRegistry.register(WireComponent);
|
||||
gComponentRegistry.register(ConstantSignalComponent);
|
||||
gComponentRegistry.register(LogicGateComponent);
|
||||
gComponentRegistry.register(LeverComponent);
|
||||
|
||||
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS
|
||||
|
||||
|
20
src/js/game/components/lever.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { Component } from "../component";
|
||||
|
||||
export class LeverComponent extends Component {
|
||||
static getId() {
|
||||
return "Lever";
|
||||
}
|
||||
|
||||
duplicateWithoutContents() {
|
||||
return new LeverComponent({ toggled: this.toggled });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} param0
|
||||
* @param {boolean=} param0.toggled
|
||||
*/
|
||||
constructor({ toggled = false }) {
|
||||
super();
|
||||
this.toggled = toggled;
|
||||
}
|
||||
}
|
26
src/js/game/components/logic_gate.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { Component } from "../component";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumLogicGateType = {
|
||||
and: "and",
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -24,6 +24,11 @@ export class WireComponent extends Component {
|
||||
constructor({ type = enumWireType.regular }) {
|
||||
super();
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* @type {import("../systems/wire").WireNetwork}
|
||||
*/
|
||||
this.linkedNetwork = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,7 +18,8 @@ export const enumPinSlotType = {
|
||||
* pos: Vector,
|
||||
* type: enumPinSlotType,
|
||||
* direction: enumDirection,
|
||||
* value: BaseItem
|
||||
* value: BaseItem,
|
||||
* linkedNetwork: import("../systems/wire").WireNetwork
|
||||
* }} WirePinSlot */
|
||||
|
||||
export class WiredPinsComponent extends Component {
|
||||
@ -65,6 +66,7 @@ export class WiredPinsComponent extends Component {
|
||||
type: slotData.type,
|
||||
direction: slotData.direction,
|
||||
value: null,
|
||||
linkedNetwork: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import { ProductionAnalytics } from "./production_analytics";
|
||||
import { randomInt } from "../core/utils";
|
||||
import { defaultBuildingVariant } from "./meta_building";
|
||||
import { DynamicTickrate } from "./dynamic_tickrate";
|
||||
import { Rectangle } from "../core/rectangle";
|
||||
|
||||
const logger = createLogger("ingame/core");
|
||||
|
||||
@ -450,6 +451,11 @@ export class GameCore {
|
||||
// Restore to screen space
|
||||
context.restore();
|
||||
|
||||
// Restore parameters
|
||||
params.zoomLevel = 1;
|
||||
params.desiredAtlasScale = "1";
|
||||
params.visibleRect = new Rectangle(0, 0, this.root.gameWidth, this.root.gameHeight);
|
||||
|
||||
// Draw overlays, those are screen space
|
||||
root.hud.drawOverlays(params);
|
||||
|
||||
|
@ -12,6 +12,8 @@ import { UndergroundBeltComponent } from "./components/underground_belt";
|
||||
import { WiredPinsComponent } from "./components/wired_pins";
|
||||
import { WireComponent } from "./components/wire";
|
||||
import { ConstantSignalComponent } from "./components/constant_signal";
|
||||
import { LogicGateComponent } from "./components/logic_gate";
|
||||
import { LeverComponent } from "./components/lever";
|
||||
/* typehints:end */
|
||||
|
||||
/**
|
||||
@ -61,6 +63,12 @@ export class EntityComponentStorage {
|
||||
/** @type {ConstantSignalComponent} */
|
||||
this.ConstantSignal;
|
||||
|
||||
/** @type {LogicGateComponent} */
|
||||
this.LogicGate;
|
||||
|
||||
/** @type {LeverComponent} */
|
||||
this.Lever;
|
||||
|
||||
/* typehints:end */
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ import { WiredPinsSystem } from "./systems/wired_pins";
|
||||
import { BeltUnderlaysSystem } from "./systems/belt_underlays";
|
||||
import { WireSystem } from "./systems/wire";
|
||||
import { ConstantSignalSystem } from "./systems/constant_signal";
|
||||
import { LogicGateSystem } from "./systems/logic_gate";
|
||||
import { LeverSystem } from "./systems/lever";
|
||||
|
||||
const logger = createLogger("game_system_manager");
|
||||
|
||||
@ -72,6 +74,12 @@ export class GameSystemManager {
|
||||
/** @type {ConstantSignalSystem} */
|
||||
constantSignal: null,
|
||||
|
||||
/** @type {LogicGateSystem} */
|
||||
logicGate: null,
|
||||
|
||||
/** @type {LeverSystem} */
|
||||
lever: null,
|
||||
|
||||
/* typehints:end */
|
||||
};
|
||||
this.systemUpdateOrder = [];
|
||||
@ -119,6 +127,14 @@ export class GameSystemManager {
|
||||
// then would be invalid
|
||||
add("itemAcceptor", ItemAcceptorSystem);
|
||||
|
||||
// WIRES section
|
||||
add("lever", LeverSystem);
|
||||
|
||||
// IMPORTANT: We have 2 phases: In phase 1 we compute the output values of all gates,
|
||||
// processors etc. In phase 2 we propagate it through the wires network
|
||||
add("logicGate", LogicGateSystem);
|
||||
|
||||
// Wires must be after all gate, signal etc logic!
|
||||
add("wire", WireSystem);
|
||||
|
||||
logger.log("📦 There are", this.systemUpdateOrder.length, "game systems");
|
||||
|
@ -41,6 +41,8 @@ import { HUDChangesDebugger } from "./parts/debug_changes";
|
||||
import { queryParamOptions } from "../../core/query_parameters";
|
||||
import { HUDSandboxController } from "./parts/sandbox_controller";
|
||||
import { HUDWiresToolbar } from "./parts/wires_toolbar";
|
||||
import { HUDWireInfo } from "./parts/wire_info";
|
||||
import { HUDLeverToggle } from "./parts/lever_toggle";
|
||||
|
||||
export class GameHUD {
|
||||
/**
|
||||
@ -66,6 +68,8 @@ export class GameHUD {
|
||||
shop: new HUDShop(this.root),
|
||||
statistics: new HUDStatistics(this.root),
|
||||
waypoints: new HUDWaypoints(this.root),
|
||||
wireInfo: new HUDWireInfo(this.root),
|
||||
leverToggle: new HUDLeverToggle(this.root),
|
||||
|
||||
// Must always exist
|
||||
pinnedShapes: new HUDPinnedShapes(this.root),
|
||||
@ -250,7 +254,7 @@ export class GameHUD {
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
drawOverlays(parameters) {
|
||||
const partsOrder = ["watermark"];
|
||||
const partsOrder = ["watermark", "wireInfo"];
|
||||
|
||||
for (let i = 0; i < partsOrder.length; ++i) {
|
||||
if (this.parts[partsOrder[i]]) {
|
||||
|
@ -10,6 +10,7 @@ import { MetaTrashBuilding } from "../../buildings/trash";
|
||||
import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt";
|
||||
import { enumLayer } from "../../root";
|
||||
import { HUDBaseToolbar } from "./base_toolbar";
|
||||
import { MetaLeverBuilding } from "../../buildings/lever";
|
||||
|
||||
const supportedBuildings = [
|
||||
MetaBeltBaseBuilding,
|
||||
@ -22,6 +23,7 @@ const supportedBuildings = [
|
||||
MetaMixerBuilding,
|
||||
MetaPainterBuilding,
|
||||
MetaTrashBuilding,
|
||||
MetaLeverBuilding,
|
||||
];
|
||||
|
||||
export class HUDBuildingsToolbar extends HUDBaseToolbar {
|
||||
|
30
src/js/game/hud/parts/lever_toggle.js
Normal file
@ -0,0 +1,30 @@
|
||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||
import { Vector } from "../../../core/vector";
|
||||
import { enumMouseButton } from "../../camera";
|
||||
import { enumLayer } from "../../root";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
|
||||
export class HUDLeverToggle extends BaseHUDPart {
|
||||
initialize() {
|
||||
this.root.camera.downPreHandler.add(this.downPreHandler, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Vector} pos
|
||||
* @param {enumMouseButton} button
|
||||
*/
|
||||
downPreHandler(pos, button) {
|
||||
if (button === enumMouseButton.left) {
|
||||
const tile = this.root.camera.screenToWorld(pos).toTileSpace();
|
||||
const contents = this.root.map.getLayerContentXY(tile.x, tile.y, enumLayer.regular);
|
||||
|
||||
if (contents) {
|
||||
const leverComp = contents.components.Lever;
|
||||
if (leverComp) {
|
||||
leverComp.toggled = !leverComp.toggled;
|
||||
return STOP_PROPAGATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
src/js/game/hud/parts/wire_info.js
Normal file
@ -0,0 +1,58 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { enumLayer } from "../../root";
|
||||
import { globalConfig } from "../../../core/config";
|
||||
|
||||
export class HUDWireInfo extends BaseHUDPart {
|
||||
initialize() {}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("../../../core/draw_utils").DrawParameters} parameters
|
||||
*/
|
||||
drawOverlays(parameters) {
|
||||
if (this.root.currentLayer !== enumLayer.wires) {
|
||||
// Not in the wires layer
|
||||
return;
|
||||
}
|
||||
|
||||
const mousePos = this.root.app.mousePosition;
|
||||
if (!mousePos) {
|
||||
// No mouse
|
||||
return;
|
||||
}
|
||||
|
||||
const tile = this.root.camera.screenToWorld(mousePos).toTileSpace();
|
||||
const entity = this.root.map.getLayerContentXY(tile.x, tile.y, enumLayer.wires);
|
||||
|
||||
if (entity) {
|
||||
const wireComp = entity.components.Wire;
|
||||
if (wireComp) {
|
||||
const screenTile = this.root.camera.worldToScreen(tile.toWorldSpace());
|
||||
parameters.context.fillStyle = "rgba(0, 0, 0, 0.1)";
|
||||
parameters.context.fillRect(
|
||||
screenTile.x,
|
||||
screenTile.y,
|
||||
globalConfig.tileSize * this.root.camera.zoomLevel,
|
||||
globalConfig.tileSize * this.root.camera.zoomLevel
|
||||
);
|
||||
|
||||
parameters.context.font = "25px GameFont";
|
||||
const network = wireComp.linkedNetwork;
|
||||
if (!network) {
|
||||
parameters.context.fillStyle = "#333";
|
||||
parameters.context.fillText("empty", mousePos.x, mousePos.y);
|
||||
} else {
|
||||
if (network.valueConflict) {
|
||||
parameters.context.fillStyle = "#a10";
|
||||
parameters.context.fillText("conflict", mousePos.x, mousePos.y);
|
||||
} else if (!network.currentValue) {
|
||||
parameters.context.fillStyle = "#333";
|
||||
parameters.context.fillText("empty", mousePos.x, mousePos.y);
|
||||
} else {
|
||||
network.currentValue.draw(mousePos.x + 20, mousePos.y, parameters, 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,6 +32,13 @@ export class BooleanItem extends BaseItem {
|
||||
this.value = value ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BaseItem} other
|
||||
*/
|
||||
equalsImpl(other) {
|
||||
return this.value === /** @type {BooleanItem} */ (other).value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
|
@ -27,6 +27,13 @@ export class ColorItem extends BaseItem {
|
||||
return enumItemType.color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BaseItem} other
|
||||
*/
|
||||
equalsImpl(other) {
|
||||
return this.color === /** @type {ColorItem} */ (other).color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {enumColors} color
|
||||
*/
|
||||
|
@ -25,6 +25,13 @@ export class ShapeItem extends BaseItem {
|
||||
return enumItemType.shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BaseItem} other
|
||||
*/
|
||||
equalsImpl(other) {
|
||||
return this.definition.getHash() === /** @type {ShapeItem} */ (other).definition.getHash();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ShapeDefinition} definition
|
||||
*/
|
||||
|
@ -58,6 +58,7 @@ export const KEYMAPPINGS = {
|
||||
wire: { keyCode: key("1") },
|
||||
constant_signal: { keyCode: key("2") },
|
||||
logic_gate: { keyCode: key("3") },
|
||||
lever: { keyCode: key("4") },
|
||||
},
|
||||
|
||||
placement: {
|
||||
|
@ -52,6 +52,7 @@ export class MapChunkView extends MapChunk {
|
||||
const systems = this.root.systemMgr.systems;
|
||||
systems.miner.drawChunk(parameters, this);
|
||||
systems.staticMapEntities.drawChunk(parameters, this);
|
||||
systems.lever.drawChunk(parameters, this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@ import { gBuildingVariants, registerBuildingVariant } from "./building_codes";
|
||||
import { defaultBuildingVariant } from "./meta_building";
|
||||
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
|
||||
import { MetaLogicGateBuilding } from "./buildings/logic_gate";
|
||||
import { MetaLeverBuilding } from "./buildings/lever";
|
||||
|
||||
const logger = createLogger("building_registry");
|
||||
|
||||
@ -35,6 +36,7 @@ export function initMetaBuildingRegistry() {
|
||||
gMetaBuildingRegistry.register(MetaWireBuilding);
|
||||
gMetaBuildingRegistry.register(MetaConstantSignalBuilding);
|
||||
gMetaBuildingRegistry.register(MetaLogicGateBuilding);
|
||||
gMetaBuildingRegistry.register(MetaLeverBuilding);
|
||||
|
||||
// Belt
|
||||
registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0);
|
||||
@ -96,6 +98,9 @@ export function initMetaBuildingRegistry() {
|
||||
// Logic gate
|
||||
registerBuildingVariant(32, MetaLogicGateBuilding);
|
||||
|
||||
// Lever
|
||||
registerBuildingVariant(33, MetaLeverBuilding);
|
||||
|
||||
// Propagate instances
|
||||
for (const key in gBuildingVariants) {
|
||||
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(
|
||||
|
@ -13,6 +13,7 @@ import { Entity } from "../entity";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { MapChunkView } from "../map_chunk_view";
|
||||
import { defaultBuildingVariant } from "../meta_building";
|
||||
import { getCodeFromBuildingData } from "../building_codes";
|
||||
|
||||
export const BELT_ANIM_COUNT = 28;
|
||||
|
||||
@ -169,6 +170,13 @@ export class BeltSystem extends GameSystemWithFilter {
|
||||
targetStaticComp.rotation = rotation;
|
||||
metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant);
|
||||
|
||||
// Update code as well
|
||||
targetStaticComp.code = getCodeFromBuildingData(
|
||||
metaBelt,
|
||||
defaultBuildingVariant,
|
||||
rotationVariant
|
||||
);
|
||||
|
||||
// Now add it again
|
||||
this.addEntityToPaths(targetEntity);
|
||||
|
||||
|
48
src/js/game/systems/lever.js
Normal file
@ -0,0 +1,48 @@
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { LeverComponent } from "../components/lever";
|
||||
import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item";
|
||||
import { MapChunkView } from "../map_chunk_view";
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { Loader } from "../../core/loader";
|
||||
|
||||
export class LeverSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
super(root, [LeverComponent]);
|
||||
|
||||
this.spriteOn = Loader.getSprite("sprites/wires/lever_on.png");
|
||||
this.spriteOff = Loader.getSprite("sprites/buildings/lever.png");
|
||||
}
|
||||
|
||||
update() {
|
||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||
const entity = this.allEntities[i];
|
||||
|
||||
const leverComp = entity.components.Lever;
|
||||
const pinsComp = entity.components.WiredPins;
|
||||
|
||||
// Simply sync the status to the first slot
|
||||
pinsComp.slots[0].value = leverComp.toggled ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a given chunk
|
||||
* @param {import("../../core/draw_utils").DrawParameters} parameters
|
||||
* @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];
|
||||
|
||||
if (entity && entity.components.Lever) {
|
||||
const sprite = entity.components.Lever.toggled ? this.spriteOn : this.spriteOff;
|
||||
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
src/js/game/systems/logic_gate.js
Normal file
@ -0,0 +1,78 @@
|
||||
import { LogicGateComponent, enumLogicGateType } from "../components/logic_gate";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { BaseItem, enumItemType } from "../base_item";
|
||||
import { enumPinSlotType } from "../components/wired_pins";
|
||||
import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON, BooleanItem } from "../items/boolean_item";
|
||||
|
||||
export class LogicGateSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
super(root, [LogicGateComponent]);
|
||||
|
||||
this.boundOperations = {
|
||||
[enumLogicGateType.and]: this.compute_AND.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<BaseItem|null>} 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 null;
|
||||
}
|
||||
|
||||
const itemType = param1.getItemType();
|
||||
|
||||
if (itemType !== param2.getItemType()) {
|
||||
// Differing type
|
||||
return BOOL_FALSE_SINGLETON;
|
||||
}
|
||||
|
||||
if (itemType === enumItemType.boolean) {
|
||||
return /** @type {BooleanItem} */ (param1).value && /** @type {BooleanItem} */ (param2).value
|
||||
? BOOL_TRUE_SINGLETON
|
||||
: BOOL_FALSE_SINGLETON;
|
||||
}
|
||||
|
||||
return BOOL_FALSE_SINGLETON;
|
||||
}
|
||||
}
|
@ -6,8 +6,69 @@ import { Loader } from "../../core/loader";
|
||||
import { Entity } from "../entity";
|
||||
import { gMetaBuildingRegistry } from "../../core/global_registries";
|
||||
import { MetaWireBuilding, arrayWireRotationVariantToType } from "../buildings/wire";
|
||||
import { Vector } from "../../core/vector";
|
||||
import {
|
||||
Vector,
|
||||
enumDirection,
|
||||
enumDirectionToVector,
|
||||
arrayAllDirections,
|
||||
enumInvertedDirections,
|
||||
} from "../../core/vector";
|
||||
import { defaultBuildingVariant } from "../meta_building";
|
||||
import { createLogger } from "../../core/logging";
|
||||
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
|
||||
import { getCodeFromBuildingData } from "../building_codes";
|
||||
import { BaseItem, enumItemType } from "../base_item";
|
||||
|
||||
const logger = createLogger("wires");
|
||||
|
||||
let networkUidCounter = 0;
|
||||
|
||||
const VERBOSE_WIRES = false;
|
||||
|
||||
export class WireNetwork {
|
||||
constructor() {
|
||||
/**
|
||||
* Who contributes to this network
|
||||
* @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} */
|
||||
this.providers = [];
|
||||
|
||||
/**
|
||||
* Who takes values from this network
|
||||
* @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} */
|
||||
this.receivers = [];
|
||||
|
||||
/**
|
||||
* All connected slots
|
||||
* @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>}
|
||||
*/
|
||||
this.allSlots = [];
|
||||
|
||||
/**
|
||||
* Which wires are in this network
|
||||
* @type {Array<Entity>}
|
||||
*/
|
||||
this.wires = [];
|
||||
|
||||
/**
|
||||
* The current value of this network
|
||||
* @type {BaseItem}
|
||||
*/
|
||||
this.currentValue = null;
|
||||
|
||||
/**
|
||||
* Whether this network has a value conflict, that is, more than one
|
||||
* sender has sent a value
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.valueConflict = false;
|
||||
|
||||
/**
|
||||
* Unique network identifier
|
||||
* @type {number}
|
||||
*/
|
||||
this.uid = ++networkUidCounter;
|
||||
}
|
||||
}
|
||||
|
||||
export class WireSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
@ -22,6 +83,327 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
|
||||
this.root.signals.entityDestroyed.add(this.updateSurroundingWirePlacement, this);
|
||||
this.root.signals.entityAdded.add(this.updateSurroundingWirePlacement, this);
|
||||
|
||||
this.root.signals.entityDestroyed.add(this.queueRecomputeIfWire, this);
|
||||
this.root.signals.entityChanged.add(this.queueRecomputeIfWire, this);
|
||||
this.root.signals.entityAdded.add(this.queueRecomputeIfWire, this);
|
||||
|
||||
this.needsRecompute = true;
|
||||
|
||||
/**
|
||||
* @type {Array<WireNetwork>}
|
||||
*/
|
||||
this.networks = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the wires network if the given entity is relevant for it
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
queueRecomputeIfWire(entity) {
|
||||
if (!this.root.gameInitialized) {
|
||||
return;
|
||||
}
|
||||
if (entity.components.Wire || entity.components.WiredPins) {
|
||||
this.needsRecompute = true;
|
||||
this.networks = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recomputes the whole wires network
|
||||
*/
|
||||
recomputeWiresNetwork() {
|
||||
this.needsRecompute = false;
|
||||
logger.log("Recomputing wires network");
|
||||
|
||||
this.networks = [];
|
||||
|
||||
// Clear all network references
|
||||
const wireEntities = this.root.entityMgr.getAllWithComponent(WireComponent);
|
||||
for (let i = 0; i < wireEntities.length; ++i) {
|
||||
wireEntities[i].components.Wire.linkedNetwork = null;
|
||||
}
|
||||
|
||||
const pinEntities = this.root.entityMgr.getAllWithComponent(WiredPinsComponent);
|
||||
for (let i = 0; i < pinEntities.length; ++i) {
|
||||
const slots = pinEntities[i].components.WiredPins.slots;
|
||||
for (let k = 0; k < slots.length; ++k) {
|
||||
slots[k].linkedNetwork = null;
|
||||
}
|
||||
}
|
||||
|
||||
VERBOSE_WIRES && logger.log("Recomputing slots");
|
||||
|
||||
// Iterate over all ejector slots
|
||||
for (let i = 0; i < pinEntities.length; ++i) {
|
||||
const entity = pinEntities[i];
|
||||
const slots = entity.components.WiredPins.slots;
|
||||
for (let k = 0; k < slots.length; ++k) {
|
||||
const slot = slots[k];
|
||||
|
||||
// Ejectors are computed directly, acceptors are just set
|
||||
if (slot.type === enumPinSlotType.logicalEjector && !slot.linkedNetwork) {
|
||||
this.findNetworkForEjector(entity, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the network for the given slot
|
||||
* @param {Entity} initialEntity
|
||||
* @param {import("../components/wired_pins").WirePinSlot} slot
|
||||
*/
|
||||
findNetworkForEjector(initialEntity, slot) {
|
||||
let currentNetwork = new WireNetwork();
|
||||
VERBOSE_WIRES &&
|
||||
logger.log(
|
||||
"Finding network for entity",
|
||||
initialEntity.uid,
|
||||
initialEntity.components.StaticMapEntity.origin.toString(),
|
||||
"(nw-id:",
|
||||
currentNetwork.uid,
|
||||
")"
|
||||
);
|
||||
const entitiesToVisit = [
|
||||
{
|
||||
entity: initialEntity,
|
||||
slot,
|
||||
},
|
||||
];
|
||||
|
||||
while (entitiesToVisit.length > 0) {
|
||||
const nextData = entitiesToVisit.pop();
|
||||
const nextEntity = nextData.entity;
|
||||
|
||||
const wireComp = nextEntity.components.Wire;
|
||||
const staticComp = nextEntity.components.StaticMapEntity;
|
||||
|
||||
VERBOSE_WIRES && logger.log("Visiting", staticComp.origin.toString(), "(", nextEntity.uid, ")");
|
||||
|
||||
// Where to search for neighbours
|
||||
let newSearchDirections = [];
|
||||
let newSearchTile = null;
|
||||
|
||||
//// WIRE
|
||||
if (wireComp) {
|
||||
// Sanity check
|
||||
assert(
|
||||
!wireComp.linkedNetwork || wireComp.linkedNetwork === currentNetwork,
|
||||
"Mismatching wire network on wire entity " +
|
||||
(wireComp.linkedNetwork ? wireComp.linkedNetwork.uid : "<empty>") +
|
||||
" vs " +
|
||||
currentNetwork.uid +
|
||||
" @ " +
|
||||
staticComp.origin.toString()
|
||||
);
|
||||
|
||||
if (!wireComp.linkedNetwork) {
|
||||
// This one is new! :D
|
||||
VERBOSE_WIRES && logger.log(" Visited new wire:", staticComp.origin.toString());
|
||||
wireComp.linkedNetwork = currentNetwork;
|
||||
currentNetwork.wires.push(nextEntity);
|
||||
|
||||
newSearchDirections = arrayAllDirections;
|
||||
newSearchTile = nextEntity.components.StaticMapEntity.origin;
|
||||
}
|
||||
}
|
||||
|
||||
//// PINS
|
||||
const pinsComp = nextEntity.components.WiredPins;
|
||||
if (pinsComp) {
|
||||
const slot = nextData.slot;
|
||||
assert(slot, "No slot set for next entity");
|
||||
|
||||
if (slot.type === enumPinSlotType.logicalEjector) {
|
||||
VERBOSE_WIRES &&
|
||||
logger.log(" Visiting ejector slot", staticComp.origin.toString(), "->", slot.type);
|
||||
} else if (slot.type === enumPinSlotType.logicalAcceptor) {
|
||||
VERBOSE_WIRES &&
|
||||
logger.log(" Visiting acceptor slot", staticComp.origin.toString(), "->", slot.type);
|
||||
} else {
|
||||
assertAlways(false, "Bad slot type: " + slot.type);
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
assert(
|
||||
!slot.linkedNetwork || slot.linkedNetwork === currentNetwork,
|
||||
"Mismatching wire network on pin slot entity " +
|
||||
(slot.linkedNetwork ? slot.linkedNetwork.uid : "<empty>") +
|
||||
" vs " +
|
||||
currentNetwork.uid
|
||||
);
|
||||
if (!slot.linkedNetwork) {
|
||||
// This one is new
|
||||
VERBOSE_WIRES && logger.log(" Visited new slot:", staticComp.origin.toString());
|
||||
|
||||
// Add to the right list
|
||||
if (slot.type === enumPinSlotType.logicalEjector) {
|
||||
currentNetwork.providers.push({ entity: nextEntity, slot });
|
||||
} else if (slot.type === enumPinSlotType.logicalAcceptor) {
|
||||
currentNetwork.receivers.push({ entity: nextEntity, slot });
|
||||
} else {
|
||||
assertAlways(false, "unknown slot type:" + slot.type);
|
||||
}
|
||||
|
||||
// Register on the network
|
||||
currentNetwork.allSlots.push({ entity: nextEntity, slot });
|
||||
slot.linkedNetwork = currentNetwork;
|
||||
|
||||
// Specify where to search next
|
||||
newSearchDirections = [staticComp.localDirectionToWorld(slot.direction)];
|
||||
newSearchTile = staticComp.localTileToWorld(slot.pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (newSearchTile) {
|
||||
// Find new surrounding wire targets
|
||||
const newTargets = this.findSurroundingWireTargets(newSearchTile, newSearchDirections);
|
||||
|
||||
VERBOSE_WIRES && logger.log(" Found", newTargets, "new targets to visit!");
|
||||
for (let i = 0; i < newTargets.length; ++i) {
|
||||
entitiesToVisit.push(newTargets[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
currentNetwork.providers.length > 0 &&
|
||||
(currentNetwork.wires.length > 0 || currentNetwork.receivers.length > 0)
|
||||
) {
|
||||
this.networks.push(currentNetwork);
|
||||
VERBOSE_WIRES && logger.log("Attached new network with uid", currentNetwork);
|
||||
} else {
|
||||
// Unregister network again
|
||||
for (let i = 0; i < currentNetwork.wires.length; ++i) {
|
||||
currentNetwork.wires[i].components.Wire.linkedNetwork = null;
|
||||
}
|
||||
|
||||
for (let i = 0; i < currentNetwork.allSlots.length; ++i) {
|
||||
currentNetwork.allSlots[i].slot.linkedNetwork = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds surrounding entities which are not yet assigned to a network
|
||||
* @param {Vector} tile
|
||||
* @param {Array<enumDirection>} directions
|
||||
* @returns {Array<any>}
|
||||
*/
|
||||
findSurroundingWireTargets(tile, directions) {
|
||||
let result = [];
|
||||
|
||||
VERBOSE_WIRES &&
|
||||
logger.log(" Searching for new targets at", tile.toString(), "and d=", directions);
|
||||
|
||||
for (let i = 0; i < directions.length; ++i) {
|
||||
const direction = directions[i];
|
||||
const offset = enumDirectionToVector[direction];
|
||||
const searchTile = tile.add(offset);
|
||||
|
||||
const contents = this.root.map.getLayersContentsMultipleXY(searchTile.x, searchTile.y);
|
||||
for (let k = 0; k < contents.length; ++k) {
|
||||
const entity = contents[k];
|
||||
const wireComp = entity.components.Wire;
|
||||
|
||||
// Check for wire
|
||||
if (wireComp && !wireComp.linkedNetwork) {
|
||||
// Wires accept connections from everywhere
|
||||
result.push({
|
||||
entity,
|
||||
});
|
||||
}
|
||||
|
||||
// Check for connected slots
|
||||
const pinComp = entity.components.WiredPins;
|
||||
if (pinComp) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
|
||||
// Go over all slots and see if they are connected
|
||||
const pinSlots = pinComp.slots;
|
||||
for (let j = 0; j < pinSlots.length; ++j) {
|
||||
const slot = pinSlots[j];
|
||||
|
||||
// Check if the position matches
|
||||
const pinPos = staticComp.localTileToWorld(slot.pos);
|
||||
if (!pinPos.equals(searchTile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the direction (inverted) matches
|
||||
const pinDirection = staticComp.localDirectionToWorld(slot.direction);
|
||||
if (pinDirection !== enumInvertedDirections[direction]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push({
|
||||
entity,
|
||||
slot,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VERBOSE_WIRES && logger.log(" -> Found", result.length);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the wires network
|
||||
*/
|
||||
update() {
|
||||
if (this.needsRecompute) {
|
||||
this.recomputeWiresNetwork();
|
||||
}
|
||||
|
||||
// Re-compute values of all networks
|
||||
for (let i = 0; i < this.networks.length; ++i) {
|
||||
const network = this.networks[i];
|
||||
|
||||
// Reset conflicts
|
||||
network.valueConflict = false;
|
||||
|
||||
// Aggregate values of all senders
|
||||
const senders = network.providers;
|
||||
let value = null;
|
||||
for (let k = 0; k < senders.length; ++k) {
|
||||
const senderSlot = senders[k];
|
||||
const slotValue = senderSlot.slot.value;
|
||||
|
||||
// The first sender can just put in his value
|
||||
if (!value) {
|
||||
value = slotValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the slot is empty itself, just skip it
|
||||
if (!slotValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there is already an value, compare if it matches ->
|
||||
// otherwise there is a conflict
|
||||
if (value.equals(slotValue)) {
|
||||
// All good
|
||||
continue;
|
||||
}
|
||||
|
||||
// There is a conflict, this means the value will be null anyways
|
||||
network.valueConflict = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Assign value
|
||||
if (network.valueConflict) {
|
||||
network.currentValue = null;
|
||||
} else {
|
||||
network.currentValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,11 +417,43 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
||||
const entity = contents[x][y];
|
||||
if (entity && entity.components.Wire) {
|
||||
const wireType = entity.components.Wire.type;
|
||||
const sprite = this.wireSprites[wireType];
|
||||
const wireComp = entity.components.Wire;
|
||||
const wireType = wireComp.type;
|
||||
const network = wireComp.linkedNetwork;
|
||||
|
||||
let opacity = 1;
|
||||
let spriteSet = this.wireSprites;
|
||||
|
||||
if (!network) {
|
||||
opacity = 0.3;
|
||||
} else {
|
||||
if (network.valueConflict) {
|
||||
opacity = 1;
|
||||
// TODO
|
||||
} else {
|
||||
if (network.currentValue) {
|
||||
if (
|
||||
network.currentValue.getItemType() === enumItemType.boolean &&
|
||||
// @ts-ignore
|
||||
network.currentValue.value === 0
|
||||
) {
|
||||
opacity = 0.5;
|
||||
} else {
|
||||
opacity = 1;
|
||||
}
|
||||
} else {
|
||||
opacity = 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sprite = spriteSet[wireType];
|
||||
|
||||
assert(sprite, "Unknown wire type: " + wireType);
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
parameters.context.globalAlpha = opacity;
|
||||
staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0);
|
||||
parameters.context.globalAlpha = 1;
|
||||
|
||||
if (G_IS_DEV && globalConfig.debug.renderWireRotations) {
|
||||
parameters.context.fillStyle = "red";
|
||||
@ -68,6 +482,25 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG Rendering
|
||||
if (G_IS_DEV && globalConfig.debug.renderWireNetworkInfos) {
|
||||
if (entity) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const wireComp = entity.components.Wire;
|
||||
|
||||
// Draw network info for wires
|
||||
if (wireComp && wireComp.linkedNetwork) {
|
||||
parameters.context.fillStyle = "red";
|
||||
parameters.context.font = "5px Tahoma";
|
||||
parameters.context.fillText(
|
||||
"W" + wireComp.linkedNetwork.uid,
|
||||
(staticComp.origin.x + 0.5) * globalConfig.tileSize,
|
||||
(staticComp.origin.y + 0.5) * globalConfig.tileSize
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,6 +519,8 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log("Updating surrounding wire placement");
|
||||
|
||||
const metaWire = gMetaBuildingRegistry.findByClass(MetaWireBuilding);
|
||||
|
||||
// Compute affected area
|
||||
@ -130,6 +565,13 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
targetStaticComp.rotation = rotation;
|
||||
metaWire.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant);
|
||||
|
||||
// Update code as well
|
||||
targetStaticComp.code = getCodeFromBuildingData(
|
||||
metaWire,
|
||||
defaultBuildingVariant,
|
||||
rotationVariant
|
||||
);
|
||||
|
||||
// Make sure the chunks know about the update
|
||||
this.root.signals.entityChanged.dispatch(targetEntity);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { enumLayer } from "../root";
|
||||
import { STOP_PROPAGATION } from "../../core/signal";
|
||||
import { drawRotatedSprite } from "../../core/draw_utils";
|
||||
import { GLOBAL_APP } from "../../core/globals";
|
||||
|
||||
export class WiredPinsSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
@ -187,9 +188,23 @@ export class WiredPinsSystem extends GameSystemWithFilter {
|
||||
const value = slot.value;
|
||||
if (value) {
|
||||
const offset = new Vector(0, -5).rotated(effectiveRotation);
|
||||
|
||||
value.draw(worldPos.x + offset.x, worldPos.y + offset.y, parameters, 12);
|
||||
}
|
||||
|
||||
// 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -555,6 +555,11 @@ buildings:
|
||||
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
|
||||
@ -830,6 +835,7 @@ keybindings:
|
||||
wire: *wire
|
||||
constant_signal: *constant_signal
|
||||
logic_gate: *logic_gate
|
||||
lever: *lever
|
||||
# ---
|
||||
|
||||
pipette: Pipette
|
||||
|