mirror of
https://github.com/osmarks/ewo3.git
synced 2025-06-10 10:24:08 +00:00
initial commit
This commit is contained in:
commit
db02d05778
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
/node_modules
|
893
Cargo.lock
generated
Normal file
893
Cargo.lock
generated
Normal file
@ -0,0 +1,893 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.86"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.72"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "euclid"
|
||||||
|
version = "0.22.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0f0eb73b934648cd7a4a61f1b15391cd95dab0b4da6e2e66c2a072c144b4a20"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ewo3"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"euclid",
|
||||||
|
"fastrand",
|
||||||
|
"futures-util",
|
||||||
|
"hecs",
|
||||||
|
"lazy_static",
|
||||||
|
"noise-functions",
|
||||||
|
"seahash",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"slab",
|
||||||
|
"tokio",
|
||||||
|
"tokio-macros 0.2.6",
|
||||||
|
"tokio-tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.66",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.29.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hecs"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1cbc675ee8d97b4d206a985137f8ad59666538f56f906474f554467a63c776d"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
"serde",
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"itoa",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httparse"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.155"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "noise-functions"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "822a69eedf004ac2f492119af7a8203790b1c9115b9a9ef6bcd0cde5d6783565"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.35.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.85"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "seahash"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.203"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.203"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.66",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.117"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.66"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.66",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.38.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"bytes",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"num_cpus",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
|
"socket2",
|
||||||
|
"tokio-macros 2.3.0",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.66",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "becd34a233e7e31a3dbf7c7241b38320f57393dcae8e7324b0167d21b8e320b0"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"tokio",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tungstenite"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
|
"data-encoding",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"rand",
|
||||||
|
"sha1",
|
||||||
|
"thiserror",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||||
|
dependencies = [
|
||||||
|
"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]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
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"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.66",
|
||||||
|
]
|
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "ewo3"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
hecs = { version = "0.10", features = ["column-serialize"] }
|
||||||
|
euclid = { version = "0.22", features = ["serde"] }
|
||||||
|
fastrand = "2"
|
||||||
|
tokio-tungstenite = "0.23"
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
futures-util = "0.3"
|
||||||
|
tokio-macros = { version = "0.2.0-alpha.6" }
|
||||||
|
anyhow = "1"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
slab = "0.4"
|
||||||
|
lazy_static = "1"
|
||||||
|
seahash = "4"
|
||||||
|
noise-functions = "0.2"
|
463
package-lock.json
generated
Normal file
463
package-lock.json
generated
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
{
|
||||||
|
"name": "ewo3",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"devDependencies": {
|
||||||
|
"esbuild": "^0.12.15",
|
||||||
|
"esbuild-svelte": "^0.5.3",
|
||||||
|
"sass": "^1.68.0",
|
||||||
|
"svelte-preprocess-sass": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/anymatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/binary-extensions": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chokidar": {
|
||||||
|
"version": "3.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
|
||||||
|
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.10.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/esbuild": {
|
||||||
|
"version": "0.12.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.15.tgz",
|
||||||
|
"integrity": "sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"esbuild": "bin/esbuild"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/esbuild-svelte": {
|
||||||
|
"version": "0.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.5.3.tgz",
|
||||||
|
"integrity": "sha512-KByKD/yt8QaqKjLu32MG3MXBExJYlDM0QwzW3pzKLJR4eev0923DrUKRHPBBjB+OVirUtZnEJE/qitjdW/WyAw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"svelte": "^3.38.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"esbuild": ">=0.9.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/immutable": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass": {
|
||||||
|
"version": "1.68.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.68.0.tgz",
|
||||||
|
"integrity": "sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": ">=3.0.0 <4.0.0",
|
||||||
|
"immutable": "^4.0.0",
|
||||||
|
"source-map-js": ">=0.6.2 <2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"sass": "sass.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/source-map-js": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/svelte": {
|
||||||
|
"version": "3.38.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.3.tgz",
|
||||||
|
"integrity": "sha512-N7bBZJH0iF24wsalFZF+fVYMUOigaAUQMIcEKHO3jstK/iL8VmP9xE+P0/a76+FkNcWt+TDv2Gx1taUoUscrvw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/svelte-preprocess-filter": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-preprocess-filter/-/svelte-preprocess-filter-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-92innv59nyEx24xbfcSurB5ocwC8qFdDtGli/JVMHzJsxyvV2yjQKIcbUqU9VIV5mKUWO2PoY93nncS2yF4ULQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/svelte-preprocess-sass": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-preprocess-sass/-/svelte-preprocess-sass-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-0y4FjRsRWcN7rJeNJnSfZ7LVAz6S7/j9Dg24XFRelr/rjMMjXORdEvXy4r38fUYmyk9Y7yjwlHCiqyGxMHhEbg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"svelte-preprocess-filter": "^1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"sass": "^1.35.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"anymatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary-extensions": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"braces": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fill-range": "^7.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chokidar": {
|
||||||
|
"version": "3.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
|
||||||
|
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"fsevents": "~2.3.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"esbuild": {
|
||||||
|
"version": "0.12.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.15.tgz",
|
||||||
|
"integrity": "sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"esbuild-svelte": {
|
||||||
|
"version": "0.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.5.3.tgz",
|
||||||
|
"integrity": "sha512-KByKD/yt8QaqKjLu32MG3MXBExJYlDM0QwzW3pzKLJR4eev0923DrUKRHPBBjB+OVirUtZnEJE/qitjdW/WyAw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"svelte": "^3.38.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fill-range": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"immutable": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"is-glob": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"picomatch": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sass": {
|
||||||
|
"version": "1.68.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.68.0.tgz",
|
||||||
|
"integrity": "sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chokidar": ">=3.0.0 <4.0.0",
|
||||||
|
"immutable": "^4.0.0",
|
||||||
|
"source-map-js": ">=0.6.2 <2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source-map-js": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"svelte": {
|
||||||
|
"version": "3.38.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.3.tgz",
|
||||||
|
"integrity": "sha512-N7bBZJH0iF24wsalFZF+fVYMUOigaAUQMIcEKHO3jstK/iL8VmP9xE+P0/a76+FkNcWt+TDv2Gx1taUoUscrvw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"svelte-preprocess-filter": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-preprocess-filter/-/svelte-preprocess-filter-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-92innv59nyEx24xbfcSurB5ocwC8qFdDtGli/JVMHzJsxyvV2yjQKIcbUqU9VIV5mKUWO2PoY93nncS2yF4ULQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"svelte-preprocess-sass": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-preprocess-sass/-/svelte-preprocess-sass-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-0y4FjRsRWcN7rJeNJnSfZ7LVAz6S7/j9Dg24XFRelr/rjMMjXORdEvXy4r38fUYmyk9Y7yjwlHCiqyGxMHhEbg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"svelte-preprocess-filter": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
package.json
Normal file
8
package.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"esbuild": "^0.12.15",
|
||||||
|
"esbuild-svelte": "^0.5.3",
|
||||||
|
"sass": "^1.68.0",
|
||||||
|
"svelte-preprocess-sass": "^2.0.1"
|
||||||
|
}
|
||||||
|
}
|
171
src/App.svelte
Normal file
171
src/App.svelte
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<style lang="sass">
|
||||||
|
\:global(*)
|
||||||
|
box-sizing: border-box
|
||||||
|
|
||||||
|
\:global(html)
|
||||||
|
scrollbar-color: black lightgray
|
||||||
|
|
||||||
|
\:global(body)
|
||||||
|
font-family: "Fira Sans", "Noto Sans", "Segoe UI", Verdana, sans-serif
|
||||||
|
font-weight: 300
|
||||||
|
overflow-anchor: none
|
||||||
|
//margin: 0
|
||||||
|
//min-height: 100vh
|
||||||
|
|
||||||
|
\:global(strong)
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
|
@mixin header
|
||||||
|
border-bottom: 1px solid gray
|
||||||
|
margin: 0
|
||||||
|
margin-bottom: 0.5em
|
||||||
|
font-weight: 500
|
||||||
|
//a
|
||||||
|
//color: inherit
|
||||||
|
|
||||||
|
\:global(h1)
|
||||||
|
@include header
|
||||||
|
\:global(h2)
|
||||||
|
@include header
|
||||||
|
\:global(h3)
|
||||||
|
@include header
|
||||||
|
\:global(h4)
|
||||||
|
@include header
|
||||||
|
\:global(h5)
|
||||||
|
@include header
|
||||||
|
\:global(h6)
|
||||||
|
@include header
|
||||||
|
\:global(ul)
|
||||||
|
list-style-type: square
|
||||||
|
padding: 0
|
||||||
|
padding-left: 1em
|
||||||
|
|
||||||
|
input, button, select
|
||||||
|
border-radius: 0
|
||||||
|
border: 1px solid gray
|
||||||
|
padding: 0.5em
|
||||||
|
|
||||||
|
.game-display
|
||||||
|
.row
|
||||||
|
white-space: nowrap
|
||||||
|
.cell
|
||||||
|
display: inline-block
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
.wrapper
|
||||||
|
display: flex
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<h1>EWO3 Memetic Edition</h1>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="game-display">
|
||||||
|
{#each grid as row, y}
|
||||||
|
<div class="row" style={`height: ${VERT}px; ` + (y % 2 === 1 ? `padding-left: ${HORIZ/2}px` : "")}>
|
||||||
|
{#each row as cell}
|
||||||
|
<div class="cell" style={`width: ${HORIZ}px; height: ${VERT}px; line-height: ${VERT}px; opacity: ${cell[1] * 100}%`}>{cell[0]}</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
{#if dead}
|
||||||
|
You have died to death. <a href="#" on:click={restart}>Restart</a>.
|
||||||
|
{/if}
|
||||||
|
{#if players}
|
||||||
|
{players} connected players.
|
||||||
|
{/if}
|
||||||
|
{#if health}
|
||||||
|
Your health is {health}.
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<svelte:window on:keydown={keydown} on:keyup={keyup}></svelte:window>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as util from "./util"
|
||||||
|
|
||||||
|
let dead = false
|
||||||
|
let health
|
||||||
|
let players
|
||||||
|
|
||||||
|
let ws
|
||||||
|
const connect = () => {
|
||||||
|
ws = new WebSocket(window.location.protocol === "https:" ? "wss://ewo.osmarks.net/" : "ws://localhost:8080/")
|
||||||
|
|
||||||
|
ws.addEventListener("message", ev => {
|
||||||
|
const data = JSON.parse(ev.data)
|
||||||
|
if (data.Display) {
|
||||||
|
const newGrid = blankGrid()
|
||||||
|
for (const [q, r, c, o] of data.Display.nearby) {
|
||||||
|
const col = q + (r - (r & 1)) / 2
|
||||||
|
const row = r
|
||||||
|
newGrid[row + OFFSET][col + OFFSET] = [c, o]
|
||||||
|
}
|
||||||
|
grid = newGrid
|
||||||
|
health = data.Display.health
|
||||||
|
}
|
||||||
|
if (data === "Dead") {
|
||||||
|
dead = true
|
||||||
|
}
|
||||||
|
if (data.PlayerCount) {
|
||||||
|
players = data.PlayerCount
|
||||||
|
}
|
||||||
|
for (const key of keysDown) {
|
||||||
|
const input = INPUTS[key]
|
||||||
|
if (input) {
|
||||||
|
ws.send(JSON.stringify(input))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keysDown = new Set(Array.from(keysDown).map(k => !keysCleared.has(k)))
|
||||||
|
keysCleared = new Set()
|
||||||
|
})
|
||||||
|
|
||||||
|
ws.addEventListener("close", ev => {
|
||||||
|
console.warn("oh no")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const reconnect = () => {
|
||||||
|
if (ws) ws.close()
|
||||||
|
connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
const restart = ev => {
|
||||||
|
ev.preventDefault()
|
||||||
|
dead = false
|
||||||
|
reconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
const GRIDSIZE = 33
|
||||||
|
const OFFSET = Math.floor(GRIDSIZE/2)
|
||||||
|
const SIZE = 16
|
||||||
|
const HORIZ = Math.sqrt(3) * SIZE
|
||||||
|
const VERT = 3/2 * SIZE
|
||||||
|
|
||||||
|
const blankGrid = () => new Array(GRIDSIZE).fill(null).map(() => new Array(GRIDSIZE).fill(""))
|
||||||
|
|
||||||
|
let grid = blankGrid()
|
||||||
|
|
||||||
|
let keysDown = new Set()
|
||||||
|
let keysCleared = new Set()
|
||||||
|
|
||||||
|
const keydown = ev => {
|
||||||
|
keysDown.add(ev.key)
|
||||||
|
}
|
||||||
|
const keyup = ev => {
|
||||||
|
keysCleared.add(ev.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const INPUTS = {
|
||||||
|
"w": "UpLeft",
|
||||||
|
"e": "UpRight",
|
||||||
|
"a": "Left",
|
||||||
|
"d": "Right",
|
||||||
|
"z": "DownLeft",
|
||||||
|
"x": "DownRight"
|
||||||
|
}
|
||||||
|
|
||||||
|
connect()
|
||||||
|
</script>
|
5
src/app.js
Normal file
5
src/app.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import App from "./App.svelte"
|
||||||
|
|
||||||
|
new App({
|
||||||
|
target: document.body,
|
||||||
|
})
|
25
src/build.js
Normal file
25
src/build.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const esbuild = require("esbuild")
|
||||||
|
const sveltePlugin = require("esbuild-svelte")
|
||||||
|
const path = require("path")
|
||||||
|
const { sass } = require("svelte-preprocess-sass")
|
||||||
|
|
||||||
|
esbuild
|
||||||
|
.build({
|
||||||
|
entryPoints: [path.join(__dirname, "app.js")],
|
||||||
|
bundle: true,
|
||||||
|
minify: false,
|
||||||
|
outfile: path.join(__dirname, "../static/app.js"),
|
||||||
|
plugins: [sveltePlugin({
|
||||||
|
preprocess: {
|
||||||
|
style: sass()
|
||||||
|
}
|
||||||
|
})],
|
||||||
|
loader: {
|
||||||
|
".woff": "file",
|
||||||
|
".woff2": "file",
|
||||||
|
".ttf": "file"
|
||||||
|
},
|
||||||
|
logLevel: "info",
|
||||||
|
watch: process.argv.join(" ").includes("watch")
|
||||||
|
})
|
||||||
|
.catch(() => process.exit(1))
|
671
src/main.rs
Normal file
671
src/main.rs
Normal file
@ -0,0 +1,671 @@
|
|||||||
|
use hecs::{Entity, World};
|
||||||
|
use euclid::{Point3D, Point2D, Vector2D};
|
||||||
|
use futures_util::{stream::TryStreamExt, SinkExt, StreamExt};
|
||||||
|
use noise_functions::Sample3;
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio_tungstenite::tungstenite::protocol::Message;
|
||||||
|
use tokio::sync::{mpsc, Mutex};
|
||||||
|
use anyhow::{Result, Context, anyhow};
|
||||||
|
use std::{collections::{hash_map::Entry, HashMap}, hash::{Hash, Hasher}, net::SocketAddr, sync::Arc, thread::current, time::Duration};
|
||||||
|
use slab::Slab;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
struct AxialWorldSpace;
|
||||||
|
struct CubicWorldSpace;
|
||||||
|
type Coord = Point2D<i64, AxialWorldSpace>;
|
||||||
|
type CubicCoord = Point3D<i64, CubicWorldSpace>;
|
||||||
|
type CoordVec = Vector2D<i64, AxialWorldSpace>;
|
||||||
|
|
||||||
|
fn to_cubic(p0: Coord) -> CubicCoord {
|
||||||
|
CubicCoord::new(p0.x, p0.y, -p0.x - p0.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hex_distance(p0: Coord, p1: Coord) -> i64 {
|
||||||
|
let ax_dist = p0 - p1;
|
||||||
|
(ax_dist.x.abs() + ax_dist.y.abs() + (ax_dist.x + ax_dist.y).abs()) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_axis(p: CoordVec) -> bool {
|
||||||
|
let p = to_cubic(Coord::origin() + p);
|
||||||
|
let mut zero_ax = 0;
|
||||||
|
if p.x == 0 { zero_ax += 1 }
|
||||||
|
if p.y == 0 { zero_ax += 1 }
|
||||||
|
if p.z == 0 { zero_ax += 1 }
|
||||||
|
zero_ax >= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_connection(raw_stream: TcpStream, addr: SocketAddr, mut frames_rx: mpsc::Receiver<Frame>, inputs_tx: mpsc::Sender<Input>) -> Result<()> {
|
||||||
|
let ws_stream = tokio_tungstenite::accept_async(raw_stream).await.context("websocket handshake failure")?;
|
||||||
|
let (mut outgoing, incoming) = ws_stream.split();
|
||||||
|
|
||||||
|
let broadcast_incoming = incoming.map_err(anyhow::Error::from).try_for_each(|msg| {
|
||||||
|
let inputs_tx = inputs_tx.clone();
|
||||||
|
async move {
|
||||||
|
if msg.is_close() { return Err(anyhow!("connection closed")) }
|
||||||
|
|
||||||
|
let input: Input = serde_json::from_str(msg.to_text()?)?;
|
||||||
|
|
||||||
|
inputs_tx.send(input).await?;
|
||||||
|
|
||||||
|
anyhow::Result::<(), anyhow::Error>::Ok(())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let send_state = async move {
|
||||||
|
while let Some(frame) = frames_rx.recv().await {
|
||||||
|
outgoing.send(Message::Text(serde_json::to_string(&frame)?)).await?;
|
||||||
|
match frame {
|
||||||
|
Frame::Dead => return Ok(()),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anyhow::Result::<(), anyhow::Error>::Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
result = broadcast_incoming => {
|
||||||
|
println!("{:?}", result)
|
||||||
|
},
|
||||||
|
result = send_state => {
|
||||||
|
println!("{:?}", result)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{} disconnected", &addr);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
enum Input {
|
||||||
|
UpLeft,
|
||||||
|
UpRight,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
DownLeft,
|
||||||
|
DownRight,
|
||||||
|
Dig
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
enum Frame {
|
||||||
|
Dead,
|
||||||
|
Display { nearby: Vec<(i64, i64, char, f32)>, health: f32 },
|
||||||
|
PlayerCount(usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Client {
|
||||||
|
inputs_rx: mpsc::Receiver<Input>,
|
||||||
|
frames_tx: mpsc::Sender<Frame>,
|
||||||
|
entity: Entity
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GameState {
|
||||||
|
world: World,
|
||||||
|
clients: Slab<Client>,
|
||||||
|
ticks: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum Item {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct PlayerCharacter;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
struct Position(Coord);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
struct MovingInto(Coord);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Health(f32, f32);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Render(char);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Attack { damage: StochasticNumber, energy: f32 }
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct RangedAttack { damage: StochasticNumber, energy: f32, range: u64 }
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct DespawnOnTick(u64);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct DespawnRandomly(u64);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct EnemyTarget { spawn_range: std::ops::RangeInclusive<i64>, spawn_density: f32, spawn_rate_inv: usize, aggression_range: i64 }
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Enemy;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct MoveCost(StochasticNumber);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Collidable;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Velocity(CoordVec);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct DeferredRandomly<T: Clone + std::fmt::Debug + hecs::Bundle>(u64, T);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Terrain;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Obstruction { entry_cost: StochasticNumber, exit_cost: StochasticNumber }
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Energy { current: f32, regeneration_rate: f32, burst: f32 }
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct DespawnOnImpact;
|
||||||
|
|
||||||
|
impl Energy {
|
||||||
|
fn try_consume(&mut self, cost: f32) -> bool {
|
||||||
|
if self.current >= -1e-12 { // numerics
|
||||||
|
self.current -= cost;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const VIEW: i64 = 15;
|
||||||
|
const WALL: i64 = 128;
|
||||||
|
const RANDOM_DESPAWN_INV_RATE: u64 = 4000;
|
||||||
|
const DIRECTIONS: &[CoordVec] = &[CoordVec::new(0, -1), CoordVec::new(1, -1), CoordVec::new(-1, 0), CoordVec::new(1, 0), CoordVec::new(0, 1), CoordVec::new(-1, 1)];
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
enum BaseTerrain {
|
||||||
|
Empty,
|
||||||
|
Occupied,
|
||||||
|
VeryOccupied
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BaseTerrain {
|
||||||
|
fn can_enter(&self) -> bool {
|
||||||
|
*self == BaseTerrain::Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symbol(&self) -> Option<char> {
|
||||||
|
match *self {
|
||||||
|
Self::Empty => None,
|
||||||
|
Self::Occupied => Some('#'),
|
||||||
|
Self::VeryOccupied => Some('█')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NOISE_SCALE: f32 = 0.05;
|
||||||
|
|
||||||
|
fn get_base_terrain(pos: Coord) -> BaseTerrain {
|
||||||
|
let distance = hex_distance(pos, Coord::origin());
|
||||||
|
if distance >= (WALL + 12) {
|
||||||
|
return BaseTerrain::VeryOccupied
|
||||||
|
}
|
||||||
|
if distance >= WALL {
|
||||||
|
return BaseTerrain::Occupied
|
||||||
|
}
|
||||||
|
let pos = to_cubic(pos);
|
||||||
|
let noise = noise_functions::CellDistance.ridged(2, 1.00, 0.20).seed(406).sample3([pos.x as f32 * NOISE_SCALE, pos.y as f32 * NOISE_SCALE, pos.z as f32 * NOISE_SCALE]);
|
||||||
|
if noise >= 0.3 {
|
||||||
|
return BaseTerrain::VeryOccupied
|
||||||
|
}
|
||||||
|
if noise >= 0.2 {
|
||||||
|
return BaseTerrain::Occupied
|
||||||
|
}
|
||||||
|
return BaseTerrain::Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sample_range(range: i64) -> CoordVec {
|
||||||
|
let q = fastrand::i64(-range..=range);
|
||||||
|
let r = fastrand::i64((-range).max(-q-range)..=range.min(-q+range));
|
||||||
|
CoordVec::new(q, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EnemySpec {
|
||||||
|
symbol: char,
|
||||||
|
min_damage: f32,
|
||||||
|
damage_range: f32,
|
||||||
|
initial_health: f32,
|
||||||
|
move_delay: usize,
|
||||||
|
attack_cooldown: u64,
|
||||||
|
ranged: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnemySpec {
|
||||||
|
// Numbers ported from original EWO. Fudge constants added elsewhere.
|
||||||
|
fn random() -> EnemySpec {
|
||||||
|
match fastrand::usize(0..650) {
|
||||||
|
0..=99 => EnemySpec { symbol: 'I', min_damage: 10.0, damage_range: 5.0, initial_health: 50.0, move_delay: 70, attack_cooldown: 10, ranged: false }, // IBIS
|
||||||
|
100..=199 => EnemySpec { symbol: 'K', min_damage: 5.0, damage_range: 15.0, initial_health: 30.0, move_delay: 40, attack_cooldown: 10, ranged: false }, // KESTREL
|
||||||
|
200..=299 => EnemySpec { symbol: 'S', min_damage: 5.0, damage_range: 5.0, initial_health: 20.0, move_delay: 50, attack_cooldown: 10, ranged: false }, // SNAKE
|
||||||
|
300..=399 => EnemySpec { symbol: 'E', min_damage: 10.0, damage_range: 20.0, initial_health: 80.0, move_delay: 80, attack_cooldown: 10, ranged: false }, // EMU
|
||||||
|
400..=499 => EnemySpec { symbol: 'O', min_damage: 8.0, damage_range: 17.0, initial_health: 150.0, move_delay: 100, attack_cooldown: 10, ranged: false }, // OGRE
|
||||||
|
500..=599 => EnemySpec { symbol: 'R', min_damage: 5.0, damage_range: 5.0, initial_health: 15.0, move_delay: 40, attack_cooldown: 10, ranged: false }, // RAT
|
||||||
|
600..=609 => EnemySpec { symbol: 'M' , min_damage: 20.0, damage_range: 10.0, initial_health: 150.0, move_delay: 70, attack_cooldown: 10, ranged: false }, // MOA
|
||||||
|
610..=649 => EnemySpec { symbol: 'P', min_damage: 10.0, damage_range: 5.0, initial_health: 15.0, move_delay: 20, attack_cooldown: 10, ranged: true }, // PLATYPUS
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_hexes(x: i64) -> i64 {
|
||||||
|
x*(x+1)*3+1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rng_from_hash<H: Hash>(x: H) -> fastrand::Rng {
|
||||||
|
let mut h = seahash::SeaHasher::new();
|
||||||
|
x.hash(&mut h);
|
||||||
|
fastrand::Rng::with_seed(h.finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn consume_energy_if_available(e: &mut Option<&mut Energy>, cost: f32) -> bool {
|
||||||
|
e.is_none() || e.as_mut().unwrap().try_consume(cost)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Box-Muller transform
|
||||||
|
fn normal() -> f32 {
|
||||||
|
let u = fastrand::f32();
|
||||||
|
let v = fastrand::f32();
|
||||||
|
(v * std::f32::consts::TAU).cos() * (-2.0 * u.ln()).sqrt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normal_scaled(mu: f32, sigma: f32) -> f32 {
|
||||||
|
normal() * sigma + mu
|
||||||
|
}
|
||||||
|
|
||||||
|
fn triangle_distribution(min: f32, max: f32, mode: f32) -> f32 {
|
||||||
|
let sample = fastrand::f32();
|
||||||
|
let threshold = (mode - min) / (max - min);
|
||||||
|
if sample < threshold {
|
||||||
|
min + (sample * (max - min) * (mode - min)).sqrt()
|
||||||
|
} else {
|
||||||
|
max - ((1.0 - sample) * (max - min) * (max - mode)).sqrt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum StochasticNumber {
|
||||||
|
Constant(f32),
|
||||||
|
Triangle { min: f32, max: f32, mode: f32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StochasticNumber {
|
||||||
|
fn sample(&self) -> f32 {
|
||||||
|
match self {
|
||||||
|
StochasticNumber::Constant(x) => *x,
|
||||||
|
StochasticNumber::Triangle { min, max, mode } => triangle_distribution(*min, *max, *mode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn triangle_from_min_range(min: f32, range: f32) -> Self {
|
||||||
|
StochasticNumber::Triangle { min: min, max: min + range, mode: (min + range) / 2.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn game_tick(state: &mut GameState) -> Result<()> {
|
||||||
|
let mut terrain_positions = HashMap::new();
|
||||||
|
let mut positions = HashMap::new();
|
||||||
|
|
||||||
|
for (entity, pos) in state.world.query_mut::<hecs::With<&Position, &Collidable>>() {
|
||||||
|
positions.insert(pos.0, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, pos) in state.world.query_mut::<hecs::With<&Position, &Terrain>>() {
|
||||||
|
terrain_positions.insert(pos.0, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buffer = hecs::CommandBuffer::new();
|
||||||
|
|
||||||
|
// Spawn enemies
|
||||||
|
for (_entity, (Position(pos), EnemyTarget { spawn_range, spawn_density, spawn_rate_inv, .. })) in state.world.query::<(&Position, &EnemyTarget)>().iter() {
|
||||||
|
if fastrand::usize(0..*spawn_rate_inv) == 0 {
|
||||||
|
let c = count_hexes(*spawn_range.end());
|
||||||
|
let mut newpos = *pos + sample_range(*spawn_range.end());
|
||||||
|
let mut occupied = false;
|
||||||
|
for _ in 0..(c as f32 / spawn_density * 0.005).ceil() as usize {
|
||||||
|
if positions.contains_key(&newpos) {
|
||||||
|
occupied = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
newpos = *pos + sample_range(*spawn_range.end());
|
||||||
|
}
|
||||||
|
if !occupied && get_base_terrain(newpos).can_enter() && hex_distance(newpos, *pos) >= *spawn_range.start() {
|
||||||
|
let spec = EnemySpec::random();
|
||||||
|
if spec.ranged {
|
||||||
|
buffer.spawn((
|
||||||
|
Render(spec.symbol),
|
||||||
|
Health(spec.initial_health, spec.initial_health),
|
||||||
|
Enemy,
|
||||||
|
RangedAttack { damage: StochasticNumber::triangle_from_min_range(spec.min_damage, spec.damage_range), energy: spec.attack_cooldown as f32, range: 4 },
|
||||||
|
Position(newpos),
|
||||||
|
MoveCost(StochasticNumber::Triangle { min: 0.0, max: 2.0 * spec.move_delay as f32 / 3.0, mode: spec.move_delay as f32 / 3.0 }),
|
||||||
|
Collidable,
|
||||||
|
DespawnRandomly(RANDOM_DESPAWN_INV_RATE),
|
||||||
|
Energy { regeneration_rate: 1.0, current: 0.0, burst: 0.0 }
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
buffer.spawn((
|
||||||
|
Render(spec.symbol),
|
||||||
|
Health(spec.initial_health, spec.initial_health),
|
||||||
|
Enemy,
|
||||||
|
Attack { damage: StochasticNumber::triangle_from_min_range(spec.min_damage, spec.damage_range), energy: spec.attack_cooldown as f32 },
|
||||||
|
Position(newpos),
|
||||||
|
MoveCost(StochasticNumber::Triangle { min: 0.0, max: 2.0 * spec.move_delay as f32 / 3.0, mode: spec.move_delay as f32 / 3.0 }),
|
||||||
|
Collidable,
|
||||||
|
DespawnRandomly(RANDOM_DESPAWN_INV_RATE),
|
||||||
|
Energy { regeneration_rate: 1.0, current: 0.0, burst: 0.0 }
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process enemy motion and ranged attacks
|
||||||
|
for (entity, (Position(pos), ranged, energy)) in state.world.query::<hecs::With<(&Position, Option<&mut RangedAttack>, Option<&mut Energy>), &Enemy>>().iter() {
|
||||||
|
for direction in DIRECTIONS.iter() {
|
||||||
|
if let Some(target) = positions.get(&(*pos + *direction)) {
|
||||||
|
if let Ok(_) = state.world.get::<&EnemyTarget>(*target) {
|
||||||
|
buffer.insert_one(entity, MovingInto(*pos + *direction));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut closest = None;
|
||||||
|
|
||||||
|
// TODO we maybe need a spatial index for this
|
||||||
|
for (_entity, (target_pos, target)) in state.world.query::<(&Position, &EnemyTarget)>().iter() {
|
||||||
|
let distance = hex_distance(*pos, target_pos.0);
|
||||||
|
if distance < target.aggression_range {
|
||||||
|
match closest {
|
||||||
|
Some((_pos, old_distance)) if old_distance < distance => closest = Some((target_pos.0, distance)),
|
||||||
|
None => closest = Some((target_pos.0, distance)),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((target_pos, _)) = closest {
|
||||||
|
if let Some(ranged_attack) = ranged {
|
||||||
|
// slightly smart behaviour for ranged attacker: try to stay just within range
|
||||||
|
let direction = DIRECTIONS.iter().min_by_key(|dir|
|
||||||
|
(hex_distance(*pos + **dir, target_pos) - (ranged_attack.range as i64 - 1)).abs()).unwrap();
|
||||||
|
buffer.insert_one(entity, MovingInto(*pos + *direction));
|
||||||
|
// do ranged attack if valid
|
||||||
|
let atk_dir = target_pos - *pos;
|
||||||
|
if on_axis(atk_dir) && (energy.is_none() || energy.unwrap().try_consume(ranged_attack.energy)) {
|
||||||
|
let atk_dir = atk_dir.clamp(-CoordVec::one(), CoordVec::one());
|
||||||
|
buffer.spawn((
|
||||||
|
Render('*'),
|
||||||
|
Enemy,
|
||||||
|
Attack { damage: ranged_attack.damage, energy: 0.0 },
|
||||||
|
Velocity(atk_dir),
|
||||||
|
Position(*pos),
|
||||||
|
DespawnOnTick(state.ticks.wrapping_add(ranged_attack.range))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let direction = DIRECTIONS.iter().min_by_key(|dir| hex_distance(*pos + **dir, target_pos)).unwrap();
|
||||||
|
buffer.insert_one(entity, MovingInto(*pos + *direction));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// wander randomly (ethical)
|
||||||
|
buffer.insert_one(entity, MovingInto(*pos + *fastrand::choice(DIRECTIONS).unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process velocity
|
||||||
|
for (entity, (Position(pos), Velocity(vel))) in state.world.query_mut::<(&Position, &Velocity)>() {
|
||||||
|
buffer.insert_one(entity, MovingInto(*pos + *vel));
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.run_on(&mut state.world);
|
||||||
|
|
||||||
|
// Process inputs
|
||||||
|
for (_id, client) in state.clients.iter_mut() {
|
||||||
|
let mut next_movement = CoordVec::zero();
|
||||||
|
loop {
|
||||||
|
let recv = client.inputs_rx.try_recv();
|
||||||
|
match recv {
|
||||||
|
Err(e) if e == mpsc::error::TryRecvError::Empty => break,
|
||||||
|
Ok(input) => match input {
|
||||||
|
Input::UpLeft => next_movement = CoordVec::new(0, -1),
|
||||||
|
Input::UpRight => next_movement = CoordVec::new(1, -1),
|
||||||
|
Input::Left => next_movement = CoordVec::new(-1, 0),
|
||||||
|
Input::Right => next_movement = CoordVec::new(1, 0),
|
||||||
|
Input::DownRight => next_movement = CoordVec::new(0, 1),
|
||||||
|
Input::DownLeft => next_movement = CoordVec::new(-1, 1),
|
||||||
|
Input::Dig => {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => return Err(e.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let position = state.world.get::<&mut Position>(client.entity)?.0;
|
||||||
|
let target = position + next_movement;
|
||||||
|
if get_base_terrain(target).can_enter() && target != position {
|
||||||
|
state.world.insert_one(client.entity, MovingInto(target)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process motion and attacks
|
||||||
|
for (entity, (Position(current_pos), MovingInto(target_pos), damage, mut energy, move_cost, despawn_on_impact)) in state.world.query::<(&mut Position, &MovingInto, Option<&mut Attack>, Option<&mut Energy>, Option<&MoveCost>, Option<&DespawnOnImpact>)>().iter() {
|
||||||
|
let mut move_cost = move_cost.map(|x| x.0.sample()).unwrap_or(0.0);
|
||||||
|
if let Some(current_terrain) = terrain_positions.get(current_pos) {
|
||||||
|
move_cost += 1.0;
|
||||||
|
}
|
||||||
|
// TODO will break attacks kind of, desirable? Doubtful.
|
||||||
|
if let Some(target_terrain) = terrain_positions.get(target_pos) {
|
||||||
|
move_cost += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if get_base_terrain(*target_pos).can_enter() {
|
||||||
|
let entry = match positions.entry(*target_pos) {
|
||||||
|
Entry::Occupied(o) => {
|
||||||
|
let target_entity = *o.get();
|
||||||
|
if let Ok(mut x) = state.world.get::<&mut Health>(target_entity) {
|
||||||
|
match damage {
|
||||||
|
Some(Attack { damage, energy: energy_cost }) => {
|
||||||
|
if consume_energy_if_available(&mut energy, *energy_cost) {
|
||||||
|
x.0 -= damage.sample();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
if despawn_on_impact.is_some() {
|
||||||
|
buffer.despawn(entity);
|
||||||
|
}
|
||||||
|
if x.0 <= 0.0 {
|
||||||
|
buffer.despawn(target_entity);
|
||||||
|
Some(Entry::Occupied(o))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None // TODO: on pickup or something
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Entry::Vacant(v) => Some(Entry::Vacant(v))
|
||||||
|
};
|
||||||
|
if let Some(entry) = entry {
|
||||||
|
// TODO: perhaps this should be applied to attacks too?
|
||||||
|
if consume_energy_if_available(&mut energy, move_cost) {
|
||||||
|
*entry.or_insert(entity) = entity;
|
||||||
|
positions.remove(current_pos);
|
||||||
|
*current_pos = *target_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.remove_one::<MovingInto>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.run_on(&mut state.world);
|
||||||
|
|
||||||
|
for (_entity, energy) in state.world.query_mut::<&mut Energy>() {
|
||||||
|
energy.current = (energy.current + energy.regeneration_rate).min(energy.burst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process transient entities
|
||||||
|
for (entity, tick) in state.world.query_mut::<&DespawnOnTick>() {
|
||||||
|
if state.ticks == tick.0 {
|
||||||
|
buffer.despawn(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, DespawnRandomly(inv_rate)) in state.world.query_mut::<&DespawnRandomly>() {
|
||||||
|
if fastrand::u64(0..*inv_rate) == 0 {
|
||||||
|
buffer.despawn(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.run_on(&mut state.world);
|
||||||
|
|
||||||
|
// Send views to clients
|
||||||
|
for (_id, client) in state.clients.iter() {
|
||||||
|
client.frames_tx.send(Frame::PlayerCount(state.clients.len())).await?;
|
||||||
|
let mut nearby = vec![];
|
||||||
|
if let Ok(pos) = state.world.get::<&Position>(client.entity) {
|
||||||
|
let pos = pos.0;
|
||||||
|
for q in -VIEW..=VIEW {
|
||||||
|
for r in (-VIEW).max(-q - VIEW)..= VIEW.min(-q+VIEW) {
|
||||||
|
let offset = CoordVec::new(q, r);
|
||||||
|
let pos = pos + offset;
|
||||||
|
if let Some(symbol) = get_base_terrain(pos).symbol() {
|
||||||
|
nearby.push((q, r, symbol, 1.0));
|
||||||
|
} else {
|
||||||
|
if let Some(entity) = positions.get(&pos) {
|
||||||
|
let render = state.world.get::<&Render>(*entity)?;
|
||||||
|
let health = if let Ok(h) = state.world.get::<&Health>(*entity) {
|
||||||
|
h.0 / h.1
|
||||||
|
} else { 1.0 };
|
||||||
|
nearby.push((q, r, render.0, health))
|
||||||
|
} else {
|
||||||
|
let mut rng = rng_from_hash(pos);
|
||||||
|
let bg = if rng.usize(0..10) == 0 { ',' } else { '.' };
|
||||||
|
nearby.push((q, r, bg, rng.f32() * 0.1 + 0.9))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let health = state.world.get::<&Health>(client.entity)?.0;
|
||||||
|
client.frames_tx.send(Frame::Display { nearby, health }).await?;
|
||||||
|
} else {
|
||||||
|
client.frames_tx.send(Frame::Dead).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.ticks = state.ticks.wrapping_add(1);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref IDENTS: Vec<char> = {
|
||||||
|
let mut chars = vec![];
|
||||||
|
for range in [
|
||||||
|
'Α'..='ω',
|
||||||
|
'א'..='ת',
|
||||||
|
'Ⓐ'..='ⓩ',
|
||||||
|
'🨀'..='🨅'
|
||||||
|
] {
|
||||||
|
chars.extend(range);
|
||||||
|
}
|
||||||
|
chars.extend("𝔸𝕒𝔹𝕓ℂ𝕔𝔻𝕕ⅅⅆ𝔼𝕖ⅇ𝔽𝕗𝔾𝕘ℍ𝕙𝕀𝕚ⅈ𝕁𝕛ⅉ𝕂𝕜𝕃𝕝𝕄𝕞ℕ𝕟𝕆𝕠ℙ𝕡ℚ𝕢ℝ𝕣𝕊𝕤𝕋𝕥𝕌𝕦𝕍𝕧𝕎𝕨𝕏𝕩𝕐𝕪ℤ𝕫ℾℽℿℼ⅀𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡🩊".chars());
|
||||||
|
chars
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_identifier() -> char {
|
||||||
|
*fastrand::choice(IDENTS.iter()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_new_player(state: &mut GameState) -> Result<Entity> {
|
||||||
|
let pos = loop {
|
||||||
|
let pos = Coord::origin() + sample_range(WALL - 10);
|
||||||
|
if get_base_terrain(pos).can_enter() {
|
||||||
|
break pos;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(state.world.spawn((
|
||||||
|
Position(pos),
|
||||||
|
PlayerCharacter,
|
||||||
|
Render(random_identifier()),
|
||||||
|
Collidable,
|
||||||
|
Attack { damage: StochasticNumber::Triangle { min: 20.0, max: 60.0, mode: 20.0 }, energy: 5.0 },
|
||||||
|
Health(128.0, 128.0),
|
||||||
|
EnemyTarget {
|
||||||
|
spawn_density: 0.01,
|
||||||
|
spawn_range: 3..=10,
|
||||||
|
spawn_rate_inv: 20,
|
||||||
|
aggression_range: 5
|
||||||
|
}
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
let addr = std::env::args().nth(1).unwrap_or_else(|| "0.0.0.0:8080".to_string());
|
||||||
|
|
||||||
|
let state = Arc::new(Mutex::new(GameState {
|
||||||
|
world: World::new(),
|
||||||
|
clients: Slab::new(),
|
||||||
|
ticks: 0
|
||||||
|
}));
|
||||||
|
|
||||||
|
let try_socket = TcpListener::bind(&addr).await;
|
||||||
|
let listener = try_socket.expect("Failed to bind");
|
||||||
|
println!("Listening on: {}", addr);
|
||||||
|
|
||||||
|
let state_ = state.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let state = state_.clone();
|
||||||
|
let mut interval = tokio::time::interval(Duration::from_millis(56));
|
||||||
|
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
|
||||||
|
loop {
|
||||||
|
let mut state = state.lock().await;
|
||||||
|
if let Err(e) = game_tick(&mut state).await {
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
interval.tick().await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let state_ = state.clone();
|
||||||
|
while let Ok((stream, addr)) = listener.accept().await {
|
||||||
|
let state_ = state_.clone();
|
||||||
|
let (frames_tx, frames_rx) = mpsc::channel(10);
|
||||||
|
let (inputs_tx, inputs_rx) = mpsc::channel(10);
|
||||||
|
let (id, entity) = {
|
||||||
|
let mut state = state_.lock().await;
|
||||||
|
let entity = add_new_player(&mut state)?; // TODO
|
||||||
|
let client = Client {
|
||||||
|
inputs_rx,
|
||||||
|
frames_tx,
|
||||||
|
entity
|
||||||
|
};
|
||||||
|
let id = state.clients.insert(client);
|
||||||
|
(id, entity)
|
||||||
|
};
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
println!("conn result {:?}", handle_connection(stream, addr, frames_rx, inputs_tx).await);
|
||||||
|
let mut state = state_.lock().await;
|
||||||
|
state.clients.remove(id);
|
||||||
|
let _ = state.world.despawn(entity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
0
src/util.js
Normal file
0
src/util.js
Normal file
71
static/app.css
Normal file
71
static/app.css
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* fakecss:/home/osmarks/Programming/ewo3/src/App.esbuild-svelte-fake-css */
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
scrollbar-color: black lightgray;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family:
|
||||||
|
"Fira Sans",
|
||||||
|
"Noto Sans",
|
||||||
|
"Segoe UI",
|
||||||
|
Verdana,
|
||||||
|
sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
overflow-anchor: none;
|
||||||
|
}
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
h5 {
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: square;
|
||||||
|
padding: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
.game-display.svelte-oncm9j .row.svelte-oncm9j {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.game-display.svelte-oncm9j .row .cell.svelte-oncm9j {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.wrapper.svelte-oncm9j.svelte-oncm9j {
|
||||||
|
display: flex;
|
||||||
|
}
|
802
static/app.js
Normal file
802
static/app.js
Normal file
@ -0,0 +1,802 @@
|
|||||||
|
(() => {
|
||||||
|
// node_modules/svelte/internal/index.mjs
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
function run(fn) {
|
||||||
|
return fn();
|
||||||
|
}
|
||||||
|
function blank_object() {
|
||||||
|
return Object.create(null);
|
||||||
|
}
|
||||||
|
function run_all(fns) {
|
||||||
|
fns.forEach(run);
|
||||||
|
}
|
||||||
|
function is_function(thing) {
|
||||||
|
return typeof thing === "function";
|
||||||
|
}
|
||||||
|
function safe_not_equal(a, b) {
|
||||||
|
return a != a ? b == b : a !== b || (a && typeof a === "object" || typeof a === "function");
|
||||||
|
}
|
||||||
|
function is_empty(obj) {
|
||||||
|
return Object.keys(obj).length === 0;
|
||||||
|
}
|
||||||
|
var tasks = new Set();
|
||||||
|
var is_hydrating = false;
|
||||||
|
function start_hydrating() {
|
||||||
|
is_hydrating = true;
|
||||||
|
}
|
||||||
|
function end_hydrating() {
|
||||||
|
is_hydrating = false;
|
||||||
|
}
|
||||||
|
function upper_bound(low, high, key, value) {
|
||||||
|
while (low < high) {
|
||||||
|
const mid = low + (high - low >> 1);
|
||||||
|
if (key(mid) <= value) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
high = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
function init_hydrate(target) {
|
||||||
|
if (target.hydrate_init)
|
||||||
|
return;
|
||||||
|
target.hydrate_init = true;
|
||||||
|
const children2 = target.childNodes;
|
||||||
|
const m = new Int32Array(children2.length + 1);
|
||||||
|
const p = new Int32Array(children2.length);
|
||||||
|
m[0] = -1;
|
||||||
|
let longest = 0;
|
||||||
|
for (let i = 0; i < children2.length; i++) {
|
||||||
|
const current = children2[i].claim_order;
|
||||||
|
const seqLen = upper_bound(1, longest + 1, (idx) => children2[m[idx]].claim_order, current) - 1;
|
||||||
|
p[i] = m[seqLen] + 1;
|
||||||
|
const newLen = seqLen + 1;
|
||||||
|
m[newLen] = i;
|
||||||
|
longest = Math.max(newLen, longest);
|
||||||
|
}
|
||||||
|
const lis = [];
|
||||||
|
const toMove = [];
|
||||||
|
let last = children2.length - 1;
|
||||||
|
for (let cur = m[longest] + 1; cur != 0; cur = p[cur - 1]) {
|
||||||
|
lis.push(children2[cur - 1]);
|
||||||
|
for (; last >= cur; last--) {
|
||||||
|
toMove.push(children2[last]);
|
||||||
|
}
|
||||||
|
last--;
|
||||||
|
}
|
||||||
|
for (; last >= 0; last--) {
|
||||||
|
toMove.push(children2[last]);
|
||||||
|
}
|
||||||
|
lis.reverse();
|
||||||
|
toMove.sort((a, b) => a.claim_order - b.claim_order);
|
||||||
|
for (let i = 0, j = 0; i < toMove.length; i++) {
|
||||||
|
while (j < lis.length && toMove[i].claim_order >= lis[j].claim_order) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
const anchor = j < lis.length ? lis[j] : null;
|
||||||
|
target.insertBefore(toMove[i], anchor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function append(target, node) {
|
||||||
|
if (is_hydrating) {
|
||||||
|
init_hydrate(target);
|
||||||
|
if (target.actual_end_child === void 0 || target.actual_end_child !== null && target.actual_end_child.parentElement !== target) {
|
||||||
|
target.actual_end_child = target.firstChild;
|
||||||
|
}
|
||||||
|
if (node !== target.actual_end_child) {
|
||||||
|
target.insertBefore(node, target.actual_end_child);
|
||||||
|
} else {
|
||||||
|
target.actual_end_child = node.nextSibling;
|
||||||
|
}
|
||||||
|
} else if (node.parentNode !== target) {
|
||||||
|
target.appendChild(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function insert(target, node, anchor) {
|
||||||
|
if (is_hydrating && !anchor) {
|
||||||
|
append(target, node);
|
||||||
|
} else if (node.parentNode !== target || anchor && node.nextSibling !== anchor) {
|
||||||
|
target.insertBefore(node, anchor || null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function detach(node) {
|
||||||
|
node.parentNode.removeChild(node);
|
||||||
|
}
|
||||||
|
function destroy_each(iterations, detaching) {
|
||||||
|
for (let i = 0; i < iterations.length; i += 1) {
|
||||||
|
if (iterations[i])
|
||||||
|
iterations[i].d(detaching);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function element(name) {
|
||||||
|
return document.createElement(name);
|
||||||
|
}
|
||||||
|
function text(data) {
|
||||||
|
return document.createTextNode(data);
|
||||||
|
}
|
||||||
|
function space() {
|
||||||
|
return text(" ");
|
||||||
|
}
|
||||||
|
function listen(node, event, handler, options) {
|
||||||
|
node.addEventListener(event, handler, options);
|
||||||
|
return () => node.removeEventListener(event, handler, options);
|
||||||
|
}
|
||||||
|
function attr(node, attribute, value) {
|
||||||
|
if (value == null)
|
||||||
|
node.removeAttribute(attribute);
|
||||||
|
else if (node.getAttribute(attribute) !== value)
|
||||||
|
node.setAttribute(attribute, value);
|
||||||
|
}
|
||||||
|
function children(element2) {
|
||||||
|
return Array.from(element2.childNodes);
|
||||||
|
}
|
||||||
|
function set_data(text2, data) {
|
||||||
|
data = "" + data;
|
||||||
|
if (text2.wholeText !== data)
|
||||||
|
text2.data = data;
|
||||||
|
}
|
||||||
|
var active_docs = new Set();
|
||||||
|
var current_component;
|
||||||
|
function set_current_component(component) {
|
||||||
|
current_component = component;
|
||||||
|
}
|
||||||
|
var dirty_components = [];
|
||||||
|
var binding_callbacks = [];
|
||||||
|
var render_callbacks = [];
|
||||||
|
var flush_callbacks = [];
|
||||||
|
var resolved_promise = Promise.resolve();
|
||||||
|
var update_scheduled = false;
|
||||||
|
function schedule_update() {
|
||||||
|
if (!update_scheduled) {
|
||||||
|
update_scheduled = true;
|
||||||
|
resolved_promise.then(flush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function add_render_callback(fn) {
|
||||||
|
render_callbacks.push(fn);
|
||||||
|
}
|
||||||
|
var flushing = false;
|
||||||
|
var seen_callbacks = new Set();
|
||||||
|
function flush() {
|
||||||
|
if (flushing)
|
||||||
|
return;
|
||||||
|
flushing = true;
|
||||||
|
do {
|
||||||
|
for (let i = 0; i < dirty_components.length; i += 1) {
|
||||||
|
const component = dirty_components[i];
|
||||||
|
set_current_component(component);
|
||||||
|
update(component.$$);
|
||||||
|
}
|
||||||
|
set_current_component(null);
|
||||||
|
dirty_components.length = 0;
|
||||||
|
while (binding_callbacks.length)
|
||||||
|
binding_callbacks.pop()();
|
||||||
|
for (let i = 0; i < render_callbacks.length; i += 1) {
|
||||||
|
const callback = render_callbacks[i];
|
||||||
|
if (!seen_callbacks.has(callback)) {
|
||||||
|
seen_callbacks.add(callback);
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render_callbacks.length = 0;
|
||||||
|
} while (dirty_components.length);
|
||||||
|
while (flush_callbacks.length) {
|
||||||
|
flush_callbacks.pop()();
|
||||||
|
}
|
||||||
|
update_scheduled = false;
|
||||||
|
flushing = false;
|
||||||
|
seen_callbacks.clear();
|
||||||
|
}
|
||||||
|
function update($$) {
|
||||||
|
if ($$.fragment !== null) {
|
||||||
|
$$.update();
|
||||||
|
run_all($$.before_update);
|
||||||
|
const dirty = $$.dirty;
|
||||||
|
$$.dirty = [-1];
|
||||||
|
$$.fragment && $$.fragment.p($$.ctx, dirty);
|
||||||
|
$$.after_update.forEach(add_render_callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var outroing = new Set();
|
||||||
|
function transition_in(block, local) {
|
||||||
|
if (block && block.i) {
|
||||||
|
outroing.delete(block);
|
||||||
|
block.i(local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var globals = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : global;
|
||||||
|
var boolean_attributes = new Set([
|
||||||
|
"allowfullscreen",
|
||||||
|
"allowpaymentrequest",
|
||||||
|
"async",
|
||||||
|
"autofocus",
|
||||||
|
"autoplay",
|
||||||
|
"checked",
|
||||||
|
"controls",
|
||||||
|
"default",
|
||||||
|
"defer",
|
||||||
|
"disabled",
|
||||||
|
"formnovalidate",
|
||||||
|
"hidden",
|
||||||
|
"ismap",
|
||||||
|
"loop",
|
||||||
|
"multiple",
|
||||||
|
"muted",
|
||||||
|
"nomodule",
|
||||||
|
"novalidate",
|
||||||
|
"open",
|
||||||
|
"playsinline",
|
||||||
|
"readonly",
|
||||||
|
"required",
|
||||||
|
"reversed",
|
||||||
|
"selected"
|
||||||
|
]);
|
||||||
|
function mount_component(component, target, anchor, customElement) {
|
||||||
|
const { fragment, on_mount, on_destroy, after_update } = component.$$;
|
||||||
|
fragment && fragment.m(target, anchor);
|
||||||
|
if (!customElement) {
|
||||||
|
add_render_callback(() => {
|
||||||
|
const new_on_destroy = on_mount.map(run).filter(is_function);
|
||||||
|
if (on_destroy) {
|
||||||
|
on_destroy.push(...new_on_destroy);
|
||||||
|
} else {
|
||||||
|
run_all(new_on_destroy);
|
||||||
|
}
|
||||||
|
component.$$.on_mount = [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
after_update.forEach(add_render_callback);
|
||||||
|
}
|
||||||
|
function destroy_component(component, detaching) {
|
||||||
|
const $$ = component.$$;
|
||||||
|
if ($$.fragment !== null) {
|
||||||
|
run_all($$.on_destroy);
|
||||||
|
$$.fragment && $$.fragment.d(detaching);
|
||||||
|
$$.on_destroy = $$.fragment = null;
|
||||||
|
$$.ctx = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function make_dirty(component, i) {
|
||||||
|
if (component.$$.dirty[0] === -1) {
|
||||||
|
dirty_components.push(component);
|
||||||
|
schedule_update();
|
||||||
|
component.$$.dirty.fill(0);
|
||||||
|
}
|
||||||
|
component.$$.dirty[i / 31 | 0] |= 1 << i % 31;
|
||||||
|
}
|
||||||
|
function init(component, options, instance2, create_fragment2, not_equal, props, dirty = [-1]) {
|
||||||
|
const parent_component = current_component;
|
||||||
|
set_current_component(component);
|
||||||
|
const $$ = component.$$ = {
|
||||||
|
fragment: null,
|
||||||
|
ctx: null,
|
||||||
|
props,
|
||||||
|
update: noop,
|
||||||
|
not_equal,
|
||||||
|
bound: blank_object(),
|
||||||
|
on_mount: [],
|
||||||
|
on_destroy: [],
|
||||||
|
on_disconnect: [],
|
||||||
|
before_update: [],
|
||||||
|
after_update: [],
|
||||||
|
context: new Map(parent_component ? parent_component.$$.context : options.context || []),
|
||||||
|
callbacks: blank_object(),
|
||||||
|
dirty,
|
||||||
|
skip_bound: false
|
||||||
|
};
|
||||||
|
let ready = false;
|
||||||
|
$$.ctx = instance2 ? instance2(component, options.props || {}, (i, ret, ...rest) => {
|
||||||
|
const value = rest.length ? rest[0] : ret;
|
||||||
|
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
|
||||||
|
if (!$$.skip_bound && $$.bound[i])
|
||||||
|
$$.bound[i](value);
|
||||||
|
if (ready)
|
||||||
|
make_dirty(component, i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}) : [];
|
||||||
|
$$.update();
|
||||||
|
ready = true;
|
||||||
|
run_all($$.before_update);
|
||||||
|
$$.fragment = create_fragment2 ? create_fragment2($$.ctx) : false;
|
||||||
|
if (options.target) {
|
||||||
|
if (options.hydrate) {
|
||||||
|
start_hydrating();
|
||||||
|
const nodes = children(options.target);
|
||||||
|
$$.fragment && $$.fragment.l(nodes);
|
||||||
|
nodes.forEach(detach);
|
||||||
|
} else {
|
||||||
|
$$.fragment && $$.fragment.c();
|
||||||
|
}
|
||||||
|
if (options.intro)
|
||||||
|
transition_in(component.$$.fragment);
|
||||||
|
mount_component(component, options.target, options.anchor, options.customElement);
|
||||||
|
end_hydrating();
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
set_current_component(parent_component);
|
||||||
|
}
|
||||||
|
var SvelteElement;
|
||||||
|
if (typeof HTMLElement === "function") {
|
||||||
|
SvelteElement = class extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.attachShadow({ mode: "open" });
|
||||||
|
}
|
||||||
|
connectedCallback() {
|
||||||
|
const { on_mount } = this.$$;
|
||||||
|
this.$$.on_disconnect = on_mount.map(run).filter(is_function);
|
||||||
|
for (const key in this.$$.slotted) {
|
||||||
|
this.appendChild(this.$$.slotted[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attributeChangedCallback(attr2, _oldValue, newValue) {
|
||||||
|
this[attr2] = newValue;
|
||||||
|
}
|
||||||
|
disconnectedCallback() {
|
||||||
|
run_all(this.$$.on_disconnect);
|
||||||
|
}
|
||||||
|
$destroy() {
|
||||||
|
destroy_component(this, 1);
|
||||||
|
this.$destroy = noop;
|
||||||
|
}
|
||||||
|
$on(type, callback) {
|
||||||
|
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
|
||||||
|
callbacks.push(callback);
|
||||||
|
return () => {
|
||||||
|
const index = callbacks.indexOf(callback);
|
||||||
|
if (index !== -1)
|
||||||
|
callbacks.splice(index, 1);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
$set($$props) {
|
||||||
|
if (this.$$set && !is_empty($$props)) {
|
||||||
|
this.$$.skip_bound = true;
|
||||||
|
this.$$set($$props);
|
||||||
|
this.$$.skip_bound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var SvelteComponent = class {
|
||||||
|
$destroy() {
|
||||||
|
destroy_component(this, 1);
|
||||||
|
this.$destroy = noop;
|
||||||
|
}
|
||||||
|
$on(type, callback) {
|
||||||
|
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
|
||||||
|
callbacks.push(callback);
|
||||||
|
return () => {
|
||||||
|
const index = callbacks.indexOf(callback);
|
||||||
|
if (index !== -1)
|
||||||
|
callbacks.splice(index, 1);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
$set($$props) {
|
||||||
|
if (this.$$set && !is_empty($$props)) {
|
||||||
|
this.$$.skip_bound = true;
|
||||||
|
this.$$set($$props);
|
||||||
|
this.$$.skip_bound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/App.svelte
|
||||||
|
var { window: window_1 } = globals;
|
||||||
|
function get_each_context(ctx, list, i) {
|
||||||
|
const child_ctx = ctx.slice();
|
||||||
|
child_ctx[17] = list[i];
|
||||||
|
child_ctx[19] = i;
|
||||||
|
return child_ctx;
|
||||||
|
}
|
||||||
|
function get_each_context_1(ctx, list, i) {
|
||||||
|
const child_ctx = ctx.slice();
|
||||||
|
child_ctx[20] = list[i];
|
||||||
|
return child_ctx;
|
||||||
|
}
|
||||||
|
function create_each_block_1(ctx) {
|
||||||
|
let div;
|
||||||
|
let t_value = ctx[20][0] + "";
|
||||||
|
let t;
|
||||||
|
let div_style_value;
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
div = element("div");
|
||||||
|
t = text(t_value);
|
||||||
|
attr(div, "class", "cell svelte-oncm9j");
|
||||||
|
attr(div, "style", div_style_value = `width: ${ctx[5]}px; height: ${ctx[6]}px; line-height: ${ctx[6]}px; opacity: ${ctx[20][1] * 100}%`);
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, div, anchor);
|
||||||
|
append(div, t);
|
||||||
|
},
|
||||||
|
p(ctx2, dirty) {
|
||||||
|
if (dirty & 8 && t_value !== (t_value = ctx2[20][0] + ""))
|
||||||
|
set_data(t, t_value);
|
||||||
|
if (dirty & 8 && div_style_value !== (div_style_value = `width: ${ctx2[5]}px; height: ${ctx2[6]}px; line-height: ${ctx2[6]}px; opacity: ${ctx2[20][1] * 100}%`)) {
|
||||||
|
attr(div, "style", div_style_value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching)
|
||||||
|
detach(div);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function create_each_block(ctx) {
|
||||||
|
let div;
|
||||||
|
let t;
|
||||||
|
let div_style_value;
|
||||||
|
let each_value_1 = ctx[17];
|
||||||
|
let each_blocks = [];
|
||||||
|
for (let i = 0; i < each_value_1.length; i += 1) {
|
||||||
|
each_blocks[i] = create_each_block_1(get_each_context_1(ctx, each_value_1, i));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
div = element("div");
|
||||||
|
for (let i = 0; i < each_blocks.length; i += 1) {
|
||||||
|
each_blocks[i].c();
|
||||||
|
}
|
||||||
|
t = space();
|
||||||
|
attr(div, "class", "row svelte-oncm9j");
|
||||||
|
attr(div, "style", div_style_value = `height: ${ctx[6]}px; ` + (ctx[19] % 2 === 1 ? `padding-left: ${ctx[5] / 2}px` : ""));
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, div, anchor);
|
||||||
|
for (let i = 0; i < each_blocks.length; i += 1) {
|
||||||
|
each_blocks[i].m(div, null);
|
||||||
|
}
|
||||||
|
append(div, t);
|
||||||
|
},
|
||||||
|
p(ctx2, dirty) {
|
||||||
|
if (dirty & 104) {
|
||||||
|
each_value_1 = ctx2[17];
|
||||||
|
let i;
|
||||||
|
for (i = 0; i < each_value_1.length; i += 1) {
|
||||||
|
const child_ctx = get_each_context_1(ctx2, each_value_1, i);
|
||||||
|
if (each_blocks[i]) {
|
||||||
|
each_blocks[i].p(child_ctx, dirty);
|
||||||
|
} else {
|
||||||
|
each_blocks[i] = create_each_block_1(child_ctx);
|
||||||
|
each_blocks[i].c();
|
||||||
|
each_blocks[i].m(div, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; i < each_blocks.length; i += 1) {
|
||||||
|
each_blocks[i].d(1);
|
||||||
|
}
|
||||||
|
each_blocks.length = each_value_1.length;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching)
|
||||||
|
detach(div);
|
||||||
|
destroy_each(each_blocks, detaching);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function create_if_block_2(ctx) {
|
||||||
|
let t0;
|
||||||
|
let a;
|
||||||
|
let t2;
|
||||||
|
let mounted;
|
||||||
|
let dispose;
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
t0 = text("You have died to death. ");
|
||||||
|
a = element("a");
|
||||||
|
a.textContent = "Restart";
|
||||||
|
t2 = text(".");
|
||||||
|
attr(a, "href", "#");
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, t0, anchor);
|
||||||
|
insert(target, a, anchor);
|
||||||
|
insert(target, t2, anchor);
|
||||||
|
if (!mounted) {
|
||||||
|
dispose = listen(a, "click", ctx[4]);
|
||||||
|
mounted = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
p: noop,
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching)
|
||||||
|
detach(t0);
|
||||||
|
if (detaching)
|
||||||
|
detach(a);
|
||||||
|
if (detaching)
|
||||||
|
detach(t2);
|
||||||
|
mounted = false;
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function create_if_block_1(ctx) {
|
||||||
|
let t0;
|
||||||
|
let t1;
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
t0 = text(ctx[2]);
|
||||||
|
t1 = text(" connected players.");
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, t0, anchor);
|
||||||
|
insert(target, t1, anchor);
|
||||||
|
},
|
||||||
|
p(ctx2, dirty) {
|
||||||
|
if (dirty & 4)
|
||||||
|
set_data(t0, ctx2[2]);
|
||||||
|
},
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching)
|
||||||
|
detach(t0);
|
||||||
|
if (detaching)
|
||||||
|
detach(t1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function create_if_block(ctx) {
|
||||||
|
let t0;
|
||||||
|
let t1;
|
||||||
|
let t2;
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
t0 = text("Your health is ");
|
||||||
|
t1 = text(ctx[1]);
|
||||||
|
t2 = text(".");
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, t0, anchor);
|
||||||
|
insert(target, t1, anchor);
|
||||||
|
insert(target, t2, anchor);
|
||||||
|
},
|
||||||
|
p(ctx2, dirty) {
|
||||||
|
if (dirty & 2)
|
||||||
|
set_data(t1, ctx2[1]);
|
||||||
|
},
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching)
|
||||||
|
detach(t0);
|
||||||
|
if (detaching)
|
||||||
|
detach(t1);
|
||||||
|
if (detaching)
|
||||||
|
detach(t2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function create_fragment(ctx) {
|
||||||
|
let h1;
|
||||||
|
let t1;
|
||||||
|
let div2;
|
||||||
|
let div0;
|
||||||
|
let t2;
|
||||||
|
let div1;
|
||||||
|
let t3;
|
||||||
|
let t4;
|
||||||
|
let mounted;
|
||||||
|
let dispose;
|
||||||
|
let each_value = ctx[3];
|
||||||
|
let each_blocks = [];
|
||||||
|
for (let i = 0; i < each_value.length; i += 1) {
|
||||||
|
each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
|
||||||
|
}
|
||||||
|
let if_block0 = ctx[0] && create_if_block_2(ctx);
|
||||||
|
let if_block1 = ctx[2] && create_if_block_1(ctx);
|
||||||
|
let if_block2 = ctx[1] && create_if_block(ctx);
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
h1 = element("h1");
|
||||||
|
h1.textContent = "EWO3 Memetic Edition";
|
||||||
|
t1 = space();
|
||||||
|
div2 = element("div");
|
||||||
|
div0 = element("div");
|
||||||
|
for (let i = 0; i < each_blocks.length; i += 1) {
|
||||||
|
each_blocks[i].c();
|
||||||
|
}
|
||||||
|
t2 = space();
|
||||||
|
div1 = element("div");
|
||||||
|
if (if_block0)
|
||||||
|
if_block0.c();
|
||||||
|
t3 = space();
|
||||||
|
if (if_block1)
|
||||||
|
if_block1.c();
|
||||||
|
t4 = space();
|
||||||
|
if (if_block2)
|
||||||
|
if_block2.c();
|
||||||
|
attr(div0, "class", "game-display svelte-oncm9j");
|
||||||
|
attr(div1, "class", "controls");
|
||||||
|
attr(div2, "class", "wrapper svelte-oncm9j");
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, h1, anchor);
|
||||||
|
insert(target, t1, anchor);
|
||||||
|
insert(target, div2, anchor);
|
||||||
|
append(div2, div0);
|
||||||
|
for (let i = 0; i < each_blocks.length; i += 1) {
|
||||||
|
each_blocks[i].m(div0, null);
|
||||||
|
}
|
||||||
|
append(div2, t2);
|
||||||
|
append(div2, div1);
|
||||||
|
if (if_block0)
|
||||||
|
if_block0.m(div1, null);
|
||||||
|
append(div1, t3);
|
||||||
|
if (if_block1)
|
||||||
|
if_block1.m(div1, null);
|
||||||
|
append(div1, t4);
|
||||||
|
if (if_block2)
|
||||||
|
if_block2.m(div1, null);
|
||||||
|
if (!mounted) {
|
||||||
|
dispose = [
|
||||||
|
listen(window_1, "keydown", ctx[7]),
|
||||||
|
listen(window_1, "keyup", ctx[8])
|
||||||
|
];
|
||||||
|
mounted = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
p(ctx2, [dirty]) {
|
||||||
|
if (dirty & 104) {
|
||||||
|
each_value = ctx2[3];
|
||||||
|
let i;
|
||||||
|
for (i = 0; i < each_value.length; i += 1) {
|
||||||
|
const child_ctx = get_each_context(ctx2, each_value, i);
|
||||||
|
if (each_blocks[i]) {
|
||||||
|
each_blocks[i].p(child_ctx, dirty);
|
||||||
|
} else {
|
||||||
|
each_blocks[i] = create_each_block(child_ctx);
|
||||||
|
each_blocks[i].c();
|
||||||
|
each_blocks[i].m(div0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; i < each_blocks.length; i += 1) {
|
||||||
|
each_blocks[i].d(1);
|
||||||
|
}
|
||||||
|
each_blocks.length = each_value.length;
|
||||||
|
}
|
||||||
|
if (ctx2[0]) {
|
||||||
|
if (if_block0) {
|
||||||
|
if_block0.p(ctx2, dirty);
|
||||||
|
} else {
|
||||||
|
if_block0 = create_if_block_2(ctx2);
|
||||||
|
if_block0.c();
|
||||||
|
if_block0.m(div1, t3);
|
||||||
|
}
|
||||||
|
} else if (if_block0) {
|
||||||
|
if_block0.d(1);
|
||||||
|
if_block0 = null;
|
||||||
|
}
|
||||||
|
if (ctx2[2]) {
|
||||||
|
if (if_block1) {
|
||||||
|
if_block1.p(ctx2, dirty);
|
||||||
|
} else {
|
||||||
|
if_block1 = create_if_block_1(ctx2);
|
||||||
|
if_block1.c();
|
||||||
|
if_block1.m(div1, t4);
|
||||||
|
}
|
||||||
|
} else if (if_block1) {
|
||||||
|
if_block1.d(1);
|
||||||
|
if_block1 = null;
|
||||||
|
}
|
||||||
|
if (ctx2[1]) {
|
||||||
|
if (if_block2) {
|
||||||
|
if_block2.p(ctx2, dirty);
|
||||||
|
} else {
|
||||||
|
if_block2 = create_if_block(ctx2);
|
||||||
|
if_block2.c();
|
||||||
|
if_block2.m(div1, null);
|
||||||
|
}
|
||||||
|
} else if (if_block2) {
|
||||||
|
if_block2.d(1);
|
||||||
|
if_block2 = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
i: noop,
|
||||||
|
o: noop,
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching)
|
||||||
|
detach(h1);
|
||||||
|
if (detaching)
|
||||||
|
detach(t1);
|
||||||
|
if (detaching)
|
||||||
|
detach(div2);
|
||||||
|
destroy_each(each_blocks, detaching);
|
||||||
|
if (if_block0)
|
||||||
|
if_block0.d();
|
||||||
|
if (if_block1)
|
||||||
|
if_block1.d();
|
||||||
|
if (if_block2)
|
||||||
|
if_block2.d();
|
||||||
|
mounted = false;
|
||||||
|
run_all(dispose);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var GRIDSIZE = 33;
|
||||||
|
var SIZE = 16;
|
||||||
|
function instance($$self, $$props, $$invalidate) {
|
||||||
|
let dead = false;
|
||||||
|
let health;
|
||||||
|
let players;
|
||||||
|
let ws;
|
||||||
|
const connect = () => {
|
||||||
|
ws = new WebSocket(window.location.protocol === "https:" ? "wss://ewo.osmarks.net/" : "ws://localhost:8080/");
|
||||||
|
ws.addEventListener("message", (ev) => {
|
||||||
|
const data = JSON.parse(ev.data);
|
||||||
|
if (data.Display) {
|
||||||
|
const newGrid = blankGrid();
|
||||||
|
for (const [q, r, c, o] of data.Display.nearby) {
|
||||||
|
const col = q + (r - (r & 1)) / 2;
|
||||||
|
const row = r;
|
||||||
|
newGrid[row + OFFSET][col + OFFSET] = [c, o];
|
||||||
|
}
|
||||||
|
$$invalidate(3, grid = newGrid);
|
||||||
|
$$invalidate(1, health = data.Display.health);
|
||||||
|
}
|
||||||
|
if (data === "Dead") {
|
||||||
|
$$invalidate(0, dead = true);
|
||||||
|
}
|
||||||
|
if (data.PlayerCount) {
|
||||||
|
$$invalidate(2, players = data.PlayerCount);
|
||||||
|
}
|
||||||
|
for (const key of keysDown) {
|
||||||
|
const input = INPUTS[key];
|
||||||
|
if (input) {
|
||||||
|
ws.send(JSON.stringify(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keysDown = new Set(Array.from(keysDown).map((k) => !keysCleared.has(k)));
|
||||||
|
keysCleared = new Set();
|
||||||
|
});
|
||||||
|
ws.addEventListener("close", (ev) => {
|
||||||
|
console.warn("oh no");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const reconnect = () => {
|
||||||
|
if (ws)
|
||||||
|
ws.close();
|
||||||
|
connect();
|
||||||
|
};
|
||||||
|
const restart = (ev) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
$$invalidate(0, dead = false);
|
||||||
|
reconnect();
|
||||||
|
};
|
||||||
|
const OFFSET = Math.floor(GRIDSIZE / 2);
|
||||||
|
const HORIZ = Math.sqrt(3) * SIZE;
|
||||||
|
const VERT = 3 / 2 * SIZE;
|
||||||
|
const blankGrid = () => new Array(GRIDSIZE).fill(null).map(() => new Array(GRIDSIZE).fill("\u200B"));
|
||||||
|
let grid = blankGrid();
|
||||||
|
let keysDown = new Set();
|
||||||
|
let keysCleared = new Set();
|
||||||
|
const keydown = (ev) => {
|
||||||
|
keysDown.add(ev.key);
|
||||||
|
};
|
||||||
|
const keyup = (ev) => {
|
||||||
|
keysCleared.add(ev.key);
|
||||||
|
};
|
||||||
|
const INPUTS = {
|
||||||
|
"w": "UpLeft",
|
||||||
|
"e": "UpRight",
|
||||||
|
"a": "Left",
|
||||||
|
"d": "Right",
|
||||||
|
"z": "DownLeft",
|
||||||
|
"x": "DownRight"
|
||||||
|
};
|
||||||
|
connect();
|
||||||
|
return [dead, health, players, grid, restart, HORIZ, VERT, keydown, keyup];
|
||||||
|
}
|
||||||
|
var App = class extends SvelteComponent {
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
init(this, options, instance, create_fragment, safe_not_equal, {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var App_default = App;
|
||||||
|
|
||||||
|
// src/app.js
|
||||||
|
new App_default({
|
||||||
|
target: document.body
|
||||||
|
});
|
||||||
|
})();
|
15
static/index.html
Normal file
15
static/index.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" height="100vh">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
|
||||||
|
<meta name="description" content="Emu War Online">
|
||||||
|
|
||||||
|
<title>EWO3</title>
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" href="app.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user