refactor(vm): pull generated data into new crate

pregenerate prefab templates -> locked behind crate feature
This commit is contained in:
Rachel Powers
2024-05-19 21:44:15 -07:00
parent b0bdc37a8a
commit 4346bc5302
40 changed files with 59148 additions and 15792 deletions

315
Cargo.lock generated
View File

@@ -119,7 +119,7 @@ checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -130,14 +130,14 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
name = "autocfg"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "backtrace"
@@ -196,9 +196,9 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bumpalo"
version = "3.15.4"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytes"
@@ -228,9 +228,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.90"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
[[package]]
name = "cexpr"
@@ -249,15 +249,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.37"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"serde",
"windows-targets 0.52.4",
"windows-targets 0.52.5",
]
[[package]]
@@ -302,7 +302,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -396,7 +396,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -407,7 +407,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [
"darling_core",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -417,7 +417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
"hashbrown 0.14.3",
"hashbrown 0.14.5",
"lock_api",
"once_cell",
"parking_lot_core",
@@ -536,7 +536,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -602,9 +602,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "heck"
@@ -685,6 +685,7 @@ dependencies = [
"serde_derive",
"serde_json",
"serde_with",
"stationeers_data",
"strum",
"strum_macros",
"thiserror",
@@ -784,15 +785,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
"hashbrown 0.14.5",
"serde",
]
[[package]]
name = "itertools"
version = "0.12.1"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
@@ -837,7 +838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [
"cfg-if",
"windows-targets 0.52.4",
"windows-targets 0.52.5",
]
[[package]]
@@ -848,9 +849,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_api"
version = "0.4.11"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
@@ -933,6 +934,39 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "num"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.1.0"
@@ -940,10 +974,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-traits"
version = "0.2.18"
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
@@ -1011,9 +1076,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "parking_lot"
version = "0.12.1"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -1021,22 +1086,22 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.9"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.48.5",
"windows-targets 0.52.5",
]
[[package]]
name = "paste"
version = "1.0.14"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "peeking_take_while"
@@ -1125,7 +1190,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1163,7 +1228,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1196,6 +1261,16 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "prettyplease"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
dependencies = [
"proc-macro2",
"syn 2.0.64",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.20+deprecated"
@@ -1204,18 +1279,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.79"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
@@ -1252,11 +1327,11 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.4.1"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
dependencies = [
"bitflags 1.3.2",
"bitflags 2.5.0",
]
[[package]]
@@ -1290,9 +1365,9 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
@@ -1321,9 +1396,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
@@ -1333,9 +1408,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.201"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
dependencies = [
"serde_derive",
]
@@ -1364,13 +1439,13 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.201"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1381,7 +1456,7 @@ checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1422,7 +1497,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1452,7 +1527,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1472,9 +1547,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
@@ -1502,14 +1577,25 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.6"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "stationeers_data"
version = "0.2.3"
dependencies = [
"num-integer",
"phf 0.11.2",
"serde",
"serde_derive",
"strum",
]
[[package]]
name = "strsim"
version = "0.10.0"
@@ -1542,7 +1628,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1558,9 +1644,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.57"
version = "2.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35"
checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
dependencies = [
"proc-macro2",
"quote",
@@ -1575,22 +1661,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
[[package]]
name = "thiserror"
version = "1.0.58"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1605,9 +1691,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.34"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
@@ -1629,9 +1715,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.17"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
@@ -1679,7 +1765,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1748,7 +1834,7 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1776,7 +1862,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
@@ -1872,7 +1958,17 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.57",
"syn 2.0.64",
]
[[package]]
name = "uneval"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63cc5d2fd8648d7e2be86098f60c9ece7045cc710b3c1e226910e2f37d11dc73"
dependencies = [
"serde",
"thiserror",
]
[[package]]
@@ -1953,7 +2049,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
"wasm-bindgen-shared",
]
@@ -1988,7 +2084,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.57",
"syn 2.0.64",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -2040,7 +2136,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.4",
"windows-targets 0.52.5",
]
[[package]]
@@ -2058,7 +2154,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.4",
"windows-targets 0.52.5",
]
[[package]]
@@ -2078,17 +2174,18 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm 0.52.4",
"windows_aarch64_msvc 0.52.4",
"windows_i686_gnu 0.52.4",
"windows_i686_msvc 0.52.4",
"windows_x86_64_gnu 0.52.4",
"windows_x86_64_gnullvm 0.52.4",
"windows_x86_64_msvc 0.52.4",
"windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.5",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
]
[[package]]
@@ -2099,9 +2196,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
@@ -2111,9 +2208,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
@@ -2123,9 +2220,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
@@ -2135,9 +2238,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
@@ -2147,9 +2250,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -2159,9 +2262,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
@@ -2171,9 +2274,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "xtask"
@@ -2183,8 +2286,13 @@ dependencies = [
"color-eyre",
"convert_case",
"indexmap 2.2.6",
"num",
"num-integer",
"onig",
"phf_codegen",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"serde",
"serde_derive",
@@ -2192,7 +2300,10 @@ dependencies = [
"serde_json",
"serde_path_to_error",
"serde_with",
"stationeers_data",
"syn 2.0.64",
"textwrap",
"thiserror",
"tracing",
"uneval",
]

View File

@@ -1,5 +1,11 @@
[workspace]
members = ["ic10lsp_wasm", "ic10emu_wasm", "ic10emu", "xtask"]
members = [
"ic10lsp_wasm",
"stationeers_data",
"ic10emu",
"ic10emu_wasm",
"xtask",
]
resolver = "2"
[workspace.package]

File diff suppressed because one or more lines are too long

View File

@@ -10,20 +10,21 @@ crate-type = ["lib", "cdylib"]
[dependencies]
stationeers_data = { path = "../stationeers_data" }
const-crc32 = "1.3.0"
itertools = "0.12.1"
itertools = "0.13.0"
macro_rules_attribute = "0.2.0"
paste = "1.0.14"
paste = "1.0.15"
phf = { version = "0.11.2", features = ["macros"] }
rand = "0.8.5"
regex = "1.10.3"
serde = "1.0.201"
serde_derive = "1.0.201"
serde_with = "3.7.0"
regex = "1.10.4"
serde = "1.0.202"
serde_derive = "1.0.202"
serde_with = "3.8.1"
strum = { version = "0.26.2", features = ["derive", "phf", "strum_macros"] }
strum_macros = "0.26.2"
thiserror = "1.0.58"
time = { version = "0.3.34", features = [
thiserror = "1.0.61"
time = { version = "0.3.36", features = [
"formatting",
"serde",
"local-offset",
@@ -31,7 +32,7 @@ time = { version = "0.3.34", features = [
[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
time = { version = "0.3.34", features = [
time = { version = "0.3.36", features = [
"formatting",
"serde",
"local-offset",

View File

@@ -2,66 +2,20 @@ use crate::{
errors::{ICError, ParseError},
interpreter,
tokens::{SplitConsecutiveIndicesExt, SplitConsecutiveWithIndices},
vm::{
enums::{
basic_enums::BasicEnum,
script_enums::{LogicBatchMethod, LogicReagentMode, LogicSlotType, LogicType},
},
instructions::{
enums::InstructionOp,
operands::{Device, DeviceSpec, Identifier, Number, Operand, RegisterSpec},
Instruction, CONSTANTS_LOOKUP,
},
vm::instructions::{
enums::InstructionOp,
operands::{Device, DeviceSpec, Identifier, Number, Operand, RegisterSpec},
Instruction, CONSTANTS_LOOKUP,
},
};
use itertools::Itertools;
use stationeers_data::enums::{
basic_enums::BasicEnum,
script_enums::{LogicBatchMethod, LogicReagentMode, LogicSlotType, LogicType},
};
use std::{fmt::Display, str::FromStr};
use strum::IntoEnumIterator;
impl TryFrom<f64> for LogicType {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicType as TryFrom<f64>>::Error> {
if let Some(lt) = LogicType::iter().find(|lt| *lt as u16 as f64 == value) {
Ok(lt)
} else {
Err(ICError::UnknownLogicType(value))
}
}
}
impl TryFrom<f64> for LogicSlotType {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicSlotType as TryFrom<f64>>::Error> {
if let Some(slt) = LogicSlotType::iter().find(|lt| *lt as u8 as f64 == value) {
Ok(slt)
} else {
Err(ICError::UnknownLogicSlotType(value))
}
}
}
impl TryFrom<f64> for LogicBatchMethod {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicBatchMethod as TryFrom<f64>>::Error> {
if let Some(bm) = LogicBatchMethod::iter().find(|lt| *lt as u8 as f64 == value) {
Ok(bm)
} else {
Err(ICError::UnknownBatchMode(value))
}
}
}
impl TryFrom<f64> for LogicReagentMode {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicReagentMode as TryFrom<f64>>::Error> {
if let Some(rm) = LogicReagentMode::iter().find(|lt| *lt as u8 as f64 == value) {
Ok(rm)
} else {
Err(ICError::UnknownReagentMode(value))
}
}
}
pub fn parse(code: &str) -> Result<Vec<Line>, ParseError> {
code.lines()
.enumerate()

View File

@@ -2,7 +2,6 @@ use crate::{
errors::ICError,
interpreter::{i64_to_f64, ICState},
vm::{
enums::script_enums::LogicReagentMode,
instructions::{
operands::{InstOperand, RegisterSpec},
traits::*,
@@ -14,6 +13,7 @@ use crate::{
},
},
};
use stationeers_data::enums::script_enums::LogicReagentMode;
pub trait IC10Marker: IntegratedCircuit {}
impl<T: IC10Marker> SleepInstruction for T {

View File

@@ -51,61 +51,6 @@ pub enum Connection {
None,
}
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
Serialize,
Deserialize,
EnumIter,
AsRefStr,
)]
pub enum ConnectionType {
Pipe,
Power,
Data,
Chute,
Elevator,
PipeLiquid,
LandingPad,
LaunchPad,
PowerAndData,
#[serde(other)]
#[default]
None,
}
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
Serialize,
Deserialize,
EnumIter,
AsRefStr,
)]
pub enum ConnectionRole {
Input,
Input2,
Output,
Output2,
Waste,
#[serde(other)]
#[default]
None,
}
impl Connection {
#[allow(dead_code)]

View File

@@ -1,15 +1,18 @@
pub mod enums;
pub mod instructions;
pub mod object;
use crate::{
errors::{ICError, TemplateError, VMError},
interpreter::ICState,
network::{CableConnectionType, CableNetwork, Connection, ConnectionRole, FrozenCableNetwork},
vm::{
enums::script_enums::{LogicBatchMethod, LogicSlotType, LogicType},
object::{templates::ObjectTemplate, traits::ParentSlotInfo, ObjectID, VMObject},
network::{CableConnectionType, CableNetwork, Connection, FrozenCableNetwork},
vm::object::{traits::ParentSlotInfo, ObjectID, VMObject},
};
use stationeers_data::{
enums::{
script_enums::{LogicBatchMethod, LogicSlotType, LogicType},
ConnectionRole,
},
templates::ObjectTemplate,
};
use std::{
cell::RefCell,
@@ -690,7 +693,7 @@ impl VM {
})
.filter_ok(|val| !val.is_nan())
.collect::<Result<Vec<_>, ICError>>()?;
Ok(mode.apply(&samples))
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
pub fn get_batch_name_device_field(
@@ -713,7 +716,7 @@ impl VM {
})
.filter_ok(|val| !val.is_nan())
.collect::<Result<Vec<_>, ICError>>()?;
Ok(mode.apply(&samples))
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
pub fn get_batch_name_device_slot_field(
@@ -737,7 +740,7 @@ impl VM {
})
.filter_ok(|val| !val.is_nan())
.collect::<Result<Vec<_>, ICError>>()?;
Ok(mode.apply(&samples))
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
pub fn get_batch_device_slot_field(
@@ -760,7 +763,7 @@ impl VM {
})
.filter_ok(|val| !val.is_nan())
.collect::<Result<Vec<_>, ICError>>()?;
Ok(mode.apply(&samples))
Ok(LogicBatchMethodWrapper(mode).apply(&samples))
}
pub fn remove_object(self: &Rc<Self>, id: ObjectID) -> Result<(), VMError> {
@@ -771,7 +774,7 @@ impl VM {
if let Some(device) = obj.borrow().as_device() {
for conn in device.connection_list().iter() {
if let Connection::CableNetwork { net: Some(net), .. } = conn {
if let Some(network) = self.networks.borrow().get(net) {
if let Some(network) = self.networks.borrow().get(&net) {
network
.borrow_mut()
.as_mut_network()
@@ -1067,7 +1070,7 @@ impl VMTransaction {
role: ConnectionRole::None,
} = conn
{
if let Some(net) = self.networks.get_mut(net_id) {
if let Some(net) = self.networks.get_mut(&net_id) {
match typ {
CableConnectionType::Power => net.power_only.push(obj_id),
_ => net.devices.push(obj_id),
@@ -1085,9 +1088,11 @@ impl VMTransaction {
}
}
impl LogicBatchMethod {
pub struct LogicBatchMethodWrapper(LogicBatchMethod);
impl LogicBatchMethodWrapper {
pub fn apply(&self, samples: &[f64]) -> f64 {
match self {
match self.0 {
LogicBatchMethod::Sum => samples.iter().sum(),
// Both c-charp and rust return NaN for 0.0/0.0 so we're good here
LogicBatchMethod::Average => {

View File

@@ -1,3 +0,0 @@
pub mod basic_enums;
pub mod prefabs;
pub mod script_enums;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,10 @@
use crate::errors::ICError;
use crate::interpreter;
use crate::vm::{
enums::script_enums::{
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType, LogicType,
},
instructions::enums::InstructionOp,
object::traits::IntegratedCircuit,
};
use crate::vm::{instructions::enums::InstructionOp, object::traits::IntegratedCircuit};
use serde_derive::{Deserialize, Serialize};
use stationeers_data::enums::script_enums::{
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType, LogicType,
};
use strum::EnumProperty;
#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize)]
@@ -249,7 +246,10 @@ impl InstOperand {
logic_type: Some(lt),
..
} => Ok(*lt),
_ => LogicType::try_from(self.as_value(ic)?),
_ => {
let val = self.as_value(ic)?;
LogicType::try_from(val).map_err(|| ICError::UnknownLogicType(val))
}
}
}
@@ -262,7 +262,10 @@ impl InstOperand {
slot_logic_type: Some(slt),
..
} => Ok(*slt),
_ => LogicSlotType::try_from(self.as_value(ic)?),
_ => {
let val = self.as_value(ic)?;
LogicSlotType::try_from(val).map_err(|| ICError::UnknownLogicSlotType(val))
}
}
}
@@ -272,7 +275,10 @@ impl InstOperand {
batch_mode: Some(bm),
..
} => Ok(*bm),
_ => BatchMode::try_from(self.as_value(ic)?),
_ => {
let val = self.as_value(ic)?;
BatchMode::try_from(val).map_err(|| ICError::UnknownBatchMode(val))
}
}
}
@@ -282,7 +288,10 @@ impl InstOperand {
reagent_mode: Some(rm),
..
} => Ok(*rm),
_ => ReagentMode::try_from(self.as_value(ic)?),
_ => {
let val = self.as_value(ic)?;
ReagentMode::try_from(val).map_err(|| ICError::UnknownReagentMode(val))
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@ use std::{
cell::RefCell,
ops::{Deref, DerefMut},
rc::Rc,
str::FromStr,
};
use macro_rules_attribute::derive;
@@ -17,12 +16,12 @@ pub mod traits;
use traits::Object;
use crate::vm::{
enums::{basic_enums::Class as SlotClass, script_enums::LogicSlotType},
VM,
};
use crate::vm::VM;
use super::enums::prefabs::StationpediaPrefab;
use stationeers_data::enums::{
basic_enums::Class as SlotClass, prefabs::StationpediaPrefab, script_enums::LogicSlotType,
MemoryAccess,
};
pub type ObjectID = u32;
pub type BoxedObject = Rc<RefCell<dyn Object>>;
@@ -97,13 +96,6 @@ impl Name {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum MemoryAccess {
Read,
Write,
ReadWrite,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogicField {
pub field_type: MemoryAccess,

View File

@@ -1,7 +1,7 @@
use serde_derive::{Deserialize, Serialize};
use thiserror::Error;
use crate::vm::enums::script_enums::{LogicSlotType, LogicType};
use stationeers_data::enums::script_enums::{LogicSlotType, LogicType};
#[derive(Error, Debug, Clone, Serialize, Deserialize)]
pub enum LogicError {

View File

@@ -3,17 +3,15 @@ use super::{macros::*, traits::*};
use crate::{
network::Connection,
vm::{
enums::script_enums::LogicType,
object::{
macros::ObjectInterface,
templates::{DeviceInfo, ItemInfo},
traits::*,
LogicField, Name, ObjectID, Slot,
},
object::{macros::ObjectInterface, traits::*, LogicField, Name, ObjectID, Slot},
VM,
},
};
use macro_rules_attribute::derive;
use stationeers_data::{
enums::script_enums::LogicType,
templates::{DeviceInfo, ItemInfo},
};
use std::{collections::BTreeMap, rc::Rc};
#[derive(ObjectInterface!, GWStructure!)]

View File

@@ -1,18 +1,19 @@
use crate::{
network::Connection,
vm::{
enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
},
object::{
errors::{LogicError, MemoryError},
templates::{DeviceInfo, ItemInfo},
traits::*,
LogicField, MemoryAccess, ObjectID, Slot,
},
vm::object::{
errors::{LogicError, MemoryError},
traits::*,
LogicField, MemoryAccess, ObjectID, Slot,
},
};
use stationeers_data::{
enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
},
templates::{DeviceInfo, ItemInfo},
};
use std::{collections::BTreeMap, usize};
use strum::IntoEnumIterator;

View File

@@ -1,9 +1,10 @@
use std::rc::Rc;
use crate::vm::object::VMObject;
use crate::vm::{enums::prefabs::StationpediaPrefab, VM};
use stationeers_data::{enums::prefabs::StationpediaPrefab, templates::ObjectTemplate};
use crate::vm::object::VMObject;
use crate::vm::VM;
use super::templates::ObjectTemplate;
use super::ObjectID;
pub mod structs;

View File

@@ -1,11 +1,6 @@
use crate::{
network::{CableConnectionType, Connection, ConnectionRole},
network::{CableConnectionType, Connection},
vm::{
enums::{
basic_enums::Class as SlotClass,
prefabs::StationpediaPrefab,
script_enums::{LogicSlotType, LogicType},
},
object::{
errors::LogicError, macros::ObjectInterface, traits::*, Name, ObjectID, Slot, VMObject,
},
@@ -13,6 +8,12 @@ use crate::{
},
};
use macro_rules_attribute::derive;
use stationeers_data::enums::{
basic_enums::Class as SlotClass,
prefabs::StationpediaPrefab,
script_enums::{LogicSlotType, LogicType},
ConnectionRole,
};
use std::rc::Rc;
use strum::EnumProperty;

View File

@@ -2,10 +2,6 @@ use crate::{
errors::ICError,
interpreter::{instructions::IC10Marker, ICState, Program},
vm::{
enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
},
instructions::{operands::Operand, Instruction},
object::{
errors::{LogicError, MemoryError},
@@ -17,6 +13,10 @@ use crate::{
},
};
use macro_rules_attribute::derive;
use stationeers_data::enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
};
use std::{collections::BTreeMap, rc::Rc};
static RETURN_ADDRESS_INDEX: usize = 17;

View File

@@ -2,13 +2,8 @@ use std::{collections::BTreeMap, rc::Rc};
use crate::{
errors::TemplateError,
network::{Connection, ConnectionRole, ConnectionType},
network::Connection,
vm::{
enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
prefabs::StationpediaPrefab,
script_enums::{LogicSlotType, LogicType},
},
object::{
generic::structs::{
Generic, GenericItem, GenericItemLogicable,
@@ -24,56 +19,48 @@ use crate::{
},
};
use serde_derive::{Deserialize, Serialize};
use stationeers_data::{
enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
prefabs::StationpediaPrefab,
script_enums::{LogicSlotType, LogicType},
ConnectionRole, ConnectionType,
},
templates::*,
};
use strum::{EnumProperty, IntoEnumIterator};
use super::{stationpedia, MemoryAccess, ObjectID, VMObject};
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ObjectTemplate {
Structure(StructureTemplate),
StructureSlots(StructureSlotsTemplate),
StructureLogic(StructureLogicTemplate),
StructureLogicDevice(StructureLogicDeviceTemplate),
StructureLogicDeviceMemory(StructureLogicDeviceMemoryTemplate),
Item(ItemTemplate),
ItemSlots(ItemSlotsTemplate),
ItemLogic(ItemLogicTemplate),
ItemLogicMemory(ItemLogicMemoryTemplate),
#[serde(rename_all = "camelCase")]
pub struct ObjectInfo {
pub name: Option<String>,
pub id: Option<ObjectID>,
}
impl ObjectTemplate {
pub fn prefab_info(&self) -> &PrefabInfo {
use ObjectTemplate::*;
match self {
Structure(s) => &s.prefab,
StructureSlots(s) => &s.prefab,
StructureLogic(s) => &s.prefab,
StructureLogicDevice(s) => &s.prefab,
StructureLogicDeviceMemory(s) => &s.prefab,
Item(i) => &i.prefab,
ItemSlots(i) => &i.prefab,
ItemLogic(i) => &i.prefab,
ItemLogicMemory(i) => &i.prefab,
impl From<&VMObject> for ObjectInfo {
fn from(obj: &VMObject) -> Self {
let obj_ref = obj.borrow();
ObjectInfo {
name: Some(obj_ref.get_name().value.clone()),
id: Some(*obj_ref.get_id()),
}
}
}
pub fn object_info(&self) -> Option<&ObjectInfo> {
use ObjectTemplate::*;
match self {
Structure(s) => s.object.as_ref(),
StructureSlots(s) => s.object.as_ref(),
StructureLogic(s) => s.object.as_ref(),
StructureLogicDevice(s) => s.object.as_ref(),
StructureLogicDeviceMemory(s) => s.object.as_ref(),
Item(i) => i.object.as_ref(),
ItemSlots(i) => i.object.as_ref(),
ItemLogic(i) => i.object.as_ref(),
ItemLogicMemory(i) => i.object.as_ref(),
}
}
pub struct FrozenObjectTemplate {
obj_info: ObjectInfo,
template: ObjectTemplate,
}
pub fn build(&self, id: ObjectID, vm: &Rc<VM>) -> VMObject {
pub struct FrozenObject {
obj_info: ObjectInfo,
template: Option<ObjectTemplate>,
}
impl FrozenObjectTemplate {
pub fn build_vm_obj(&self, id: ObjectID, vm: &Rc<VM>) -> VMObject {
if let Some(obj) = stationpedia::object_from_prefab_template(self, id, vm) {
obj
} else {
@@ -83,7 +70,7 @@ impl ObjectTemplate {
pub fn connected_networks(&self) -> Vec<ObjectID> {
use ObjectTemplate::*;
match self {
match self.template {
StructureLogicDevice(s) => s
.device
.connection_list
@@ -104,7 +91,7 @@ impl ObjectTemplate {
pub fn contained_object_ids(&self) -> Vec<ObjectID> {
use ObjectTemplate::*;
match self {
match self.template {
StructureSlots(s) => s
.slots
.iter()
@@ -181,7 +168,7 @@ impl ObjectTemplate {
pub fn templates_from_slots(&self) -> Vec<Option<ObjectTemplate>> {
use ObjectTemplate::*;
match self {
match self.template {
StructureSlots(s) => s.slots.iter().map(|info| info.occupant.clone()).collect(),
StructureLogic(s) => s.slots.iter().map(|info| info.occupant.clone()).collect(),
StructureLogicDevice(s) => s.slots.iter().map(|info| info.occupant.clone()).collect(),
@@ -197,7 +184,7 @@ impl ObjectTemplate {
fn build_generic(&self, id: ObjectID, vm: Rc<VM>) -> VMObject {
use ObjectTemplate::*;
match self {
match self.template {
Structure(s) => VMObject::new(Generic {
id,
prefab: Name::from_prefab_name(&s.prefab.prefab_name),
@@ -1193,15 +1180,6 @@ fn freeze_storage(storage: StorageRef<'_>, vm: &Rc<VM>) -> Result<Vec<SlotInfo>,
Ok(slots)
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PrefabInfo {
pub prefab_name: String,
pub prefab_hash: i32,
pub desc: String,
pub name: String,
}
impl From<&VMObject> for PrefabInfo {
fn from(obj: &VMObject) -> Self {
let obj_ref = obj.borrow();
@@ -1221,61 +1199,6 @@ impl From<&VMObject> for PrefabInfo {
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ObjectInfo {
pub name: Option<String>,
pub id: Option<ObjectID>,
}
impl From<&VMObject> for ObjectInfo {
fn from(obj: &VMObject) -> Self {
let obj_ref = obj.borrow();
ObjectInfo {
name: Some(obj_ref.get_name().value.clone()),
id: Some(*obj_ref.get_id()),
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SlotInfo {
pub name: String,
pub typ: SlotClass,
#[serde(skip_serializing_if = "Option::is_none")]
pub occupant: Option<ObjectTemplate>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<u32>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct LogicSlotTypes {
#[serde(flatten)]
pub slot_types: BTreeMap<LogicSlotType, MemoryAccess>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct LogicTypes {
#[serde(flatten)]
pub types: BTreeMap<LogicType, MemoryAccess>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LogicInfo {
pub logic_slot_types: BTreeMap<u32, LogicSlotTypes>,
pub logic_types: LogicTypes,
#[serde(skip_serializing_if = "Option::is_none")]
pub modes: Option<BTreeMap<u32, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub logic_values: Option<BTreeMap<LogicType, f64>>,
pub transmission_receiver: bool,
pub wireless_logic: bool,
pub circuit_holder: bool,
}
impl From<LogicableRef<'_>> for LogicInfo {
fn from(logic: LogicableRef) -> Self {
// Logicable: Storage -> !None
@@ -1350,22 +1273,6 @@ impl From<LogicableRef<'_>> for LogicInfo {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemInfo {
pub consumable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub filter_type: Option<GasType>,
pub ingredient: bool,
pub max_quantity: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub reagents: Option<BTreeMap<String, f64>>,
pub slot_class: SlotClass,
pub sorting_class: SortingClass,
#[serde(skip_serializing_if = "Option::is_none")]
pub damage: Option<f32>,
}
impl From<ItemRef<'_>> for ItemInfo {
fn from(item: ItemRef<'_>) -> Self {
ItemInfo {
@@ -1385,35 +1292,6 @@ impl From<ItemRef<'_>> for ItemInfo {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConnectionInfo {
pub typ: ConnectionType,
pub role: ConnectionRole,
#[serde(skip_serializing_if = "Option::is_none")]
pub network: Option<ObjectID>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DeviceInfo {
pub connection_list: Vec<ConnectionInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_pins_length: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_pins: Option<Vec<Option<ObjectID>>>,
pub has_activate_state: bool,
pub has_atmosphere: bool,
pub has_color_state: bool,
pub has_lock_state: bool,
pub has_mode_state: bool,
pub has_on_off_state: bool,
pub has_open_state: bool,
pub has_reagents: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub reagents: Option<BTreeMap<i32, f64>>,
}
impl From<DeviceRef<'_>> for DeviceInfo {
fn from(device: DeviceRef) -> Self {
let reagents: BTreeMap<i32, f64> = device.get_reagents().iter().copied().collect();
@@ -1442,12 +1320,6 @@ impl From<DeviceRef<'_>> for DeviceInfo {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureInfo {
pub small_grid: bool,
}
impl From<StructureRef<'_>> for StructureInfo {
fn from(value: StructureRef) -> Self {
StructureInfo {
@@ -1455,26 +1327,6 @@ impl From<StructureRef<'_>> for StructureInfo {
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Instruction {
pub description: String,
pub typ: String,
pub value: i64,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MemoryInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<BTreeMap<String, Instruction>>,
pub memory_access: MemoryAccess,
pub memory_size: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub values: Option<Vec<f64>>,
}
impl From<MemoryReadableRef<'_>> for MemoryInfo {
fn from(mem_r: MemoryReadableRef<'_>) -> Self {
let mem_w = mem_r.as_memory_writable();
@@ -1491,103 +1343,6 @@ impl From<MemoryReadableRef<'_>> for MemoryInfo {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureSlotsTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceMemoryTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
pub memory: MemoryInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSlotsTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicMemoryTemplate {
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<ObjectInfo>,
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub memory: MemoryInfo,
}
#[cfg(test)]
mod tests {

View File

@@ -5,10 +5,6 @@ use crate::{
interpreter::ICState,
network::Connection,
vm::{
enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
},
instructions::{traits::ICInstructable, Instruction},
object::{
errors::{LogicError, MemoryError},
@@ -17,6 +13,10 @@ use crate::{
},
},
};
use stationeers_data::enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
};
use std::{collections::BTreeMap, fmt::Debug};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]

View File

@@ -9,22 +9,22 @@ ic10emu = { path = "../ic10emu" }
console_error_panic_hook = {version = "0.1.7", optional = true}
js-sys = "0.3.69"
web-sys = { version = "0.3.69", features = ["WritableStream", "console"] }
wasm-bindgen = "0.2.81"
wasm-bindgen-futures = { version = "0.4.30", features = [
wasm-bindgen = "0.2.92"
wasm-bindgen-futures = { version = "0.4.42", features = [
"futures-core-03-stream",
] }
wasm-streams = "0.4"
serde-wasm-bindgen = "0.6.5"
itertools = "0.12.1"
serde = { version = "1.0.197", features = ["derive"] }
serde_with = "3.7.0"
itertools = "0.13.0"
serde = { version = "1.0.202", features = ["derive"] }
serde_with = "3.8.1"
tsify = { version = "0.4.5", default-features = false, features = ["js", "wasm-bindgen"] }
thiserror = "1.0.58"
thiserror = "1.0.61"
[build-dependencies]
ic10emu = { path = "../ic10emu" }
strum = { version = "0.26.2"}
itertools = "0.12.1"
itertools = "0.13.0"
[features]
default = ["console_error_panic_hook"]

View File

@@ -11,16 +11,16 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
console_error_panic_hook = "0.1.7"
futures = "0.3.21"
futures = "0.3.30"
js-sys = "0.3.69"
web-sys = { version = "0.3.69", features = ["WritableStream", "console"] }
tokio = { version = "1.26.0", features = ["sync"] }
tokio = { version = "1.37.0", features = ["sync"] }
tower-lsp = { version = "0.20.0", default-features = false, features = [
"runtime-agnostic",
] }
# tree-sitter = { version = "0.9.0", package = "tree-sitter-facade" }
wasm-bindgen = "0.2.81"
wasm-bindgen-futures = { version = "0.4.30", features = [
wasm-bindgen = "0.2.92"
wasm-bindgen-futures = { version = "0.4.42", features = [
"futures-core-03-stream",
] }
wasm-streams = "0.4"

View File

@@ -1,3 +1,5 @@
{
"rust-analyzer.cargo.target": "wasm32-unknown-unknown"
"rust-analyzer.cargo.target": "wasm32-unknown-unknown",
"rust-analyzer.cargo.features": [
]
}

View File

@@ -0,0 +1,16 @@
[package]
name = "stationeers_data"
version.workspace = true
edition.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
prefab_database = [] # compile with the prefab database enabled
[dependencies]
num-integer = "0.1.46"
phf = "0.11.2"
serde = "1.0.202"
serde_derive = "1.0.202"
strum = { version = "0.26.2", features = ["derive", "phf", "strum_macros"] }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

108
stationeers_data/src/lib.rs Normal file
View File

@@ -0,0 +1,108 @@
use std::collections::BTreeMap;
pub mod templates;
pub mod enums {
use serde_derive::{Deserialize, Serialize};
use std::fmt::Display;
use strum::{AsRefStr, EnumIter, EnumString};
pub mod basic_enums;
pub mod script_enums;
pub mod prefabs;
#[derive(Debug)]
pub struct ParseError {
pub enm: String,
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Unknown enum '{}'", self.enm)
}
}
impl std::error::Error for ParseError {}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumString,
)]
pub enum MemoryAccess {
Read,
Write,
ReadWrite,
}
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
Serialize,
Deserialize,
EnumIter,
AsRefStr,
EnumString,
)]
pub enum ConnectionType {
Pipe,
Power,
Data,
Chute,
Elevator,
PipeLiquid,
LandingPad,
LaunchPad,
PowerAndData,
#[serde(other)]
#[default]
None,
}
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
PartialOrd,
Eq,
Ord,
Hash,
Serialize,
Deserialize,
EnumIter,
AsRefStr,
EnumString,
)]
pub enum ConnectionRole {
Input,
Input2,
Output,
Output2,
Waste,
#[serde(other)]
#[default]
None,
}
}
#[must_use]
pub fn build_prefab_database() -> Option<BTreeMap<i32, templates::ObjectTemplate>> {
#[cfg(feature = "prefab_database")]
let _map = Some(database::build_prefab_database());
#[cfg(not(feature = "prefab_database"))]
let _map = None;
_map
}
#[cfg(feature = "prefab_database")]
pub mod database {
mod prefab_map;
pub use prefab_map::build_prefab_database;
}

View File

@@ -0,0 +1,237 @@
use std::collections::BTreeMap;
use crate::enums::{
basic_enums::{Class as SlotClass, GasType, SortingClass},
script_enums::{LogicSlotType, LogicType},
ConnectionRole, ConnectionType, MemoryAccess,
};
use serde_derive::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ObjectTemplate {
Structure(StructureTemplate),
StructureSlots(StructureSlotsTemplate),
StructureLogic(StructureLogicTemplate),
StructureLogicDevice(StructureLogicDeviceTemplate),
StructureLogicDeviceMemory(StructureLogicDeviceMemoryTemplate),
Item(ItemTemplate),
ItemSlots(ItemSlotsTemplate),
ItemLogic(ItemLogicTemplate),
ItemLogicMemory(ItemLogicMemoryTemplate),
}
#[allow(dead_code)]
impl ObjectTemplate {
pub fn prefab(&self) -> &PrefabInfo {
use ObjectTemplate::*;
match self {
Structure(s) => &s.prefab,
StructureSlots(s) => &s.prefab,
StructureLogic(s) => &s.prefab,
StructureLogicDevice(s) => &s.prefab,
StructureLogicDeviceMemory(s) => &s.prefab,
Item(i) => &i.prefab,
ItemSlots(i) => &i.prefab,
ItemLogic(i) => &i.prefab,
ItemLogicMemory(i) => &i.prefab,
}
}
}
impl From<StructureTemplate> for ObjectTemplate {
fn from(value: StructureTemplate) -> Self {
Self::Structure(value)
}
}
impl From<StructureSlotsTemplate> for ObjectTemplate {
fn from(value: StructureSlotsTemplate) -> Self {
Self::StructureSlots(value)
}
}
impl From<StructureLogicTemplate> for ObjectTemplate {
fn from(value: StructureLogicTemplate) -> Self {
Self::StructureLogic(value)
}
}
impl From<StructureLogicDeviceTemplate> for ObjectTemplate {
fn from(value: StructureLogicDeviceTemplate) -> Self {
Self::StructureLogicDevice(value)
}
}
impl From<StructureLogicDeviceMemoryTemplate> for ObjectTemplate {
fn from(value: StructureLogicDeviceMemoryTemplate) -> Self {
Self::StructureLogicDeviceMemory(value)
}
}
impl From<ItemTemplate> for ObjectTemplate {
fn from(value: ItemTemplate) -> Self {
Self::Item(value)
}
}
impl From<ItemSlotsTemplate> for ObjectTemplate {
fn from(value: ItemSlotsTemplate) -> Self {
Self::ItemSlots(value)
}
}
impl From<ItemLogicTemplate> for ObjectTemplate {
fn from(value: ItemLogicTemplate) -> Self {
Self::ItemLogic(value)
}
}
impl From<ItemLogicMemoryTemplate> for ObjectTemplate {
fn from(value: ItemLogicMemoryTemplate) -> Self {
Self::ItemLogicMemory(value)
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct PrefabInfo {
pub prefab_name: String,
pub prefab_hash: i32,
pub desc: String,
pub name: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct SlotInfo {
pub name: String,
pub typ: SlotClass,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct LogicInfo {
pub logic_slot_types: BTreeMap<u32, BTreeMap<LogicSlotType, MemoryAccess>>,
pub logic_types: BTreeMap<LogicType, MemoryAccess>,
pub modes: Option<BTreeMap<u32, String>>,
pub transmission_receiver: bool,
pub wireless_logic: bool,
pub circuit_holder: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ItemInfo {
pub consumable: bool,
pub filter_type: Option<GasType>,
pub ingredient: bool,
pub max_quantity: u32,
pub reagents: Option<BTreeMap<String, f64>>,
pub slot_class: SlotClass,
pub sorting_class: SortingClass,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct ConnectionInfo {
pub typ: ConnectionType,
pub role: ConnectionRole,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct DeviceInfo {
pub connection_list: Vec<ConnectionInfo>,
pub device_pins_length: Option<u32>,
pub has_activate_state: bool,
pub has_atmosphere: bool,
pub has_color_state: bool,
pub has_lock_state: bool,
pub has_mode_state: bool,
pub has_on_off_state: bool,
pub has_open_state: bool,
pub has_reagents: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct StructureInfo {
pub small_grid: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct Instruction {
pub description: String,
pub typ: String,
pub value: i64,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct MemoryInfo {
pub instructions: Option<BTreeMap<String, Instruction>>,
pub memory_access: MemoryAccess,
pub memory_size: u32,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct StructureTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct StructureSlotsTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct StructureLogicTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct StructureLogicDeviceTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct StructureLogicDeviceMemoryTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
pub memory: MemoryInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ItemTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ItemSlotsTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ItemLogicTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ItemLogicMemoryTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub memory: MemoryInfo,
}

View File

@@ -4,6 +4,7 @@ version.workspace = true
edition.workspace = true
[dependencies]
stationeers_data = { path = "../stationeers_data" }
clap = { version = "4.5.4", features = ["derive", "env"] }
color-eyre = "0.6.3"
convert_case = "0.6.0"
@@ -11,15 +12,21 @@ indexmap = { version = "2.2.6", features = ["serde"] }
# onig = "6.4.0"
phf_codegen = "0.11.2"
regex = "1.10.4"
serde = "1.0.200"
serde_derive = "1.0.200"
serde = "1.0.202"
serde_derive = "1.0.202"
serde_ignored = "0.1.10"
serde_json = "1.0.116"
serde_json = "1.0.117"
serde_path_to_error = "0.1.16"
serde_with = "3.8.1"
textwrap = { version = "0.16.1", default-features = false }
thiserror = "1.0.58"
thiserror = "1.0.61"
onig = { git = "https://github.com/rust-onig/rust-onig", revision = "fa90c0e97e90a056af89f183b23cd417b59ee6a2" }
tracing = "0.1.40"
quote = "1.0.36"
prettyplease = "0.2.20"
syn = "2.0.64"
proc-macro2 = "1.0.82"
num-integer = "0.1.46"
num = "0.4.3"
uneval = "0.2.4"

View File

@@ -1,6 +1,7 @@
use color_eyre::eyre;
use quote::ToTokens;
use std::{collections::BTreeMap, process::Command};
use std::collections::BTreeMap;
use crate::{enums::Enums, stationpedia::Stationpedia};
@@ -12,6 +13,7 @@ mod utils;
pub fn generate(
stationpedia_path: &std::path::Path,
workspace: &std::path::Path,
modules: &[&str],
) -> color_eyre::Result<()> {
let mut pedia: Stationpedia = parse_json(&mut serde_json::Deserializer::from_reader(
std::io::BufReader::new(std::fs::File::open(
@@ -37,21 +39,41 @@ pub fn generate(
std::io::BufReader::new(std::fs::File::open(stationpedia_path.join("Enums.json"))?),
))?;
database::generate_database(&pedia, &enums, workspace)?;
let enums_files = enums::generate_enums(&pedia, &enums, workspace)?;
let inst_files = instructions::generate_instructions(&pedia, workspace)?;
let mut generated_files = Vec::new();
if modules.contains(&"enums") {
if modules.len() > 1 {
eprintln!(
"generating enums alone, recompile the xtask and run again with other modules."
)
} else {
eprintln!("generating enums...");
}
let generated_files = [enums_files.as_slice(), inst_files.as_slice()].concat();
let enums_files = enums::generate_enums(&pedia, &enums, workspace)?;
eprintln!("Formatting generated files...");
for file in &enums_files {
prepend_generated_comment_and_format(file)?;
}
return Ok(());
}
if modules.contains(&"database") {
eprintln!("generating database...");
let database_files = database::generate_database(&pedia, &enums, workspace)?;
generated_files.extend(database_files);
}
if modules.contains(&"instructions") {
eprintln!("generating instructions...");
let inst_files = instructions::generate_instructions(&pedia, workspace)?;
generated_files.extend(inst_files);
}
eprintln!("Formatting generated files...");
for file in &generated_files {
prepend_generated_comment(file)?;
prepend_generated_comment_and_format(file)?;
}
let mut cmd = Command::new("cargo");
cmd.current_dir(workspace);
cmd.arg("fmt").arg("--");
cmd.args(&generated_files);
cmd.status()?;
Ok(())
}
@@ -71,29 +93,34 @@ pub fn parse_json<'a, T: serde::Deserialize<'a>>(
})
}
fn prepend_generated_comment(file_path: &std::path::Path) -> color_eyre::Result<()> {
fn format_rust(content: impl ToTokens) -> color_eyre::Result<String> {
let content = syn::parse2(content.to_token_stream())?;
Ok(prettyplease::unparse(&content))
}
fn prepend_generated_comment_and_format(file_path: &std::path::Path) -> color_eyre::Result<()> {
use std::io::Write;
let tmp_path = file_path.with_extension("rs.tmp");
{
let mut tmp = std::fs::File::create(&tmp_path)?;
let mut src = std::fs::File::open(file_path)?;
write!(
&mut tmp,
"// ================================================= \n\
// !! <-----> DO NOT MODIFY <-----> !! \n\
// \n\
// This module was automatically generated by an
// xtask \n\
// \n\
// run `cargo xtask generate` from the workspace \n\
// to regenerate \n\
// \n\
// ================================================= \n\
\n\
\n\
"
)?;
std::io::copy(&mut src, &mut tmp)?;
let src = syn::parse_file(&std::fs::read_to_string(file_path)?)?;
let formated = format_rust(quote::quote! {
// =================================================
// !! <-----> DO NOT MODIFY <-----> !!
//
// This module was automatically generated by an
// xtask
//
// run `cargo xtask generate` from the workspace
// to regenerate
//
// =================================================
#src
})?;
write!(&mut tmp, "{formated}")?;
}
std::fs::remove_file(file_path)?;
std::fs::rename(&tmp_path, file_path)?;

View File

@@ -1,5 +1,10 @@
use std::{collections::BTreeMap, io::Write};
use std::{
collections::BTreeMap,
io::{BufWriter, Write},
path::PathBuf,
};
use quote::quote;
use serde_derive::{Deserialize, Serialize};
use crate::{
@@ -7,11 +12,18 @@ use crate::{
stationpedia::{self, Page, Stationpedia},
};
use stationeers_data::templates::{
ConnectionInfo, DeviceInfo, Instruction, ItemInfo, ItemLogicMemoryTemplate, ItemLogicTemplate,
ItemSlotsTemplate, ItemTemplate, LogicInfo, MemoryInfo, ObjectTemplate, PrefabInfo, SlotInfo,
StructureInfo, StructureLogicDeviceMemoryTemplate, StructureLogicDeviceTemplate,
StructureLogicTemplate, StructureSlotsTemplate, StructureTemplate,
};
pub fn generate_database(
stationpedia: &stationpedia::Stationpedia,
enums: &enums::Enums,
workspace: &std::path::Path,
) -> color_eyre::Result<()> {
) -> color_eyre::Result<Vec<PathBuf>> {
let templates = generate_templates(stationpedia)?;
eprintln!("Writing prefab database ...");
@@ -104,6 +116,58 @@ pub fn generate_database(
let mut database_file = std::io::BufWriter::new(std::fs::File::create(database_path)?);
serde_json::to_writer(&mut database_file, &db)?;
database_file.flush()?;
let prefab_map_path = workspace
.join("stationeers_data")
.join("src")
.join("database")
.join("prefab_map.rs");
let mut prefab_map_file = std::io::BufWriter::new(std::fs::File::create(&prefab_map_path)?);
write_prefab_map(&mut prefab_map_file, &db.prefabs)?;
Ok(vec![prefab_map_path])
}
fn write_prefab_map<T: std::io::Write>(
writer: &mut BufWriter<T>,
prefabs: &BTreeMap<String, ObjectTemplate>,
) -> color_eyre::Result<()> {
write!(
writer,
"{}",
quote! {
use crate::enums::script_enums::*;
use crate::enums::basic_enums::*;
use crate::enums::{MemoryAccess, ConnectionType, ConnectionRole};
use crate::templates::*;
}
)?;
let entries = prefabs
.values()
.map(|prefab| {
let hash = prefab.prefab().prefab_hash;
let obj = syn::parse_str::<syn::Expr>(&uneval::to_string(prefab)?)?;
let entry = quote! {
(
#hash,
#obj.into(),
)
};
Ok(entry)
})
.collect::<Result<Vec<_>, color_eyre::Report>>()?;
write!(
writer,
"{}",
quote! {
pub fn build_prefab_database() -> std::collections::BTreeMap<i32, crate::templates::ObjectTemplate> {
#[allow(clippy::unreadable_literal)]
std::collections::BTreeMap::from([
#(#entries),*
])
}
},
)?;
Ok(())
}
@@ -360,7 +424,10 @@ fn slot_inserts_to_info(slots: &[stationpedia::SlotInsert]) -> Vec<SlotInfo> {
tmp.iter()
.map(|slot| SlotInfo {
name: slot.slot_name.clone(),
typ: slot.slot_type.clone(),
typ: slot
.slot_type
.parse()
.unwrap_or_else(|err| panic!("faild to parse slot class: {err}")),
})
.collect()
}
@@ -386,73 +453,45 @@ pub struct ObjectDatabase {
pub logicable_items: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ObjectTemplate {
Structure(StructureTemplate),
StructureSlots(StructureSlotsTemplate),
StructureLogic(StructureLogicTemplate),
StructureLogicDevice(StructureLogicDeviceTemplate),
StructureLogicDeviceMemory(StructureLogicDeviceMemoryTemplate),
Item(ItemTemplate),
ItemSlots(ItemSlotsTemplate),
ItemLogic(ItemLogicTemplate),
ItemLogicMemory(ItemLogicMemoryTemplate),
}
impl ObjectTemplate {
fn prefab(&self) -> &PrefabInfo {
use ObjectTemplate::*;
match self {
Structure(s) => &s.prefab,
StructureSlots(s) => &s.prefab,
StructureLogic(s) => &s.prefab,
StructureLogicDevice(s) => &s.prefab,
StructureLogicDeviceMemory(s) => &s.prefab,
Item(i) => &i.prefab,
ItemSlots(i) => &i.prefab,
ItemLogic(i) => &i.prefab,
ItemLogicMemory(i) => &i.prefab,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct PrefabInfo {
pub prefab_name: String,
pub prefab_hash: i32,
pub desc: String,
pub name: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct SlotInfo {
pub name: String,
pub typ: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct LogicInfo {
pub logic_slot_types: BTreeMap<u32, stationpedia::LogicSlotTypes>,
pub logic_types: stationpedia::LogicTypes,
#[serde(skip_serializing_if = "Option::is_none")]
pub modes: Option<BTreeMap<u32, String>>,
pub transmission_receiver: bool,
pub wireless_logic: bool,
pub circuit_holder: bool,
}
impl From<&stationpedia::LogicInfo> for LogicInfo {
fn from(value: &stationpedia::LogicInfo) -> Self {
LogicInfo {
logic_slot_types: value.logic_slot_types.clone(),
logic_types: value.logic_types.clone(),
logic_slot_types: value
.logic_slot_types
.iter()
.map(|(index, slt_map)| {
(
*index,
slt_map
.slot_types
.iter()
.map(|(key, val)| {
(
key.parse().unwrap_or_else(|err| {
panic!("failed to parse logic slot type: {err}")
}),
val.parse().unwrap_or_else(|err| {
panic!("failed to parse memory access: {err}")
}),
)
})
.collect(),
)
})
.collect(),
logic_types: value
.logic_types
.types
.iter()
.map(|(key, val)| {
(
key.parse()
.unwrap_or_else(|err| panic!("failed to parse logic type: {err}")),
val.parse()
.unwrap_or_else(|err| panic!("failed to parse memory access: {err}")),
)
})
.collect(),
modes: None,
transmission_receiver: false,
wireless_logic: false,
@@ -461,63 +500,32 @@ impl From<&stationpedia::LogicInfo> for LogicInfo {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemInfo {
pub consumable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub filter_type: Option<String>,
pub ingredient: bool,
pub max_quantity: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub reagents: Option<BTreeMap<String, f64>>,
pub slot_class: String,
pub sorting_class: String,
}
impl From<&stationpedia::Item> for ItemInfo {
fn from(item: &stationpedia::Item) -> Self {
ItemInfo {
consumable: item.consumable.unwrap_or(false),
filter_type: item.filter_type.clone(),
filter_type: item.filter_type.as_ref().map(|typ| {
typ.parse()
.unwrap_or_else(|err| panic!("failed to parse filter type: {err}"))
}),
ingredient: item.ingredient.unwrap_or(false),
max_quantity: item.max_quantity.unwrap_or(1.0) as u32,
reagents: item
.reagents
.as_ref()
.map(|map| map.iter().map(|(key, val)| (key.clone(), *val)).collect()),
slot_class: item.slot_class.clone(),
sorting_class: item.sorting_class.clone(),
slot_class: item
.slot_class
.parse()
.unwrap_or_else(|err| panic!("failed to parse slot class: {err}")),
sorting_class: item
.sorting_class
.parse()
.unwrap_or_else(|err| panic!("failed to parse sorting class: {err}")),
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ConnectionInfo {
pub typ: String,
pub role: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct DeviceInfo {
pub connection_list: Vec<ConnectionInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_pins_length: Option<i64>,
pub has_activate_state: bool,
pub has_atmosphere: bool,
pub has_color_state: bool,
pub has_lock_state: bool,
pub has_mode_state: bool,
pub has_on_off_state: bool,
pub has_open_state: bool,
pub has_reagents: bool,
}
impl From<&stationpedia::Device> for DeviceInfo {
fn from(value: &stationpedia::Device) -> Self {
DeviceInfo {
@@ -525,8 +533,12 @@ impl From<&stationpedia::Device> for DeviceInfo {
.connection_list
.iter()
.map(|(typ, role)| ConnectionInfo {
typ: typ.to_string(),
role: role.to_string(),
typ: typ
.parse()
.unwrap_or_else(|err| panic!("failed to parse connection type: {err}")),
role: role
.parse()
.unwrap_or_else(|err| panic!("failed to parse connection role: {err}")),
})
.collect(),
device_pins_length: value.devices_length,
@@ -542,13 +554,6 @@ impl From<&stationpedia::Device> for DeviceInfo {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureInfo {
pub small_grid: bool,
}
impl From<&stationpedia::Structure> for StructureInfo {
fn from(value: &stationpedia::Structure) -> Self {
StructureInfo {
@@ -556,14 +561,6 @@ impl From<&stationpedia::Structure> for StructureInfo {
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Instruction {
pub description: String,
pub typ: String,
pub value: i64,
}
impl From<&stationpedia::Instruction> for Instruction {
fn from(value: &stationpedia::Instruction) -> Self {
@@ -575,16 +572,6 @@ impl From<&stationpedia::Instruction> for Instruction {
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct MemoryInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<BTreeMap<String, Instruction>>,
pub memory_access: String,
pub memory_size: i64,
}
impl From<&stationpedia::Memory> for MemoryInfo {
fn from(value: &stationpedia::Memory) -> Self {
MemoryInfo {
@@ -594,96 +581,11 @@ impl From<&stationpedia::Memory> for MemoryInfo {
.map(|(key, value)| (key.clone(), value.into()))
.collect()
}),
memory_access: value.memory_access.clone(),
memory_access: value
.memory_access
.parse()
.unwrap_or_else(|err| panic!("failed to parse memory access: {err}")),
memory_size: value.memory_size,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureSlotsTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceMemoryTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
pub memory: MemoryInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemSlotsTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicMemoryTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub memory: MemoryInfo,
}

View File

@@ -6,17 +6,17 @@ use std::{
path::PathBuf,
str::FromStr,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
pub fn generate_enums(
stationpedia: &crate::stationpedia::Stationpedia,
enums: &crate::enums::Enums,
workspace: &std::path::Path,
) -> color_eyre::Result<Vec<PathBuf>> {
println!("Writing Enum Listings ...");
let enums_path = workspace
.join("ic10emu")
.join("src")
.join("vm")
.join("enums");
let enums_path = workspace.join("stationeers_data").join("src").join("enums");
if !enums_path.exists() {
std::fs::create_dir(&enums_path)?;
}
@@ -81,172 +81,136 @@ pub fn generate_enums(
])
}
#[allow(clippy::type_complexity)]
fn write_enum_aggragate_mod<T: std::io::Write>(
writer: &mut BufWriter<T>,
enums: &BTreeMap<String, crate::enums::EnumListing>,
) -> color_eyre::Result<()> {
let variant_lines = enums
.iter()
.map(|(name, listing)| {
let name = if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
};
format!(
" {}({}),",
name.to_case(Case::Pascal),
listing.enum_name.to_case(Case::Pascal)
)
})
.collect::<Vec<_>>()
.join("\n");
let value_arms = enums
.keys()
.map(|name| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
format!(" Self::{variant_name}(enm) => *enm as u32,",)
})
.collect::<Vec<_>>()
.join("\n");
let get_str_arms = enums
.keys()
.map(|name| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
format!(" Self::{variant_name}(enm) => enm.get_str(prop),",)
})
.collect::<Vec<_>>()
.join("\n");
let iter_chain = enums
let (
(variant_lines, value_arms),
(
(get_str_arms, iter_chain),
(from_str_arms_iter, display_arms)
)
): (
(Vec<_>, Vec<_>),
((Vec<_>, Vec<_>), (Vec<_>, Vec<_>)),
) = enums
.iter()
.enumerate()
.map(|(index, (name, listing))| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
let variant_name: TokenStream = if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
let enum_name = listing.enum_name.to_case(Case::Pascal);
if index == 0 {
format!("{enum_name}::iter().map(Self::{variant_name})")
} else {
format!(".chain({enum_name}::iter().map(Self::{variant_name}))")
}
})
.collect::<Vec<_>>()
.join("\n");
write!(
writer,
"pub enum BasicEnum {{\n\
{variant_lines}
}}\n\
impl BasicEnum {{\n \
pub fn get_value(&self) -> u32 {{\n \
match self {{\n \
{value_arms}\n \
}}\n \
}}\n\
pub fn get_str(&self, prop: &str) -> Option<&'static str> {{\n \
match self {{\n \
{get_str_arms}\n \
}}\n \
}}\n\
pub fn iter() -> impl std::iter::Iterator<Item = Self> {{\n \
use strum::IntoEnumIterator;\n \
{iter_chain}\n \
}}
}}\n\
"
)?;
let arms = enums
.iter()
.flat_map(|(name, listing)| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
let name = if name == "_unnamed" {
"".to_string()
} else {
name.clone()
};
let enum_name = listing.enum_name.to_case(Case::Pascal);
listing.values.keys().map(move |variant| {
let sep = if name.is_empty() { "" } else { "." };
let pat = format!("{name}{sep}{variant}").to_lowercase();
let variant = variant.to_case(Case::Pascal);
format!("\"{pat}\" => Ok(Self::{variant_name}({enum_name}::{variant})),")
})
})
.collect::<Vec<_>>()
.join("\n ");
write!(
writer,
"\
impl std::str::FromStr for BasicEnum {{\n \
type Err = crate::errors::ParseError;\n \
fn from_str(s: &str) -> Result<Self, Self::Err> {{\n \
let end = s.len();\n \
match s.to_lowercase().as_str() {{\n \
{arms}\n \
_ => Err(crate::errors::ParseError{{ line: 0, start: 0, end, msg: format!(\"Unknown enum '{{}}'\", s) }})\n \
}}\n \
}}\n\
}}\
"
)?;
let display_arms = enums
.keys()
.map(|name| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
let name = if name == "_unnamed" {
"".to_string()
} else {
name.clone()
};
let sep = if name.is_empty() || name == "_unnamed" {
.to_case(Case::Pascal)
.parse()
.unwrap();
let fromstr_variant_name = variant_name.clone();
let enum_name: TokenStream = listing.enum_name.to_case(Case::Pascal).parse().unwrap();
let display_sep = if name.is_empty() || name == "_unnamed" {
""
} else {
"."
};
let pat = format!("{name}{sep}{{}}");
format!(" Self::{variant_name}(enm) => write!(f, \"{pat}\", enm),",)
let display_pat = format!("{name}{display_sep}{{}}");
let name: TokenStream = if name == "_unnamed" {
"".to_string()
} else {
name.clone()
}
.parse()
.unwrap();
(
(
quote! {
#variant_name(#enum_name),
},
quote! {
Self::#variant_name(enm) => *enm as u32,
},
),
(
(
quote! {
Self::#variant_name(enm) => enm.get_str(prop),
},
if index == 0 {
quote! {
#enum_name::iter().map(Self::#variant_name)
}
} else {
quote! {
.chain(#enum_name::iter().map(Self::#variant_name))
}
},
),
(
listing.values.keys().map(move |variant| {
let sep = if name.is_empty() { "" } else { "." };
let fromstr_pat = format!("{name}{sep}{variant}").to_lowercase();
let variant: TokenStream = variant.to_case(Case::Pascal).parse().unwrap();
quote! {
#fromstr_pat => Ok(Self::#fromstr_variant_name(#enum_name::#variant)),
}
}),
quote! {
Self::#variant_name(enm) => write!(f, #display_pat, enm),
},
),
),
)
})
.collect::<Vec<_>>()
.join("\n ");
write!(
writer,
"\
impl std::fmt::Display for BasicEnum {{\n \
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{\n \
match self {{\n \
{display_arms}\n \
}}\n \
}}\n\
}}\
"
)?;
.unzip();
let from_str_arms = from_str_arms_iter.into_iter().flatten().collect::<Vec<_>>();
let tokens = quote! {
pub enum BasicEnum {
#(#variant_lines)*
}
impl BasicEnum {
pub fn get_value(&self) -> u32 {
match self {
#(#value_arms)*
}
}
pub fn get_str(&self, prop: &str) -> Option<&'static str> {
match self {
#(#get_str_arms)*
}
}
pub fn iter() -> impl std::iter::Iterator<Item = Self> {
use strum::IntoEnumIterator;
#(#iter_chain)*
}
}
impl std::str::FromStr for BasicEnum {
type Err = super::ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
#(#from_str_arms)*
_ => Err(super::ParseError { enm: s.to_string() })
}
}
}
impl std::fmt::Display for BasicEnum {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#(#display_arms)*
}
}
}
};
write!(writer, "{tokens}",)?;
Ok(())
}
pub fn write_enum_listing<T: std::io::Write>(
writer: &mut BufWriter<T>,
enm: &crate::enums::EnumListing,
@@ -357,10 +321,13 @@ fn write_repr_enum_use_header<T: std::io::Write>(
) -> color_eyre::Result<()> {
write!(
writer,
"use serde_derive::{{Deserialize, Serialize}};\n\
use strum::{{\n \
AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr,\n\
}};\n"
"{}",
quote! {
use serde_derive::{{Deserialize, Serialize}};
use strum::{
AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr,
};
}
)?;
Ok(())
}
@@ -369,14 +336,15 @@ fn write_repr_basic_use_header<T: std::io::Write>(
writer: &mut BufWriter<T>,
script_enums: &[&crate::enums::EnumListing],
) -> color_eyre::Result<()> {
let enums = script_enums
.iter()
.map(|enm| Ident::new(&enm.enum_name.to_case(Case::Pascal), Span::call_site()))
.collect::<Vec<_>>();
write!(
writer,
"use crate::vm::enums::script_enums::{{ {} }};",
script_enums
.iter()
.map(|enm| enm.enum_name.to_case(Case::Pascal))
.collect::<Vec<_>>()
.join(", ")
"{}",
quote! {use super::script_enums::{ #(#enums),*};},
)?;
Ok(())
}
@@ -388,60 +356,104 @@ fn write_repr_enum<'a, T: std::io::Write, I, P>(
use_phf: bool,
) -> color_eyre::Result<()>
where
P: Display + FromStr + Ord + 'a,
P: Display + FromStr + num::integer::Integer + num::cast::AsPrimitive<i64> + 'a,
I: IntoIterator<Item = &'a (String, ReprEnumVariant<P>)>,
{
let additional_strum = if use_phf { "#[strum(use_phf)]\n" } else { "" };
let repr = std::any::type_name::<P>();
let additional_strum = if use_phf {
quote! {#[strum(use_phf)]}
} else {
TokenStream::new()
};
let repr = Ident::new(std::any::type_name::<P>(), Span::call_site());
let mut sorted: Vec<_> = variants.into_iter().collect::<Vec<_>>();
sorted.sort_by_key(|(_, variant)| &variant.value);
let default_derive = if sorted
let mut derives = [
"Debug",
"Display",
"Clone",
"Copy",
"PartialEq",
"Eq",
"PartialOrd",
"Ord",
"Hash",
"EnumString",
"AsRefStr",
"EnumProperty",
"EnumIter",
"FromRepr",
"Serialize",
"Deserialize",
]
.into_iter()
.map(|d| Ident::new(d, Span::call_site()))
.collect::<Vec<_>>();
if sorted
.iter()
.any(|(name, _)| name == "None" || name == "Default")
{
"Default, "
} else {
""
};
derives.insert(0, Ident::new("Default", Span::call_site()));
}
let variants = sorted
.iter()
.map(|(name, variant)| {
let variant_name = Ident::new(
&name.replace('.', "").to_case(Case::Pascal),
Span::call_site(),
);
let mut props = Vec::new();
if variant.deprecated {
props.push(quote! {deprecated = "true"});
}
for (prop_name, prop_val) in &variant.props {
let prop_name = Ident::new(prop_name, Span::call_site());
let val_string = prop_val.to_string();
props.push(quote! { #prop_name = #val_string });
}
let val: TokenStream = format!("{}{repr}", variant.value).parse().unwrap();
let val_string = variant.value.as_().to_string();
props.push(quote! {value = #val_string });
let default = if variant_name == "None" || variant_name == "Default" {
quote! {#[default]}
} else {
TokenStream::new()
};
quote! {
#[strum(serialize = #name)]
#[strum(props(#(#props),*))]
#default
#variant_name = #val,
}
})
.collect::<Vec<_>>();
let name = Ident::new(name, Span::call_site());
write!(
writer,
"#[derive(Debug, {default_derive}Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumString, AsRefStr, EnumProperty, EnumIter, FromRepr, Serialize, Deserialize)]\n\
{additional_strum}\
#[repr({repr})]\n\
pub enum {name} {{\n"
"{}",
quote! {
#[derive(#(#derives),*)]
#additional_strum
#[repr(#repr)]
pub enum #name {
#(#variants)*
}
impl TryFrom<f64> for #name {
type Error = super::ParseError;
fn try_from(value: f64) -> Result<Self, <#name as TryFrom<f64>>::Error> {
use strum::IntoEnumIterator;
if let Some(enm) = #name::iter().find(|enm| (f64::from(*enm as #repr) - value).abs() < f64::EPSILON ) {
Ok(enm)
} else {
Err(super::ParseError {
enm: value.to_string()
})
}
}
}
}
)?;
for (name, variant) in sorted {
let variant_name = name.replace('.', "").to_case(Case::Pascal);
let serialize = vec![name.clone()];
let serialize_str = serialize
.into_iter()
.map(|s| format!("serialize = \"{s}\""))
.collect::<Vec<String>>()
.join(", ");
let mut props = Vec::new();
if variant.deprecated {
props.push("deprecated = \"true\"".to_owned());
}
for (prop_name, prop_val) in &variant.props {
props.push(format!("{prop_name} = r#\"{prop_val}\"#"));
}
let val = &variant.value;
props.push(format!("value = \"{val}\""));
let props_str = if !props.is_empty() {
format!(", props( {} )", props.join(", "))
} else {
"".to_owned()
};
let default = if variant_name == "None" || variant_name == "Default" {
"#[default]"
} else {
""
};
writeln!(
writer,
" #[strum({serialize_str}{props_str})]{default} {variant_name} = {val}{repr},"
)?;
}
writeln!(writer, "}}")?;
Ok(())
}

View File

@@ -1,4 +1,6 @@
use convert_case::{Case, Casing};
use proc_macro2::{Ident, Span};
use quote::quote;
use std::{collections::BTreeMap, path::PathBuf};
use crate::{generate::utils, stationpedia};
@@ -47,82 +49,93 @@ fn write_instructions_enum<T: std::io::Write>(
write!(
writer,
"use serde_derive::{{Deserialize, Serialize}};\n\
use strum::{{\n \
Display, EnumIter, EnumProperty, EnumString, FromRepr,\n\
}};\n
use crate::vm::object::traits::Programmable;\n\
"
"{}",
quote::quote! {
use serde_derive::{Deserialize, Serialize};
use strum::{
Display, EnumIter, EnumProperty, EnumString, FromRepr,
};
use crate::vm::object::traits::Programmable;
}
)?;
let inst_variants = instructions
.iter()
.map(|(name, info)| {
let example = &info.example;
let desc = &info.desc;
let op_count = count_operands(&info.example).to_string();
let props =
quote::quote! { props( example = #example, desc = #desc, operands = #op_count ) };
let name = Ident::new(&name.to_case(Case::Pascal), Span::call_site());
quote::quote! {
#[strum(#props)] #name,
}
})
.collect::<Vec<_>>();
write!(
writer,
"#[derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)]\n\
#[derive(EnumIter, EnumString, EnumProperty, FromRepr)]\n\
#[strum(use_phf, serialize_all = \"lowercase\")]\n\
#[serde(rename_all = \"lowercase\")]\n\
pub enum InstructionOp {{\n\
"
"{}",
quote::quote! {#[derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)]
#[derive(EnumIter, EnumString, EnumProperty, FromRepr)]
#[strum(use_phf, serialize_all = "lowercase")]
#[serde(rename_all = "lowercase")]
pub enum InstructionOp {
Nop,
#(#inst_variants)*
}
}
)?;
writeln!(writer, " Nop,")?;
for (name, info) in &instructions {
let props_str = format!(
"props( example = \"{}\", desc = \"{}\", operands = \"{}\" )",
&info.example,
&info.desc,
count_operands(&info.example)
);
writeln!(
writer,
" #[strum({props_str})] {},",
name.to_case(Case::Pascal)
)?;
}
writeln!(writer, "}}")?;
let exec_arms = instructions
.iter()
.map(|(name, info)| {
let num_operands = count_operands(&info.example);
let operands = (0..num_operands)
.map(|i| quote! {&operands[#i]})
.collect::<Vec<_>>();
let trait_name = Ident::new(&name.to_case(Case::Pascal), Span::call_site());
let fn_name = Ident::new(&format!("execute_{name}"), Span::call_site());
quote! {
Self::#trait_name => ic.#fn_name(#(#operands),*),
}
})
.collect::<Vec<_>>();
write!(
writer,
"impl InstructionOp {{\n \
pub fn num_operands(&self) -> usize {{\n \
self.get_str(\"operands\").expect(\"instruction without operand property\").parse::<usize>().expect(\"invalid instruction operand property\")\n \
}}\n\
\n \
pub fn execute<T>(\n \
&self,\n \
ic: &mut T,\n \
operands: &[crate::vm::instructions::operands::Operand],\n \
) -> Result<(), crate::errors::ICError>\n \
where\n \
T: Programmable,\n\
{{\n \
let num_operands = self.num_operands();\n \
if operands.len() != num_operands {{\n \
return Err(crate::errors::ICError::mismatch_operands(operands.len(), num_operands as u32));\n \
}}\n \
match self {{\n \
Self::Nop => Ok(()),\n \
"
)?;
"{}",
quote! {
impl InstructionOp {
pub fn num_operands(&self) -> usize {
self.get_str("operands")
.expect("instruction without operand property")
.parse::<usize>()
.expect("invalid instruction operand property")
}
for (name, info) in instructions {
let num_operands = count_operands(&info.example);
let operands = (0..num_operands)
.map(|i| format!("&operands[{}]", i))
.collect::<Vec<_>>()
.join(", ");
let trait_name = name.to_case(Case::Pascal);
writeln!(
writer,
" Self::{trait_name} => ic.execute_{name}({operands}),",
)?;
}
write!(
writer,
" }}\
}}\n\
}}
"
pub fn execute<T>(
&self,
ic: &mut T,
operands: &[crate::vm::instructions::operands::Operand],
) -> Result<(), crate::errors::ICError>
where
T: Programmable,
{
let num_operands = self.num_operands();
if operands.len() != num_operands {
return Err(crate::errors::ICError::mismatch_operands(operands.len(), num_operands as u32));
}
match self {
Self::Nop => Ok(()),
#(#exec_arms)*
}
}
}
}
)?;
Ok(())
@@ -134,7 +147,8 @@ fn write_instruction_trait<T: std::io::Write>(
) -> color_eyre::Result<()> {
let (name, info) = instruction;
let op_name = name.to_case(Case::Pascal);
let trait_name = format!("{op_name}Instruction");
let trait_name = Ident::new(&format!("{op_name}Instruction"), Span::call_site());
let op_ident = Ident::new(&op_name, Span::call_site());
let operands = operand_names(&info.example)
.iter()
.map(|name| {
@@ -142,13 +156,13 @@ fn write_instruction_trait<T: std::io::Write>(
if n == "str" {
n = "string";
}
format!(
"{}: &crate::vm::instructions::operands::Operand",
n.to_case(Case::Snake)
)
let n = Ident::new(&n.to_case(Case::Snake), Span::call_site());
quote! {
#n: &crate::vm::instructions::operands::Operand
}
})
.collect::<Vec<_>>()
.join(", ");
.collect::<Vec<_>>();
let operands_inner = operand_names(&info.example)
.iter()
.map(|name| {
@@ -156,13 +170,13 @@ fn write_instruction_trait<T: std::io::Write>(
if n == "str" {
n = "string";
}
format!(
"{}: &crate::vm::instructions::operands::InstOperand",
n.to_case(Case::Snake)
)
let n = Ident::new(&n.to_case(Case::Snake), Span::call_site());
quote! {
#n: &crate::vm::instructions::operands::InstOperand
}
})
.collect::<Vec<_>>()
.join(", ");
.collect::<Vec<_>>();
let operand_call = operand_names(&info.example)
.iter()
.enumerate()
@@ -171,24 +185,27 @@ fn write_instruction_trait<T: std::io::Write>(
if n == "str" {
n = "string";
}
format!(
"&crate::vm::instructions::operands::InstOperand::new({}, InstructionOp::{op_name}, {index})",
n.to_case(Case::Snake)
)
let n = Ident::new(&n.to_case(Case::Snake), Span::call_site());
quote!{
&crate::vm::instructions::operands::InstOperand::new(#n, InstructionOp::#op_ident, #index)
}
})
.collect::<Vec<_>>()
.join(", ");
.collect::<Vec<_>>();
let example = utils::strip_color(&info.example);
let fn_name = Ident::new(&format!("execute_{name}"), Span::call_site());
write!(
writer,
"pub trait {trait_name}: IntegratedCircuit {{\n \
/// {example} \n \
fn execute_{name}(&mut self, {operands}) -> Result<(), crate::errors::ICError> {{\n \
{trait_name}::execute_inner(self, {operand_call})\n \
}}\n \
/// {example} \n \
fn execute_inner(&mut self, {operands_inner}) -> Result<(), crate::errors::ICError>;\n\
}}"
"{}",
quote! {
pub trait #trait_name: IntegratedCircuit {
#[doc = #example]
fn #fn_name(&mut self, #(#operands),*) -> Result<(), crate::errors::ICError> {
#trait_name::execute_inner(self, #(#operand_call),*)
}
#[doc = #example]
fn execute_inner(&mut self, #(#operands_inner),*) -> Result<(), crate::errors::ICError>;
}
}
)?;
Ok(())
}
@@ -208,10 +225,11 @@ fn operand_names(example: &str) -> Vec<String> {
fn write_instruction_trait_use<T: std::io::Write>(writer: &mut T) -> color_eyre::Result<()> {
write!(
writer,
"\
use crate::vm::object::traits::IntegratedCircuit;\n\
use crate::vm::instructions::enums::InstructionOp;\n\
"
"{}",
quote! {
use crate::vm::object::traits::IntegratedCircuit;
use crate::vm::instructions::enums::InstructionOp;
}
)?;
Ok(())
}
@@ -222,15 +240,20 @@ fn write_instruction_super_trait<T: std::io::Write>(
) -> color_eyre::Result<()> {
let traits = instructions
.keys()
.map(|name| format!("{}Instruction", name.to_case(Case::Pascal)))
.collect::<Vec<_>>()
.join(" + ");
.map(|name| {
Ident::new(
&format!("{}Instruction", name.to_case(Case::Pascal)),
Span::call_site(),
)
})
.collect::<Vec<_>>();
write!(
writer,
"\
pub trait ICInstructable: {traits} {{}}\n\
impl <T> ICInstructable for T where T: {traits} {{}}
"
"{}",
quote! {
pub trait ICInstructable: #(#traits +)* {}
impl <T> ICInstructable for T where T: #(#traits )+* {}
}
)?;
Ok(())
}

View File

@@ -24,6 +24,17 @@ struct Args {
const PACKAGES: &[&str] = &["ic10lsp_wasm", "ic10emu_wasm"];
const VALID_VERSION_TYPE: &[&str] = &["patch", "minor", "major"];
const VALID_GENERATE_TYPE: &[&str] = &["enums", "instructions", "database"];
const DEFAULT_GENERATE: &[&str] = &["enums"];
fn parse_generate_modules(s: &str) -> Result<String, String> {
if !VALID_GENERATE_TYPE.contains(&s) {
let valid_str = VALID_GENERATE_TYPE.join(", ");
return Err(format!(
"{s} is not a valid generate module. One of: {valid_str}"
));
}
Ok(s.to_string())
}
#[derive(Debug, Subcommand)]
enum Task {
@@ -54,6 +65,8 @@ enum Task {
/// update changelog
Changelog {},
Generate {
#[arg(long, short = 'm', value_delimiter = ',', default_values = DEFAULT_GENERATE, value_parser = parse_generate_modules)]
modules: Vec<String>,
#[arg()]
/// Path to Stationeers installation. Used to locate "Stationpedia.json" and "Enums.json"
/// generated by https://github.com/Ryex/StationeersStationpediaExtractor
@@ -166,7 +179,7 @@ fn main() -> color_eyre::Result<()> {
.status()
.map_err(|e| Error::Command(format!("{}", cmd.get_program().to_string_lossy()), e))?;
}
Task::Generate { path } => {
Task::Generate { modules, path } => {
let path = match path {
Some(path) => {
let mut path = std::path::PathBuf::from(path);
@@ -214,7 +227,11 @@ fn main() -> color_eyre::Result<()> {
&& path.join("Stationpedia.json").exists()
&& path.join("Enums.json").exists()
{
generate::generate(&path, &workspace)?;
generate::generate(
&path,
&workspace,
&modules.iter().map(String::as_str).collect::<Vec<_>>(),
)?;
} else {
return Err(Error::BadStationeersPath(path).into());
}

View File

@@ -214,7 +214,7 @@ pub struct Memory {
#[serde(rename = "MemoryAccess")]
pub memory_access: String,
#[serde(rename = "MemorySize")]
pub memory_size: i64,
pub memory_size: u32,
#[serde(rename = "MemorySizeReadable")]
pub memory_size_readable: String,
}
@@ -308,7 +308,7 @@ pub struct Device {
#[serde(rename = "ConnectionList")]
pub connection_list: Vec<(String, String)>,
#[serde(rename = "DevicesLength")]
pub devices_length: Option<i64>,
pub devices_length: Option<u32>,
#[serde(rename = "HasActivateState")]
pub has_activate_state: bool,
#[serde(rename = "HasAtmosphere")]