Refactor into different crates

This commit is contained in:
hal8174 2025-01-18 17:30:55 +01:00
parent 94473c64e0
commit dfdeae5638
82 changed files with 624 additions and 647 deletions

View file

@ -0,0 +1,13 @@
[package]
name = "factorio-blueprint"
version = "0.1.0"
edition = "2024"
[dependencies]
factorio-core = { path = "../factorio-core" }
base64 = "0.22.1"
bon = "3.3.2"
clap = { version = "4.5.26", features = ["derive"] }
serde = "1.0.217"
serde_json = "1.0.135"
flate2 = "1.0.35"

View file

@ -0,0 +1 @@
0eNqVkmFuwjAMhe/i32FipV3XXgWhKgRTLFKHNWk3hHL3OS0TaEOTkCpVSezv+dm+wNYOeOqJA9QXIOPYQ72+gKeWtU13rDuEGnpNFqIC4h1+Qf0a1YMg64zrXKAR70KzuFGAHCgQzvDpcG546LbYC0v95PsgMu0hLCY1BSfnJctxkkikslBwlv9qFZP+L06mHtTxDyR/eS+LmGrTW4uNdS35QMY3nweSc+dG4hbqvbYeFbieRE/PpKW4C9jNdmh33ydnjhgW+wGTgY9BWykxlYQt8k7356kzc66kckM8CtfJw8S6naQtPmhznNSMG9KIsmXcRPn+ml8938TiURPz5zllTBP2QZw3skCMJoVd9yjdXncguRbubeMUjNj7CVm8ZVVeVUVeVmVRyni/ARwe37c=

View file

@ -0,0 +1,78 @@
{
"blueprint": {
"entities": [
{
"entity_number": 1,
"name": "straight-rail",
"position": {
"x": 275,
"y": 233
}
},
{
"enable_logistics_while_moving": false,
"entity_number": 2,
"items": [
{
"id": {
"name": "rocket-fuel",
"quality": "legendary"
},
"items": {
"in_inventory": [
{
"count": 20,
"inventory": 1,
"stack": 0
}
]
}
}
],
"name": "locomotive",
"orientation": 0,
"position": {
"x": 275,
"y": 234.875
}
},
{
"entity_number": 3,
"name": "straight-rail",
"position": {
"x": 275,
"y": 235
}
},
{
"entity_number": 4,
"name": "straight-rail",
"position": {
"x": 275,
"y": 237
}
}
],
"icons": [
{
"index": 1,
"signal": {
"name": "rail"
}
},
{
"index": 2,
"signal": {
"name": "locomotive"
}
}
],
"item": "blueprint",
"stock_connections": [
{
"stock": 2
}
],
"version": 562949954797573
}
}

View file

@ -0,0 +1 @@
0eNqN000KwjAQBeC7zDpdaJvG5Coi0p+hDrTTkkRRSu9u2iIuRJhlyHtfApPMUPd3nDxxBDdD4GrK4ph1ntp1/QR3KBW8wBWLAmpGDuDOKUcdV/2a4GpAcOAr6mGNcItrabkoQI4UCffGtnhd+T7U6FNAfZohpm53i9lGKJjGkFojf47fTs8T3ZLHZt9Jl/kRj1Ixl4q5VNRSsZCKRipqqWilYimejHg0RkyKZ3MSk3+Gk94nRRwS8P0ACh7owxbQ5dEW1urCWKNNvixvl10L0w==

View file

@ -0,0 +1,92 @@
{
"blueprint": {
"entities": [
{
"direction": 4,
"entity_number": 1,
"name": "straight-rail",
"position": {
"x": 1,
"y": 3
}
},
{
"direction": 4,
"entity_number": 2,
"name": "straight-rail",
"position": {
"x": 3,
"y": 3
}
},
{
"direction": 4,
"entity_number": 3,
"name": "straight-rail",
"position": {
"x": 5,
"y": 3
}
},
{
"direction": 4,
"entity_number": 4,
"name": "straight-rail",
"position": {
"x": 7,
"y": 3
}
},
{
"direction": 4,
"entity_number": 5,
"name": "straight-rail",
"position": {
"x": 9,
"y": 3
}
},
{
"direction": 4,
"entity_number": 6,
"name": "straight-rail",
"position": {
"x": 11,
"y": 3
}
},
{
"direction": 4,
"entity_number": 7,
"name": "straight-rail",
"position": {
"x": 13,
"y": 3
}
},
{
"direction": 4,
"entity_number": 8,
"name": "straight-rail",
"position": {
"x": 15,
"y": 3
}
}
],
"icons": [
{
"index": 1,
"signal": {
"name": "rail"
}
}
],
"item": "blueprint",
"snap-to-grid": {
"x": 16,
"y": 4
},
"version": 562949954797573
}
}

View file

@ -0,0 +1 @@
0eNqdlttugzAMht/F12mVhBgIrzJNUw9RFYkGFMI0VPHuC0Xa2kHWkCsEsr/Y/m2cGxzrXrVWGwfVDfSpMR1Ubzfo9MUc6umbOVwVVODswXRtY93uqGoHIwFtzuoLKjaSFfOurbVzyj4Y8vGdgDJOO63mQ+4vw4fpr0dvWTGy8CbQNp13aMzE9hCkBAaodozSPY7T0X8gPAbCX0AyEkh7gRJyjzNMlusskcKS6yz8YfW+pvZiG/8M0JA+RUbADe3k2fSu7ScBF/R8C51tpRcxwrD/8y+ja4n8lS4yhRWIi9EUkYsAjG2pVB6A8Pj06FNEBM7aqtNswPgaO348HtpkwRZraJGiSqiQmKKKCMDyFBhGJV2kjbV4HDxtAnPHyrSxjqTLlF7AwL+bpjRtCMZSWimgPucpMIwaJ55t2HsyCwQoNuy9GeK3sXbq6j1+7wAEPpXt7h6YcymkRMzKIpPZOH4DJhSmag==

View file

@ -0,0 +1 @@
0eNqdlN1uhCAQhd9lrnEDVtefV2k2Bu3slhTBCG5qNr57UdO4SXW13DED851wYOYBpeywaYWyRan1F+SPJWMgf38Kxz1RaTWnjbgpLsec7RuEHITFGggoXo+R0ZK3QcMVShgICPWB35Cz4UIAlRVW4IyZgr5QXV1i6w6sAgg02rgarUY9xwnClJ1iAr1bMhqd4mEgf1jhUVaS7rLeDrPiXVZ0mBXusuKjrHO2yzr7eM/WWYmPXxus1OeOG6xsYdVcygAlVrYVVdBoiXt/Y2S6ehS3z1J37fiBGb2sqDD6b5nwpUy2qrI0y/UaGBSmdgqm4kq57ZfvlqXr9jCPntlkefTMJsujZzZZHj0zs9zsmoZc/jQTCdyxNVOV8zdKMucMozRK6TL16FplMI1bAryy4o7F79EXvOEHwC3N0A==

View file

@ -0,0 +1 @@
0eNqd1N1ugyAUB/B3OdfYgNP68SpNs6A77UgQDOAyY3j3ob3okml13Il6fv945DBBIwfsjVAO6glEq5WF+jKBFXfF5XzPjT1CDcJhBwQU7+aV1ZKbpOcKJXgCQn3gN9TMXwmgcsIJfDDLYnxXQ9egCS+sAgR6bUONVnNecJK0ZKecwBguGc1Ouffkj5UetYpy13o7bOW7VnbYSnet/Kh1rnatc0zv2bpVxPRrwypjvnHDqp5Wx6VMUGLrjGiTXkvc2xuzGepR3D8bPZh5AzN6XUlh9N8x6cuYajXlOSy3W2JR2C4k2JYrFR6//G9Vud4eFjEzm1bEzGxaETOzaUXMzMMKZ9dyyNW/zkQCX2jsUhX6mxVV6AyjNCup9z8fYqg/

View file

@ -0,0 +1 @@
0eNqVkN0OgjAMRt+l14XwVw28ijFmYKNNYCAbRkL27o55oVET42Wbfue0XaBuJx5G0RaqBaTptYFqt4CRk1bt2tOqY6jAWOY2as5sLDgE0Ue+QZU6/DGLcJlUK3b2fR6keQlnbo/A2ooVflhDMR/01NU8ejp+Jw698Zler0rPIaKYELwhKmJyH0aEWnnaNlmXfVNkfysoKAIxT9YLxHLn889HIlx5NCFMm6wsypKooKzMU+fu/rR3Gg==

View file

@ -0,0 +1 @@
0eNqd0MEOgjAMANB/6bkQYU7dfoUQA9iYJmyQbaiE7N8dePCg8eClWbv1Le0CbT/R6NgG0AtwN1gPulrA89U2/VqzjSHQYOjCk8mopy447rJx6AkiAtsLPUAXsUYgGzgwvYQtmc92Mi259AB/Sgjj4FPzYNc/EyhyiTCDzopdkcsY8UMs/xVV+R0U/4KnwwqmBdzZbdNXBUosUdZYpYgindItBzIJf28c4UbOb6A8lGqvlJTidBRKxPgE1KeFBQ==

View file

@ -0,0 +1 @@
0eJydlNGOgyAQRf9lnqERamv1cX9j02y0TtxJAA3iZpvGf19sG+Ou25TyCMycS7iXuUClBuwsGQfFBejUmh6K9wv01JhSTXvu3CEUQA41MDClnlbVYA1arsmQaXhtSSkYGZCp8RsKMR4ZoHHkCG+4exsqPDlLp9+NDLq297WtmfR8P5ebHYOzB212nlqT9W3XY3nnnj/MoCu0kxZ7FS8e0fcrulzQnS1N37XW8QqV++fWySNusuJuY7jJc24aw5XPubvXX3k2kQe4uI93cY1f25gt8BprGjSfVbpW4Zq+DX/zg/8VSM1n1Q52Snt+fFmNp+Fy+R+5wzHGcx6gJJIockD8hYgiBwRVyGn2XIdVsZhtDL7Q9rfwHUSa5TJLZZ5vc8FAlV7XV7/N1eP4Ay9CrIM=

View file

@ -0,0 +1 @@
0eNq9lGFvgyAQhv/LfcYGnLbqX2kag+7akSEYwGZN438f2iwumVbLh32D4+55wwt3d6hkh60RypWV1p9Q3KeIheJ4fyFhOBO1Vo+wFRfF5RBztxahAOGwAQKKN8POaslN1HKFEnoCQr3jFxSsPxFA5YQT+MCMm1upuqZC4xNmAQRabX2NVoOe50RxxnYpgZtfMprs0r4nf1jxVtYhW2W9bWalq6xkMyteZaVbWft8lbUP8Z7Nsw4hfi2wspA7LrDyidVwKSOUWDsj6qjVEtf+xsD09SguH5XuzPCBGT3NqDD6skz8VCafVZma5XyOLArbeAVbc6X88dN3y7N5e1hAzyyyAnpmkRXQM4usgJ55sPzsGodc8WsmEriisWOV9zc55N4ZRmmS0Wnq0bnKaBy3BHjtxBXLn9R/5PXfnorzYQ==

View file

@ -0,0 +1 @@
0eNrFlPFqgzAQxt/l/s6kNbFOX2UUSe3VHY1JZ6JbKb77LrqthVHoOthAyF2S++77YbgTbEyPh45sgPIEVDvroXw6gafGahP3rG4RSug0GRgFkN3iG5TLcS0AbaBAOFdMybGyfbvBji+Iz0rjate6QAOCgIPzXOJsVGaZNON7R16lStLlY56NUVVvDFbGNeQD1b56fSbOWzeQbaDcaeNRgOuIO+pZa8G+ArazEdpe2nb1HsPDrkfD3V96bdhkNIUN2q3ujhPTXMultiI7sK7jg0nrnLFRH3S9527jeuRPfGNOb2NWMlkx6gyu5J3ISVT4S2oBtevjO1HX+OWN/7xICvl7/vS/+NNr/Opnbz5bJEre/eST/8KXM/46HnGjimeGxTq6+hgdcTdOCPEVpxexvIhVVIlG2Nx5EAkYsPMTZbZKC1UUmcqLPMvlOL4DS3+ZEg==

View file

@ -0,0 +1,137 @@
{
"blueprint": {
"entities": [
{
"enable_logistics_while_moving": false,
"entity_number": 1,
"items": [
{
"id": {
"name": "rocket-fuel",
"quality": "legendary"
},
"items": {
"in_inventory": [
{
"inventory": 1,
"stack": 0
}
]
}
}
],
"name": "locomotive",
"orientation": 0,
"position": {
"x": 251,
"y": 234.21875
}
},
{
"enable_logistics_while_moving": false,
"entity_number": 2,
"items": [
{
"id": {
"name": "rocket-fuel",
"quality": "legendary"
},
"items": {
"in_inventory": [
{
"count": 4,
"inventory": 1,
"stack": 0
}
]
}
}
],
"name": "locomotive",
"orientation": 0.75,
"position": {
"x": 243.6875,
"y": 243
}
},
{
"enable_logistics_while_moving": false,
"entity_number": 3,
"items": [
{
"id": {
"name": "rocket-fuel",
"quality": "legendary"
},
"items": {
"in_inventory": [
{
"count": 2,
"inventory": 1,
"stack": 0
}
]
}
}
],
"name": "locomotive",
"orientation": 0.25,
"position": {
"x": 259.9375,
"y": 243
}
},
{
"enable_logistics_while_moving": false,
"entity_number": 4,
"items": [
{
"id": {
"name": "rocket-fuel",
"quality": "legendary"
},
"items": {
"in_inventory": [
{
"count": 3,
"inventory": 1,
"stack": 0
}
]
}
}
],
"name": "locomotive",
"orientation": 0.5,
"position": {
"x": 251,
"y": 250.4375
}
}
],
"icons": [
{
"index": 1,
"signal": {
"name": "rail"
}
}
],
"item": "blueprint",
"stock_connections": [
{
"stock": 1
},
{
"stock": 2
},
{
"stock": 3
},
{
"stock": 4
}
],
"version": 562949954797573
}
}

View file

@ -0,0 +1,45 @@
{
"blueprint": {
"item": "blueprint",
"label": "test",
"entities": [
{
"entity_number": 1,
"name": "locomotive",
"orientation": 0,
"position": {
"x": 0,
"y": 0
}
},
{
"entity_number": 2,
"name": "cargo-wagon",
"orientation": 0,
"position": {
"x": 0,
"y": 7
}
}
],
"stock_connections": [
{
"back": 2,
"stock": 1
},
{
"stock": 2,
"front": 1
}
],
"icons": [
{
"index": 1,
"signal": {
"name": "rail"
}
}
],
"version": 562949954797573
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
0eJxtjs0KwjAQhN9lzhEaioo5+hoikraLBNJNSbZiKXl30x/Eg5eF3Z35ZmY0fqQhOhaYGa4NnGBuM5J7svXLTaaBYOCEeiiw7ZdNouU0hCiHhrwgKzju6A2j812BWJw42kj/HQpDSEUUeMkoxkphKrOQOhep3T7VzpoePPYNxZ2/djE/1RVeFNNqOdeVPtYnfdQXBW9LWFFev8qcP37OUWQ=

View file

@ -0,0 +1 @@
0eNqd0W8LgjAQBvDvcq+n+G/l9lUiQuuIgZ6ynZHIvnuziMISopcbz/O7Y5ugbgbsrSEGPYE5duRA7yZw5kxVM99R1SJoYFuR6zvLUY0Ngxdg6IRX0KkXX+Kubwwz2rdg5vcCkNiwwceQ+2E80NDWIalT8dEW0HcuFDqa7YCUWwEj6ChN0lj6efQCycTKxp9UGcsnlnzH8r+wlc2KnzGVLLDwcIaxDdXXdwm4oHX3ktxkqlBKyrzc5ir3/gbLs5nn

View file

@ -0,0 +1 @@
0eNp1jsEOgjAQRP9lzoWItUL7K8YYqhvTBLakLUZC+u8WPHjyuJN5b3aFHWaaguMEs8LdPUeYy4rontwPW8b9SDBIoec4+ZAqS0NCFnD8oDdMk68CxMklR192P5Ybz6OlUArij0Ng8rFgnredouraWgksMFVzkLXKm9klGgv6e1PgRSHukDof9UlrpWTXSi1z/gD180RL

View file

@ -0,0 +1 @@
0eNqtlGFvwiAQhv/LfUZjaxHbv7IsDa1YL6NgAOuM6X/f0Tq3ZF3Ckn0ivHAP78Fxd2j0RZ0dmgDVHbC1xkP1cgePnZE6akb2CipwEjWMDNAc1DtU2fjKQJmAAdUcMU1utbn0jXK0gX1G+kCx3SmsJgSDs/UUZU2EEynfcAY3GouM8Ad0qp1Xi5H9oObpVJFO3T6prXSdXV1lR1sXmPv1bi++21VGNlrV2nboA7a+vp6Q5r0d0HRQHaX2ioF1SCfKGbVZ5zxe40CSdUQyF60XTBXpqZbpqfJkapalU3fp1G06VTyp2ra2twEHtYTk//QqCxb26Yn9oYrLdOofqjjbpGN/rRj61T7Y9q2mTmBm+dEQojp9laOzsVuIaOGhkstGTssRgEH1ZOKrszAYlPPTCXyXl0VZ8kKUgovtOH4AgIx9uw==

View file

@ -0,0 +1,119 @@
{
"blueprint": {
"entities": [
{
"direction": 4,
"entity_number": 1,
"name": "straight-rail",
"position": {
"x": 205,
"y": 0
}
},
{
"direction": 4,
"entity_number": 2,
"name": "straight-rail",
"position": {
"x": 207,
"y": 0
}
},
{
"enable_logistics_while_moving": false,
"entity_number": 3,
"inventory": null,
"name": "cargo-wagon",
"orientation": 0.25,
"position": {
"x": 208.6875,
"y": 0
}
},
{
"direction": 4,
"entity_number": 4,
"name": "straight-rail",
"position": {
"x": 209,
"y": 0
}
},
{
"direction": 4,
"entity_number": 5,
"name": "straight-rail",
"position": {
"x": 211,
"y": 0
}
},
{
"direction": 4,
"entity_number": 6,
"name": "straight-rail",
"position": {
"x": 213,
"y": 0
}
},
{
"enable_logistics_while_moving": false,
"entity_number": 7,
"name": "locomotive",
"orientation": 0.25,
"position": {
"x": 215.6875,
"y": 0
}
},
{
"direction": 4,
"entity_number": 8,
"name": "straight-rail",
"position": {
"x": 215,
"y": 0
}
},
{
"direction": 4,
"entity_number": 9,
"name": "straight-rail",
"position": {
"x": 217,
"y": 0
}
},
{
"direction": 4,
"entity_number": 10,
"name": "straight-rail",
"position": {
"x": 219,
"y": 0
}
}
],
"icons": [
{
"index": 1,
"signal": {
"name": "rail"
}
}
],
"item": "blueprint",
"stock_connections": [
{
"front": 7,
"stock": 3
},
{
"back": 3,
"stock": 7
}
],
"version": 562949954797573
}
}

View file

@ -0,0 +1 @@
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

View file

@ -0,0 +1 @@
0eNrFld2OmzAQhV9lNZeVWfETkgWpfYJe9i6KLAKTrlWwqW3SRhHv3jE4JLv1ptVetIqExoP9cebMQM6wbwfstZAWyjOIWkkD5fYMRnyVVetysuoQSmiwFg3qqFbdXsjKKg0jAyEb/AllMrLAEasrISNjVX+zNR13DFBaYQXOj5oWJy6Hbo+aWCxwnkGvDB1R0vEJs85o3wnKqMiITbKtVi3f43N1FCSNNhmUDbeKTxQoD1VrkM1M7pg9Nvwq2Z5698ij0HagzKJh3hF9cRUYtDPN8FZ0ghyzergwfe7vkZ9hdExbzVUBOA9feZGyO/a/7cnT02NO7EZorOf7SRo2yWM53WsmlHHZ2xU16CC0uS3MS+orTYElUTHMPaBi3BylcRy7LqvB9oN9PU9/tsWx+hNpGqTlB606LiSBfA/H3TgGrMreadXmv1qVkFVu3bkdTmkJn+Cfe7daQB02YugibMkNLeqoVy0G3XvMvX9r8i+AzBfkfmi/RfR+oKb6Q6z4wtoExjaAXl/LtohtVD+jsXdFTuAAafP+ujeFQ1KjfpBa16ZtwhKWsmzHtilFGUumKHM/imjNVlOOrmzjo5yinKK1zxFvGZW5977joiE1dHk5Sgy+0xhQRdEyhk6pT9JmqXQ3zcmLCfsIkxke7c1gl6AE9/5eZyul8ECcoa3c42NuKNFgT59XlP4beBeXvMAlv+EePjykASR5ISx2boKWvygGRzJmKjNfp8WqKPJ8ladFlozjL1XOQeE=

View file

@ -0,0 +1 @@
0eNrFlM9unDAQxt9lziZaYIHAoU/QY2+rFeLPbGPV2JY9bLNa8e4ZA9msIppWOTRCQuOx/fM33xiu0KoRrZOaoLqC7Iz2UB2u4OVP3aiQ082AUEGPnezRRZ0ZWqkbMg4mAVL3+AxVPImNLeQaqSNPxt4tTaajANQkSeJy1Dy41HocWnTMEhv7BVjjeYvRgc+YPOV1F6iiMmU2yyZnVN3iU3OWLI0XedR9TaaeKVCdGuVRLMw6MC329Ztkuthw5Fk6Gjlz07CsiH6ECjzSQvO1koNkx8iNr8w19+/I7zAFJjVLVQDBw3deJOID+//syePjQ8bsXjrslvk42TZpxdY8188oH7L3I27QSTp/X9gqSTqjI6saQlhawLWEa5TsdrvQZDOSHen9dfq7K4FlLyxp1FSfnBlqqRm0tnA6TtOGU+knnSq+0qmYnQrjwTZuFlrBN/jv1u1voAF7OQ4RKjbDyS6yRuGmeQ/Zal/O9m0gsxuyHdWviL8OdISbjdi9soqNS7uBzt/KJkQVdU/o6UORM3iDVHy+7qIMSG7Ub1Yb2nSIRSwSkR7FIeEoFfEcpeHhiMdiP+f4LYo1yjjKOMrXHPMk4RBcu/2UBZzR+VlEliflviyzbJ8lZRpP0wudqOug

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,59 @@
use factorio_core::{pathfield::PathField, prelude::*};
use crate::misc::Beltspeed;
use super::{BlueprintEntity, BlueprintPosition};
pub fn convert_belt_to_blueprint(
belt: &PathField,
speed: &Beltspeed,
nextfree: &mut u32,
) -> impl Iterator<Item = BlueprintEntity> + use<> {
match belt {
PathField::Belt { pos, dir } => {
*nextfree += 1;
vec![
BlueprintEntity::builder(
speed.string(),
*nextfree - 1,
BlueprintPosition::new(pos.x as f64 + 0.5, pos.y as f64 + 0.5),
)
.direction(dir.get_index() * 4)
.build(),
]
.into_iter()
}
PathField::Underground { pos, dir, len } => {
*nextfree += 2;
let endpos = pos.in_direction(dir, *len as PositionType);
vec![
BlueprintEntity::builder(
speed.string_underground(),
*nextfree - 2,
BlueprintPosition::new(pos.x as f64 + 0.5, pos.y as f64 + 0.5),
)
.underground_type("input".to_string())
.direction(dir.get_index() * 4)
.build(),
BlueprintEntity::builder(
speed.string_underground(),
*nextfree - 1,
BlueprintPosition::new(endpos.x as f64 + 0.5, endpos.y as f64 + 0.5),
)
.underground_type("output".to_string())
.direction(dir.get_index() * 4)
.build(),
]
.into_iter()
}
}
}
pub fn convert_to_blueprint<'p, 's, 'n>(
path: &'p [PathField],
speed: &'s Beltspeed,
nextfree: &'n mut u32,
) -> impl Iterator<Item = BlueprintEntity> + use<'p, 's, 'n> {
path.iter()
.flat_map(|b| convert_belt_to_blueprint(b, speed, nextfree))
}

View file

@ -0,0 +1,28 @@
use clap::Parser;
use factorio_blueprint::{decode, encode};
use std::path::PathBuf;
#[derive(Debug, Parser)]
struct Args {
filename: PathBuf,
#[arg(short, long)]
encode: bool,
}
fn main() {
let args = Args::parse();
let s = std::fs::read_to_string(args.filename).unwrap();
if args.encode {
let j: serde_json::Value = serde_json::from_str(&s).unwrap();
let d = encode(&serde_json::to_string(&j).unwrap());
println!("{}", d);
} else {
let d = decode(&s);
let j: serde_json::Value = serde_json::from_str(&d).unwrap();
println!("{}", serde_json::to_string_pretty(&j).unwrap());
}
}

View file

@ -0,0 +1,40 @@
use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use base64::prelude::BASE64_STANDARD;
use std::io::Cursor;
use std::io::Read;
pub mod misc;
pub mod structs;
pub mod belt;
pub use structs::*;
pub fn decode(s: &str) -> String {
let raw = s.trim().as_bytes();
assert!(raw[0] == b'0');
let u = BASE64_STANDARD.decode(&raw[1..]).unwrap();
let mut o = String::new();
flate2::bufread::ZlibDecoder::new(Cursor::new(u))
.read_to_string(&mut o)
.unwrap();
o
}
pub fn encode(s: &str) -> String {
let mut u = Vec::new();
flate2::bufread::ZlibEncoder::new(Cursor::new(s), flate2::Compression::new(9))
.read_to_end(&mut u)
.unwrap();
let mut o = String::from("0");
STANDARD.encode_string(u, &mut o);
o
}

View file

@ -0,0 +1,82 @@
use clap::ValueEnum;
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum Beltspeed {
Normal,
Fast,
Express,
Turbo,
}
impl Beltspeed {
pub fn string(self) -> String {
match self {
Beltspeed::Normal => "transport-belt",
Beltspeed::Fast => "fast-transport-belt",
Beltspeed::Express => "express-transport-belt",
Beltspeed::Turbo => "turbo-transport-belt",
}
.to_owned()
}
pub fn string_underground(self) -> String {
match self {
Beltspeed::Normal => "underground-belt",
Beltspeed::Fast => "fast-underground-belt",
Beltspeed::Express => "express-underground-belt",
Beltspeed::Turbo => "turbo-underground-belt",
}
.to_owned()
}
pub fn string_splitter(self) -> String {
match self {
Beltspeed::Normal => "splitter",
Beltspeed::Fast => "fast-splitter",
Beltspeed::Express => "express-splitter",
Beltspeed::Turbo => "turbo-splitter",
}
.to_owned()
}
pub fn halve(self) -> Self {
match self {
Beltspeed::Normal => Beltspeed::Normal,
Beltspeed::Fast => Beltspeed::Normal,
Beltspeed::Express => Beltspeed::Fast,
Beltspeed::Turbo => Beltspeed::Fast,
}
}
pub fn halvings(self, i: usize) -> Self {
let mut s = self;
for _ in 0..i {
s = s.halve();
}
s
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum Belttype {
Full,
Left,
Right,
}
impl Belttype {
pub fn contains_left(self) -> bool {
match self {
Belttype::Full => true,
Belttype::Left => true,
Belttype::Right => false,
}
}
pub fn contains_right(self) -> bool {
match self {
Belttype::Full => true,
Belttype::Left => false,
Belttype::Right => true,
}
}
}

View file

@ -0,0 +1,303 @@
use std::collections::HashMap;
use bon::Builder;
use serde::Deserialize;
use serde::Serialize;
static VERSION: u64 = calculate_version(2, 0, 19, 173);
const fn calculate_version(major: u16, minor: u16, patch: u16, dev: u16) -> u64 {
((major as u64) << 48) | ((minor as u64) << 32) | ((patch as u64) << 16) | (dev as u64)
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum BlueprintString {
#[serde(rename = "blueprint_book")]
BlueprintBook(BlueprintBook),
#[serde(rename = "blueprint")]
Blueprint(Blueprint),
}
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
pub struct BlueprintBook {
#[builder(skip = "blueprint-book".to_owned())]
item: String,
#[serde(skip_serializing_if = "Option::is_none")]
label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
label_color: Option<BlueprintColor>,
blueprints: Vec<BlueprintBookEntry>,
active_index: i32,
#[builder(skip = VERSION)]
version: u64,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintBookEntry {
#[serde(flatten)]
entry: BlueprintString,
index: u32,
}
impl BlueprintBookEntry {
pub fn new(entry: BlueprintString, index: u32) -> Self {
Self { entry, index }
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
pub struct Blueprint {
#[builder(skip = "blueprint".to_owned())]
item: String,
label: String,
#[serde(skip_serializing_if = "Option::is_none")]
label_color: Option<BlueprintColor>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[builder(default)]
entities: Vec<BlueprintEntity>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[builder(default)]
tiles: Vec<BlueprintTile>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[builder(default)]
icons: Vec<BlueprintIcon>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[builder(default)]
schedules: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[builder(default)]
stock_connections: Vec<BlueprintStockConnection>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
snap_to_grid: Option<BlueprintPosition>,
#[serde(skip_serializing_if = "Option::is_none")]
absolute_snapping: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
position_relative_to_grid: Option<BlueprintPosition>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[builder(default)]
wires: Vec<[u32; 4]>,
#[builder(skip = VERSION)]
version: u64,
}
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
pub struct BlueprintStockConnection {
#[builder(start_fn)]
stock: u32,
#[serde(skip_serializing_if = "Option::is_none")]
front: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
back: Option<u32>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
pub struct BlueprintEntity {
#[builder(start_fn)]
name: String,
#[builder(start_fn)]
pub entity_number: u32,
#[builder(start_fn)]
pub position: BlueprintPosition,
#[serde(skip_serializing_if = "Option::is_none")]
direction: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
orientation: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
connections: Option<BlueprintConnection>,
#[serde(skip_serializing_if = "Option::is_none")]
neighbours: Option<Vec<u64>>,
#[serde(skip_serializing_if = "Option::is_none")]
control_behaviour: Option<()>,
#[serde(skip_serializing_if = "Option::is_none")]
items: Option<Vec<BlueprintItemRequest>>,
#[serde(skip_serializing_if = "Option::is_none")]
recipe: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
bar: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
inventory: Option<BlueprintInventory>,
#[serde(skip_serializing_if = "Option::is_none")]
infinity_settings: Option<()>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
underground_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
input_priority: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
output_priority: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
filter: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
filters: Option<Vec<BlueprintItemFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
filter_mode: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
override_stack_size: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
drop_position: Option<BlueprintPosition>,
#[serde(skip_serializing_if = "Option::is_none")]
pickup_position: Option<BlueprintPosition>,
#[serde(skip_serializing_if = "Option::is_none")]
request_filters: Option<Vec<BlueprintLogisticFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
request_from_buffers: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
parameters: Option<BlueprintSpeakerParameter>,
#[serde(skip_serializing_if = "Option::is_none")]
alert_parameters: Option<BlueprintSpeakerAlertParameter>,
#[serde(skip_serializing_if = "Option::is_none")]
auto_launch: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
variation: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
color: Option<BlueprintColor>,
#[serde(skip_serializing_if = "Option::is_none")]
station: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
manuel_trains_limit: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
switch_state: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
tags: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintItemRequest {
id: BlueprintItemID,
items: BlueprintItem,
}
impl BlueprintItemRequest {
pub fn new(id: BlueprintItemID, items: Vec<BlueprintInventoryLocation>) -> Self {
Self {
id,
items: BlueprintItem {
in_inventory: items,
},
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
pub struct BlueprintItemID {
#[builder(start_fn)]
name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintItem {
in_inventory: Vec<BlueprintInventoryLocation>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintInventoryLocation {
count: u32,
inventory: u32,
stack: u32,
}
impl BlueprintInventoryLocation {
pub fn new(count: u32, inventory: u32, stack: u32) -> Self {
Self {
count,
inventory,
stack,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintInventory {
filters: Vec<BlueprintItemFilter>,
bar: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintConnection {
#[serde(rename = "1")]
first: Option<BlueprintConnectionPoint>,
#[serde(rename = "2")]
second: Option<BlueprintConnectionPoint>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintConnectionPoint {
#[serde(default)]
red: Vec<BlueprintConnectionData>,
#[serde(default)]
green: Vec<BlueprintConnectionData>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub struct BlueprintConnectionData {
entity_id: u64,
circuit_id: Option<u64>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintItemFilter {
name: String,
index: u32,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintLogisticFilter {
name: String,
index: u32,
count: u32,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintSpeakerParameter {
playback_volume: f64,
playback_globally: bool,
allow_polyphony: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintSpeakerAlertParameter {
show_alert: bool,
show_on_map: bool,
icon_signal_id: BlueprintSignalID,
alert_message: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintSignalID {
name: String,
#[serde(rename = "type")]
signal_type: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub struct BlueprintPosition {
pub x: f64,
pub y: f64,
}
impl BlueprintPosition {
pub fn new(x: f64, y: f64) -> Self {
BlueprintPosition { x, y }
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintIcon {
index: u32,
signal: BlueprintSignalID,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintTile {
name: String,
position: BlueprintPosition,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BlueprintColor {
r: f32,
g: f32,
b: f32,
a: f32,
}