Compare commits

..

14 Commits

Author SHA1 Message Date
11e87e69c6 change inequality inclusivity 2026-03-25 08:40:06 -07:00
1eeb6d5a25 print fev 2026-03-25 08:39:48 -07:00
311575aed7 disable comparison 2026-03-25 08:39:44 -07:00
a92526407c a 2026-03-25 08:20:20 -07:00
47239b10a8 print 2026-03-25 08:16:46 -07:00
f5588989e9 Revert "remove unhelpful debug prints"
This reverts commit f17648e7fa.
2026-03-25 08:16:46 -07:00
979d46e42a print crawl_to output 2026-03-25 08:16:46 -07:00
f858fa86e6 p 2026-03-25 08:16:46 -07:00
8e6d598ea3 debug 2026-03-25 08:16:46 -07:00
78c0cab05a debug 2026-03-25 08:16:11 -07:00
dd972c91ee debug 2026-03-25 08:15:40 -07:00
8a897ca377 hack in md lua 2026-03-25 08:15:40 -07:00
65f29fd395 no ignore 2026-03-25 08:14:08 -07:00
a673d62ffd bug 26 2026-03-25 08:14:08 -07:00
21 changed files with 469 additions and 242 deletions

222
Cargo.lock generated
View File

@@ -72,21 +72,23 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]] [[package]]
name = "android-activity" name = "android-activity"
version = "0.6.1" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046"
dependencies = [ dependencies = [
"android-properties", "android-properties",
"bitflags 2.11.0", "bitflags 2.11.0",
"cc", "cc",
"cesu8",
"jni", "jni",
"jni-sys",
"libc", "libc",
"log", "log",
"ndk", "ndk",
"ndk-context", "ndk-context",
"ndk-sys", "ndk-sys",
"num_enum", "num_enum",
"thiserror 2.0.18", "thiserror 1.0.69",
] ]
[[package]] [[package]]
@@ -431,9 +433,9 @@ dependencies = [
[[package]] [[package]]
name = "bnum" name = "bnum"
version = "0.14.4" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1b08cb4ecbb540b940016b0a0f35b7e48ab0cc372ab88150c351de4cc469959" checksum = "acf40f6d425354fe40ff439c2a4a2733f583e49379eb8601a4c79e50c4a3c579"
[[package]] [[package]]
name = "bstr" name = "bstr"
@@ -548,6 +550,12 @@ dependencies = [
"shlex", "shlex",
] ]
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.4" version = "1.0.4"
@@ -1044,7 +1052,7 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]] [[package]]
name = "fixed_wide" name = "fixed_wide"
version = "0.3.0" version = "0.2.2"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bnum", "bnum",
@@ -1783,9 +1791,9 @@ checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
[[package]] [[package]]
name = "iri-string" name = "iri-string"
version = "0.7.11" version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a"
dependencies = [ dependencies = [
"memchr", "memchr",
"serde", "serde",
@@ -1827,67 +1835,31 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.18" version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
[[package]] [[package]]
name = "jni" name = "jni"
version = "0.22.4" version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
dependencies = [ dependencies = [
"cesu8",
"cfg-if", "cfg-if",
"combine", "combine",
"jni-macros", "jni-sys",
"jni-sys 0.4.1",
"log", "log",
"simd_cesu8", "thiserror 1.0.69",
"thiserror 2.0.18",
"walkdir", "walkdir",
"windows-link", "windows-sys 0.45.0",
]
[[package]]
name = "jni-macros"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"simd_cesu8",
"syn 2.0.117",
] ]
[[package]] [[package]]
name = "jni-sys" name = "jni-sys"
version = "0.3.1" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
dependencies = [
"jni-sys 0.4.1",
]
[[package]]
name = "jni-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
dependencies = [
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "jobserver" name = "jobserver"
@@ -1978,9 +1950,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.15" version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a"
dependencies = [ dependencies = [
"bitflags 2.11.0", "bitflags 2.11.0",
"libc", "libc",
@@ -1990,7 +1962,7 @@ dependencies = [
[[package]] [[package]]
name = "linear_ops" name = "linear_ops"
version = "0.2.0" version = "0.1.1"
dependencies = [ dependencies = [
"fixed_wide", "fixed_wide",
"paste", "paste",
@@ -2318,7 +2290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
dependencies = [ dependencies = [
"bitflags 2.11.0", "bitflags 2.11.0",
"jni-sys 0.3.1", "jni-sys",
"log", "log",
"ndk-sys", "ndk-sys",
"num_enum", "num_enum",
@@ -2338,7 +2310,7 @@ version = "0.6.0+11769913"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
dependencies = [ dependencies = [
"jni-sys 0.3.1", "jni-sys",
] ]
[[package]] [[package]]
@@ -3631,15 +3603,6 @@ version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.44" version = "0.38.44"
@@ -3690,9 +3653,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.103.10" version = "0.103.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
dependencies = [ dependencies = [
"ring", "ring",
"rustls-pki-types", "rustls-pki-types",
@@ -3861,16 +3824,6 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
[[package]]
name = "simd_cesu8"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
dependencies = [
"rustc_version",
"simdutf8",
]
[[package]] [[package]]
name = "simd_helpers" name = "simd_helpers"
version = "0.1.0" version = "0.1.0"
@@ -3880,12 +3833,6 @@ dependencies = [
"quote", "quote",
] ]
[[package]]
name = "simdutf8"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "1.0.2" version = "1.0.2"
@@ -4013,7 +3960,7 @@ dependencies = [
[[package]] [[package]]
name = "strafesnet_common" name = "strafesnet_common"
version = "0.9.0" version = "0.8.7"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bitflags 2.11.0", "bitflags 2.11.0",
@@ -4033,7 +3980,7 @@ dependencies = [
[[package]] [[package]]
name = "strafesnet_graphics" name = "strafesnet_graphics"
version = "0.0.11" version = "0.0.8"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"ddsfile", "ddsfile",
@@ -4045,11 +3992,12 @@ dependencies = [
[[package]] [[package]]
name = "strafesnet_physics" name = "strafesnet_physics"
version = "0.0.2" version = "0.0.1"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"glam", "glam",
"id", "id",
"mlua",
"strafesnet_common", "strafesnet_common",
] ]
@@ -4096,7 +4044,7 @@ dependencies = [
[[package]] [[package]]
name = "strafesnet_snf" name = "strafesnet_snf"
version = "0.4.0" version = "0.3.2"
dependencies = [ dependencies = [
"binrw 0.15.1", "binrw 0.15.1",
"id", "id",
@@ -4388,18 +4336,18 @@ dependencies = [
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "1.1.0+spec-1.1.0" version = "1.0.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9"
dependencies = [ dependencies = [
"serde_core", "serde_core",
] ]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.25.8+spec-1.1.0" version = "0.25.5+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" checksum = "8ca1a40644a28bce036923f6a431df0b34236949d111cc07cb6dca830c9ef2e1"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"toml_datetime", "toml_datetime",
@@ -4409,9 +4357,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_parser" name = "toml_parser"
version = "1.1.0+spec-1.1.0" version = "1.0.10+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420"
dependencies = [ dependencies = [
"winnow", "winnow",
] ]
@@ -4524,9 +4472,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.13.1" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da36089a805484bcccfffe0739803392c8298778a2d2f09febf76fac5ad9025b" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
@@ -5297,6 +5245,15 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets 0.42.2",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"
@@ -5333,6 +5290,21 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.48.5" version = "0.48.5"
@@ -5373,6 +5345,12 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.48.5" version = "0.48.5"
@@ -5385,6 +5363,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.48.5" version = "0.48.5"
@@ -5397,6 +5381,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.48.5" version = "0.48.5"
@@ -5415,6 +5405,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.48.5" version = "0.48.5"
@@ -5427,6 +5423,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.48.5" version = "0.48.5"
@@ -5439,6 +5441,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.48.5" version = "0.48.5"
@@ -5451,6 +5459,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.48.5" version = "0.48.5"
@@ -5712,18 +5726,18 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.8.47" version = "0.8.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.8.47" version = "0.8.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -5853,9 +5867,9 @@ dependencies = [
[[package]] [[package]]
name = "zune-jpeg" name = "zune-jpeg"
version = "0.5.14" version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7a1c0af6e5d8d1363f4994b7a091ccf963d8b694f7da5b0b9cceb82da2c0a6" checksum = "ec5f41c76397b7da451efd19915684f727d7e1d516384ca6bd0ec43ec94de23c"
dependencies = [ dependencies = [
"zune-core", "zune-core",
] ]

View File

@@ -42,16 +42,16 @@ wgpu = "29.0.0"
# engine # engine
strafesnet_graphics = { path = "engine/graphics", registry = "strafesnet" } strafesnet_graphics = { path = "engine/graphics", registry = "strafesnet" }
strafesnet_physics = { path = "engine/physics", registry = "strafesnet" } strafesnet_physics = { version = "0.0.1", path = "engine/physics", registry = "strafesnet" }
strafesnet_session = { path = "engine/session", registry = "strafesnet" } strafesnet_session = { path = "engine/session", registry = "strafesnet" }
strafesnet_settings = { path = "engine/settings", registry = "strafesnet" } strafesnet_settings = { path = "engine/settings", registry = "strafesnet" }
# lib # lib
fixed_wide = { version = "0.3.0", path = "lib/fixed_wide", registry = "strafesnet" } fixed_wide = { version = "0.2.2", path = "lib/fixed_wide", registry = "strafesnet" }
linear_ops = { version = "0.2.0", path = "lib/linear_ops", registry = "strafesnet" } linear_ops = { version = "0.1.1", path = "lib/linear_ops", registry = "strafesnet" }
ratio_ops = { version = "0.1.0", path = "lib/ratio_ops", registry = "strafesnet" } ratio_ops = { version = "0.1.0", path = "lib/ratio_ops", registry = "strafesnet" }
strafesnet_bsp_loader = { version = "0.5.0", path = "lib/bsp_loader", registry = "strafesnet" } strafesnet_bsp_loader = { version = "0.5.0", path = "lib/bsp_loader", registry = "strafesnet" }
strafesnet_common = { version = "0.9.0", path = "lib/common", registry = "strafesnet" } strafesnet_common = { version = "0.8.7", path = "lib/common", registry = "strafesnet" }
strafesnet_deferred_loader = { version = "0.6.0", path = "lib/deferred_loader", registry = "strafesnet" } strafesnet_deferred_loader = { version = "0.6.0", path = "lib/deferred_loader", registry = "strafesnet" }
strafesnet_rbx_loader = { version = "0.10.2", path = "lib/rbx_loader", registry = "strafesnet" } strafesnet_rbx_loader = { version = "0.10.2", path = "lib/rbx_loader", registry = "strafesnet" }
strafesnet_snf = { version = "0.4.0", path = "lib/snf", registry = "strafesnet" } strafesnet_snf = { version = "0.3.2", path = "lib/snf", registry = "strafesnet" }

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "strafesnet_graphics" name = "strafesnet_graphics"
version = "0.0.11" version = "0.0.8"
edition = "2024" edition = "2024"
[dependencies] [dependencies]

View File

@@ -127,7 +127,6 @@ pub struct GraphicsState{
camera_buf:wgpu::Buffer, camera_buf:wgpu::Buffer,
temp_squid_texture_view:wgpu::TextureView, temp_squid_texture_view:wgpu::TextureView,
models:Vec<GraphicsModel>, models:Vec<GraphicsModel>,
depth:wgpu::Texture,
depth_view:wgpu::TextureView, depth_view:wgpu::TextureView,
staging_belt:wgpu::util::StagingBelt, staging_belt:wgpu::util::StagingBelt,
model_instances_uniform_len:usize, model_instances_uniform_len:usize,
@@ -138,8 +137,8 @@ impl GraphicsState{
fn create_depth_texture( fn create_depth_texture(
size:glam::UVec2, size:glam::UVec2,
device:&wgpu::Device, device:&wgpu::Device,
)->wgpu::Texture{ )->wgpu::TextureView{
device.create_texture(&wgpu::TextureDescriptor{ let depth_texture=device.create_texture(&wgpu::TextureDescriptor{
size:wgpu::Extent3d{ size:wgpu::Extent3d{
width:size.x, width:size.x,
height:size.y, height:size.y,
@@ -150,15 +149,11 @@ impl GraphicsState{
dimension:wgpu::TextureDimension::D2, dimension:wgpu::TextureDimension::D2,
format:Self::DEPTH_FORMAT, format:Self::DEPTH_FORMAT,
usage:wgpu::TextureUsages::RENDER_ATTACHMENT, usage:wgpu::TextureUsages::RENDER_ATTACHMENT,
label:Some("Depth Texture"), label:None,
view_formats:&[], view_formats:&[],
}) });
}
pub const fn depth_texture(&self)->&wgpu::Texture{ depth_texture.create_view(&wgpu::TextureViewDescriptor::default())
&self.depth
}
pub const fn depth_texture_view(&self)->&wgpu::TextureView{
&self.depth_view
} }
pub fn clear(&mut self){ pub fn clear(&mut self){
self.models.clear(); self.models.clear();
@@ -883,8 +878,7 @@ impl GraphicsState{
label:Some("Sky Texture"), label:Some("Sky Texture"),
}); });
let depth=Self::create_depth_texture(size,device); let depth_view=Self::create_depth_texture(size,device);
let depth_view=depth.create_view(&wgpu::TextureViewDescriptor::default());
Self{ Self{
pipelines:GraphicsPipelines{ pipelines:GraphicsPipelines{
@@ -898,7 +892,6 @@ impl GraphicsState{
camera, camera,
camera_buf, camera_buf,
models:Vec::new(), models:Vec::new(),
depth,
depth_view, depth_view,
staging_belt:wgpu::util::StagingBelt::new(device.clone(),0x100), staging_belt:wgpu::util::StagingBelt::new(device.clone(),0x100),
bind_group_layouts:GraphicsBindGroupLayouts{model:model_bind_group_layout}, bind_group_layouts:GraphicsBindGroupLayouts{model:model_bind_group_layout},
@@ -913,8 +906,7 @@ impl GraphicsState{
size:glam::UVec2, size:glam::UVec2,
fov:glam::Vec2, fov:glam::Vec2,
){ ){
self.depth=Self::create_depth_texture(size,device); self.depth_view=Self::create_depth_texture(size,device);
self.depth_view=self.depth.create_view(&wgpu::TextureViewDescriptor::default());
self.camera.screen_size=size; self.camera.screen_size=size;
self.camera.fov=fov; self.camera.fov=fov;
} }

View File

@@ -39,18 +39,23 @@ impl<'window> Surface<'window>{
} }
#[must_use] #[must_use]
pub fn new_frame(&self,device:&wgpu::Device)->Result<Frame,FrameError>{ pub fn new_frame(&self,device:&wgpu::Device)->Result<Frame,FrameError>{
let frame=loop{ let frame=match self.surface.get_current_texture(){
match self.surface.get_current_texture(){ wgpu::CurrentSurfaceTexture::Success(surface_texture)=>surface_texture,
wgpu::CurrentSurfaceTexture::Success(surface_texture)=>break surface_texture, wgpu::CurrentSurfaceTexture::Suboptimal(surface_texture)=>{
// Suboptimal -> surface_texture must be dropped and surface reconfigured self.surface.configure(device,&self.config);
wgpu::CurrentSurfaceTexture::Suboptimal(_) surface_texture
|wgpu::CurrentSurfaceTexture::Outdated=>{}, },
wgpu::CurrentSurfaceTexture::Timeout wgpu::CurrentSurfaceTexture::Outdated=>{
|wgpu::CurrentSurfaceTexture::Occluded=>return Err(FrameError::Skip), self.surface.configure(device,&self.config);
wgpu::CurrentSurfaceTexture::Lost=>return Err(FrameError::DeviceLost), match self.surface.get_current_texture(){
wgpu::CurrentSurfaceTexture::Validation=>unreachable!(), wgpu::CurrentSurfaceTexture::Success(surface_texture)=>surface_texture,
}; _=>panic!("Failed to acquire next surface texture!"),
self.surface.configure(device,&self.config); }
}
wgpu::CurrentSurfaceTexture::Timeout
|wgpu::CurrentSurfaceTexture::Occluded=>return Err(FrameError::Skip),
wgpu::CurrentSurfaceTexture::Lost=>return Err(FrameError::DeviceLost),
wgpu::CurrentSurfaceTexture::Validation=>unreachable!(),
}; };
let view=frame.texture.create_view(&wgpu::TextureViewDescriptor{ let view=frame.texture.create_view(&wgpu::TextureViewDescriptor{
format:Some(self.config.view_formats[0]), format:Some(self.config.view_formats[0]),

View File

@@ -1,12 +1,13 @@
[package] [package]
name = "strafesnet_physics" name = "strafesnet_physics"
version = "0.0.2" version = "0.0.1"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
arrayvec = "0.7.6" arrayvec = "0.7.6"
glam.workspace = true glam.workspace = true
id = { version = "0.1.0", registry = "strafesnet" } id = { version = "0.1.0", registry = "strafesnet" }
mlua = { version = "0.11.5", features = ["luau"] }
strafesnet_common.workspace = true strafesnet_common.workspace = true
[lints] [lints]

View File

@@ -5,6 +5,7 @@ mod minkowski;
mod model; mod model;
mod push_solve; mod push_solve;
mod minimum_difference; mod minimum_difference;
mod minimum_difference_lua;
pub mod physics; pub mod physics;

View File

@@ -11,7 +11,7 @@ use crate::minkowski::{MinkowskiMesh,MinkowskiVert};
// written by Trey Reynolds in 2021 // written by Trey Reynolds in 2021
type Simplex<const N:usize,Vert>=[Vert;N]; type Simplex<const N:usize,Vert>=[Vert;N];
#[derive(Clone,Copy)] #[derive(Clone,Copy,Debug)]
enum Simplex1_3<Vert>{ enum Simplex1_3<Vert>{
Simplex1(Simplex<1,Vert>), Simplex1(Simplex<1,Vert>),
Simplex2(Simplex<2,Vert>), Simplex2(Simplex<2,Vert>),
@@ -139,12 +139,15 @@ fn reduce1<M:MeshQuery<Position=Planar64Vec3>>(
)->Reduced<M::Vert> )->Reduced<M::Vert>
where M::Vert:Copy, where M::Vert:Copy,
{ {
println!("reduce1");
// --debug.profilebegin("reduceSimplex0") // --debug.profilebegin("reduceSimplex0")
// local a = a1 - a0 // local a = a1 - a0
let p0=mesh.vert(v0); let p0=mesh.vert(v0);
println!("p0={p0}");
// local p = -a // local p = -a
let p=-(p0+point); let p=-(p0+point);
println!("p={p}");
// local direction = p // local direction = p
let mut dir=p; let mut dir=p;
@@ -171,6 +174,7 @@ fn reduce2<M:MeshQuery<Position=Planar64Vec3>>(
where where
M::Vert:Copy M::Vert:Copy
{ {
println!("reduce2");
// --debug.profilebegin("reduceSimplex1") // --debug.profilebegin("reduceSimplex1")
// local a = a1 - a0 // local a = a1 - a0
// local b = b1 - b0 // local b = b1 - b0
@@ -187,7 +191,7 @@ fn reduce2<M:MeshQuery<Position=Planar64Vec3>>(
let p_u=p.dot(u); let p_u=p.dot(u);
// if p_u >= 0 then // if p_u >= 0 then
if !p_u.is_negative(){ if p_u.is_positive(){
// local direction = u:Cross(p):Cross(u) // local direction = u:Cross(p):Cross(u)
let direction=u.cross(p).cross(u); let direction=u.cross(p).cross(u);
@@ -231,6 +235,7 @@ fn reduce3<M:MeshQuery<Position=Planar64Vec3>>(
where where
M::Vert:Copy M::Vert:Copy
{ {
println!("reduce3");
// --debug.profilebegin("reduceSimplex2") // --debug.profilebegin("reduceSimplex2")
// local a = a1 - a0 // local a = a1 - a0
// local b = b1 - b0 // local b = b1 - b0
@@ -258,7 +263,7 @@ fn reduce3<M:MeshQuery<Position=Planar64Vec3>>(
let uv_pv=uv.dot(pv); let uv_pv=uv.dot(pv);
// if uv_up >= 0 and uv_pv >= 0 then // if uv_up >= 0 and uv_pv >= 0 then
if !uv_up.is_negative()&&!uv_pv.is_negative(){ if uv_up.is_positive()&&uv_pv.is_positive(){
// local uvp = uv:Dot(p) // local uvp = uv:Dot(p)
let uvp=uv.dot(p); let uvp=uv.dot(p);
@@ -298,7 +303,7 @@ fn reduce3<M:MeshQuery<Position=Planar64Vec3>>(
let p_u=p.dot(u); let p_u=p.dot(u);
// if p_u >= 0 then // if p_u >= 0 then
if !p_u.is_negative(){ if p_u.is_positive(){
// local direction = up:Cross(u) // local direction = up:Cross(u)
let direction=up.cross(u); let direction=up.cross(u);
// if direction.magnitude == 0 then // if direction.magnitude == 0 then
@@ -343,6 +348,7 @@ fn reduce4<M:MeshQuery<Position=Planar64Vec3>>(
where where
M::Vert:Copy M::Vert:Copy
{ {
println!("reduce4");
// --debug.profilebegin("reduceSimplex3") // --debug.profilebegin("reduceSimplex3")
// local a = a1 - a0 // local a = a1 - a0
// local b = b1 - b0 // local b = b1 - b0
@@ -378,9 +384,9 @@ fn reduce4<M:MeshQuery<Position=Planar64Vec3>>(
let uv_p=uv.dot(p); let uv_p=uv.dot(p);
// if pvw/uvw >= 0 and upw/uvw >= 0 and uvp/uvw >= 0 then // if pvw/uvw >= 0 and upw/uvw >= 0 and uvp/uvw >= 0 then
if !pv_w.div_sign(uv_w).is_negative() if pv_w.div_sign(uv_w).is_positive()
&&!up_w.div_sign(uv_w).is_negative() &&up_w.div_sign(uv_w).is_positive()
&&!uv_p.div_sign(uv_w).is_negative(){ &&uv_p.div_sign(uv_w).is_positive(){
// origin is contained, this is a positive detection // origin is contained, this is a positive detection
// local direction = Vector3.new(0, 0, 0) // local direction = Vector3.new(0, 0, 0)
// return direction, a0, a1, b0, b1, c0, c1, d0, d1 // return direction, a0, a1, b0, b1, c0, c1, d0, d1
@@ -433,7 +439,7 @@ fn reduce4<M:MeshQuery<Position=Planar64Vec3>>(
let uv_pv=uv.dot(pv); let uv_pv=uv.dot(pv);
// if uv_up >= 0 and uv_pv >= 0 then // if uv_up >= 0 and uv_pv >= 0 then
if !uv_up.is_negative()&&!uv_pv.is_negative(){ if uv_up.is_positive()&&uv_pv.is_positive(){
// local direction = uvw < 0 and uv or -uv // local direction = uvw < 0 and uv or -uv
// return direction, a0, a1, b0, b1, c0, c1 // return direction, a0, a1, b0, b1, c0, c1
let dir=if uv_w.is_negative(){ let dir=if uv_w.is_negative(){
@@ -469,7 +475,7 @@ fn reduce4<M:MeshQuery<Position=Planar64Vec3>>(
let p_u=p.dot(u); let p_u=p.dot(u);
// if p_u >= 0 then // if p_u >= 0 then
if !p_u.is_negative(){ if p_u.is_positive(){
// local direction = up:Cross(u) // local direction = up:Cross(u)
let direction=up.cross(u); let direction=up.cross(u);
// if direction.magnitude == 0 then // if direction.magnitude == 0 then
@@ -734,6 +740,7 @@ fn crawl_to_closest_fev<'a>(mesh:&MinkowskiMesh<'a>,simplex:Simplex<3,MinkowskiV
//if test point is behind face, the face is invalid //if test point is behind face, the face is invalid
// TODO: find out why I thought of this backwards // TODO: find out why I thought of this backwards
if !(face_n.dot(point)-d).is_positive(){ if !(face_n.dot(point)-d).is_positive(){
println!("behind");
continue; continue;
} }
//edge-face boundary nd, n facing out of the face towards the edge //edge-face boundary nd, n facing out of the face towards the edge
@@ -743,6 +750,8 @@ fn crawl_to_closest_fev<'a>(mesh:&MinkowskiMesh<'a>,simplex:Simplex<3,MinkowskiV
if !boundary_d.is_positive(){ if !boundary_d.is_positive(){
//both faces cannot pass this condition, return early if one does. //both faces cannot pass this condition, return early if one does.
return FEV::Face(face_id); return FEV::Face(face_id);
}else{
println!("boundary_d is positive");
} }
} }
FEV::Edge(edge_id) FEV::Edge(edge_id)
@@ -751,11 +760,21 @@ fn crawl_to_closest_fev<'a>(mesh:&MinkowskiMesh<'a>,simplex:Simplex<3,MinkowskiV
} }
pub fn closest_fev_not_inside<'a>(mesh:&MinkowskiMesh<'a>,point:Planar64Vec3)->Option<FEV<MinkowskiMesh<'a>>>{ pub fn closest_fev_not_inside<'a>(mesh:&MinkowskiMesh<'a>,point:Planar64Vec3)->Option<FEV<MinkowskiMesh<'a>>>{
// println!("=== LUA ===");
// let (hits,_details)=crate::minimum_difference_lua::minimum_difference_details(mesh,point).unwrap();
// println!("=== RUST ===");
let closest_fev_not_inside=closest_fev_not_inside_inner(mesh,point);
// assert_eq!(hits,closest_fev_not_inside.is_none(),"algorithms disagree");
closest_fev_not_inside
}
pub fn closest_fev_not_inside_inner<'a>(mesh:&MinkowskiMesh<'a>,point:Planar64Vec3)->Option<FEV<MinkowskiMesh<'a>>>{
const ENABLE_FAST_FAIL:bool=false; const ENABLE_FAST_FAIL:bool=false;
// TODO: remove mesh negation // TODO: remove mesh negation
minimum_difference::<ENABLE_FAST_FAIL,_,_>(&-mesh,point, minimum_difference::<ENABLE_FAST_FAIL,_,_>(&-mesh,point,
// on_exact // on_exact
|is_intersecting,simplex|{ |is_intersecting,simplex|{
println!("on_exact simplex={simplex:?}");
if is_intersecting{ if is_intersecting{
return None; return None;
} }
@@ -766,7 +785,11 @@ pub fn closest_fev_not_inside<'a>(mesh:&MinkowskiMesh<'a>,point:Planar64Vec3)->O
Simplex1_3::Simplex2([v0,v1])=>{ Simplex1_3::Simplex2([v0,v1])=>{
// invert // invert
let (v0,v1)=(-v0,-v1); let (v0,v1)=(-v0,-v1);
crawl_to_closest_ev(mesh,[v0,v1],point).into() let ev=crawl_to_closest_ev(mesh,[v0,v1],point);
if !matches!(ev,EV::Edge(_)){
println!("I can't believe it's not an edge!");
}
ev.into()
}, },
Simplex1_3::Simplex3([v0,v1,v2])=>{ Simplex1_3::Simplex3([v0,v1,v2])=>{
// invert // invert
@@ -774,7 +797,11 @@ pub fn closest_fev_not_inside<'a>(mesh:&MinkowskiMesh<'a>,point:Planar64Vec3)->O
// Shimmy to the side until you find a face that contains the closest point // Shimmy to the side until you find a face that contains the closest point
// it's ALWAYS representable as a face, but this algorithm may // it's ALWAYS representable as a face, but this algorithm may
// return E or V in edge cases but I don't think that will break the face crawler // return E or V in edge cases but I don't think that will break the face crawler
crawl_to_closest_fev(mesh,[v0,v1,v2],point) let fev=crawl_to_closest_fev(mesh,[v0,v1,v2],point);
if !matches!(fev,FEV::Face(_)){
println!("I can't believe it's not a face!");
}
fev
}, },
}) })
}, },
@@ -832,6 +859,7 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T,M:MeshQuery<Position=Planar6
if initial_axis==vec3::zero(){ if initial_axis==vec3::zero(){
initial_axis=choose_any_direction(); initial_axis=choose_any_direction();
} }
println!("initial_axis={initial_axis}");
let last_point=mesh.farthest_vert(-initial_axis); let last_point=mesh.farthest_vert(-initial_axis);
// this represents the 'a' value in the commented code // this represents the 'a' value in the commented code
let mut last_pos=mesh.vert(last_point); let mut last_pos=mesh.vert(last_point);
@@ -840,6 +868,8 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T,M:MeshQuery<Position=Planar6
// exitRadius = testIntersection and 0 or exitRadius or 1/0 // exitRadius = testIntersection and 0 or exitRadius or 1/0
// for _ = 1, 100 do // for _ = 1, 100 do
loop{ loop{
println!("direction={direction}");
// new_point_p = queryP(-direction) // new_point_p = queryP(-direction)
// new_point_q = queryQ(direction) // new_point_q = queryQ(direction)
// local next_point = new_point_q - new_point_p // local next_point = new_point_q - new_point_p
@@ -847,7 +877,11 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T,M:MeshQuery<Position=Planar6
let next_pos=mesh.vert(next_point); let next_pos=mesh.vert(next_point);
// if -direction:Dot(next_point) > (exitRadius + radiusP + radiusQ)*direction.magnitude then // if -direction:Dot(next_point) > (exitRadius + radiusP + radiusQ)*direction.magnitude then
if ENABLE_FAST_FAIL&&direction.dot(next_pos+point).is_negative(){ let d=direction.dot(next_pos+point);
let fast_fail=d.is_negative();
println!("ENABLE_FAST_FAIL={ENABLE_FAST_FAIL} fast_fail={fast_fail} next_point={} dot={d}",next_pos+point);
if ENABLE_FAST_FAIL&&fast_fail{
println!("on_fast_fail");
return on_fast_fail(); return on_fast_fail();
} }
@@ -856,8 +890,11 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T,M:MeshQuery<Position=Planar6
// if // if
// direction:Dot(next_point - a) <= 0 or // direction:Dot(next_point - a) <= 0 or
// absDet(next_point, a, b, c) < 1e-6 // absDet(next_point, a, b, c) < 1e-6
if !direction.dot(next_pos-last_pos).is_positive() let d1=direction.dot(next_pos-last_pos);
||simplex_big.det_is_zero(mesh){ let cond2=simplex_big.det_is_zero(mesh);
println!("d1={d1:?} cond2={cond2}");
if d1.is_negative()||cond2{
println!("on_exact");
// Found enough information to compute the exact closest point. // Found enough information to compute the exact closest point.
// local norm = direction.unit // local norm = direction.unit
// local dist = a:Dot(norm) // local dist = a:Dot(norm)
@@ -870,6 +907,7 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T,M:MeshQuery<Position=Planar6
match simplex_big.reduce(mesh,point){ match simplex_big.reduce(mesh,point){
// if a and b and c and d then // if a and b and c and d then
Reduce::Escape(simplex)=>{ Reduce::Escape(simplex)=>{
println!("on_escape");
// Enough information to conclude that the meshes are intersecting. // Enough information to conclude that the meshes are intersecting.
// Topology information is computed if needed. // Topology information is computed if needed.
return on_escape(simplex); return on_escape(simplex);

View File

@@ -0,0 +1,174 @@
use mlua::{Lua,FromLuaMulti,IntoLuaMulti,Function,Result as LuaResult,Vector};
use strafesnet_common::integer::{Planar64,Planar64Vec3,FixedFromFloatError};
use crate::mesh_query::MeshQuery;
use crate::minkowski::MinkowskiMesh;
pub fn contains_point(
mesh:&MinkowskiMesh,
point:Planar64Vec3,
)->LuaResult<bool>{
Ok(minimum_difference(mesh,point,true)?.hits)
}
pub fn minimum_difference_details(
mesh:&MinkowskiMesh,
point:Planar64Vec3,
)->LuaResult<(bool,Option<Details>)>{
let md=minimum_difference(mesh,point,false)?;
Ok((md.hits,md.details))
}
fn p64v3(v:Vector)->Result<Planar64Vec3,FixedFromFloatError>{
Ok(Planar64Vec3::new([
v.x().try_into()?,
v.y().try_into()?,
v.z().try_into()?,
]))
}
fn vec(v:Planar64Vec3)->Vector{
Vector::new(v.x.into(),v.y.into(),v.z.into())
}
struct MinimumDifference{
hits:bool,
details:Option<Details>
}
pub struct Details{
pub distance:Planar64,
pub p_pos:Planar64Vec3,
pub p_norm:Planar64Vec3,
pub q_pos:Planar64Vec3,
pub q_norm:Planar64Vec3,
}
impl FromLuaMulti for MinimumDifference{
fn from_lua_multi(mut values:mlua::MultiValue,_lua:&Lua)->LuaResult<Self>{
match values.make_contiguous(){
&mut [
mlua::Value::Boolean(hits),
mlua::Value::Nil,
mlua::Value::Nil,
mlua::Value::Nil,
mlua::Value::Nil,
mlua::Value::Nil,
]=>Ok(Self{hits,details:None}),
&mut [
mlua::Value::Boolean(hits),
mlua::Value::Number(distance),
mlua::Value::Vector(p_pos),
mlua::Value::Vector(p_norm),
mlua::Value::Vector(q_pos),
mlua::Value::Vector(q_norm),
]=>Ok(Self{
hits,
details:Some(Details{
distance:distance.try_into().unwrap(),
p_pos:p64v3(p_pos).unwrap(),
p_norm:p64v3(p_norm).unwrap(),
q_pos:p64v3(q_pos).unwrap(),
q_norm:p64v3(q_norm).unwrap(),
}),
}),
&mut [
mlua::Value::Boolean(hits),
mlua::Value::Integer(distance),
mlua::Value::Vector(p_pos),
mlua::Value::Vector(p_norm),
mlua::Value::Vector(q_pos),
mlua::Value::Vector(q_norm),
]=>Ok(Self{
hits,
details:Some(Details{
distance:distance.into(),
p_pos:p64v3(p_pos).unwrap(),
p_norm:p64v3(p_norm).unwrap(),
q_pos:p64v3(q_pos).unwrap(),
q_norm:p64v3(q_norm).unwrap(),
}),
}),
values=>Err(mlua::Error::runtime(format!("Invalid return values: {values:?}"))),
}
}
}
struct Args{
query_p:Function,
radius_p:f64,
query_q:Function,
radius_q:f64,
test_intersection:bool,
}
impl Args{
fn new(
lua:&Lua,
mesh:&'static MinkowskiMesh<'static>,
point:Planar64Vec3,
test_intersection:bool,
)->LuaResult<Self>{
let radius_p=0.0;
let radius_q=0.0;
// Query the farthest point on the mesh in the given direction.
let query_p=lua.create_function(move|_,dir:Option<Vector>|{
let Some(dir)=dir else{
return Ok(vec(mesh.mesh0.hint_point()));
};
let dir=p64v3(dir).unwrap();
let vert_id=mesh.mesh0.farthest_vert(dir);
let dir=mesh.mesh0.vert(vert_id);
Ok(vec(dir))
})?;
// query_q is different since it includes the test point offset.
let query_q=lua.create_function(move|_,dir:Option<Vector>|{
let Some(dir)=dir else{
return Ok(vec(mesh.mesh1.hint_point()+point));
};
let dir=p64v3(dir).unwrap();
let vert_id=mesh.mesh1.farthest_vert(dir);
let dir=mesh.mesh1.vert(vert_id)+point;
Ok(vec(dir))
})?;
Ok(Args{
query_p,
radius_p,
query_q,
radius_q,
test_intersection,
})
}
}
impl IntoLuaMulti for Args{
fn into_lua_multi(self,lua:&Lua)->LuaResult<mlua::MultiValue>{
use mlua::IntoLua;
Ok(mlua::MultiValue::from_vec(vec![
self.query_p.into_lua(lua)?,
self.radius_p.into_lua(lua)?,
self.query_q.into_lua(lua)?,
self.radius_q.into_lua(lua)?,
mlua::Value::Nil,
self.test_intersection.into_lua(lua)?,
]))
}
}
fn minimum_difference(
mesh:&MinkowskiMesh,
point:Planar64Vec3,
test_intersection:bool,
)->LuaResult<MinimumDifference>{
let ctx=init_lua()?;
// SAFETY: mesh lifetime must outlive args usages
let mesh=unsafe{core::mem::transmute(mesh)};
let args=Args::new(&ctx.lua,mesh,point,test_intersection)?;
ctx.f.call(args)
}
struct Ctx{
lua:Lua,
f:Function,
}
fn init_lua()->LuaResult<Ctx>{
static SOURCE:std::sync::LazyLock<String>=std::sync::LazyLock::new(||std::fs::read_to_string("../../Trey-MinimumDifference.lua").unwrap());
let lua=Lua::new();
lua.sandbox(true)?;
let lib_f=lua.load(SOURCE.as_str()).set_name("Trey-MinimumDifference").into_function()?;
let lib:mlua::Table=lib_f.call(())?;
let f=lib.raw_get("difference")?;
Ok(Ctx{lua,f})
}

View File

@@ -80,8 +80,8 @@ pub enum MinkowskiFace{
#[derive(Debug)] #[derive(Debug)]
pub struct MinkowskiMesh<'a>{ pub struct MinkowskiMesh<'a>{
mesh0:TransformedMesh<'a>, pub mesh0:TransformedMesh<'a>,
mesh1:TransformedMesh<'a>, pub mesh1:TransformedMesh<'a>,
} }
// TODO: remove this // TODO: remove this
@@ -99,6 +99,9 @@ impl MinkowskiMesh<'_>{
mesh1, mesh1,
} }
} }
pub fn closest_point(&self,point:Planar64Vec3)->Option<crate::mesh_query::FEV<Self>>{
crate::minimum_difference::closest_fev_not_inside(self,point)
}
pub fn predict_collision_in(&self,trajectory:&Trajectory,range:impl RangeBounds<Time>)->Option<(MinkowskiFace,GigaTime)>{ pub fn predict_collision_in(&self,trajectory:&Trajectory,range:impl RangeBounds<Time>)->Option<(MinkowskiFace,GigaTime)>{
let start_position=match range.start_bound(){ let start_position=match range.start_bound(){
Bound::Included(time)=>trajectory.extrapolated_position(*time), Bound::Included(time)=>trajectory.extrapolated_position(*time),
@@ -106,6 +109,7 @@ impl MinkowskiMesh<'_>{
Bound::Unbounded=>trajectory.position, Bound::Unbounded=>trajectory.position,
}; };
let fev=crate::minimum_difference::closest_fev_not_inside(self,start_position)?; let fev=crate::minimum_difference::closest_fev_not_inside(self,start_position)?;
println!("fev={fev:?}");
//continue forwards along the body parabola //continue forwards along the body parabola
fev.crawl(self,trajectory,range.start_bound(),range.end_bound()).hit() fev.crawl(self,trajectory,range.start_bound(),range.end_bound()).hit()
} }

View File

@@ -478,7 +478,7 @@ impl PhysicsMeshTransform{
#[derive(Debug,Clone,Copy)] #[derive(Debug,Clone,Copy)]
pub struct TransformedMesh<'a>{ pub struct TransformedMesh<'a>{
view:PhysicsMeshView<'a>, view:PhysicsMeshView<'a>,
transform:&'a PhysicsMeshTransform, pub transform:&'a PhysicsMeshTransform,
} }
impl TransformedMesh<'_>{ impl TransformedMesh<'_>{
pub const fn new<'a>( pub const fn new<'a>(

View File

@@ -501,27 +501,6 @@ impl StyleHelper for StyleModifiers{
} }
} }
#[derive(Clone,Debug)] #[derive(Clone,Debug)]
struct StrafeTickState{
tick_number:u64,
}
impl StrafeTickState{
fn new(time:Time,settings:&gameplay_style::StrafeSettings)->Self{
// let time=n*seconds/ticks;
let time=time.nanos() as i128;
let ticks=settings.tick_rate.num() as i128;
let seconds=settings.tick_rate.den() as i128;
let tick_number=(time*ticks/seconds) as u64;
StrafeTickState{tick_number}
}
fn next_tick(&self,settings:&gameplay_style::StrafeSettings)->Time{
let n=self.tick_number as i128;
let ticks=settings.tick_rate.num() as i128;
let seconds=settings.tick_rate.den() as i128;
let time=n*seconds/ticks;
Time::from_nanos(time as i64)
}
}
#[derive(Clone,Debug)]
enum MoveState{ enum MoveState{
Air, Air,
Walk(ContactMoveState), Walk(ContactMoveState),
@@ -599,7 +578,7 @@ impl MoveState{
=>None, =>None,
} }
} }
fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,Time>>{ fn next_move_instruction(&self,strafe:&Option<gameplay_style::StrafeSettings>,time:Time)->Option<TimedInstruction<InternalInstruction,Time>>{
//check if you have a valid walk state and create an instruction //check if you have a valid walk state and create an instruction
match self{ match self{
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.target{ MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.target{
@@ -611,7 +590,13 @@ impl MoveState{
|TransientAcceleration::Reached |TransientAcceleration::Reached
=>None, =>None,
} }
MoveState::Air=>None, MoveState::Air=>strafe.as_ref().map(|strafe|{
TimedInstruction{
time:strafe.next_tick(time),
//only poll the physics if there is a before and after mouse event
instruction:InternalInstruction::StrafeTick
}
}),
MoveState::Water=>None,//TODO MoveState::Water=>None,//TODO
MoveState::Fly=>None, MoveState::Fly=>None,
} }
@@ -620,26 +605,25 @@ impl MoveState{
*self=move_state; *self=move_state;
//this function call reads the above state that was just set //this function call reads the above state that was just set
self.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state); self.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state);
// Never used? make body immutable
self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state); self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state);
} }
fn cull_velocity(&mut self,velocity:Planar64Vec3,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){ fn cull_velocity(&mut self,velocity:Planar64Vec3,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
//TODO: be more precise about contacts
if set_velocity_cull(body,touching,models,hitbox_mesh,velocity){ if set_velocity_cull(body,touching,models,hitbox_mesh,velocity){
self.update_move_state(body,touching,models,hitbox_mesh,style,camera,input_state,|contact|!touching.contains_contact(&contact.convex_mesh_id)); // TODO do better
} // TODO: unduplicate this code
} match self.get_walk_state(){
fn update_move_state(&mut self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState,is_contact_removed:impl Fn(&ContactCollision)->bool){ // did you stop touching the thing you were walking on?
match self.get_walk_state(){ Some(walk_state)=>if !touching.contains_contact(&walk_state.contact.convex_mesh_id){
// did you stop touching the thing you were walking on? self.set_move_state(MoveState::Air,body,touching,models,hitbox_mesh,style,camera,input_state);
Some(walk_state)=>if is_contact_removed(&walk_state.contact){ }else{
self.set_move_state(MoveState::Air,body,touching,models,hitbox_mesh,style,camera,input_state); // stopped touching something else while walking
}else{ self.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state);
// stopped touching something else while walking self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state);
self.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state); },
self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state); // not walking, but stopped touching something
}, None=>self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state),
// not walking, but stopped touching something }
None=>self.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state),
} }
} }
} }
@@ -893,7 +877,6 @@ pub struct PhysicsState{
//gameplay_state //gameplay_state
mode_state:ModeState, mode_state:ModeState,
move_state:MoveState, move_state:MoveState,
strafe_tick_state:StrafeTickState,
//run is non optional: when you spawn in a run is created //run is non optional: when you spawn in a run is created
//the run cannot be finished unless you start it by visiting //the run cannot be finished unless you start it by visiting
//a start zone. If you change mode, a new run is created. //a start zone. If you change mode, a new run is created.
@@ -912,7 +895,6 @@ impl Default for PhysicsState{
input_state:InputState::default(), input_state:InputState::default(),
_world:WorldState{}, _world:WorldState{},
mode_state:ModeState::default(), mode_state:ModeState::default(),
strafe_tick_state:StrafeTickState::new(Time::ZERO,&StyleModifiers::default().strafe.unwrap()),
run:run::Run::new(), run:run::Run::new(),
} }
} }
@@ -959,7 +941,10 @@ impl PhysicsState{
*self=Self::default(); *self=Self::default();
} }
fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,Time>>{ fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,Time>>{
self.move_state.next_move_instruction() self.move_state.next_move_instruction(&self.style.strafe,self.time)
}
fn cull_velocity(&mut self,data:&PhysicsData,velocity:Planar64Vec3){
self.move_state.cull_velocity(velocity,&mut self.body,&mut self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
} }
fn set_move_state(&mut self,data:&PhysicsData,move_state:MoveState){ fn set_move_state(&mut self,data:&PhysicsData,move_state:MoveState){
self.move_state.set_move_state(move_state,&mut self.body,&self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state); self.move_state.set_move_state(move_state,&mut self.body,&self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
@@ -1018,6 +1003,12 @@ impl PhysicsData{
hitbox_mesh:StyleModifiers::default().calculate_mesh(), hitbox_mesh:StyleModifiers::default().calculate_mesh(),
} }
} }
pub fn closest_point(&self,mesh_id:u32,point:Planar64Vec3)->Option<crate::mesh_query::FEV<MinkowskiMesh<'_>>>{
let model_mesh=self.models.mesh(ConvexMeshId{model_id:PhysicsModelId::Contact(ContactModelId(mesh_id)),submesh_id:PhysicsSubmeshId::new(0)});
println!("transform={:?}",model_mesh.transform.vertex.matrix3);
let minkowski=MinkowskiMesh::minkowski_sum(model_mesh,self.hitbox_mesh.transformed_mesh());
minkowski.closest_point(point)
}
pub fn new(map:&map::CompleteMap)->Self{ pub fn new(map:&map::CompleteMap)->Self{
let modes=map.modes.clone().denormalize(); let modes=map.modes.clone().denormalize();
let mut used_contact_attributes=Vec::new(); let mut used_contact_attributes=Vec::new();
@@ -1217,18 +1208,8 @@ fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Ti
//JUST POLLING!!! NO MUTATION //JUST POLLING!!! NO MUTATION
let mut collector=instruction::InstructionCollector::new(time_limit); let mut collector=instruction::InstructionCollector::new(time_limit);
// walking
collector.collect(state.next_move_instruction()); collector.collect(state.next_move_instruction());
// strafe tick
collector.collect(state.style.strafe.as_ref().map(|strafe|{
TimedInstruction{
time:state.strafe_tick_state.next_tick(strafe),
//only poll the physics if there is a before and after mouse event
instruction:InternalInstruction::StrafeTick
}
}));
let trajectory=state.body.with_acceleration(state.acceleration(data)); let trajectory=state.body.with_acceleration(state.acceleration(data));
//check for collision ends //check for collision ends
state.touching.predict_collision_end(&mut collector,&data.models,&data.hitbox_mesh,&trajectory,state.time); state.touching.predict_collision_end(&mut collector,&data.models,&data.hitbox_mesh,&trajectory,state.time);
@@ -1726,7 +1707,22 @@ fn collision_end_contact(
){ ){
touching.remove_contact(convex_mesh_id);//remove contact before calling contact_constrain_acceleration touching.remove_contact(convex_mesh_id);//remove contact before calling contact_constrain_acceleration
//check ground //check ground
move_state.update_move_state(body,touching,models,hitbox_mesh,style,camera,input_state,|contact|contact.convex_mesh_id==*convex_mesh_id); //TODO do better
//this is inner code from move_state.cull_velocity
match move_state.get_walk_state(){
// did you stop touching the thing you were walking on?
// This does not check the face! Is that a bad thing? It should be
// impossible to stop touching a different face than you started touching...
Some(walk_state)=>if &walk_state.contact.convex_mesh_id==convex_mesh_id{
move_state.set_move_state(MoveState::Air,body,touching,models,hitbox_mesh,style,camera,input_state);
}else{
// stopped touching something else while walking
move_state.update_walk_target(body,touching,models,hitbox_mesh,style,camera,input_state);
move_state.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state);
},
// not walking, but stopped touching something
None=>move_state.update_fly_velocity(body,touching,models,hitbox_mesh,style,camera,input_state),
}
} }
fn collision_end_intersect( fn collision_end_intersect(
move_state:&mut MoveState, move_state:&mut MoveState,
@@ -1809,7 +1805,6 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
), ),
}, },
InternalInstruction::StrafeTick=>{ InternalInstruction::StrafeTick=>{
state.strafe_tick_state.tick_number+=1;
//TODO make this less huge //TODO make this less huge
if let Some(strafe_settings)=&state.style.strafe{ if let Some(strafe_settings)=&state.style.strafe{
let controls=state.input_state.controls; let controls=state.input_state.controls;
@@ -1824,7 +1819,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
state.body=extrapolated_body; state.body=extrapolated_body;
//this is wrong but will work ig //this is wrong but will work ig
//need to note which push planes activate in push solve and keep those //need to note which push planes activate in push solve and keep those
state.move_state.cull_velocity(ticked_velocity,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); state.cull_velocity(data,ticked_velocity);
} }
} }
} }
@@ -1908,7 +1903,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
let jump_dir=walk_state.jump_direction.direction(&data.models,&data.hitbox_mesh,&walk_state.contact); let jump_dir=walk_state.jump_direction.direction(&data.models,&data.hitbox_mesh,&walk_state.contact);
let booster_option=data.models.contact_attr(walk_state.contact.convex_mesh_id.model_id).general.booster.as_ref(); let booster_option=data.models.contact_attr(walk_state.contact.convex_mesh_id.model_id).general.booster.as_ref();
let jumped_velocity=jump_settings.jumped_velocity(&state.style,jump_dir,state.body.velocity,booster_option); let jumped_velocity=jump_settings.jumped_velocity(&state.style,jump_dir,state.body.velocity,booster_option);
state.move_state.cull_velocity(jumped_velocity,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); state.cull_velocity(data,jumped_velocity);
} }
} }
b_refresh_walk_target=false; b_refresh_walk_target=false;
@@ -1981,7 +1976,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
if b_refresh_walk_target{ if b_refresh_walk_target{
state.move_state.update_walk_target(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); state.move_state.update_walk_target(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state);
state.move_state.update_fly_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); state.move_state.update_fly_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state);
state.move_state.cull_velocity(state.body.velocity,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state); state.cull_velocity(data,state.body.velocity);
//also check if accelerating away from surface //also check if accelerating away from surface
} }
} }

View File

@@ -244,18 +244,18 @@ impl InstructionConsumer<Instruction<'_>> for Session{
self.clear_recording(); self.clear_recording();
let mode_id=self.simulation.physics.mode(); let mode_id=self.simulation.physics.mode();
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset)); run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset));
// TODO: think about this harder. This works around a bug where you fall infinitely when you reset.
self.simulation.timer.set_time(ins.time,PhysicsTime::ZERO);
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))); run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())));
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Restart(mode_id))); run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Restart(mode_id)));
// TODO: think about this harder. This works around a bug where you fall infinitely when you reset.
self.simulation.timer.set_time(ins.time,PhysicsTime::ZERO);
}, },
Instruction::Input(SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndSpawn(mode_id,spawn_id)))=>{ Instruction::Input(SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndSpawn(mode_id,spawn_id)))=>{
self.clear_recording(); self.clear_recording();
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset)); run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset));
// TODO: think about this harder. This works around a bug where you fall infinitely when you reset.
self.simulation.timer.set_time(ins.time,PhysicsTime::ZERO);
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))); run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())));
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id))); run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id)));
// TODO: think about this harder. This works around a bug where you fall infinitely when you reset.
self.simulation.timer.set_time(ins.time,PhysicsTime::ZERO);
}, },
Instruction::Input(SessionInputInstruction::Misc(misc_instruction))=>{ Instruction::Input(SessionInputInstruction::Misc(misc_instruction))=>{
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(misc_instruction)); run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(misc_instruction));

View File

@@ -111,22 +111,3 @@ fn bug_3(){
assert_eq!(body.velocity,vec3::int(0,0,0)); assert_eq!(body.velocity,vec3::int(0,0,0));
assert_eq!(body.time,Time::from_secs(2)); assert_eq!(body.time,Time::from_secs(2));
} }
#[test]
fn press_w(){
let physics_data=test_scene();
let mut physics=PhysicsState::default();
// press W
PhysicsContext::run_input_instruction(&mut physics,&physics_data,strafesnet_common::instruction::TimedInstruction{
time:Time::ZERO,
instruction:strafesnet_common::physics::Instruction::SetControl(strafesnet_common::physics::SetControlInstruction::SetMoveForward(true)),
});
// wait 10 ms
const SAMPLE_TIME:strafesnet_common::physics::Time=Time::from_millis(10);
PhysicsContext::run_input_instruction(&mut physics,&physics_data,strafesnet_common::instruction::TimedInstruction{
time:SAMPLE_TIME,
instruction:strafesnet_common::physics::Instruction::Idle,
});
// observe current velocity
assert_eq!(physics.camera_trajectory(&physics_data).extrapolated_velocity(SAMPLE_TIME),vec3::raw_xyz(0,-1<<32,-0x2b3333333));
}

View File

@@ -76,3 +76,21 @@ fn physics_bug_3()->Result<(),ReplayError>{
Ok(()) Ok(())
} }
#[test]
fn physics_bug_26()->Result<(),ReplayError>{
println!("loading map file..");
let data=read_entire_file("../tools/bhop_maps/5692124338.snfm")?;
let map=strafesnet_snf::read_map(data)?.into_complete_map()?;
// create recording
println!("generating models..");
let physics_data=PhysicsData::new(&map);
println!("reproducing bug...");
//teleport to bug
let fev=physics_data.closest_point(1020,strafesnet_common::integer::vec3::try_from_f32_array([76.889,363.188,-309.263]).unwrap()).unwrap();
println!("{fev:?}");
Ok(())
}

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "strafesnet_common" name = "strafesnet_common"
version = "0.9.0" version = "0.8.7"
edition = "2024" edition = "2024"
repository = "https://git.itzana.me/StrafesNET/strafe-project" repository = "https://git.itzana.me/StrafesNET/strafe-project"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@@ -2,6 +2,7 @@ const VALVE_SCALE:Planar64=Planar64::raw(1<<28);// 1/16
use crate::integer::{int,vec3::int as int3,AbsoluteTime,Ratio64,Planar64,Planar64Vec3}; use crate::integer::{int,vec3::int as int3,AbsoluteTime,Ratio64,Planar64,Planar64Vec3};
use crate::controls_bitflag::Controls; use crate::controls_bitflag::Controls;
use crate::physics::Time as PhysicsTime;
#[derive(Clone,Debug)] #[derive(Clone,Debug)]
pub struct StyleModifiers{ pub struct StyleModifiers{
@@ -272,6 +273,9 @@ impl StrafeSettings{
false=>None, false=>None,
} }
} }
pub fn next_tick(&self,time:PhysicsTime)->PhysicsTime{
PhysicsTime::from_nanos(self.tick_rate.rhs_div_int(self.tick_rate.mul_int(time.nanos())+1))
}
pub const fn activates(&self,controls:Controls)->bool{ pub const fn activates(&self,controls:Controls)->bool{
self.enable.activates(controls) self.enable.activates(controls)
} }

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "fixed_wide" name = "fixed_wide"
version = "0.3.0" version = "0.2.2"
edition = "2024" edition = "2024"
repository = "https://git.itzana.me/StrafesNET/strafe-project" repository = "https://git.itzana.me/StrafesNET/strafe-project"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@@ -605,8 +605,8 @@ macro_rules! macro_16 {
macro_16!( impl_multiplicative_assign_operator_not_const_generic, (MulAssign, mul_assign, mul) ); macro_16!( impl_multiplicative_assign_operator_not_const_generic, (MulAssign, mul_assign, mul) );
macro_16!( impl_multiply_operator_not_const_generic, (Mul, mul, Self) ); macro_16!( impl_multiply_operator_not_const_generic, (Mul, mul, Self) );
macro_16!( impl_multiplicative_assign_operator_not_const_generic, (DivAssign, div_assign, div) ); macro_16!( impl_multiplicative_assign_operator_not_const_generic, (DivAssign, div_assign, div_euclid) );
macro_16!( impl_divide_operator_not_const_generic, (Div, div, Self) ); macro_16!( impl_divide_operator_not_const_generic, (Div, div_euclid, Self) );
impl_multiplicative_assign_operator!( MulAssign, mul_assign, mul ); impl_multiplicative_assign_operator!( MulAssign, mul_assign, mul );
impl_multiplicative_operator!( Mul, mul, mul, Self ); impl_multiplicative_operator!( Mul, mul, mul, Self );
impl_multiplicative_assign_operator!( DivAssign, div_assign, div_euclid ); impl_multiplicative_assign_operator!( DivAssign, div_assign, div_euclid );

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "linear_ops" name = "linear_ops"
version = "0.2.0" version = "0.1.1"
edition = "2024" edition = "2024"
repository = "https://git.itzana.me/StrafesNET/strafe-project" repository = "https://git.itzana.me/StrafesNET/strafe-project"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "strafesnet_snf" name = "strafesnet_snf"
version = "0.4.0" version = "0.3.2"
edition = "2024" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html