From fe2b9921b4e1f8ad4ef6b97b78c6290c0c1669cd Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 15 Jan 2024 19:09:34 -0800 Subject: [PATCH 01/55] Initial commit --- .gitignore | 1 + Cargo.lock | 7 +++++ Cargo.toml | 8 ++++++ src/bot.rs | 33 ++++++++++++++++++++++ src/demo.rs | 13 +++++++++ src/file.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 19 +++++++++++++ src/map.rs | 44 +++++++++++++++++++++++++++++ 8 files changed, 204 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/bot.rs create mode 100644 src/demo.rs create mode 100644 src/file.rs create mode 100644 src/lib.rs create mode 100644 src/map.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0adf322 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "snf" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1f86192 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "snf" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/bot.rs b/src/bot.rs new file mode 100644 index 0000000..c90b823 --- /dev/null +++ b/src/bot.rs @@ -0,0 +1,33 @@ +pub enum Error{ + +} + +/* block types + +BLOCK_BOT_HEADER: +u128 map_resource_uuid //which map is this bot running +u128 time_resource_uuid //resource database time +//don't include style info in bot header because it's in the simulation state +//blocks are laid out in chronological order, but indices may jump around. +u64 num_segments +for _ in 0..num_segments{ + i64 time //simulation_state timestamp + u64 block_id +} + +BLOCK_BOT_SEGMENT: +//format version indicates what version of these structures to use +SimulationState simulation_state //SimulationState is just under ClientState which includes Play/Pause events that the simulation doesn't know about. +//to read, greedily decode instructions until eof +loop{ + //delta encode as much as possible (time,mousepos) + //strafe ticks are implied + //physics can be implied in an input-only bot file + TimedInstruction instruction +} + +*/ + +pub struct Bot{ + // +} \ No newline at end of file diff --git a/src/demo.rs b/src/demo.rs new file mode 100644 index 0000000..c2d30d4 --- /dev/null +++ b/src/demo.rs @@ -0,0 +1,13 @@ +pub enum Error{ + +} + +/* +BLOCK_DEMO_HEADER: +//timeline of loading maps, bots +*/ + +pub struct Demo{ + map:Box, + bots:Vec, +} \ No newline at end of file diff --git a/src/file.rs b/src/file.rs new file mode 100644 index 0000000..d615526 --- /dev/null +++ b/src/file.rs @@ -0,0 +1,79 @@ +//file format "sniff" + +pub enum Error{ + Header(HeaderError), + Map(crate::map::Error), + Bot(crate::bot::Error), + Demo(crate::demo::Error), +} + +pub enum MissingData{ + NeedExactly(usize),//missing exactly this many bytes + NeedAtLeast(usize),//missing at least this many bytes +} + +pub enum HeaderError{ + InvalidMagic, + InvalidVersion, + UnexpectedEOF{ + eof:usize, + missing_data:MissingData, + },//file ends in the middle of the header +} + +/* spec + +//begin global header + +//global metadata (32 bytes) +b"SNFB" +u32 format_version +u64 priming_bytes + //how many bytes of the file must be read to guarantee all of the expected + //format-specific metadata is available to facilitate streaming the remaining contents + //used by the database to guarantee that it serves at least the bare minimum +u128 resource_uuid + //identifies the file from anywhere for any other file + +//global block layout (variable size) +u64 num_blocks +for block_id in 0..num_blocks{ + u64 first_byte +} + +//end global header + +//begin blocks + +//each block is compressed with zstd or gz or something + +*/ + +pub enum Magic{ + Map, //"SNFM" + Bot, //"SNFB" + Demo, //"SNFD" + PlaylistDemo, +} + +pub struct Header{ + /// Type of file + magic:Magic, + /// Type version + version:u32, + /// Minimum data required to know the location of all streamable resources for this specific file + priming:u64, + /// uuid for this file + resource:u128, +} + +pub struct BlockLayout{ + count:u64, + location:Vec, +} + +pub enum SNF{ + Map(crate::map::Map), + Bot(crate::bot::Bot), + Demo(crate::demo::Demo), +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6312614 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,19 @@ +use std::io::Read; + +mod file; +mod map; +mod bot; +mod demo; + +pub fn read(input:R)->Result{ + Err(file::Error::Header(file::HeaderError::InvalidMagic)) +} + +#[cfg(test)] +mod tests { + //use super::*; + + #[test] + fn test() { + } +} diff --git a/src/map.rs b/src/map.rs new file mode 100644 index 0000000..81e73b6 --- /dev/null +++ b/src/map.rs @@ -0,0 +1,44 @@ +pub enum Error{ + +} + +/* block types + +BLOCK_MAP_HEADER: +DefaultStyleInfo style_info +//bvh goes here +u64 num_nodes +//node 0 parent node is implied to be None +for node_id in 1..num_nodes{ + u64 parent_node +} +u64 num_spacial_blocks +for spacial_block_id in 0..num_spacial_blocks{ + u64 node_id + u64 block_id //data block + Aabb block_extents +} +//ideally spacial blocks are sorted from distance to start zone +//texture blocks are inserted before the first spacial block they are used in + +BLOCK_MAP_RESOURCE: +//an individual one of the following: + - model (IndexedModel) + - shader (compiled SPIR-V) + - image (JpegXL) + - sound (Opus) + - video (AV1) + - animation (Trey thing) + +BLOCK_MAP_OBJECT: +//an individual one of the following: + - model instance + - located resource +//for a list of resources, parse the object. +//alternatively, BLOCK_MAP_REGION lists a group of objects to be decoded all at once + +*/ + +pub struct Map{ + // +} \ No newline at end of file From a9504a192b613046d1f0d8fd03e6e59ee19f898c Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 15 Jan 2024 19:27:30 -0800 Subject: [PATCH 02/55] License + README --- LICENSE-APACHE | 176 +++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 23 +++++++ README.md | 30 +++++++++ 3 files changed, 229 insertions(+) create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..a7e77cb --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..468cd79 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1d9e111 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +StrafesNET File Format +====================== + +## Example + +```rust +let file=std::fs::File::open(path)?; +let mut input=std::io::BufReader::new(file); +let snf=snf::read(input)?; +match snf{ + snf::SNF::Map(map)=>{}, + snf::SNF::Bot(bot)=>{}, + snf::SNF::Demo(demo)=>{}, +} +``` + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + \ No newline at end of file From fc1c9e843f66b50d8229a0a1294b977897768565 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 15 Jan 2024 19:30:26 -0800 Subject: [PATCH 03/55] oopsies --- src/file.rs | 24 +----------------------- src/lib.rs | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/file.rs b/src/file.rs index d615526..c25d2b2 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,24 +1,9 @@ //file format "sniff" pub enum Error{ - Header(HeaderError), - Map(crate::map::Error), - Bot(crate::bot::Error), - Demo(crate::demo::Error), -} - -pub enum MissingData{ - NeedExactly(usize),//missing exactly this many bytes - NeedAtLeast(usize),//missing at least this many bytes -} - -pub enum HeaderError{ InvalidMagic, InvalidVersion, - UnexpectedEOF{ - eof:usize, - missing_data:MissingData, - },//file ends in the middle of the header + UnexpectedEOF, } /* spec @@ -53,7 +38,6 @@ pub enum Magic{ Map, //"SNFM" Bot, //"SNFB" Demo, //"SNFD" - PlaylistDemo, } pub struct Header{ @@ -71,9 +55,3 @@ pub struct BlockLayout{ count:u64, location:Vec, } - -pub enum SNF{ - Map(crate::map::Map), - Bot(crate::bot::Bot), - Demo(crate::demo::Demo), -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6312614..01caa08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,26 @@ use std::io::Read; -mod file; -mod map; -mod bot; -mod demo; +pub mod file; +pub mod map; +pub mod bot; +pub mod demo; -pub fn read(input:R)->Result{ - Err(file::Error::Header(file::HeaderError::InvalidMagic)) +pub enum Error{ + Header(file::Error), + Map(map::Error), + Bot(bot::Error), + Demo(demo::Error), +} + +pub enum SNF{ + Map(map::Map), + Bot(bot::Bot), + Demo(demo::Demo), +} + +pub fn read(input:R)->Result{ + //let header:file::Header=input.read()?; + Err(Error::Header(file::Error::InvalidMagic)) } #[cfg(test)] From ec60086109fa2706d5ac0ba022cda61d6061ffda Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 16 Jan 2024 18:50:02 -0800 Subject: [PATCH 04/55] ideas --- src/map.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/map.rs b/src/map.rs index 81e73b6..df2d59b 100644 --- a/src/map.rs +++ b/src/map.rs @@ -12,16 +12,23 @@ u64 num_nodes for node_id in 1..num_nodes{ u64 parent_node } +//ideally spacial blocks are sorted from distance to start zone +//texture blocks are inserted before the first spacial block they are used in u64 num_spacial_blocks for spacial_block_id in 0..num_spacial_blocks{ u64 node_id u64 block_id //data block Aabb block_extents } -//ideally spacial blocks are sorted from distance to start zone -//texture blocks are inserted before the first spacial block they are used in +//if the map file references external resources, num_resources = 0 +u64 num_resources +for resource_id in 0..num_resources{ + u64 block_id + u128 resource_id +} BLOCK_MAP_RESOURCE: +Resource resource_type //an individual one of the following: - model (IndexedModel) - shader (compiled SPIR-V) @@ -30,12 +37,12 @@ BLOCK_MAP_RESOURCE: - video (AV1) - animation (Trey thing) -BLOCK_MAP_OBJECT: -//an individual one of the following: - - model instance - - located resource -//for a list of resources, parse the object. -//alternatively, BLOCK_MAP_REGION lists a group of objects to be decoded all at once +BLOCK_MAP_REGION: +u64 num_models +for model_id in 0..num_models{ + u128 model_resource_uuid + ModelInstance mode_instance +} */ From b2673f17323fede93dbf5f3abf8915786d09b900 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 18 Jan 2024 15:33:22 -0800 Subject: [PATCH 05/55] Streamables --- src/bot.rs | 23 ++++++++++++++++++++--- src/demo.rs | 20 +++++++++++++++----- src/lib.rs | 6 +++--- src/map.rs | 26 ++++++++++++++++++++++++-- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index c90b823..cd23d82 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -1,5 +1,5 @@ pub enum Error{ - + InvalidSegment, } /* block types @@ -28,6 +28,23 @@ loop{ */ -pub struct Bot{ - // +struct SegmentId(u64); + +pub struct Segment{ + state:simulation::State, + instructions:Vec> +} + +pub struct StreamableBot{ + file:crate::file::File, + timeline:timeline::Timeline, +} +impl StreamableBot{ + pub fn load_segment(&mut self,segment_id:u64)->Result{ + //load region from disk + //parse the models and determine what resources need to be loaded + //load resources into self.resources + //return Region + Err(Error::InvalidSegment) + } } \ No newline at end of file diff --git a/src/demo.rs b/src/demo.rs index c2d30d4..ea66dc5 100644 --- a/src/demo.rs +++ b/src/demo.rs @@ -1,13 +1,23 @@ pub enum Error{ - + // } /* BLOCK_DEMO_HEADER: -//timeline of loading maps, bots +u128 map_resource_id +u64 map_header_block_id +u32 num_bots +for bot_id in 0..num_bots{ + u128 bot_resource_id + u64 bot_header_block_id +} + +//bot loading timeline +how to do worldstate for deathrun!? + */ -pub struct Demo{ - map:Box, - bots:Vec, +pub struct StreamableDemo{ + map:Box, + bots:Vec, } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 01caa08..e36ef03 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,9 +13,9 @@ pub enum Error{ } pub enum SNF{ - Map(map::Map), - Bot(bot::Bot), - Demo(demo::Demo), + Map(map::StreamableMap), + Bot(bot::StreamableBot), + Demo(demo::StreamableDemo), } pub fn read(input:R)->Result{ diff --git a/src/map.rs b/src/map.rs index df2d59b..e4fc21f 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,5 +1,5 @@ pub enum Error{ - + InvalidNode, } /* block types @@ -46,6 +46,28 @@ for model_id in 0..num_models{ */ -pub struct Map{ +struct Uuid(u128); +struct BvhNodeId(u64); +struct BvhNode{ // +} +enum Resource{ + IndexedModel(model::IndexedModel), + Image(image::Image),//? +} + +pub struct StreamableMap{ + file:crate::file::File, + style:physics::StyleModifiers,//probably should move this out of physics + bvh:BvhNode, + resources:std::collections::HashMap, +} +impl StreamableMap{ + pub fn load_node(&mut self,node_id:BvhNodeId)->Result,Error>{ + //load region from disk + //parse the models and determine what resources need to be loaded + //load resources into self.resources + //return Region + Err(Error::InvalidNode) + } } \ No newline at end of file From 134e3fc79a18ada8ec4b2c0a30b96de2d1120e01 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 18 Jan 2024 15:33:37 -0800 Subject: [PATCH 06/55] data normalization --- src/bot.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bot.rs b/src/bot.rs index cd23d82..d1472e0 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -6,7 +6,6 @@ pub enum Error{ BLOCK_BOT_HEADER: u128 map_resource_uuid //which map is this bot running -u128 time_resource_uuid //resource database time //don't include style info in bot header because it's in the simulation state //blocks are laid out in chronological order, but indices may jump around. u64 num_segments From 6f22aaeec4347ddd643e2cb950209ed3a9f2d691 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 16 Jan 2024 20:07:11 -0800 Subject: [PATCH 07/55] temp code for improved focus --- src/bot.rs | 14 ++++++++++++++ src/file.rs | 4 ++++ src/map.rs | 28 +++++++++++++++++++++------- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index d1472e0..3071a21 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -27,6 +27,20 @@ loop{ */ +//xdd +mod simulation{ + pub struct State{} + pub struct Instruction{} +} +mod instruction{ + pub struct TimedInstruction{instruction:Instruction} +} +mod timeline{ + pub struct Timeline{timeline:Vec>} +} + +//serious code + struct SegmentId(u64); pub struct Segment{ diff --git a/src/file.rs b/src/file.rs index c25d2b2..0c2b4b9 100644 --- a/src/file.rs +++ b/src/file.rs @@ -55,3 +55,7 @@ pub struct BlockLayout{ count:u64, location:Vec, } + +pub struct File{ + //??? +} diff --git a/src/map.rs b/src/map.rs index e4fc21f..0cd0330 100644 --- a/src/map.rs +++ b/src/map.rs @@ -46,21 +46,35 @@ for model_id in 0..num_models{ */ -struct Uuid(u128); -struct BvhNodeId(u64); + +//xdd +mod physics{ + pub struct StyleModifiers{} +} +mod model{ + pub struct IndexedModel{} + pub struct ModelInstance{} +} +mod image{ + pub struct Image{} +} + +//serious code + +struct ModelUuid(u128); +struct ImageUuid(u128); +pub struct BvhNodeId(u64); struct BvhNode{ // } -enum Resource{ - IndexedModel(model::IndexedModel), - Image(image::Image),//? -} pub struct StreamableMap{ file:crate::file::File, style:physics::StyleModifiers,//probably should move this out of physics bvh:BvhNode, - resources:std::collections::HashMap, + //do not need this? return only new data with load_node + resource_model:std::collections::HashMap, + resource_image:std::collections::HashMap, } impl StreamableMap{ pub fn load_node(&mut self,node_id:BvhNodeId)->Result,Error>{ From 2d420d76769896edd239cccd8f0f8727d5294a5a Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 18 Jan 2024 15:24:00 -0800 Subject: [PATCH 08/55] good idea --- src/map.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/map.rs b/src/map.rs index 0cd0330..19f7dc6 100644 --- a/src/map.rs +++ b/src/map.rs @@ -12,6 +12,11 @@ u64 num_nodes for node_id in 1..num_nodes{ u64 parent_node } + +//NOTE: alternate realities are not necessary. +//portals/wormholes simply use an in-model and and out-model. +//skyboxes are inverted models with a special shader. + //ideally spacial blocks are sorted from distance to start zone //texture blocks are inserted before the first spacial block they are used in u64 num_spacial_blocks From 5ea8a2db5f87b085b537ac95115297ac43823b11 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 18 Jan 2024 16:39:58 -0800 Subject: [PATCH 09/55] some code --- src/bot.rs | 4 ++++ src/demo.rs | 7 ++++++- src/file.rs | 37 +++++++++++++++++++++++++++---------- src/lib.rs | 32 +++++++++++++++++++++++++++++--- src/map.rs | 4 ++++ 5 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index 3071a21..c5a5c0c 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -1,4 +1,5 @@ pub enum Error{ + InvalidHeader, InvalidSegment, } @@ -53,6 +54,9 @@ pub struct StreamableBot{ timeline:timeline::Timeline, } impl StreamableBot{ + pub fn new(file:crate::file::File)->Result{ + Err(Error::InvalidHeader) + } pub fn load_segment(&mut self,segment_id:u64)->Result{ //load region from disk //parse the models and determine what resources need to be loaded diff --git a/src/demo.rs b/src/demo.rs index ea66dc5..486f861 100644 --- a/src/demo.rs +++ b/src/demo.rs @@ -1,5 +1,5 @@ pub enum Error{ - // + InvalidHeader, } /* @@ -20,4 +20,9 @@ how to do worldstate for deathrun!? pub struct StreamableDemo{ map:Box, bots:Vec, +} +impl StreamableDemo{ + pub fn new(file:crate::file::File)->Result{ + Err(Error::InvalidHeader) + } } \ No newline at end of file diff --git a/src/file.rs b/src/file.rs index 0c2b4b9..d9ebb14 100644 --- a/src/file.rs +++ b/src/file.rs @@ -33,16 +33,16 @@ for block_id in 0..num_blocks{ //each block is compressed with zstd or gz or something */ - -pub enum Magic{ - Map, //"SNFM" - Bot, //"SNFB" - Demo, //"SNFD" +#[derive(Clone,Copy)] +pub(crate) enum FourCC{ + Map, + Bot, + Demo, } -pub struct Header{ +struct Header{ /// Type of file - magic:Magic, + fourcc:FourCC, /// Type version version:u32, /// Minimum data required to know the location of all streamable resources for this specific file @@ -51,11 +51,28 @@ pub struct Header{ resource:u128, } -pub struct BlockLayout{ +pub(crate) struct BlockLayout{ count:u64, location:Vec, } -pub struct File{ - //??? +pub(crate) struct File{ + header:Header, + block_layout:BlockLayout, + //reference to the data +} + +impl File{ + pub(crate) fn new(input:R)->Result{ + Self{ + header:input.read_le()?, + block_layout:input.read_le()?, + } + } + pub(crate) fn read_block(&mut self,block_id:u64)->Result,Error>{ + Err(Error::UnexpectedEOF) + } + pub(crate) fn fourcc(&self)->FourCC{ + self.header.fourcc + } } diff --git a/src/lib.rs b/src/lib.rs index e36ef03..2777453 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ pub mod bot; pub mod demo; pub enum Error{ + UnexpectedFourCC, Header(file::Error), Map(map::Error), Bot(bot::Error), @@ -18,9 +19,34 @@ pub enum SNF{ Demo(demo::StreamableDemo), } -pub fn read(input:R)->Result{ - //let header:file::Header=input.read()?; - Err(Error::Header(file::Error::InvalidMagic)) +pub fn read_snf(input:R)->Result{ + let file=file::File::read(input).map_err(|e|Error::Header(e))?; + Ok(match file.fourcc(){ + file::FourCC::Map=>SNF::Map(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), + file::FourCC::Bot=>SNF::Bot(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), + file::FourCC::Demo=>SNF::Demo(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), + }) +} +pub fn read_map(input:R)->Result{ + let file=file::File::read(input).map_err(|e|Error::Header(e))?; + match file.fourcc(){ + file::FourCC::Map=>Ok(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), + _=>Err(Error::UnexpectedFourCC) + } +} +pub fn read_bot(input:R)->Result{ + let file=file::File::read(input).map_err(|e|Error::Header(e))?; + match file.fourcc(){ + file::FourCC::Bot=>Ok(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), + _=>Err(Error::UnexpectedFourCC) + } +} +pub fn read_demo(input:R)->Result{ + let file=file::File::read(input).map_err(|e|Error::Header(e))?; + match file.fourcc(){ + file::FourCC::Demo=>Ok(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), + _=>Err(Error::UnexpectedFourCC) + } } #[cfg(test)] diff --git a/src/map.rs b/src/map.rs index 19f7dc6..53e6501 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,4 +1,5 @@ pub enum Error{ + InvalidHeader, InvalidNode, } @@ -82,6 +83,9 @@ pub struct StreamableMap{ resource_image:std::collections::HashMap, } impl StreamableMap{ + pub fn new(file:crate::file::File)->Result{ + Err(Error::InvalidHeader) + } pub fn load_node(&mut self,node_id:BvhNodeId)->Result,Error>{ //load region from disk //parse the models and determine what resources need to be loaded From 040b6077922fbc7d83c42ab798299c7b5182ce17 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 18 Jan 2024 16:40:04 -0800 Subject: [PATCH 10/55] add binrw dep --- Cargo.lock | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + 2 files changed, 87 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 0adf322..9f44fa2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,92 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "binrw" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173901312e9850391d4d7c1318c4e099fdc037d61870fca427429830efdb4e5f" +dependencies = [ + "array-init", + "binrw_derive", + "bytemuck", +] + +[[package]] +name = "binrw_derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb515fdd6f8d3a357c8e19b8ec59ef53880807864329b1cb1cba5c53bf76557e" +dependencies = [ + "either", + "owo-colors", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "proc-macro2" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + [[package]] name = "snf" version = "0.1.0" +dependencies = [ + "binrw", +] + +[[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 = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml index 1f86192..44e1531 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +binrw = "0.13.3" From 14e7e4df297b867c766a5b05ca127bca2c7ad7c0 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 18 Jan 2024 16:59:00 -0800 Subject: [PATCH 11/55] implement some binrw stuff --- src/file.rs | 31 ++++++++++++++++++------------- src/lib.rs | 18 +++++++++--------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/file.rs b/src/file.rs index d9ebb14..f3a2473 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,8 +1,9 @@ //file format "sniff" +use binrw::{binrw, BinReaderExt}; + pub enum Error{ - InvalidMagic, - InvalidVersion, + InvalidHeader(binrw::Error), UnexpectedEOF, } @@ -33,13 +34,19 @@ for block_id in 0..num_blocks{ //each block is compressed with zstd or gz or something */ +#[binrw] +#[brw(little)] #[derive(Clone,Copy)] pub(crate) enum FourCC{ + #[brw(magic=b"SNFM")] Map, + #[brw(magic=b"SNFB")] Bot, + #[brw(magic=b"SNFD")] Demo, } - +#[binrw] +#[brw(little)] struct Header{ /// Type of file fourcc:FourCC, @@ -49,25 +56,23 @@ struct Header{ priming:u64, /// uuid for this file resource:u128, + #[bw(try_calc(u64::try_from(block_location.len())))] + block_count:u64, + #[br(count=block_count)] + block_location:Vec, } -pub(crate) struct BlockLayout{ - count:u64, - location:Vec, -} pub(crate) struct File{ header:Header, - block_layout:BlockLayout, //reference to the data } impl File{ - pub(crate) fn new(input:R)->Result{ - Self{ - header:input.read_le()?, - block_layout:input.read_le()?, - } + pub(crate) fn new(mut input:R)->Result{ + Ok(Self{ + header:input.read_le().map_err(|e|Error::InvalidHeader(e))?, + }) } pub(crate) fn read_block(&mut self,block_id:u64)->Result,Error>{ Err(Error::UnexpectedEOF) diff --git a/src/lib.rs b/src/lib.rs index 2777453..6ea292d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -use std::io::Read; +use binrw::BinReaderExt; pub mod file; pub mod map; @@ -19,30 +19,30 @@ pub enum SNF{ Demo(demo::StreamableDemo), } -pub fn read_snf(input:R)->Result{ - let file=file::File::read(input).map_err(|e|Error::Header(e))?; +pub fn read_snf(input:R)->Result{ + let file=file::File::new(input).map_err(|e|Error::Header(e))?; Ok(match file.fourcc(){ file::FourCC::Map=>SNF::Map(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), file::FourCC::Bot=>SNF::Bot(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), file::FourCC::Demo=>SNF::Demo(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), }) } -pub fn read_map(input:R)->Result{ - let file=file::File::read(input).map_err(|e|Error::Header(e))?; +pub fn read_map(input:R)->Result{ + let file=file::File::new(input).map_err(|e|Error::Header(e))?; match file.fourcc(){ file::FourCC::Map=>Ok(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), _=>Err(Error::UnexpectedFourCC) } } -pub fn read_bot(input:R)->Result{ - let file=file::File::read(input).map_err(|e|Error::Header(e))?; +pub fn read_bot(input:R)->Result{ + let file=file::File::new(input).map_err(|e|Error::Header(e))?; match file.fourcc(){ file::FourCC::Bot=>Ok(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), _=>Err(Error::UnexpectedFourCC) } } -pub fn read_demo(input:R)->Result{ - let file=file::File::read(input).map_err(|e|Error::Header(e))?; +pub fn read_demo(input:R)->Result{ + let file=file::File::new(input).map_err(|e|Error::Header(e))?; match file.fourcc(){ file::FourCC::Demo=>Ok(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), _=>Err(Error::UnexpectedFourCC) From d5af08730b8bede824672e452d1692b0acb3609b Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 18 Jan 2024 19:28:01 -0800 Subject: [PATCH 12/55] write a bunch of binrw --- src/bot.rs | 55 +++++++++++++++++++++++++++++++++++++++-------------- src/demo.rs | 12 +++++++----- src/file.rs | 29 +++++++++++++++++++--------- src/lib.rs | 16 ++++++++-------- src/map.rs | 32 ++++++++++++++++++++++++------- 5 files changed, 101 insertions(+), 43 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index c5a5c0c..3c97671 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -1,6 +1,10 @@ +use binrw::{BinReaderExt, binrw}; + pub enum Error{ InvalidHeader, - InvalidSegment, + InvalidSegment(binrw::Error), + InvalidSegmentId(u64), + File(crate::file::Error), } /* block types @@ -28,40 +32,63 @@ loop{ */ -//xdd +//error hiding mock code mod simulation{ + #[super::binrw] + #[brw(little)] pub struct State{} + #[super::binrw] + #[brw(little)] pub struct Instruction{} } mod instruction{ - pub struct TimedInstruction{instruction:Instruction} + #[super::binrw] + #[brw(little)] + pub struct TimedInstruction{ + time:u64, + instruction:Instruction + } } mod timeline{ - pub struct Timeline{timeline:Vec>} + #[super::binrw] + #[brw(little)] + pub struct Timeline{ + #[bw(try_calc(u32::try_from(instructions.len())))] + instruction_count:u32, + #[br(count=instruction_count)] + instructions:Vec> + } } //serious code +#[binrw] +#[brw(little)] struct SegmentId(u64); +#[binrw] +#[brw(little)] pub struct Segment{ state:simulation::State, + #[bw(try_calc(u32::try_from(instructions.len())))] + instruction_count:u32, + #[br(count=instruction_count)] instructions:Vec> } -pub struct StreamableBot{ - file:crate::file::File, +pub struct StreamableBot{ + file:crate::file::File, timeline:timeline::Timeline, + segment_id_to_block_id:Vec, } -impl StreamableBot{ - pub fn new(file:crate::file::File)->Result{ +impl StreamableBot{ + pub(crate) fn new(file:crate::file::File)->Result{ Err(Error::InvalidHeader) } - pub fn load_segment(&mut self,segment_id:u64)->Result{ - //load region from disk - //parse the models and determine what resources need to be loaded - //load resources into self.resources - //return Region - Err(Error::InvalidSegment) + pub fn load_segment(&mut self,segment_id:SegmentId)->Result{ + let block_id=*self.segment_id_to_block_id.get(segment_id.0 as usize).ok_or(Error::InvalidSegmentId(segment_id.0))?; + let mut block=self.file.take_block(block_id).map_err(|e|Error::File(e))?; + let segment=block.read_le().map_err(|e|Error::InvalidSegment(e))?; + Ok(segment) } } \ No newline at end of file diff --git a/src/demo.rs b/src/demo.rs index 486f861..302ea5a 100644 --- a/src/demo.rs +++ b/src/demo.rs @@ -1,3 +1,5 @@ +use binrw::BinReaderExt; + pub enum Error{ InvalidHeader, } @@ -17,12 +19,12 @@ how to do worldstate for deathrun!? */ -pub struct StreamableDemo{ - map:Box, - bots:Vec, +pub struct StreamableDemo{ + map:Box>, + bots:Vec>, } -impl StreamableDemo{ - pub fn new(file:crate::file::File)->Result{ +impl StreamableDemo{ + pub(crate) fn new(file:crate::file::File)->Result{ Err(Error::InvalidHeader) } } \ No newline at end of file diff --git a/src/file.rs b/src/file.rs index f3a2473..f1bf2b0 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,10 +1,12 @@ //file format "sniff" -use binrw::{binrw, BinReaderExt}; +use binrw::{binrw, BinReaderExt, io::TakeSeekExt}; pub enum Error{ InvalidHeader(binrw::Error), UnexpectedEOF, + InvalidBlockId(usize), + Seek(std::io::Error), } /* spec @@ -56,26 +58,35 @@ struct Header{ priming:u64, /// uuid for this file resource:u128, - #[bw(try_calc(u64::try_from(block_location.len())))] + #[bw(try_calc(u64::try_from(block_location.len()-1)))] block_count:u64, - #[br(count=block_count)] + #[br(count=block_count+1)] block_location:Vec, } +pub struct BlockId(usize); -pub(crate) struct File{ +pub(crate) struct File{ header:Header, //reference to the data + data:R, } -impl File{ - pub(crate) fn new(mut input:R)->Result{ - Ok(Self{ +impl File{ + pub(crate) fn new(mut input:R)->Result,Error>{ + Ok(File{ header:input.read_le().map_err(|e|Error::InvalidHeader(e))?, + data:input, }) } - pub(crate) fn read_block(&mut self,block_id:u64)->Result,Error>{ - Err(Error::UnexpectedEOF) + pub(crate) fn take_block(&mut self,block_id:BlockId)->Result,Error>{ + if self.header.block_location.len()<=block_id.0{ + return Err(Error::InvalidBlockId(block_id.0)) + } + let block_start=self.header.block_location[block_id.0]; + let block_end=self.header.block_location[block_id.0+1]; + self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(|e|Error::Seek(e))?; + Ok((&mut self.data).take_seek(block_end-block_start)) } pub(crate) fn fourcc(&self)->FourCC{ self.header.fourcc diff --git a/src/lib.rs b/src/lib.rs index 6ea292d..d17883a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,13 +13,13 @@ pub enum Error{ Demo(demo::Error), } -pub enum SNF{ - Map(map::StreamableMap), - Bot(bot::StreamableBot), - Demo(demo::StreamableDemo), +pub enum SNF{ + Map(map::StreamableMap), + Bot(bot::StreamableBot), + Demo(demo::StreamableDemo), } -pub fn read_snf(input:R)->Result{ +pub fn read_snf(input:R)->Result,Error>{ let file=file::File::new(input).map_err(|e|Error::Header(e))?; Ok(match file.fourcc(){ file::FourCC::Map=>SNF::Map(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), @@ -27,21 +27,21 @@ pub fn read_snf(input:R)->Result{ file::FourCC::Demo=>SNF::Demo(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), }) } -pub fn read_map(input:R)->Result{ +pub fn read_map(input:R)->Result,Error>{ let file=file::File::new(input).map_err(|e|Error::Header(e))?; match file.fourcc(){ file::FourCC::Map=>Ok(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), _=>Err(Error::UnexpectedFourCC) } } -pub fn read_bot(input:R)->Result{ +pub fn read_bot(input:R)->Result,Error>{ let file=file::File::new(input).map_err(|e|Error::Header(e))?; match file.fourcc(){ file::FourCC::Bot=>Ok(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), _=>Err(Error::UnexpectedFourCC) } } -pub fn read_demo(input:R)->Result{ +pub fn read_demo(input:R)->Result,Error>{ let file=file::File::new(input).map_err(|e|Error::Header(e))?; match file.fourcc(){ file::FourCC::Demo=>Ok(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), diff --git a/src/map.rs b/src/map.rs index 53e6501..4ed7885 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,10 @@ +use binrw::{BinReaderExt, binrw}; + pub enum Error{ InvalidHeader, - InvalidNode, + InvalidNodeId(u64), + InvalidRegion(binrw::Error), + File(crate::file::Error), } /* block types @@ -53,12 +57,14 @@ for model_id in 0..num_models{ */ -//xdd +//error hiding mock code mod physics{ pub struct StyleModifiers{} } mod model{ pub struct IndexedModel{} + #[super::binrw] + #[brw(little)] pub struct ModelInstance{} } mod image{ @@ -73,17 +79,26 @@ pub struct BvhNodeId(u64); struct BvhNode{ // } +#[binrw] +#[brw(little)] +struct Region{ + #[bw(try_calc(u32::try_from(models.len())))] + model_count:u32, + #[br(count=model_count)] + models:Vec, +} -pub struct StreamableMap{ - file:crate::file::File, +pub struct StreamableMap{ + file:crate::file::File, style:physics::StyleModifiers,//probably should move this out of physics bvh:BvhNode, + node_id_to_block_id:Vec, //do not need this? return only new data with load_node resource_model:std::collections::HashMap, resource_image:std::collections::HashMap, } -impl StreamableMap{ - pub fn new(file:crate::file::File)->Result{ +impl StreamableMap{ + pub(crate) fn new(file:crate::file::File)->Result{ Err(Error::InvalidHeader) } pub fn load_node(&mut self,node_id:BvhNodeId)->Result,Error>{ @@ -91,6 +106,9 @@ impl StreamableMap{ //parse the models and determine what resources need to be loaded //load resources into self.resources //return Region - Err(Error::InvalidNode) + let block_id=*self.node_id_to_block_id.get(node_id.0 as usize).ok_or(Error::InvalidNodeId(node_id.0))?; + let mut block=self.file.take_block(block_id).map_err(|e|Error::File(e))?; + let region:Region=block.read_le().map_err(|e|Error::InvalidRegion(e))?; + Ok(region.models) } } \ No newline at end of file From dea408daeef576cff8ffa61356c89a9d03d95f6b Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 29 Jan 2024 15:18:05 -0800 Subject: [PATCH 13/55] change the name --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f44fa2..63c39b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,7 +69,7 @@ dependencies = [ ] [[package]] -name = "snf" +name = "strafesnet_snf" version = "0.1.0" dependencies = [ "binrw", diff --git a/Cargo.toml b/Cargo.toml index 44e1531..1ad90be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "snf" +name = "strafesnet_snf" version = "0.1.0" edition = "2021" From ce6f8074a9e90bd7378be3fa8e6eab2345df8d62 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 29 Jan 2024 22:56:15 -0800 Subject: [PATCH 14/55] add common dep --- Cargo.lock | 15 +++++++++++++++ Cargo.toml | 1 + 2 files changed, 16 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 63c39b5..3d32e37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "glam" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" + [[package]] name = "owo-colors" version = "3.5.0" @@ -68,11 +74,20 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "strafesnet_common" +version = "0.1.0" +source = "git+https://git.itzana.me/StrafesNET/common?rev=434ca29aef7e3015c9ca1ed45de8fef42e33fdfb#434ca29aef7e3015c9ca1ed45de8fef42e33fdfb" +dependencies = [ + "glam", +] + [[package]] name = "strafesnet_snf" version = "0.1.0" dependencies = [ "binrw", + "strafesnet_common", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1ad90be..30ef80c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] binrw = "0.13.3" +strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "434ca29aef7e3015c9ca1ed45de8fef42e33fdfb" } From 708c0c48ef78840bc47cd51243824e62e97ef5c9 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 29 Jan 2024 22:56:20 -0800 Subject: [PATCH 15/55] update common --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/map.rs | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d32e37..28b11ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ [[package]] name = "strafesnet_common" version = "0.1.0" -source = "git+https://git.itzana.me/StrafesNET/common?rev=434ca29aef7e3015c9ca1ed45de8fef42e33fdfb#434ca29aef7e3015c9ca1ed45de8fef42e33fdfb" +source = "git+https://git.itzana.me/StrafesNET/common?rev=5ee826d9487b5e2bea4b3cf99a68ce9a95d72f72#5ee826d9487b5e2bea4b3cf99a68ce9a95d72f72" dependencies = [ "glam", ] diff --git a/Cargo.toml b/Cargo.toml index 30ef80c..ca43200 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] binrw = "0.13.3" -strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "434ca29aef7e3015c9ca1ed45de8fef42e33fdfb" } +strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "5ee826d9487b5e2bea4b3cf99a68ce9a95d72f72" } diff --git a/src/map.rs b/src/map.rs index 4ed7885..5215770 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,3 +1,5 @@ +use strafesnet_common::model; +use strafesnet_common::gameplay_modes; use binrw::{BinReaderExt, binrw}; pub enum Error{ @@ -85,12 +87,13 @@ struct Region{ #[bw(try_calc(u32::try_from(models.len())))] model_count:u32, #[br(count=model_count)] - models:Vec, + models:Vec, } pub struct StreamableMap{ file:crate::file::File, - style:physics::StyleModifiers,//probably should move this out of physics + //this includes every platform... move the unconstrained datas to their appropriate data block? + modes:gameplay_modes::Modes, bvh:BvhNode, node_id_to_block_id:Vec, //do not need this? return only new data with load_node @@ -101,7 +104,7 @@ impl StreamableMap{ pub(crate) fn new(file:crate::file::File)->Result{ Err(Error::InvalidHeader) } - pub fn load_node(&mut self,node_id:BvhNodeId)->Result,Error>{ + pub fn load_node(&mut self,node_id:BvhNodeId)->Result,Error>{ //load region from disk //parse the models and determine what resources need to be loaded //load resources into self.resources From 3e737282dccb7c703df07bd4599a0d6fcf7b4b6a Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 1 Feb 2024 04:03:09 -0800 Subject: [PATCH 16/55] resource query instead of hold all --- src/map.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/map.rs b/src/map.rs index 5215770..910cede 100644 --- a/src/map.rs +++ b/src/map.rs @@ -60,15 +60,6 @@ for model_id in 0..num_models{ //error hiding mock code -mod physics{ - pub struct StyleModifiers{} -} -mod model{ - pub struct IndexedModel{} - #[super::binrw] - #[brw(little)] - pub struct ModelInstance{} -} mod image{ pub struct Image{} } @@ -96,9 +87,6 @@ pub struct StreamableMap{ modes:gameplay_modes::Modes, bvh:BvhNode, node_id_to_block_id:Vec, - //do not need this? return only new data with load_node - resource_model:std::collections::HashMap, - resource_image:std::collections::HashMap, } impl StreamableMap{ pub(crate) fn new(file:crate::file::File)->Result{ @@ -114,4 +102,7 @@ impl StreamableMap{ let region:Region=block.read_le().map_err(|e|Error::InvalidRegion(e))?; Ok(region.models) } + pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{ + // + } } \ No newline at end of file From 40e7717aecb83255643f63d9db71dcc5713a3d0c Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 1 Feb 2024 20:21:56 -0800 Subject: [PATCH 17/55] stop error --- src/bot.rs | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index 3c97671..17770bd 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -41,24 +41,24 @@ mod simulation{ #[brw(little)] pub struct Instruction{} } -mod instruction{ - #[super::binrw] - #[brw(little)] - pub struct TimedInstruction{ - time:u64, - instruction:Instruction - } -} -mod timeline{ - #[super::binrw] - #[brw(little)] - pub struct Timeline{ - #[bw(try_calc(u32::try_from(instructions.len())))] - instruction_count:u32, - #[br(count=instruction_count)] - instructions:Vec> - } -} +// mod instruction{ + // #[super::binrw] + // #[brw(little)] + // pub struct TimedInstruction{ + // time:u64, + // instruction:Instruction + // } +// } +// mod timeline{ + // #[super::binrw] + // #[brw(little)] + // pub struct Timeline{ + // #[bw(try_calc(u32::try_from(instructions.len())))] + // instruction_count:u32, + // #[br(count=instruction_count)] + // instructions:Vec> + // } +// } //serious code @@ -70,15 +70,15 @@ struct SegmentId(u64); #[brw(little)] pub struct Segment{ state:simulation::State, - #[bw(try_calc(u32::try_from(instructions.len())))] - instruction_count:u32, - #[br(count=instruction_count)] - instructions:Vec> + //#[bw(try_calc(u32::try_from(instructions.len())))] + //instruction_count:u32, + //#[br(count=instruction_count)] + //instructions:Vec> } pub struct StreamableBot{ file:crate::file::File, - timeline:timeline::Timeline, + //timeline:timeline::Timeline, segment_id_to_block_id:Vec, } impl StreamableBot{ From 0532b47fec5b10daea2435a39cad82c9115541cb Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 1 Feb 2024 20:27:12 -0800 Subject: [PATCH 18/55] make it build --- src/file.rs | 11 ++++++----- src/map.rs | 19 ++++++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/file.rs b/src/file.rs index f1bf2b0..d9e6979 100644 --- a/src/file.rs +++ b/src/file.rs @@ -5,7 +5,7 @@ use binrw::{binrw, BinReaderExt, io::TakeSeekExt}; pub enum Error{ InvalidHeader(binrw::Error), UnexpectedEOF, - InvalidBlockId(usize), + InvalidBlockId(u64), Seek(std::io::Error), } @@ -64,7 +64,8 @@ struct Header{ block_location:Vec, } -pub struct BlockId(usize); +#[derive(Clone,Copy,Hash,Eq,PartialEq)] +pub struct BlockId(u64); pub(crate) struct File{ header:Header, @@ -80,11 +81,11 @@ impl File{ }) } pub(crate) fn take_block(&mut self,block_id:BlockId)->Result,Error>{ - if self.header.block_location.len()<=block_id.0{ + if self.header.block_location.len() as u64<=block_id.0{ return Err(Error::InvalidBlockId(block_id.0)) } - let block_start=self.header.block_location[block_id.0]; - let block_end=self.header.block_location[block_id.0+1]; + let block_start=self.header.block_location[block_id.0 as usize]; + let block_end=self.header.block_location[block_id.0 as usize+1]; self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(|e|Error::Seek(e))?; Ok((&mut self.data).take_seek(block_end-block_start)) } diff --git a/src/map.rs b/src/map.rs index 910cede..666f46e 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,5 +1,5 @@ -use strafesnet_common::model; -use strafesnet_common::gameplay_modes; +//use strafesnet_common::model; +//use strafesnet_common::gameplay_modes; use binrw::{BinReaderExt, binrw}; pub enum Error{ @@ -60,6 +60,15 @@ for model_id in 0..num_models{ //error hiding mock code +mod gameplay_modes{ + pub struct Modes{} +} +mod model{ + pub struct IndexedModel{} + #[super::binrw] + #[brw(little)] + pub struct Model{} +} mod image{ pub struct Image{} } @@ -102,7 +111,7 @@ impl StreamableMap{ let region:Region=block.read_le().map_err(|e|Error::InvalidRegion(e))?; Ok(region.models) } - pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{ - // - } + // pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{ + // // + // } } \ No newline at end of file From 0c439bf2e6c6ef6a17f9d14955f3ed234759b896 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 7 Feb 2024 01:01:23 -0800 Subject: [PATCH 19/55] use id + new knowledge + don't need u64 --- Cargo.lock | 32 +++++++++++++++++++++++++++----- Cargo.toml | 1 + src/bot.rs | 11 ++++++----- src/file.rs | 24 +++++++++++++----------- src/lib.rs | 20 ++++++++++---------- src/map.rs | 17 +++++++++++------ 6 files changed, 68 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28b11ce..77a7aff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,14 +29,14 @@ dependencies = [ "owo-colors", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" [[package]] name = "either" @@ -50,6 +50,16 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" +[[package]] +name = "id" +version = "0.1.0" +source = "git+https://git.itzana.me/Quaternions/id?rev=1f710976cc786c8853dab73d6e1cee53158deeb0#1f710976cc786c8853dab73d6e1cee53158deeb0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "owo-colors" version = "3.5.0" @@ -58,9 +68,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -87,6 +97,7 @@ name = "strafesnet_snf" version = "0.1.0" dependencies = [ "binrw", + "id", "strafesnet_common", ] @@ -101,6 +112,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index ca43200..122fe09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] binrw = "0.13.3" +id = { git = "https://git.itzana.me/Quaternions/id", rev = "1f710976cc786c8853dab73d6e1cee53158deeb0" } strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "5ee826d9487b5e2bea4b3cf99a68ce9a95d72f72" } diff --git a/src/bot.rs b/src/bot.rs index 17770bd..a22f923 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -3,7 +3,7 @@ use binrw::{BinReaderExt, binrw}; pub enum Error{ InvalidHeader, InvalidSegment(binrw::Error), - InvalidSegmentId(u64), + InvalidSegmentId(SegmentId), File(crate::file::Error), } @@ -64,7 +64,8 @@ mod simulation{ #[binrw] #[brw(little)] -struct SegmentId(u64); +#[derive(Clone,Copy,id::Id)] +pub struct SegmentId(u32); #[binrw] #[brw(little)] @@ -86,9 +87,9 @@ impl StreamableBot{ Err(Error::InvalidHeader) } pub fn load_segment(&mut self,segment_id:SegmentId)->Result{ - let block_id=*self.segment_id_to_block_id.get(segment_id.0 as usize).ok_or(Error::InvalidSegmentId(segment_id.0))?; - let mut block=self.file.take_block(block_id).map_err(|e|Error::File(e))?; - let segment=block.read_le().map_err(|e|Error::InvalidSegment(e))?; + let block_id=*self.segment_id_to_block_id.get(segment_id.get() as usize).ok_or(Error::InvalidSegmentId(segment_id))?; + let mut block=self.file.take_block(block_id).map_err(Error::File)?; + let segment=block.read_le().map_err(Error::InvalidSegment)?; Ok(segment) } } \ No newline at end of file diff --git a/src/file.rs b/src/file.rs index d9e6979..1a9e9dd 100644 --- a/src/file.rs +++ b/src/file.rs @@ -5,7 +5,7 @@ use binrw::{binrw, BinReaderExt, io::TakeSeekExt}; pub enum Error{ InvalidHeader(binrw::Error), UnexpectedEOF, - InvalidBlockId(u64), + InvalidBlockId(BlockId), Seek(std::io::Error), } @@ -58,14 +58,16 @@ struct Header{ priming:u64, /// uuid for this file resource:u128, - #[bw(try_calc(u64::try_from(block_location.len()-1)))] - block_count:u64, + #[bw(try_calc(u32::try_from(block_location.len()-1)))] + block_count:u32, #[br(count=block_count+1)] block_location:Vec, } -#[derive(Clone,Copy,Hash,Eq,PartialEq)] -pub struct BlockId(u64); +#[binrw] +#[brw(little)] +#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)] +pub struct BlockId(u32); pub(crate) struct File{ header:Header, @@ -76,17 +78,17 @@ pub(crate) struct File{ impl File{ pub(crate) fn new(mut input:R)->Result,Error>{ Ok(File{ - header:input.read_le().map_err(|e|Error::InvalidHeader(e))?, + header:input.read_le().map_err(Error::InvalidHeader)?, data:input, }) } pub(crate) fn take_block(&mut self,block_id:BlockId)->Result,Error>{ - if self.header.block_location.len() as u64<=block_id.0{ - return Err(Error::InvalidBlockId(block_id.0)) + if self.header.block_location.len() as u32<=block_id.get(){ + return Err(Error::InvalidBlockId(block_id)) } - let block_start=self.header.block_location[block_id.0 as usize]; - let block_end=self.header.block_location[block_id.0 as usize+1]; - self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(|e|Error::Seek(e))?; + let block_start=self.header.block_location[block_id.get() as usize]; + let block_end=self.header.block_location[block_id.get() as usize+1]; + self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(Error::Seek)?; Ok((&mut self.data).take_seek(block_end-block_start)) } pub(crate) fn fourcc(&self)->FourCC{ diff --git a/src/lib.rs b/src/lib.rs index d17883a..bac2c04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,31 +20,31 @@ pub enum SNF{ } pub fn read_snf(input:R)->Result,Error>{ - let file=file::File::new(input).map_err(|e|Error::Header(e))?; + let file=file::File::new(input).map_err(Error::Header)?; Ok(match file.fourcc(){ - file::FourCC::Map=>SNF::Map(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), - file::FourCC::Bot=>SNF::Bot(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), - file::FourCC::Demo=>SNF::Demo(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), + file::FourCC::Map=>SNF::Map(map::StreamableMap::new(file).map_err(Error::Map)?), + file::FourCC::Bot=>SNF::Bot(bot::StreamableBot::new(file).map_err(Error::Bot)?), + file::FourCC::Demo=>SNF::Demo(demo::StreamableDemo::new(file).map_err(Error::Demo)?), }) } pub fn read_map(input:R)->Result,Error>{ - let file=file::File::new(input).map_err(|e|Error::Header(e))?; + let file=file::File::new(input).map_err(Error::Header)?; match file.fourcc(){ - file::FourCC::Map=>Ok(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), + file::FourCC::Map=>Ok(map::StreamableMap::new(file).map_err(Error::Map)?), _=>Err(Error::UnexpectedFourCC) } } pub fn read_bot(input:R)->Result,Error>{ - let file=file::File::new(input).map_err(|e|Error::Header(e))?; + let file=file::File::new(input).map_err(Error::Header)?; match file.fourcc(){ - file::FourCC::Bot=>Ok(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), + file::FourCC::Bot=>Ok(bot::StreamableBot::new(file).map_err(Error::Bot)?), _=>Err(Error::UnexpectedFourCC) } } pub fn read_demo(input:R)->Result,Error>{ - let file=file::File::new(input).map_err(|e|Error::Header(e))?; + let file=file::File::new(input).map_err(Error::Header)?; match file.fourcc(){ - file::FourCC::Demo=>Ok(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), + file::FourCC::Demo=>Ok(demo::StreamableDemo::new(file).map_err(Error::Demo)?), _=>Err(Error::UnexpectedFourCC) } } diff --git a/src/map.rs b/src/map.rs index 666f46e..45c104e 100644 --- a/src/map.rs +++ b/src/map.rs @@ -4,7 +4,7 @@ use binrw::{BinReaderExt, binrw}; pub enum Error{ InvalidHeader, - InvalidNodeId(u64), + InvalidBvhNodeId(BvhNodeId), InvalidRegion(binrw::Error), File(crate::file::Error), } @@ -77,9 +77,14 @@ mod image{ struct ModelUuid(u128); struct ImageUuid(u128); -pub struct BvhNodeId(u64); + +#[binrw] +#[brw(little)] +#[derive(Clone,Copy,id::Id)] +pub struct BvhNodeId(u32); struct BvhNode{ - // + //aabb + //child } #[binrw] #[brw(little)] @@ -106,9 +111,9 @@ impl StreamableMap{ //parse the models and determine what resources need to be loaded //load resources into self.resources //return Region - let block_id=*self.node_id_to_block_id.get(node_id.0 as usize).ok_or(Error::InvalidNodeId(node_id.0))?; - let mut block=self.file.take_block(block_id).map_err(|e|Error::File(e))?; - let region:Region=block.read_le().map_err(|e|Error::InvalidRegion(e))?; + let block_id=*self.node_id_to_block_id.get(node_id.get() as usize).ok_or(Error::InvalidBvhNodeId(node_id))?; + let mut block=self.file.take_block(block_id).map_err(Error::File)?; + let region:Region=block.read_le().map_err(Error::InvalidRegion)?; Ok(region.models) } // pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{ From 99351848b788f8cd113884b2c4f9142932990cc5 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 8 Feb 2024 23:13:42 -0800 Subject: [PATCH 20/55] update common --- Cargo.lock | 3 ++- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77a7aff..4dc7c44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,9 +87,10 @@ dependencies = [ [[package]] name = "strafesnet_common" version = "0.1.0" -source = "git+https://git.itzana.me/StrafesNET/common?rev=5ee826d9487b5e2bea4b3cf99a68ce9a95d72f72#5ee826d9487b5e2bea4b3cf99a68ce9a95d72f72" +source = "git+https://git.itzana.me/StrafesNET/common?rev=c915cdfc0ae1f2c934ebf06b826b05401faa3ad0#c915cdfc0ae1f2c934ebf06b826b05401faa3ad0" dependencies = [ "glam", + "id", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 122fe09..38cd5f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] binrw = "0.13.3" id = { git = "https://git.itzana.me/Quaternions/id", rev = "1f710976cc786c8853dab73d6e1cee53158deeb0" } -strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "5ee826d9487b5e2bea4b3cf99a68ce9a95d72f72" } +strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "c915cdfc0ae1f2c934ebf06b826b05401faa3ad0" } From 3c43b6c6a69e86650569dcec3b929378a5b367cb Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 8 Feb 2024 23:13:53 -0800 Subject: [PATCH 21/55] reflect common name changes --- src/map.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map.rs b/src/map.rs index 45c104e..5c8fc54 100644 --- a/src/map.rs +++ b/src/map.rs @@ -42,7 +42,7 @@ for resource_id in 0..num_resources{ BLOCK_MAP_RESOURCE: Resource resource_type //an individual one of the following: - - model (IndexedModel) + - model (Mesh) - shader (compiled SPIR-V) - image (JpegXL) - sound (Opus) @@ -64,7 +64,7 @@ mod gameplay_modes{ pub struct Modes{} } mod model{ - pub struct IndexedModel{} + pub struct Mesh{} #[super::binrw] #[brw(little)] pub struct Model{} From 856386e9bf29c337cfaef8774c71a18a2ee06ce2 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 8 Feb 2024 23:14:08 -0800 Subject: [PATCH 22/55] notes --- src/bot.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bot.rs b/src/bot.rs index a22f923..db5889d 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -75,6 +75,8 @@ pub struct Segment{ //instruction_count:u32, //#[br(count=instruction_count)] //instructions:Vec> + + //please remember that strafe ticks are implicit! 33% smaller bot files } pub struct StreamableBot{ From ec5bb74d465017787a32f9448b64a405fe64e583 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 22 Jul 2024 13:55:53 -0700 Subject: [PATCH 23/55] switch to strafesnet registry + update deps --- .cargo/config.toml | 2 ++ Cargo.lock | 51 +++++++++++++++++++++++++++------------------- Cargo.toml | 6 +++--- 3 files changed, 35 insertions(+), 24 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..8b662bc --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[registries.strafesnet] +index = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 4dc7c44..454ea1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" [[package]] name = "binrw" -version = "0.13.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "173901312e9850391d4d7c1318c4e099fdc037d61870fca427429830efdb4e5f" +checksum = "3f36b7cb3ab9ff6a2858650d8dc360e783a5d14dc29594db48c56a3c233cc265" dependencies = [ "array-init", "binrw_derive", @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "binrw_derive" -version = "0.13.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb515fdd6f8d3a357c8e19b8ec59ef53880807864329b1cb1cba5c53bf76557e" +checksum = "20ea7a8c5c8eeffffac6d54d172444e15beffac6f817fac714460a9a9aa88da3" dependencies = [ "either", "owo-colors", @@ -33,31 +33,38 @@ dependencies = [ ] [[package]] -name = "bytemuck" -version = "1.14.2" +name = "bitflags" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "glam" -version = "0.25.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" +checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94" [[package]] name = "id" version = "0.1.0" -source = "git+https://git.itzana.me/Quaternions/id?rev=1f710976cc786c8853dab73d6e1cee53158deeb0#1f710976cc786c8853dab73d6e1cee53158deeb0" +source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" +checksum = "2337e7a6c273082b672e377e159d7a168fb51438461b7c4033c79a515dd7a25a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.72", ] [[package]] @@ -68,27 +75,29 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "strafesnet_common" -version = "0.1.0" -source = "git+https://git.itzana.me/StrafesNET/common?rev=c915cdfc0ae1f2c934ebf06b826b05401faa3ad0#c915cdfc0ae1f2c934ebf06b826b05401faa3ad0" +version = "0.1.3" +source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" +checksum = "10a7e3b69506893bbdde90ce8a9d75cd56d280c0424d2dfdf98f8520179d0c1b" dependencies = [ + "bitflags", "glam", "id", ] @@ -115,9 +124,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 38cd5f7..846ca41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -binrw = "0.13.3" -id = { git = "https://git.itzana.me/Quaternions/id", rev = "1f710976cc786c8853dab73d6e1cee53158deeb0" } -strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "c915cdfc0ae1f2c934ebf06b826b05401faa3ad0" } +binrw = "0.14.0" +id = { version = "0.1.0", registry = "strafesnet" } +strafesnet_common = { version = "0.1.3", registry = "strafesnet" } From e0e635e083e1e31248b643687a174a0f9457ad9a Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 23 Jul 2024 17:18:03 -0700 Subject: [PATCH 24/55] rename function --- src/bot.rs | 4 ++-- src/file.rs | 2 +- src/map.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index db5889d..d531015 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -90,8 +90,8 @@ impl StreamableBot{ } pub fn load_segment(&mut self,segment_id:SegmentId)->Result{ let block_id=*self.segment_id_to_block_id.get(segment_id.get() as usize).ok_or(Error::InvalidSegmentId(segment_id))?; - let mut block=self.file.take_block(block_id).map_err(Error::File)?; + let mut block=self.file.block_reader(block_id).map_err(Error::File)?; let segment=block.read_le().map_err(Error::InvalidSegment)?; Ok(segment) } -} \ No newline at end of file +} diff --git a/src/file.rs b/src/file.rs index 1a9e9dd..b78405c 100644 --- a/src/file.rs +++ b/src/file.rs @@ -82,7 +82,7 @@ impl File{ data:input, }) } - pub(crate) fn take_block(&mut self,block_id:BlockId)->Result,Error>{ + pub(crate) fn block_reader(&mut self,block_id:BlockId)->Result,Error>{ if self.header.block_location.len() as u32<=block_id.get(){ return Err(Error::InvalidBlockId(block_id)) } diff --git a/src/map.rs b/src/map.rs index 5c8fc54..29cb710 100644 --- a/src/map.rs +++ b/src/map.rs @@ -112,7 +112,7 @@ impl StreamableMap{ //load resources into self.resources //return Region let block_id=*self.node_id_to_block_id.get(node_id.get() as usize).ok_or(Error::InvalidBvhNodeId(node_id))?; - let mut block=self.file.take_block(block_id).map_err(Error::File)?; + let mut block=self.file.block_reader(block_id).map_err(Error::File)?; let region:Region=block.read_le().map_err(Error::InvalidRegion)?; Ok(region.models) } From 6ee4c8014a1d62bbf014335dadc92015b5e0324e Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 23 Jul 2024 17:18:10 -0700 Subject: [PATCH 25/55] no try_calc --- src/file.rs | 2 +- src/map.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/file.rs b/src/file.rs index b78405c..3381dff 100644 --- a/src/file.rs +++ b/src/file.rs @@ -58,7 +58,7 @@ struct Header{ priming:u64, /// uuid for this file resource:u128, - #[bw(try_calc(u32::try_from(block_location.len()-1)))] + //don't need try_calc: the struct will force field initialization anyways and it can be calculated there block_count:u32, #[br(count=block_count+1)] block_location:Vec, diff --git a/src/map.rs b/src/map.rs index 29cb710..89b39fc 100644 --- a/src/map.rs +++ b/src/map.rs @@ -89,7 +89,7 @@ struct BvhNode{ #[binrw] #[brw(little)] struct Region{ - #[bw(try_calc(u32::try_from(models.len())))] + //consider including a bvh in the region instead of needing to rebalance the physics bvh on the fly model_count:u32, #[br(count=model_count)] models:Vec, From 80fc0e13dbad5dac7b71553f90cee2dbc560a3ca Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 23 Jul 2024 13:12:54 -0700 Subject: [PATCH 26/55] disallow arbitrary data gap between header and first block --- src/file.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/file.rs b/src/file.rs index 3381dff..786cef8 100644 --- a/src/file.rs +++ b/src/file.rs @@ -25,7 +25,9 @@ u128 resource_uuid //global block layout (variable size) u64 num_blocks -for block_id in 0..num_blocks{ +//the start of the first block is implicitly after the global header (32) +//num_blocks+1 used in Header.block_location is implicitly the end of the file +for block_id in 1..num_blocks{ u64 first_byte } From f0035bcee94439a5f6f12b5cc9d30da54b35a6e7 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 23 Jul 2024 11:05:01 -0700 Subject: [PATCH 27/55] newtypes (boilerplate) --- src/lib.rs | 2 + src/newtypes.rs | 6 + src/newtypes/aabb.rs | 15 ++ src/newtypes/gameplay_attributes.rs | 246 ++++++++++++++++++++++++++++ src/newtypes/gameplay_modes.rs | 126 ++++++++++++++ src/newtypes/gameplay_style.rs | 218 ++++++++++++++++++++++++ src/newtypes/integer.rs | 26 +++ src/newtypes/model.rs | 152 +++++++++++++++++ 8 files changed, 791 insertions(+) create mode 100644 src/newtypes.rs create mode 100644 src/newtypes/aabb.rs create mode 100644 src/newtypes/gameplay_attributes.rs create mode 100644 src/newtypes/gameplay_modes.rs create mode 100644 src/newtypes/gameplay_style.rs create mode 100644 src/newtypes/integer.rs create mode 100644 src/newtypes/model.rs diff --git a/src/lib.rs b/src/lib.rs index bac2c04..4f4f479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ use binrw::BinReaderExt; +mod newtypes; + pub mod file; pub mod map; pub mod bot; diff --git a/src/newtypes.rs b/src/newtypes.rs new file mode 100644 index 0000000..8b12c6b --- /dev/null +++ b/src/newtypes.rs @@ -0,0 +1,6 @@ +pub mod aabb; +pub mod model; +pub mod integer; +pub mod gameplay_modes; +pub mod gameplay_style; +pub mod gameplay_attributes; diff --git a/src/newtypes/aabb.rs b/src/newtypes/aabb.rs new file mode 100644 index 0000000..3908287 --- /dev/null +++ b/src/newtypes/aabb.rs @@ -0,0 +1,15 @@ +use super::integer::Planar64Vec3; +#[binrw::binrw] +#[brw(little)] +pub struct Aabb{ + pub min:Planar64Vec3, + pub max:Planar64Vec3, +} +impl Into for Aabb{ + fn into(self)->strafesnet_common::aabb::Aabb{ + strafesnet_common::aabb::Aabb::new( + strafesnet_common::integer::Planar64Vec3::raw_array(self.min), + strafesnet_common::integer::Planar64Vec3::raw_array(self.max), + ) + } +} diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs new file mode 100644 index 0000000..10921cd --- /dev/null +++ b/src/newtypes/gameplay_attributes.rs @@ -0,0 +1,246 @@ +use super::integer::{Time,Planar64,Planar64Vec3}; + +#[binrw::binrw] +#[brw(little)] +pub struct ContactingLadder{ + pub sticky:Option<()>, +} +impl Into for ContactingLadder{ + fn into(self)->strafesnet_common::gameplay_attributes::ContactingLadder{ + strafesnet_common::gameplay_attributes::ContactingLadder{ + sticky:self.sticky.is_some(), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub enum ContactingBehaviour{ + Surf, + Ladder(ContactingLadder), + NoJump, + Cling, + Elastic(u32), +} +impl Into for ContactingBehaviour{ + fn into(self)->strafesnet_common::gameplay_attributes::ContactingBehaviour{ + match self{ + ContactingBehaviour::Surf=> + strafesnet_common::gameplay_attributes::ContactingBehaviour::Surf, + ContactingBehaviour::Ladder(contacting_ladder)=> + strafesnet_common::gameplay_attributes::ContactingBehaviour::Ladder( + contacting_ladder.into(), + ), + ContactingBehaviour::NoJump=> + strafesnet_common::gameplay_attributes::ContactingBehaviour::NoJump, + ContactingBehaviour::Cling=> + strafesnet_common::gameplay_attributes::ContactingBehaviour::Cling, + ContactingBehaviour::Elastic(elasticity)=> + strafesnet_common::gameplay_attributes::ContactingBehaviour::Elastic(elasticity), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct IntersectingWater{ + pub viscosity:Planar64, + pub density:Planar64, + pub velocity:Planar64Vec3, +} +impl Into for IntersectingWater{ + fn into(self)->strafesnet_common::gameplay_attributes::IntersectingWater{ + strafesnet_common::gameplay_attributes::IntersectingWater{ + viscosity:strafesnet_common::integer::Planar64::raw(self.viscosity), + density:strafesnet_common::integer::Planar64::raw(self.density), + velocity:strafesnet_common::integer::Planar64Vec3::raw_array(self.velocity), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct Accelerator{ + pub acceleration:Planar64Vec3 +} +impl Into for Accelerator{ + fn into(self)->strafesnet_common::gameplay_attributes::Accelerator{ + strafesnet_common::gameplay_attributes::Accelerator{ + acceleration:strafesnet_common::integer::Planar64Vec3::raw_array(self.acceleration) + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub enum Booster{ + Velocity(Planar64Vec3), + Energy{direction:Planar64Vec3,energy:Planar64}, +} +impl Into for Booster{ + fn into(self)->strafesnet_common::gameplay_attributes::Booster{ + match self{ + Booster::Velocity(velocity)=> + strafesnet_common::gameplay_attributes::Booster::Velocity( + strafesnet_common::integer::Planar64Vec3::raw_array(velocity) + ), + Booster::Energy{direction,energy}=> + strafesnet_common::gameplay_attributes::Booster::Energy{ + direction:strafesnet_common::integer::Planar64Vec3::raw_array(direction), + energy:strafesnet_common::integer::Planar64::raw(energy) + }, + } + } +} + +#[binrw::binrw] +#[brw(little,repr=u8)] +pub enum TrajectoryChoice{ + HighArcLongDuration, + LowArcShortDuration, +} +impl Into for TrajectoryChoice{ + fn into(self)->strafesnet_common::gameplay_attributes::TrajectoryChoice{ + match self{ + TrajectoryChoice::HighArcLongDuration=> + strafesnet_common::gameplay_attributes::TrajectoryChoice::HighArcLongDuration, + TrajectoryChoice::LowArcShortDuration=> + strafesnet_common::gameplay_attributes::TrajectoryChoice::LowArcShortDuration, + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub enum SetTrajectory{ + AirTime(Time), + Height(Planar64), + DotVelocity{direction:Planar64Vec3,dot:Planar64}, + TargetPointTime{ + target_point:Planar64Vec3, + time:Time, + }, + TargetPointSpeed{ + target_point:Planar64Vec3, + speed:Planar64, + trajectory_choice:TrajectoryChoice, + }, + Velocity(Planar64Vec3), +} +impl Into for SetTrajectory{ + fn into(self)->strafesnet_common::gameplay_attributes::SetTrajectory{ + match self{ + SetTrajectory::AirTime(time)=> + strafesnet_common::gameplay_attributes::SetTrajectory::AirTime( + strafesnet_common::integer::Time::raw(time) + ), + SetTrajectory::Height(height)=> + strafesnet_common::gameplay_attributes::SetTrajectory::Height( + strafesnet_common::integer::Planar64::raw(height) + ), + SetTrajectory::DotVelocity{direction,dot}=> + strafesnet_common::gameplay_attributes::SetTrajectory::DotVelocity{ + direction:strafesnet_common::integer::Planar64Vec3::raw_array(direction), + dot:strafesnet_common::integer::Planar64::raw(dot), + }, + SetTrajectory::TargetPointTime{target_point,time}=> + strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointTime{ + target_point:strafesnet_common::integer::Planar64Vec3::raw_array(target_point), + time:strafesnet_common::integer::Time::raw(time), + }, + SetTrajectory::TargetPointSpeed{target_point,speed,trajectory_choice}=> + strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointSpeed{ + target_point:strafesnet_common::integer::Planar64Vec3::raw_array(target_point), + speed:strafesnet_common::integer::Planar64::raw(speed), + trajectory_choice:trajectory_choice.into(), + }, + SetTrajectory::Velocity(velocity)=> + strafesnet_common::gameplay_attributes::SetTrajectory::Velocity( + strafesnet_common::integer::Planar64Vec3::raw_array(velocity) + ), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct Wormhole{ + pub destination_model:u32, +} +impl Into for Wormhole{ + fn into(self)->strafesnet_common::gameplay_attributes::Wormhole{ + strafesnet_common::gameplay_attributes::Wormhole{ + destination_model:strafesnet_common::model::ModelId::new(self.destination_model), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct GeneralAttributes{ + pub booster:Option, + pub trajectory:Option, + pub wormhole:Option, + pub accelerator:Option, +} +impl Into for GeneralAttributes{ + fn into(self)->strafesnet_common::gameplay_attributes::GeneralAttributes{ + strafesnet_common::gameplay_attributes::GeneralAttributes{ + booster:self.booster.map(Into::into), + trajectory:self.trajectory.map(Into::into), + wormhole:self.wormhole.map(Into::into), + accelerator:self.accelerator.map(Into::into), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct ContactingAttributes{ + pub contact_behaviour:Option, +} +impl Into for ContactingAttributes{ + fn into(self)->strafesnet_common::gameplay_attributes::ContactingAttributes{ + strafesnet_common::gameplay_attributes::ContactingAttributes{ + contact_behaviour:self.contact_behaviour.map(Into::into), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct IntersectingAttributes{ + pub water:Option, +} +impl Into for IntersectingAttributes{ + fn into(self)->strafesnet_common::gameplay_attributes::IntersectingAttributes{ + strafesnet_common::gameplay_attributes::IntersectingAttributes{ + water:self.water.map(Into::into), + } + } +} +#[binrw::binrw] +#[brw(little)] +pub enum CollisionAttributes{ + Decoration, + Contact{ + contacting:ContactingAttributes, + general:GeneralAttributes, + }, + Intersect{ + intersecting:IntersectingAttributes, + general:GeneralAttributes, + }, +} +impl Into for CollisionAttributes{ + fn into(self)->strafesnet_common::gameplay_attributes::CollisionAttributes{ + match self{ + CollisionAttributes::Decoration=> + strafesnet_common::gameplay_attributes::CollisionAttributes::Decoration, + CollisionAttributes::Contact{contacting,general}=> + strafesnet_common::gameplay_attributes::CollisionAttributes::Contact{contacting:contacting.into(),general:general.into()}, + CollisionAttributes::Intersect{intersecting,general}=> + strafesnet_common::gameplay_attributes::CollisionAttributes::Intersect{intersecting:intersecting.into(),general:general.into()}, + } + } +} diff --git a/src/newtypes/gameplay_modes.rs b/src/newtypes/gameplay_modes.rs new file mode 100644 index 0000000..73c2eb4 --- /dev/null +++ b/src/newtypes/gameplay_modes.rs @@ -0,0 +1,126 @@ +#[binrw::binrw] +#[brw(little,repr=u8)] +pub enum StageElementBehaviour{ + SpawnAt,//must be standing on top to get effect. except cancollide false + Trigger, + Teleport, + Platform, + //Check(point) acts like a trigger if you haven't hit all the checkpoints on previous stages yet. + //Note that all stage elements act like this, this is just the isolated behaviour. + Check, + Checkpoint,//this is a combined behaviour for Ordered & Unordered in case a model is used multiple times or for both. +} +impl Into for StageElementBehaviour{ + fn into(self)->strafesnet_common::gameplay_modes::StageElementBehaviour{ + match self{ + StageElementBehaviour::SpawnAt=>strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt, + StageElementBehaviour::Trigger=>strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger, + StageElementBehaviour::Teleport=>strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport, + StageElementBehaviour::Platform=>strafesnet_common::gameplay_modes::StageElementBehaviour::Platform, + StageElementBehaviour::Check=>strafesnet_common::gameplay_modes::StageElementBehaviour::Check, + StageElementBehaviour::Checkpoint=>strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint, + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct StageElement{ + pub stage_id:u32,//which stage spawn to send to + pub behaviour:StageElementBehaviour, + pub jump_limit:Option, + pub force:Option<()>,//allow setting to lower spawn id i.e. 7->3 +} +impl Into for StageElement{ + fn into(self)->strafesnet_common::gameplay_modes::StageElement{ + strafesnet_common::gameplay_modes::StageElement::new( + strafesnet_common::gameplay_modes::StageId::new(self.stage_id), + self.force.is_some(), + self.behaviour.into(), + self.jump_limit, + ) + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct Stage{ + pub spawn:u32, + //open world support lol + pub ordered_checkpoints_count:u32, + pub unordered_checkpoints_count:u32, + //currently loaded checkpoint models + #[br(count=ordered_checkpoints_count)] + pub ordered_checkpoints:Vec<(u32,u32)>, + #[br(count=unordered_checkpoints_count)] + pub unordered_checkpoints:Vec, +} +impl Into for Stage{ + fn into(self)->strafesnet_common::gameplay_modes::Stage{ + strafesnet_common::gameplay_modes::Stage::new( + strafesnet_common::model::ModelId::new(self.spawn), + self.ordered_checkpoints_count, + self.unordered_checkpoints_count, + self.ordered_checkpoints.into_iter().map(|(checkpoint_id,model_id)|( + strafesnet_common::gameplay_modes::CheckpointId::new(checkpoint_id), + strafesnet_common::model::ModelId::new(model_id), + )).collect(), + self.unordered_checkpoints.into_iter() + .map(strafesnet_common::model::ModelId::new) + .collect(), + ) + } +} + +#[binrw::binrw] +#[brw(little,repr=u8)] +pub enum Zone{ + Start, + Finish, + Anticheat, +} +impl Into for Zone{ + fn into(self)->strafesnet_common::gameplay_modes::Zone{ + match self{ + Zone::Start=>strafesnet_common::gameplay_modes::Zone::Start, + Zone::Finish=>strafesnet_common::gameplay_modes::Zone::Finish, + Zone::Anticheat=>strafesnet_common::gameplay_modes::Zone::Anticheat, + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct ModeHeader{ + pub zones:u32, + pub stages:u32, + pub elements:u32, +} +#[binrw::binrw] +#[brw(little)] +pub struct Mode{ + pub header:ModeHeader, + pub style:super::gameplay_style::StyleModifiers, + pub start:u32, + #[br(count=header.zones)] + pub zones:Vec<(u32,Zone)>, + #[br(count=header.stages)] + pub stages:Vec, + #[br(count=header.elements)] + pub elements:Vec<(u32,StageElement)>, +} +impl Into for Mode{ + fn into(self)->strafesnet_common::gameplay_modes::Mode{ + strafesnet_common::gameplay_modes::Mode::new( + self.style.into(), + strafesnet_common::model::ModelId::new(self.start), + self.zones.into_iter().map(|(model_id,zone)| + (strafesnet_common::model::ModelId::new(model_id),zone.into()) + ).collect(), + self.stages.into_iter().map(Into::into).collect(), + self.elements.into_iter().map(|(model_id,stage_element)| + (strafesnet_common::model::ModelId::new(model_id),stage_element.into()) + ).collect(), + ) + } +} diff --git a/src/newtypes/gameplay_style.rs b/src/newtypes/gameplay_style.rs new file mode 100644 index 0000000..71c8320 --- /dev/null +++ b/src/newtypes/gameplay_style.rs @@ -0,0 +1,218 @@ +use super::integer::{Time,Ratio64,Planar64,Planar64Vec3}; + +pub type Controls=u32; + +#[binrw::binrw] +#[brw(little)] +pub struct StyleModifiers{ + pub controls_mask:Controls, + pub controls_mask_state:Controls, + pub strafe:Option, + pub rocket:Option, + pub jump:Option, + pub walk:Option, + pub ladder:Option, + pub swim:Option, + pub gravity:Planar64Vec3, + pub hitbox:Hitbox, + pub camera_offset:Planar64Vec3, + pub mass:Planar64, +} +impl Into for StyleModifiers{ + fn into(self)->strafesnet_common::gameplay_style::StyleModifiers{ + strafesnet_common::gameplay_style::StyleModifiers{ + //TODO: fail gracefully in binrw instead of panicing here + controls_mask:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).unwrap(), + controls_mask_state:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask_state).unwrap(), + strafe:self.strafe.map(Into::into), + rocket:self.rocket.map(Into::into), + jump:self.jump.map(Into::into), + walk:self.walk.map(Into::into), + ladder:self.ladder.map(Into::into), + swim:self.swim.map(Into::into), + gravity:strafesnet_common::integer::Planar64Vec3::raw_array(self.gravity), + hitbox:self.hitbox.into(), + camera_offset:strafesnet_common::integer::Planar64Vec3::raw_array(self.camera_offset), + mass:strafesnet_common::integer::Planar64::raw(self.mass), + } + } +} + +#[binrw::binrw] +#[brw(little,repr=u8)] +pub enum JumpCalculation{ + Capped, + Energy, + Linear, +} +impl Into for JumpCalculation{ + fn into(self)->strafesnet_common::gameplay_style::JumpCalculation{ + match self{ + JumpCalculation::Capped=>strafesnet_common::gameplay_style::JumpCalculation::Capped, + JumpCalculation::Energy=>strafesnet_common::gameplay_style::JumpCalculation::Energy, + JumpCalculation::Linear=>strafesnet_common::gameplay_style::JumpCalculation::Linear, + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub enum JumpImpulse{ + FromTime(Time), + FromHeight(Planar64), + FromDeltaV(Planar64), + FromEnergy(Planar64), +} +impl Into for JumpImpulse{ + fn into(self)->strafesnet_common::gameplay_style::JumpImpulse{ + match self{ + JumpImpulse::FromTime(time)=>strafesnet_common::gameplay_style::JumpImpulse::FromTime(strafesnet_common::integer::Time::raw(time)), + JumpImpulse::FromHeight(height)=>strafesnet_common::gameplay_style::JumpImpulse::FromHeight(strafesnet_common::integer::Planar64::raw(height)), + JumpImpulse::FromDeltaV(deltav)=>strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(strafesnet_common::integer::Planar64::raw(deltav)), + JumpImpulse::FromEnergy(energy)=>strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(strafesnet_common::integer::Planar64::raw(energy)), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct ControlsActivation{ + controls_mask:Controls, + controls_intersects:Controls, + controls_contains:Controls, +} +impl Into for ControlsActivation{ + fn into(self)->strafesnet_common::gameplay_style::ControlsActivation{ + strafesnet_common::gameplay_style::ControlsActivation::new( + strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).unwrap(), + strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_intersects).unwrap(), + strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_contains).unwrap(), + ) + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct StrafeSettings{ + enable:ControlsActivation, + mv:Planar64, + air_accel_limit:Option, + tick_rate:Ratio64, +} +impl Into for StrafeSettings{ + fn into(self)->strafesnet_common::gameplay_style::StrafeSettings{ + strafesnet_common::gameplay_style::StrafeSettings::new( + self.enable.into(), + strafesnet_common::integer::Planar64::raw(self.mv), + self.air_accel_limit.map(strafesnet_common::integer::Planar64::raw), + self.tick_rate.into(), + ) + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct PropulsionSettings{ + magnitude:Planar64, +} +impl Into for PropulsionSettings{ + fn into(self)->strafesnet_common::gameplay_style::PropulsionSettings{ + strafesnet_common::gameplay_style::PropulsionSettings::new( + strafesnet_common::integer::Planar64::raw(self.magnitude) + ) + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct JumpSettings{ + impulse:JumpImpulse, + calculation:JumpCalculation, +} +impl Into for JumpSettings{ + fn into(self)->strafesnet_common::gameplay_style::JumpSettings{ + strafesnet_common::gameplay_style::JumpSettings::new( + self.impulse.into(), + self.calculation.into(), + ) + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct AccelerateSettings{ + accel:Planar64, + topspeed:Planar64, +} +impl Into for AccelerateSettings{ + fn into(self)->strafesnet_common::gameplay_style::AccelerateSettings{ + strafesnet_common::gameplay_style::AccelerateSettings::new( + strafesnet_common::integer::Planar64::raw(self.accel), + strafesnet_common::integer::Planar64::raw(self.topspeed), + ) + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct WalkSettings{ + accelerate:AccelerateSettings, + static_friction:Planar64, + kinetic_friction:Planar64, + surf_dot:Planar64, +} +impl Into for WalkSettings{ + fn into(self)->strafesnet_common::gameplay_style::WalkSettings{ + strafesnet_common::gameplay_style::WalkSettings::new( + self.accelerate.into(), + strafesnet_common::integer::Planar64::raw(self.static_friction), + strafesnet_common::integer::Planar64::raw(self.kinetic_friction), + strafesnet_common::integer::Planar64::raw(self.surf_dot), + ) + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct LadderSettings{ + accelerate:AccelerateSettings, + dot:Planar64, +} +impl Into for LadderSettings{ + fn into(self)->strafesnet_common::gameplay_style::LadderSettings{ + strafesnet_common::gameplay_style::LadderSettings::new( + self.accelerate.into(), + strafesnet_common::integer::Planar64::raw(self.dot), + ) + } +} + +#[binrw::binrw] +#[brw(little,repr=u8)] +pub enum HitboxMesh{ + Box, + Cylinder, +} +impl Into for HitboxMesh{ + fn into(self)->strafesnet_common::gameplay_style::HitboxMesh{ + match self{ + HitboxMesh::Box=>strafesnet_common::gameplay_style::HitboxMesh::Box, + HitboxMesh::Cylinder=>strafesnet_common::gameplay_style::HitboxMesh::Cylinder, + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct Hitbox{ + pub halfsize:Planar64Vec3, + pub mesh:HitboxMesh, +} +impl Into for Hitbox{ + fn into(self)->strafesnet_common::gameplay_style::Hitbox{ + strafesnet_common::gameplay_style::Hitbox{ + halfsize:strafesnet_common::integer::Planar64Vec3::raw_array(self.halfsize), + mesh:self.mesh.into(), + } + } +} diff --git a/src/newtypes/integer.rs b/src/newtypes/integer.rs new file mode 100644 index 0000000..86a8b8c --- /dev/null +++ b/src/newtypes/integer.rs @@ -0,0 +1,26 @@ +pub type Time=i64; + +#[binrw::binrw] +#[brw(little)] +pub struct Ratio64{ + num:i64, + den:u64, +} +impl Into for Ratio64{ + fn into(self)->strafesnet_common::integer::Ratio64{ + strafesnet_common::integer::Ratio64::new(self.num,self.den).unwrap() + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct Ratio64Vec2{ + pub x:Ratio64, + pub y:Ratio64, +} + +pub type Angle32=i32; +pub type Planar64=i64; +pub type Planar64Vec3=[i64;3]; +pub type Planar64Mat3=[i64;9]; +pub type Planar64Affine3=[i64;12]; diff --git a/src/newtypes/model.rs b/src/newtypes/model.rs new file mode 100644 index 0000000..1ad02f3 --- /dev/null +++ b/src/newtypes/model.rs @@ -0,0 +1,152 @@ +use super::integer::{Planar64Vec3,Planar64Affine3}; + +pub type TextureCoordinate=[f32;2]; +pub type Color4=[f32;4]; + +#[binrw::binrw] +#[brw(little)] +pub struct IndexedVertex{ + pub pos:u32, + pub tex:u32, + pub normal:u32, + pub color:u32, +} + +#[binrw::binrw] +#[brw(little)] +pub struct Polygon{ + pub count:u32, + #[br(count=count)] + pub vertices:Vec, +} +#[binrw::binrw] +#[brw(little)] +pub struct PolygonGroup{ + pub count:u32, + #[br(count=count)] + pub polys:Vec, +} +#[binrw::binrw] +#[brw(little)] +pub struct RenderConfig{ + pub texture:Option, +} +impl Into for RenderConfig{ + fn into(self)->strafesnet_common::model::RenderConfig{ + strafesnet_common::model::RenderConfig{ + texture:self.texture.map(strafesnet_common::model::TextureId::new), + } + } +} +#[binrw::binrw] +#[brw(little)] +pub struct IndexedGraphicsGroup{ + pub count:u32, + pub render:u32, + #[br(count=count)] + pub groups:Vec, +} +#[binrw::binrw] +#[brw(little)] +pub struct IndexedPhysicsGroup{ + pub count:u32, + #[br(count=count)] + pub groups:Vec, +} + +#[binrw::binrw] +#[brw(little)] +pub struct MeshHeader{ + pub unique_pos:u32, + pub unique_normal:u32, + pub unique_tex:u32, + pub unique_color:u32, + pub unique_vertices:u32, + pub polygon_groups:u32, + pub graphics_groups:u32, + pub physics_groups:u32, +} +#[binrw::binrw] +#[brw(little)] +pub struct Mesh{ + pub header:MeshHeader, + #[br(count=header.unique_pos)] + pub unique_pos:Vec, + #[br(count=header.unique_normal)] + pub unique_normal:Vec, + #[br(count=header.unique_tex)] + pub unique_tex:Vec, + #[br(count=header.unique_color)] + pub unique_color:Vec, + #[br(count=header.unique_vertices)] + pub unique_vertices:Vec, + #[br(count=header.polygon_groups)] + pub polygon_groups:Vec, + #[br(count=header.graphics_groups)] + pub graphics_groups:Vec, + #[br(count=header.physics_groups)] + pub physics_groups:Vec, +} +impl Into for Mesh{ + fn into(self)->strafesnet_common::model::Mesh{ + strafesnet_common::model::Mesh{ + unique_pos:self.unique_pos.into_iter().map(strafesnet_common::integer::Planar64Vec3::raw_array).collect(), + unique_normal:self.unique_normal.into_iter().map(strafesnet_common::integer::Planar64Vec3::raw_array).collect(), + unique_tex:self.unique_tex.into_iter().map(strafesnet_common::model::TextureCoordinate::from_array).collect(), + unique_color:self.unique_color.into_iter().map(strafesnet_common::model::Color4::from_array).collect(), + unique_vertices:self.unique_vertices.into_iter().map(|vert|strafesnet_common::model::IndexedVertex{ + pos:strafesnet_common::model::PositionId::new(vert.pos), + tex:strafesnet_common::model::TextureCoordinateId::new(vert.tex), + normal:strafesnet_common::model::NormalId::new(vert.normal), + color:strafesnet_common::model::ColorId::new(vert.color), + }).collect(), + polygon_groups:self.polygon_groups.into_iter().map(|group| + strafesnet_common::model::PolygonGroup::PolygonList( + strafesnet_common::model::PolygonList::new( + group.polys.into_iter().map(|vert| + vert.vertices.into_iter().map(strafesnet_common::model::VertexId::new).collect() + ).collect() + ) + ) + ).collect(), + graphics_groups:self.graphics_groups.into_iter().map(|group| + strafesnet_common::model::IndexedGraphicsGroup{ + render:strafesnet_common::model::RenderConfigId::new(group.render), + groups:group.groups.into_iter().map(strafesnet_common::model::PolygonGroupId::new).collect(), + } + ).collect(), + physics_groups:self.physics_groups.into_iter().map(|group| + strafesnet_common::model::IndexedPhysicsGroup{ + groups:group.groups.into_iter().map(strafesnet_common::model::PolygonGroupId::new).collect(), + } + ).collect(), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct Model{ + pub mesh:u32, + pub attributes:u32, + pub color:Color4, + pub transform:Planar64Affine3, +} +impl Into for Model{ + fn into(self)->strafesnet_common::model::Model{ + let [_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b]=self.transform; + strafesnet_common::model::Model{ + mesh:strafesnet_common::model::MeshId::new(self.mesh), + attributes:strafesnet_common::gameplay_attributes::CollisionAttributesId::new(self.attributes), + color:strafesnet_common::model::Color4::from_array(self.color), + transform:strafesnet_common::integer::Planar64Affine3::new( + strafesnet_common::integer::Planar64Mat3::from_cols( + strafesnet_common::integer::Planar64Vec3::raw_xyz(_0,_1,_2), + strafesnet_common::integer::Planar64Vec3::raw_xyz(_3,_4,_5), + strafesnet_common::integer::Planar64Vec3::raw_xyz(_6,_7,_8) + ), + strafesnet_common::integer::Planar64Vec3::raw_xyz(_9,_a,_b) + ), + } + } +} From b6935b4f5fd4ab2adb773eb7feb97a3fce669056 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 25 Jul 2024 10:48:04 -0700 Subject: [PATCH 28/55] file tweaks --- src/file.rs | 5 ++++- src/lib.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/file.rs b/src/file.rs index 786cef8..6f22cf9 100644 --- a/src/file.rs +++ b/src/file.rs @@ -84,6 +84,9 @@ impl File{ data:input, }) } + pub(crate) fn as_mut(&mut self)->&mut R{ + &mut self.data + } pub(crate) fn block_reader(&mut self,block_id:BlockId)->Result,Error>{ if self.header.block_location.len() as u32<=block_id.get(){ return Err(Error::InvalidBlockId(block_id)) @@ -91,7 +94,7 @@ impl File{ let block_start=self.header.block_location[block_id.get() as usize]; let block_end=self.header.block_location[block_id.get() as usize+1]; self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(Error::Seek)?; - Ok((&mut self.data).take_seek(block_end-block_start)) + Ok(self.as_mut().take_seek(block_end-block_start)) } pub(crate) fn fourcc(&self)->FourCC{ self.header.fourcc diff --git a/src/lib.rs b/src/lib.rs index 4f4f479..90594ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ use binrw::BinReaderExt; mod newtypes; -pub mod file; +mod file; pub mod map; pub mod bot; pub mod demo; From 3434cd394a14fbea8d6ac99dac70244933c0239a Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 25 Jul 2024 10:48:07 -0700 Subject: [PATCH 29/55] implement map file format --- src/map.rs | 278 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 221 insertions(+), 57 deletions(-) diff --git a/src/map.rs b/src/map.rs index 89b39fc..ffea77b 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,11 +1,21 @@ -//use strafesnet_common::model; -//use strafesnet_common::gameplay_modes; -use binrw::{BinReaderExt, binrw}; +use std::io::Read; +use std::collections::HashMap; + +use crate::newtypes; +use crate::file::BlockId; +use binrw::{binrw,BinReaderExt}; +use strafesnet_common::model; +use strafesnet_common::aabb::Aabb; +use strafesnet_common::bvh::BvhNode; +use strafesnet_common::gameplay_modes; pub enum Error{ - InvalidHeader, - InvalidBvhNodeId(BvhNodeId), - InvalidRegion(binrw::Error), + InvalidHeader(binrw::Error), + InvalidBlockId(BlockId), + InvalidMeshId(model::MeshId), + InvalidTextureId(model::TextureId), + InvalidData(binrw::Error), + IO(std::io::Error), File(crate::file::Error), } @@ -14,10 +24,13 @@ pub enum Error{ BLOCK_MAP_HEADER: DefaultStyleInfo style_info //bvh goes here -u64 num_nodes +u32 num_nodes +u32 num_spacial_blocks +u32 num_resource_blocks +u32 num_resources_external //node 0 parent node is implied to be None for node_id in 1..num_nodes{ - u64 parent_node + u32 parent_node } //NOTE: alternate realities are not necessary. @@ -26,17 +39,21 @@ for node_id in 1..num_nodes{ //ideally spacial blocks are sorted from distance to start zone //texture blocks are inserted before the first spacial block they are used in -u64 num_spacial_blocks for spacial_block_id in 0..num_spacial_blocks{ - u64 node_id - u64 block_id //data block - Aabb block_extents + u32 node_id + u32 block_id //data block + Aabb extents } -//if the map file references external resources, num_resources = 0 -u64 num_resources -for resource_id in 0..num_resources{ - u64 block_id - u128 resource_id +//the order of these lists uniquely generates the incremental Ids +//MeshId, TextureId etc. based on resource type +//the first 8 bits of resource_uuid describe the type (mesh, texture, etc) +//if the map file references only external resources, num_resource_blocks = 0 +for resource_idx in 0..num_resource_blocks{ + Resource resource_type + u32 block_id +} +for resource_idx in 0..num_resources_external{ + u128 resource_uuid } BLOCK_MAP_RESOURCE: @@ -52,71 +69,218 @@ Resource resource_type BLOCK_MAP_REGION: u64 num_models for model_id in 0..num_models{ - u128 model_resource_uuid ModelInstance mode_instance } */ - -//error hiding mock code -mod gameplay_modes{ - pub struct Modes{} +//if you hash the resource itself and set the first 8 bits to this, that's the resource uuid +#[binrw] +#[brw(little,repr=u8)] +enum ResourceType{ + Mesh, + Texture, + //Shader, + //Sound, + //Video, + //Animation, } -mod model{ - pub struct Mesh{} - #[super::binrw] - #[brw(little)] - pub struct Model{} -} -mod image{ - pub struct Image{} +const RESOURCE_TYPE_VARIANT_COUNT:u8=2; +#[binrw] +#[brw(little)] +struct ResourceId(u128); +impl ResourceId{ + fn resource_type(&self)->Option{ + let discriminant=self.0 as u8; + //TODO: use this when it is stabilized https://github.com/rust-lang/rust/issues/73662 + //if (discriminant as usize)(){ + match discriminantSome(unsafe{std::mem::transmute::(discriminant)}), + false=>None, + } + } } -//serious code - -struct ModelUuid(u128); -struct ImageUuid(u128); +struct ResourceMap{ + meshes:HashMap, + textures:HashMap, +} +impl Default for ResourceMap{ + fn default()->Self{ + Self{ + meshes:HashMap::new(), + textures:HashMap::new(), + } + } +} #[binrw] #[brw(little)] -#[derive(Clone,Copy,id::Id)] -pub struct BvhNodeId(u32); -struct BvhNode{ - //aabb - //child +struct SpacialBlockHeader{ + id:BlockId, + extents:newtypes::aabb::Aabb, } +#[binrw] +#[brw(little)] +struct ResourceBlockHeader{ + resource:ResourceType, + id:BlockId, +} +#[binrw] +#[brw(little)] +struct ResourceExternalHeader{ + resource_uuid:ResourceId, +} + +#[binrw] +#[brw(little)] +struct MapHeader{ + num_nodes:u32, + num_spacial_blocks:u32, + num_resource_blocks:u32, + num_resources_external:u32, + num_modes:u32, + num_attributes:u32, + num_render_configs:u32, + #[br(count=num_nodes)] + nodes:Vec, + #[br(count=num_spacial_blocks)] + spacial_blocks:Vec, + #[br(count=num_resource_blocks)] + resource_blocks:Vec, + #[br(count=num_resources_external)] + external_resources:Vec, + #[br(count=num_modes)] + modes:Vec, + #[br(count=num_attributes)] + attributes:Vec, + #[br(count=num_render_configs)] + render_configs:Vec, +} + #[binrw] #[brw(little)] struct Region{ //consider including a bvh in the region instead of needing to rebalance the physics bvh on the fly model_count:u32, #[br(count=model_count)] - models:Vec, + models:Vec, +} + +//code deduplication reused in into_complete_map +fn read_region(file:&mut crate::file::File,block_id:BlockId)->Result,Error>{ + //load region from disk + //parse the models and determine what resources need to be loaded + //load resources into self.resources + //return Region + let mut block=file.block_reader(block_id).map_err(Error::File)?; + let region:Region=block.read_le().map_err(Error::InvalidData)?; + Ok(region.models.into_iter().map(Into::into).collect()) +} +fn read_mesh(file:&mut crate::file::File,block_id:BlockId)->Result{ + let mut block=file.block_reader(block_id).map_err(Error::File)?; + let mesh:newtypes::model::Mesh=block.read_le().map_err(Error::InvalidData)?; + Ok(mesh.into()) +} +fn read_texture(file:&mut crate::file::File,block_id:BlockId)->Result,Error>{ + let mut block=file.block_reader(block_id).map_err(Error::File)?; + let mut texture=Vec::new(); + block.read_to_end(&mut texture).map_err(Error::IO)?; + Ok(texture) } pub struct StreamableMap{ file:crate::file::File, //this includes every platform... move the unconstrained datas to their appropriate data block? modes:gameplay_modes::Modes, - bvh:BvhNode, - node_id_to_block_id:Vec, + //this is every possible attribute... need some sort of streaming system + attributes:Vec, + //this is every possible render configuration... shaders and such... need streaming + render_configs:Vec, + //this makes sense to keep in memory for streaming, a map of which blocks occupy what space + bvh:BvhNode, + //something something resources hashmaps + resource_blocks:ResourceMap, + //resource_external:ResourceMap, } impl StreamableMap{ - pub(crate) fn new(file:crate::file::File)->Result{ - Err(Error::InvalidHeader) + pub(crate) fn new(mut file:crate::file::File)->Result{ + //assume the file seek is in the right place to start reading a map header + let header:MapHeader=file.as_mut().read_le().map_err(Error::InvalidHeader)?; + let modes=header.modes.into_iter().map(Into::into).collect(); + let attributes=header.attributes.into_iter().map(Into::into).collect(); + let render_configs=header.render_configs.into_iter().map(Into::into).collect(); + let bvh=header.spacial_blocks.into_iter().map(|spacial_block| + (spacial_block.id,spacial_block.extents.into()) + ).collect(); + //generate mesh ids and texture ids from resource list order + let mut resource_blocks=ResourceMap::default(); + for resource_block_header in header.resource_blocks{ + match resource_block_header.resource{ + ResourceType::Mesh=>{ + resource_blocks.meshes.insert( + //generate the id from the current length + model::MeshId::new(resource_blocks.meshes.len() as u32), + resource_block_header.id + ); + }, + ResourceType::Texture=>{ + resource_blocks.textures.insert( + model::TextureId::new(resource_blocks.textures.len() as u32), + resource_block_header.id + ); + }, + } + } + Ok(Self{ + file, + modes:strafesnet_common::gameplay_modes::Modes::new(modes), + attributes, + render_configs, + bvh:strafesnet_common::bvh::generate_bvh(bvh), + resource_blocks, + //resource_external:Default::default(), + }) } - pub fn load_node(&mut self,node_id:BvhNodeId)->Result,Error>{ - //load region from disk - //parse the models and determine what resources need to be loaded - //load resources into self.resources - //return Region - let block_id=*self.node_id_to_block_id.get(node_id.get() as usize).ok_or(Error::InvalidBvhNodeId(node_id))?; - let mut block=self.file.block_reader(block_id).map_err(Error::File)?; - let region:Region=block.read_le().map_err(Error::InvalidRegion)?; - Ok(region.models) + pub fn get_intersecting_region_block_ids(&self,aabb:&Aabb)->Vec{ + let mut block_ids=Vec::new(); + self.bvh.the_tester(aabb,&mut |block_id|block_ids.push(block_id)); + block_ids } - // pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{ - // // - // } -} \ No newline at end of file + pub fn load_region(&mut self,block_id:BlockId)->Result,Error>{ + read_region(&mut self.file,block_id) + } + pub fn load_mesh(&mut self,mesh_id:model::MeshId)->Result{ + let block_id=*self.resource_blocks.meshes.get(&mesh_id).ok_or(Error::InvalidMeshId(mesh_id))?; + read_mesh(&mut self.file,block_id) + } + pub fn load_texture(&mut self,texture_id:model::TextureId)->Result,Error>{ + let block_id=*self.resource_blocks.textures.get(&texture_id).ok_or(Error::InvalidTextureId(texture_id))?; + read_texture(&mut self.file,block_id) + } + pub fn into_complete_map(mut self)->Result{ + //load all meshes + let meshes=self.resource_blocks.meshes.into_values().map(|block_id| + read_mesh(&mut self.file,block_id) + ).collect::,_>>()?; + //load all textures + let textures=self.resource_blocks.textures.into_values().map(|block_id| + read_texture(&mut self.file,block_id) + ).collect::,_>>()?; + let mut block_ids=Vec::new(); + self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); + //load all regions + let mut models=Vec::new(); + for block_id in block_ids{ + models.append(&mut read_region(&mut self.file,block_id)?); + } + Ok(strafesnet_common::map::CompleteMap{ + modes:self.modes, + attributes:self.attributes, + meshes, + models, + textures, + render_configs:self.render_configs, + }) + } +} From 47aef14ff3cdcb58adde58e07724049388e07ea5 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 25 Jul 2024 15:35:51 -0700 Subject: [PATCH 30/55] newtypes from engine types (boilerplate) --- src/newtypes/aabb.rs | 8 ++ src/newtypes/gameplay_attributes.rs | 145 ++++++++++++++++++++++++++++ src/newtypes/gameplay_modes.rs | 73 ++++++++++++++ src/newtypes/gameplay_style.rs | 117 ++++++++++++++++++++++ src/newtypes/integer.rs | 8 ++ src/newtypes/model.rs | 116 ++++++++++++++++++++++ 6 files changed, 467 insertions(+) diff --git a/src/newtypes/aabb.rs b/src/newtypes/aabb.rs index 3908287..ae8cb52 100644 --- a/src/newtypes/aabb.rs +++ b/src/newtypes/aabb.rs @@ -13,3 +13,11 @@ impl Into for Aabb{ ) } } +impl From for Aabb{ + fn from(value:strafesnet_common::aabb::Aabb)->Self{ + Self{ + max:value.max().get().to_array(), + min:value.min().get().to_array(), + } + } +} diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs index 10921cd..c8039d7 100644 --- a/src/newtypes/gameplay_attributes.rs +++ b/src/newtypes/gameplay_attributes.rs @@ -12,6 +12,16 @@ impl Into for Contacti } } } +impl From for ContactingLadder{ + fn from(value:strafesnet_common::gameplay_attributes::ContactingLadder)->Self{ + Self{ + sticky:match value.sticky{ + true=>Some(()), + false=>None, + } + } + } +} #[binrw::binrw] #[brw(little)] @@ -40,6 +50,24 @@ impl Into for Conta } } } +impl From for ContactingBehaviour{ + fn from(value:strafesnet_common::gameplay_attributes::ContactingBehaviour)->Self{ + match value{ + strafesnet_common::gameplay_attributes::ContactingBehaviour::Surf=> + ContactingBehaviour::Surf, + strafesnet_common::gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder)=> + ContactingBehaviour::Ladder( + contacting_ladder.into() + ), + strafesnet_common::gameplay_attributes::ContactingBehaviour::NoJump=> + ContactingBehaviour::NoJump, + strafesnet_common::gameplay_attributes::ContactingBehaviour::Cling=> + ContactingBehaviour::Cling, + strafesnet_common::gameplay_attributes::ContactingBehaviour::Elastic(elasticity)=> + ContactingBehaviour::Elastic(elasticity), + } + } +} #[binrw::binrw] #[brw(little)] @@ -57,6 +85,15 @@ impl Into for Interse } } } +impl From for IntersectingWater{ + fn from(value:strafesnet_common::gameplay_attributes::IntersectingWater)->Self{ + Self{ + viscosity:value.viscosity.get(), + density:value.density.get(), + velocity:value.velocity.get().to_array(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -70,6 +107,13 @@ impl Into for Accelerator{ } } } +impl From for Accelerator{ + fn from(value:strafesnet_common::gameplay_attributes::Accelerator)->Self{ + Self{ + acceleration:value.acceleration.get().to_array(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -92,6 +136,19 @@ impl Into for Booster{ } } } +impl From for Booster{ + fn from(value:strafesnet_common::gameplay_attributes::Booster)->Self{ + match value{ + strafesnet_common::gameplay_attributes::Booster::Velocity(velocity)=> + Booster::Velocity(velocity.get().to_array()), + strafesnet_common::gameplay_attributes::Booster::Energy{direction,energy}=> + Booster::Energy{ + direction:direction.get().to_array(), + energy:energy.get(), + }, + } + } +} #[binrw::binrw] #[brw(little,repr=u8)] @@ -109,6 +166,16 @@ impl Into for Trajecto } } } +impl From for TrajectoryChoice{ + fn from(value:strafesnet_common::gameplay_attributes::TrajectoryChoice)->Self{ + match value{ + strafesnet_common::gameplay_attributes::TrajectoryChoice::HighArcLongDuration=> + TrajectoryChoice::HighArcLongDuration, + strafesnet_common::gameplay_attributes::TrajectoryChoice::LowArcShortDuration=> + TrajectoryChoice::LowArcShortDuration, + } + } +} #[binrw::binrw] #[brw(little)] @@ -161,6 +228,40 @@ impl Into for SetTrajecto } } } +impl From for SetTrajectory{ + fn from(value:strafesnet_common::gameplay_attributes::SetTrajectory)->Self{ + match value{ + strafesnet_common::gameplay_attributes::SetTrajectory::AirTime(time)=> + SetTrajectory::AirTime( + time.get() + ), + strafesnet_common::gameplay_attributes::SetTrajectory::Height(height)=> + SetTrajectory::Height( + height.get() + ), + strafesnet_common::gameplay_attributes::SetTrajectory::DotVelocity{direction,dot}=> + SetTrajectory::DotVelocity{ + direction:direction.get().to_array(), + dot:dot.get(), + }, + strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointTime{target_point,time}=> + SetTrajectory::TargetPointTime{ + target_point:target_point.get().to_array(), + time:time.get(), + }, + strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointSpeed{target_point,speed,trajectory_choice}=> + SetTrajectory::TargetPointSpeed{ + target_point:target_point.get().to_array(), + speed:speed.get(), + trajectory_choice:trajectory_choice.into(), + }, + strafesnet_common::gameplay_attributes::SetTrajectory::Velocity(velocity)=> + SetTrajectory::Velocity( + velocity.get().to_array() + ), + } + } +} #[binrw::binrw] #[brw(little)] @@ -174,6 +275,13 @@ impl Into for Wormhole{ } } } +impl From for Wormhole{ + fn from(value:strafesnet_common::gameplay_attributes::Wormhole)->Self{ + Self{ + destination_model:value.destination_model.get(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -193,6 +301,16 @@ impl Into for General } } } +impl From for GeneralAttributes{ + fn from(value:strafesnet_common::gameplay_attributes::GeneralAttributes)->Self{ + Self{ + booster:value.booster.map(Into::into), + trajectory:value.trajectory.map(Into::into), + wormhole:value.wormhole.map(Into::into), + accelerator:value.accelerator.map(Into::into), + } + } +} #[binrw::binrw] #[brw(little)] @@ -206,6 +324,13 @@ impl Into for Cont } } } +impl From for ContactingAttributes{ + fn from(value:strafesnet_common::gameplay_attributes::ContactingAttributes)->Self{ + Self{ + contact_behaviour:value.contact_behaviour.map(Into::into), + } + } +} #[binrw::binrw] #[brw(little)] @@ -219,6 +344,14 @@ impl Into for In } } } +impl From for IntersectingAttributes{ + fn from(value:strafesnet_common::gameplay_attributes::IntersectingAttributes)->Self{ + Self{ + water:value.water.map(Into::into), + } + } +} + #[binrw::binrw] #[brw(little)] pub enum CollisionAttributes{ @@ -244,3 +377,15 @@ impl Into for Colli } } } +impl From for CollisionAttributes{ + fn from(value:strafesnet_common::gameplay_attributes::CollisionAttributes)->Self{ + match value{ + strafesnet_common::gameplay_attributes::CollisionAttributes::Decoration=> + CollisionAttributes::Decoration, + strafesnet_common::gameplay_attributes::CollisionAttributes::Contact{contacting,general}=> + CollisionAttributes::Contact{contacting:contacting.into(),general:general.into()}, + strafesnet_common::gameplay_attributes::CollisionAttributes::Intersect{intersecting,general}=> + CollisionAttributes::Intersect{intersecting:intersecting.into(),general:general.into()}, + } + } +} diff --git a/src/newtypes/gameplay_modes.rs b/src/newtypes/gameplay_modes.rs index 73c2eb4..aa7848e 100644 --- a/src/newtypes/gameplay_modes.rs +++ b/src/newtypes/gameplay_modes.rs @@ -22,6 +22,18 @@ impl Into for StageEle } } } +impl From for StageElementBehaviour{ + fn from(value:strafesnet_common::gameplay_modes::StageElementBehaviour)->Self{ + match value{ + strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt=>StageElementBehaviour::SpawnAt, + strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger=>StageElementBehaviour::Trigger, + strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport=>StageElementBehaviour::Teleport, + strafesnet_common::gameplay_modes::StageElementBehaviour::Platform=>StageElementBehaviour::Platform, + strafesnet_common::gameplay_modes::StageElementBehaviour::Check=>StageElementBehaviour::Check, + strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint=>StageElementBehaviour::Checkpoint, + } + } +} #[binrw::binrw] #[brw(little)] @@ -41,6 +53,16 @@ impl Into for StageElement{ ) } } +impl From for StageElement{ + fn from(value:strafesnet_common::gameplay_modes::StageElement)->Self{ + Self{ + stage_id:value.stage_id().get(), + behaviour:value.behaviour().into(), + jump_limit:value.jump_limit(), + force:match value.force(){true=>Some(()),false=>None}, + } + } +} #[binrw::binrw] #[brw(little)] @@ -71,6 +93,25 @@ impl Into for Stage{ ) } } +impl From for Stage{ + fn from(value:strafesnet_common::gameplay_modes::Stage)->Self{ + let spawn=value.spawn().get(); + let ordered_checkpoints_count=value.ordered_checkpoints_count(); + let unordered_checkpoints_count=value.unordered_checkpoints_count(); + let (ordered_checkpoints,unordered_checkpoints)=value.into_inner(); + Self{ + spawn, + ordered_checkpoints_count, + unordered_checkpoints_count, + ordered_checkpoints:ordered_checkpoints.into_iter() + .map(|(checkpoint_id,model_id)|(checkpoint_id.get(),model_id.get())) + .collect(), + unordered_checkpoints:unordered_checkpoints.into_iter() + .map(|model_id|model_id.get()) + .collect(), + } + } +} #[binrw::binrw] #[brw(little,repr=u8)] @@ -88,6 +129,15 @@ impl Into for Zone{ } } } +impl From for Zone{ + fn from(value:strafesnet_common::gameplay_modes::Zone)->Self{ + match value{ + strafesnet_common::gameplay_modes::Zone::Start=>Zone::Start, + strafesnet_common::gameplay_modes::Zone::Finish=>Zone::Finish, + strafesnet_common::gameplay_modes::Zone::Anticheat=>Zone::Anticheat, + } + } +} #[binrw::binrw] #[brw(little)] @@ -124,3 +174,26 @@ impl Into for Mode{ ) } } +impl From for Mode{ + fn from(value:strafesnet_common::gameplay_modes::Mode)->Self{ + let (style,start,zones,stages,elements)=value.into_inner(); + Self{ + header:ModeHeader{ + zones:zones.len() as u32, + stages:stages.len() as u32, + elements:elements.len() as u32, + }, + style:style.into(), + start:start.get(), + zones:zones.into_iter() + .map(|(model_id,zone)|(model_id.get(),zone.into())) + .collect(), + stages:stages.into_iter() + .map(Into::into) + .collect(), + elements:elements.into_iter() + .map(|(model_id,stage_element)|(model_id.get(),stage_element.into())) + .collect(), + } + } +} diff --git a/src/newtypes/gameplay_style.rs b/src/newtypes/gameplay_style.rs index 71c8320..1983a22 100644 --- a/src/newtypes/gameplay_style.rs +++ b/src/newtypes/gameplay_style.rs @@ -37,6 +37,24 @@ impl Into for StyleModifiers{ } } } +impl From for StyleModifiers{ + fn from(value:strafesnet_common::gameplay_style::StyleModifiers)->Self{ + Self{ + controls_mask:value.controls_mask.bits(), + controls_mask_state:value.controls_mask_state.bits(), + strafe:value.strafe.map(Into::into), + rocket:value.rocket.map(Into::into), + jump:value.jump.map(Into::into), + walk:value.walk.map(Into::into), + ladder:value.ladder.map(Into::into), + swim:value.swim.map(Into::into), + gravity:value.gravity.get().to_array(), + hitbox:value.hitbox.into(), + camera_offset:value.camera_offset.get().to_array(), + mass:value.mass.get(), + } + } +} #[binrw::binrw] #[brw(little,repr=u8)] @@ -54,6 +72,15 @@ impl Into for JumpCalculatio } } } +impl From for JumpCalculation{ + fn from(value:strafesnet_common::gameplay_style::JumpCalculation)->Self{ + match value{ + strafesnet_common::gameplay_style::JumpCalculation::Capped=>JumpCalculation::Capped, + strafesnet_common::gameplay_style::JumpCalculation::Energy=>JumpCalculation::Energy, + strafesnet_common::gameplay_style::JumpCalculation::Linear=>JumpCalculation::Linear, + } + } +} #[binrw::binrw] #[brw(little)] @@ -73,6 +100,16 @@ impl Into for JumpImpulse{ } } } +impl From for JumpImpulse{ + fn from(value:strafesnet_common::gameplay_style::JumpImpulse)->Self{ + match value{ + strafesnet_common::gameplay_style::JumpImpulse::FromTime(time)=>JumpImpulse::FromTime(time.get()), + strafesnet_common::gameplay_style::JumpImpulse::FromHeight(height)=>JumpImpulse::FromHeight(height.get()), + strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(deltav)=>JumpImpulse::FromDeltaV(deltav.get()), + strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(energy)=>JumpImpulse::FromEnergy(energy.get()), + } + } +} #[binrw::binrw] #[brw(little)] @@ -90,6 +127,15 @@ impl Into for ControlsAct ) } } +impl From for ControlsActivation{ + fn from(value:strafesnet_common::gameplay_style::ControlsActivation)->Self{ + Self{ + controls_mask:value.controls_mask().bits(), + controls_intersects:value.controls_intersects().bits(), + controls_contains:value.controls_contains().bits(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -109,6 +155,17 @@ impl Into for StrafeSettings{ ) } } +impl From for StrafeSettings{ + fn from(value:strafesnet_common::gameplay_style::StrafeSettings)->Self{ + let (enable,mv,air_accel_limit,tick_rate)=value.into_inner(); + Self{ + enable:enable.into(), + mv:mv.get(), + air_accel_limit:air_accel_limit.map(|a|a.get()), + tick_rate:tick_rate.into(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -122,6 +179,13 @@ impl Into for PropulsionS ) } } +impl From for PropulsionSettings{ + fn from(value:strafesnet_common::gameplay_style::PropulsionSettings)->Self{ + Self{ + magnitude:value.magnitude().get(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -137,6 +201,15 @@ impl Into for JumpSettings{ ) } } +impl From for JumpSettings{ + fn from(value:strafesnet_common::gameplay_style::JumpSettings)->Self{ + let (impulse,calculation)=value.into_inner(); + Self{ + impulse:impulse.into(), + calculation:calculation.into(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -152,6 +225,14 @@ impl Into for AccelerateS ) } } +impl From for AccelerateSettings{ + fn from(value:strafesnet_common::gameplay_style::AccelerateSettings)->Self{ + Self{ + accel:value.accel().get(), + topspeed:value.topspeed().get(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -171,6 +252,17 @@ impl Into for WalkSettings{ ) } } +impl From for WalkSettings{ + fn from(value:strafesnet_common::gameplay_style::WalkSettings)->Self{ + let (accelerate,static_friction,kinetic_friction,surf_dot)=value.into_inner(); + Self{ + accelerate:accelerate.into(), + static_friction:static_friction.get(), + kinetic_friction:kinetic_friction.get(), + surf_dot:surf_dot.get(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -186,6 +278,15 @@ impl Into for LadderSettings{ ) } } +impl From for LadderSettings{ + fn from(value:strafesnet_common::gameplay_style::LadderSettings)->Self{ + let (accelerate,dot)=value.into_inner(); + Self{ + accelerate:accelerate.into(), + dot:dot.get(), + } + } +} #[binrw::binrw] #[brw(little,repr=u8)] @@ -201,6 +302,14 @@ impl Into for HitboxMesh{ } } } +impl From for HitboxMesh{ + fn from(value:strafesnet_common::gameplay_style::HitboxMesh)->Self{ + match value{ + strafesnet_common::gameplay_style::HitboxMesh::Box=>HitboxMesh::Box, + strafesnet_common::gameplay_style::HitboxMesh::Cylinder=>HitboxMesh::Cylinder, + } + } +} #[binrw::binrw] #[brw(little)] @@ -216,3 +325,11 @@ impl Into for Hitbox{ } } } +impl From for Hitbox{ + fn from(value:strafesnet_common::gameplay_style::Hitbox)->Self{ + Self{ + halfsize:value.halfsize.get().to_array(), + mesh:value.mesh.into(), + } + } +} diff --git a/src/newtypes/integer.rs b/src/newtypes/integer.rs index 86a8b8c..f75ba70 100644 --- a/src/newtypes/integer.rs +++ b/src/newtypes/integer.rs @@ -11,6 +11,14 @@ impl Into for Ratio64{ strafesnet_common::integer::Ratio64::new(self.num,self.den).unwrap() } } +impl From for Ratio64{ + fn from(value:strafesnet_common::integer::Ratio64)->Self{ + Self{ + num:value.num(), + den:value.den(), + } + } +} #[binrw::binrw] #[brw(little)] diff --git a/src/newtypes/model.rs b/src/newtypes/model.rs index 1ad02f3..4d42aa9 100644 --- a/src/newtypes/model.rs +++ b/src/newtypes/model.rs @@ -1,3 +1,5 @@ +use strafesnet_common::model::PolygonIter; + use super::integer::{Planar64Vec3,Planar64Affine3}; pub type TextureCoordinate=[f32;2]; @@ -11,6 +13,16 @@ pub struct IndexedVertex{ pub normal:u32, pub color:u32, } +impl From for IndexedVertex{ + fn from(value:strafesnet_common::model::IndexedVertex)->Self{ + Self{ + pos:value.pos.get(), + tex:value.tex.get(), + normal:value.normal.get(), + color:value.color.get(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -26,6 +38,25 @@ pub struct PolygonGroup{ #[br(count=count)] pub polys:Vec, } +impl From for PolygonGroup{ + fn from(value:strafesnet_common::model::PolygonGroup)->Self{ + match value{ + strafesnet_common::model::PolygonGroup::PolygonList(polygon_list)=>{ + let polys:Vec=polygon_list.polys().map(|poly|{ + let vertices:Vec=poly.iter().map(|vert|vert.get()).collect(); + Polygon{ + count:vertices.len() as u32, + vertices, + } + }).collect(); + Self{ + count:polys.len() as u32, + polys, + } + } + } + } +} #[binrw::binrw] #[brw(little)] pub struct RenderConfig{ @@ -38,6 +69,13 @@ impl Into for RenderConfig{ } } } +impl From for RenderConfig{ + fn from(value:strafesnet_common::model::RenderConfig)->Self{ + Self{ + texture:value.texture.map(|texture_id|texture_id.get()), + } + } +} #[binrw::binrw] #[brw(little)] pub struct IndexedGraphicsGroup{ @@ -46,6 +84,15 @@ pub struct IndexedGraphicsGroup{ #[br(count=count)] pub groups:Vec, } +impl From for IndexedGraphicsGroup{ + fn from(value:strafesnet_common::model::IndexedGraphicsGroup)->Self{ + Self{ + count:value.groups.len() as u32, + render:value.render.get(), + groups:value.groups.into_iter().map(|group_id|group_id.get()).collect(), + } + } +} #[binrw::binrw] #[brw(little)] pub struct IndexedPhysicsGroup{ @@ -53,6 +100,14 @@ pub struct IndexedPhysicsGroup{ #[br(count=count)] pub groups:Vec, } +impl From for IndexedPhysicsGroup{ + fn from(value:strafesnet_common::model::IndexedPhysicsGroup)->Self{ + Self{ + count:value.groups.len() as u32, + groups:value.groups.into_iter().map(|group_id|group_id.get()).collect(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -123,6 +178,46 @@ impl Into for Mesh{ } } } +impl From for Mesh{ + fn from(value:strafesnet_common::model::Mesh)->Self{ + Self{ + header:MeshHeader{ + unique_pos:value.unique_pos.len() as u32, + unique_normal:value.unique_normal.len() as u32, + unique_tex:value.unique_tex.len() as u32, + unique_color:value.unique_color.len() as u32, + unique_vertices:value.unique_vertices.len() as u32, + polygon_groups:value.polygon_groups.len() as u32, + graphics_groups:value.graphics_groups.len() as u32, + physics_groups:value.physics_groups.len() as u32, + }, + unique_pos:value.unique_pos.into_iter() + .map(|pos|pos.get().to_array()) + .collect(), + unique_normal:value.unique_normal.into_iter() + .map(|normal|normal.get().to_array()) + .collect(), + unique_tex:value.unique_tex.into_iter() + .map(|tex|tex.to_array()) + .collect(), + unique_color:value.unique_color.into_iter() + .map(|color|color.to_array()) + .collect(), + unique_vertices:value.unique_vertices.into_iter() + .map(Into::into) + .collect(), + polygon_groups:value.polygon_groups.into_iter() + .map(Into::into) + .collect(), + graphics_groups:value.graphics_groups.into_iter() + .map(Into::into) + .collect(), + physics_groups:value.physics_groups.into_iter() + .map(Into::into) + .collect(), + } + } +} #[binrw::binrw] #[brw(little)] @@ -150,3 +245,24 @@ impl Into for Model{ } } } +impl From for Model{ + fn from(value:strafesnet_common::model::Model)->Self{ + let ( + [_0,_1,_2], + [_3,_4,_5], + [_6,_7,_8], + [_9,_a,_b] + )=( + value.transform.matrix3.x_axis.get().to_array(), + value.transform.matrix3.y_axis.get().to_array(), + value.transform.matrix3.z_axis.get().to_array(), + value.transform.translation.get().to_array() + ); + Self{ + mesh:value.mesh.get(), + attributes:value.attributes.get(), + color:value.color.to_array(), + transform:[_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b], + } + } +} From 4abeefa7e8dc7310ea4ab19ee0d685fd72f42044 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 25 Jul 2024 16:07:26 -0700 Subject: [PATCH 31/55] todo: header machinery in file (file.add_block) --- src/file.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/file.rs b/src/file.rs index 6f22cf9..d1fd674 100644 --- a/src/file.rs +++ b/src/file.rs @@ -51,19 +51,19 @@ pub(crate) enum FourCC{ } #[binrw] #[brw(little)] -struct Header{ +pub struct Header{ /// Type of file - fourcc:FourCC, - /// Type version - version:u32, + pub fourcc:FourCC, + /// File format version + pub version:u32, /// Minimum data required to know the location of all streamable resources for this specific file - priming:u64, + pub priming:u64, /// uuid for this file - resource:u128, + pub resource:u128, //don't need try_calc: the struct will force field initialization anyways and it can be calculated there - block_count:u32, + pub block_count:u32, #[br(count=block_count+1)] - block_location:Vec, + pub block_location:Vec, } #[binrw] From e1cdddc89285cbe170057ab495f1ecb4ab4c97c9 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 25 Jul 2024 15:35:54 -0700 Subject: [PATCH 32/55] write map --- src/map.rs | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 132 insertions(+), 5 deletions(-) diff --git a/src/map.rs b/src/map.rs index ffea77b..12fd577 100644 --- a/src/map.rs +++ b/src/map.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use crate::newtypes; use crate::file::BlockId; -use binrw::{binrw,BinReaderExt}; +use binrw::{binrw,BinReaderExt,BinWriterExt}; use strafesnet_common::model; use strafesnet_common::aabb::Aabb; use strafesnet_common::bvh::BvhNode; @@ -135,15 +135,12 @@ struct ResourceExternalHeader{ #[binrw] #[brw(little)] struct MapHeader{ - num_nodes:u32, num_spacial_blocks:u32, num_resource_blocks:u32, num_resources_external:u32, num_modes:u32, num_attributes:u32, num_render_configs:u32, - #[br(count=num_nodes)] - nodes:Vec, #[br(count=num_spacial_blocks)] spacial_blocks:Vec, #[br(count=num_resource_blocks)] @@ -244,7 +241,7 @@ impl StreamableMap{ } pub fn get_intersecting_region_block_ids(&self,aabb:&Aabb)->Vec{ let mut block_ids=Vec::new(); - self.bvh.the_tester(aabb,&mut |block_id|block_ids.push(block_id)); + self.bvh.the_tester(aabb,&mut |&block_id|block_ids.push(block_id)); block_ids } pub fn load_region(&mut self,block_id:BlockId)->Result,Error>{ @@ -284,3 +281,133 @@ impl StreamableMap{ }) } } + +const BVH_NODE_MAX_WEIGHT:usize=64*1024;//64 kB +fn collect_spacial_blocks( + block_location:&mut Vec, + block_headers:&mut Vec, + sequential_block_data:&mut std::io::Cursor<&mut Vec>, + bvh_node:strafesnet_common::bvh::BvhWeightNode +)->Result<(),Error>{ + //inspect the node weights top-down. + //When a node weighs less than the limit, + //serialize its entire contents into a region block + if *bvh_node.weight(){ + for bvh_node in bvh_node_list{ + collect_spacial_blocks(block_location,block_headers,sequential_block_data,bvh_node)?; + } + }, + strafesnet_common::bvh::RecursiveContent::Leaf(_)=>panic!(),//bvh branches are 20 leaves minimum + } + } + Ok(()) +} + +/// TODO: Optionally provide a bot that describes the path through the map +/// otherwise sort by distance to start zone +pub fn write_map(mut writer:W,map:strafesnet_common::map::CompleteMap)->Result<(),Error>{ + //serialize models and make a bvh that knows the file size of the branch + let boxen=map.models.into_iter().map(|model|{ + //grow your own aabb + let mesh=map.meshes.get(model.mesh.get() as usize).ok_or(Error::InvalidMeshId(model.mesh))?; + let mut aabb=strafesnet_common::aabb::Aabb::default(); + for &pos in &mesh.unique_pos{ + aabb.grow(model.transform.transform_point3(pos)); + } + Ok((model.into(),aabb)) + }).collect::,_>>()?; + let bvh=strafesnet_common::bvh::generate_bvh(boxen).weigh_contents(&|_|std::mem::size_of::()); + //build blocks + let mut block_location=vec![0];//for file header + let mut spacial_blocks=Vec::new();//for map header + let mut sequential_block_data=Vec::new(); + let mut cursor_to_data=std::io::Cursor::new(&mut sequential_block_data); + collect_spacial_blocks(&mut block_location,&mut spacial_blocks,&mut cursor_to_data,bvh)?; + let mut block_count=spacial_blocks.len() as u32;//continue block id + let mut resource_blocks=Vec::new();//for map header + //meshes + for mesh in map.meshes.into_iter(){ + resource_blocks.push(ResourceBlockHeader{ + resource:ResourceType::Mesh, + id:BlockId::new(block_count), + }); + block_count+=1; + let serializable_mesh:newtypes::model::Mesh=mesh.into(); + binrw::BinWrite::write_le(&serializable_mesh,&mut cursor_to_data).map_err(Error::InvalidData)?; + block_location.push(cursor_to_data.position()); + } + //textures + for mut texture in map.textures.into_iter(){ + resource_blocks.push(ResourceBlockHeader{ + resource:ResourceType::Texture, + id:BlockId::new(block_count), + }); + block_count+=1; + sequential_block_data.append(&mut texture); + block_location.push(sequential_block_data.len() as u64); + } + //build header + let map_header=MapHeader{ + num_spacial_blocks:spacial_blocks.len() as u32, + num_resource_blocks:resource_blocks.len() as u32, + num_resources_external:0, + num_modes:map.modes.modes.len() as u32, + num_attributes:map.attributes.len() as u32, + num_render_configs:map.render_configs.len() as u32, + spacial_blocks, + resource_blocks, + external_resources:Vec::new(), + modes:map.modes.modes.into_iter().map(Into::into).collect(), + attributes:map.attributes.into_iter().map(Into::into).collect(), + render_configs:map.render_configs.into_iter().map(Into::into).collect(), + }; + let mut file_header=crate::file::Header{ + fourcc:crate::file::FourCC::Map, + version:0, + priming:0,//TODO + resource:0, + block_count, + block_location, + }; + //probe header lengths + let mut file_header_data=Vec::new(); + binrw::BinWrite::write_le(&file_header,&mut std::io::Cursor::new(&mut file_header_data)).map_err(Error::InvalidData)?; + let mut map_header_data=Vec::new(); + binrw::BinWrite::write_le(&map_header,&mut std::io::Cursor::new(&mut map_header_data)).map_err(Error::InvalidData)?; + + //update file header according to probe data + let offset=file_header_data.len() as u64+map_header_data.len() as u64; + file_header.priming=offset; + for position in &mut file_header.block_location{ + *position+=offset; + } + + //write file header + writer.write_le(&file_header).map_err(Error::InvalidData)?; + //write map header + writer.write(&map_header_data).map_err(Error::IO)?; + //write blocks + writer.write(&sequential_block_data).map_err(Error::IO)?; + Ok(()) +} From d3e114c7b6a3607b1e05bff9e9217d0dc67d33f3 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 25 Jul 2024 17:47:00 -0700 Subject: [PATCH 33/55] implement error traits --- src/bot.rs | 3 ++- src/demo.rs | 3 ++- src/file.rs | 12 ++++++++++-- src/lib.rs | 7 +++++++ src/map.rs | 7 +++++++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index d531015..ffdaee8 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -1,5 +1,6 @@ use binrw::{BinReaderExt, binrw}; +#[derive(Debug)] pub enum Error{ InvalidHeader, InvalidSegment(binrw::Error), @@ -64,7 +65,7 @@ mod simulation{ #[binrw] #[brw(little)] -#[derive(Clone,Copy,id::Id)] +#[derive(Clone,Copy,Debug,id::Id)] pub struct SegmentId(u32); #[binrw] diff --git a/src/demo.rs b/src/demo.rs index 302ea5a..119290a 100644 --- a/src/demo.rs +++ b/src/demo.rs @@ -1,5 +1,6 @@ use binrw::BinReaderExt; +#[derive(Debug)] pub enum Error{ InvalidHeader, } @@ -27,4 +28,4 @@ impl StreamableDemo{ pub(crate) fn new(file:crate::file::File)->Result{ Err(Error::InvalidHeader) } -} \ No newline at end of file +} diff --git a/src/file.rs b/src/file.rs index d1fd674..91c7229 100644 --- a/src/file.rs +++ b/src/file.rs @@ -2,12 +2,19 @@ use binrw::{binrw, BinReaderExt, io::TakeSeekExt}; +#[derive(Debug)] pub enum Error{ InvalidHeader(binrw::Error), UnexpectedEOF, InvalidBlockId(BlockId), Seek(std::io::Error), } +impl std::fmt::Display for Error{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for Error{} /* spec @@ -40,7 +47,7 @@ for block_id in 1..num_blocks{ */ #[binrw] #[brw(little)] -#[derive(Clone,Copy)] +#[derive(Clone,Copy,Debug)] pub(crate) enum FourCC{ #[brw(magic=b"SNFM")] Map, @@ -51,6 +58,7 @@ pub(crate) enum FourCC{ } #[binrw] #[brw(little)] +#[derive(Debug)] pub struct Header{ /// Type of file pub fourcc:FourCC, @@ -68,7 +76,7 @@ pub struct Header{ #[binrw] #[brw(little)] -#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)] +#[derive(Clone,Copy,Debug,Hash,id::Id,Eq,PartialEq)] pub struct BlockId(u32); pub(crate) struct File{ diff --git a/src/lib.rs b/src/lib.rs index 90594ff..675dfdb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub mod map; pub mod bot; pub mod demo; +#[derive(Debug)] pub enum Error{ UnexpectedFourCC, Header(file::Error), @@ -14,6 +15,12 @@ pub enum Error{ Bot(bot::Error), Demo(demo::Error), } +impl std::fmt::Display for Error{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for Error{} pub enum SNF{ Map(map::StreamableMap), diff --git a/src/map.rs b/src/map.rs index 12fd577..305cabe 100644 --- a/src/map.rs +++ b/src/map.rs @@ -9,6 +9,7 @@ use strafesnet_common::aabb::Aabb; use strafesnet_common::bvh::BvhNode; use strafesnet_common::gameplay_modes; +#[derive(Debug)] pub enum Error{ InvalidHeader(binrw::Error), InvalidBlockId(BlockId), @@ -18,6 +19,12 @@ pub enum Error{ IO(std::io::Error), File(crate::file::Error), } +impl std::fmt::Display for Error{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for Error{} /* block types From 0705e879db99a830dc2e69b0d572ebc7acd440cb Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 26 Jul 2024 12:19:09 -0700 Subject: [PATCH 34/55] fix block_location --- src/map.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/map.rs b/src/map.rs index 305cabe..1903d15 100644 --- a/src/map.rs +++ b/src/map.rs @@ -346,7 +346,12 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple }).collect::,_>>()?; let bvh=strafesnet_common::bvh::generate_bvh(boxen).weigh_contents(&|_|std::mem::size_of::()); //build blocks - let mut block_location=vec![0];//for file header + //block location is initialized with two values + //the first value represents the location of the first byte after the file header + //the second value represents the first byte of the second data block + //the first data block is always the map header, so the difference is the map header size. + //this information is filled in later after the sizes are known. + let mut block_location=vec![0,0];//for file header let mut spacial_blocks=Vec::new();//for map header let mut sequential_block_data=Vec::new(); let mut cursor_to_data=std::io::Cursor::new(&mut sequential_block_data); @@ -389,28 +394,33 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple attributes:map.attributes.into_iter().map(Into::into).collect(), render_configs:map.render_configs.into_iter().map(Into::into).collect(), }; + //the map header is a block! + block_count+=1; + assert_eq!(block_count as usize+1,block_location.len()); let mut file_header=crate::file::Header{ fourcc:crate::file::FourCC::Map, version:0, - priming:0,//TODO + priming:0, resource:0, block_count, block_location, }; - //probe header lengths + //probe header length let mut file_header_data=Vec::new(); binrw::BinWrite::write_le(&file_header,&mut std::io::Cursor::new(&mut file_header_data)).map_err(Error::InvalidData)?; let mut map_header_data=Vec::new(); binrw::BinWrite::write_le(&map_header,&mut std::io::Cursor::new(&mut map_header_data)).map_err(Error::InvalidData)?; //update file header according to probe data - let offset=file_header_data.len() as u64+map_header_data.len() as u64; + let mut offset=file_header_data.len() as u64; file_header.priming=offset; - for position in &mut file_header.block_location{ + file_header.block_location[0]=offset; + offset+=map_header_data.len() as u64; + for position in &mut file_header.block_location[1..]{ *position+=offset; } - //write file header + //write (updated) file header writer.write_le(&file_header).map_err(Error::InvalidData)?; //write map header writer.write(&map_header_data).map_err(Error::IO)?; From fa7e7d58bf643b8131851afc4ad426201e5afdc6 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 26 Jul 2024 15:10:49 -0700 Subject: [PATCH 35/55] load textures and meshes in ascending order --- src/map.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/map.rs b/src/map.rs index 1903d15..a2085af 100644 --- a/src/map.rs +++ b/src/map.rs @@ -264,13 +264,19 @@ impl StreamableMap{ } pub fn into_complete_map(mut self)->Result{ //load all meshes - let meshes=self.resource_blocks.meshes.into_values().map(|block_id| - read_mesh(&mut self.file,block_id) - ).collect::,_>>()?; + let mut meshes=Vec::with_capacity(self.resource_blocks.meshes.len()); + for mesh_id in 0..self.resource_blocks.meshes.len() as u32{ + let mesh_id=model::MeshId::new(mesh_id); + let block_id=self.resource_blocks.meshes[&mesh_id]; + meshes.push(read_mesh(&mut self.file,block_id)?); + }; //load all textures - let textures=self.resource_blocks.textures.into_values().map(|block_id| - read_texture(&mut self.file,block_id) - ).collect::,_>>()?; + let mut textures=Vec::with_capacity(self.resource_blocks.textures.len()); + for texture_id in 0..self.resource_blocks.textures.len() as u32{ + let texture_id=model::TextureId::new(texture_id); + let block_id=self.resource_blocks.textures[&texture_id]; + textures.push(read_texture(&mut self.file,block_id)?); + } let mut block_ids=Vec::new(); self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); //load all regions From 2262c6feace48dacb49ef81c1e8b3d99d1edfa47 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 26 Jul 2024 15:24:20 -0700 Subject: [PATCH 36/55] fixes --- src/map.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/map.rs b/src/map.rs index a2085af..9513daf 100644 --- a/src/map.rs +++ b/src/map.rs @@ -313,7 +313,7 @@ fn collect_spacial_blocks( model_count+=1; models.push(model); }); - let id=BlockId::new(block_headers.len() as u32); + let id=BlockId::new(block_headers.len() as u32+1); block_headers.push(SpacialBlockHeader{ id, extents, @@ -362,7 +362,7 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple let mut sequential_block_data=Vec::new(); let mut cursor_to_data=std::io::Cursor::new(&mut sequential_block_data); collect_spacial_blocks(&mut block_location,&mut spacial_blocks,&mut cursor_to_data,bvh)?; - let mut block_count=spacial_blocks.len() as u32;//continue block id + let mut block_count=spacial_blocks.len() as u32+1;//continue block id let mut resource_blocks=Vec::new();//for map header //meshes for mesh in map.meshes.into_iter(){ @@ -400,9 +400,6 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple attributes:map.attributes.into_iter().map(Into::into).collect(), render_configs:map.render_configs.into_iter().map(Into::into).collect(), }; - //the map header is a block! - block_count+=1; - assert_eq!(block_count as usize+1,block_location.len()); let mut file_header=crate::file::Header{ fourcc:crate::file::FourCC::Map, version:0, From 3e8c5167dc819928effe61d81dc77cee323e5242 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 26 Jul 2024 15:42:38 -0700 Subject: [PATCH 37/55] do not include unused features --- src/map.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/map.rs b/src/map.rs index 9513daf..b758d98 100644 --- a/src/map.rs +++ b/src/map.rs @@ -144,7 +144,7 @@ struct ResourceExternalHeader{ struct MapHeader{ num_spacial_blocks:u32, num_resource_blocks:u32, - num_resources_external:u32, + //num_resources_external:u32, num_modes:u32, num_attributes:u32, num_render_configs:u32, @@ -152,8 +152,8 @@ struct MapHeader{ spacial_blocks:Vec, #[br(count=num_resource_blocks)] resource_blocks:Vec, - #[br(count=num_resources_external)] - external_resources:Vec, + //#[br(count=num_resources_external)] + //external_resources:Vec, #[br(count=num_modes)] modes:Vec, #[br(count=num_attributes)] @@ -389,13 +389,13 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple let map_header=MapHeader{ num_spacial_blocks:spacial_blocks.len() as u32, num_resource_blocks:resource_blocks.len() as u32, - num_resources_external:0, + //num_resources_external:0, num_modes:map.modes.modes.len() as u32, num_attributes:map.attributes.len() as u32, num_render_configs:map.render_configs.len() as u32, spacial_blocks, resource_blocks, - external_resources:Vec::new(), + //external_resources:Vec::new(), modes:map.modes.modes.into_iter().map(Into::into).collect(), attributes:map.attributes.into_iter().map(Into::into).collect(), render_configs:map.render_configs.into_iter().map(Into::into).collect(), From 931cef52b1f50a64349ad5159eefaafc95c048f2 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 26 Jul 2024 16:13:51 -0700 Subject: [PATCH 38/55] serial file access --- src/file.rs | 2 +- src/map.rs | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/file.rs b/src/file.rs index 91c7229..1cc2d8e 100644 --- a/src/file.rs +++ b/src/file.rs @@ -76,7 +76,7 @@ pub struct Header{ #[binrw] #[brw(little)] -#[derive(Clone,Copy,Debug,Hash,id::Id,Eq,PartialEq)] +#[derive(Clone,Copy,Debug,Hash,id::Id,Eq,Ord,PartialEq,PartialOrd)] pub struct BlockId(u32); pub(crate) struct File{ diff --git a/src/map.rs b/src/map.rs index b758d98..97e74f5 100644 --- a/src/map.rs +++ b/src/map.rs @@ -263,6 +263,15 @@ impl StreamableMap{ read_texture(&mut self.file,block_id) } pub fn into_complete_map(mut self)->Result{ + let mut block_ids=Vec::new(); + self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); + //count on reading the file in sequential order being fastest + block_ids.sort(); + //load all regions + let mut models=Vec::new(); + for block_id in block_ids{ + models.append(&mut read_region(&mut self.file,block_id)?); + } //load all meshes let mut meshes=Vec::with_capacity(self.resource_blocks.meshes.len()); for mesh_id in 0..self.resource_blocks.meshes.len() as u32{ @@ -277,13 +286,6 @@ impl StreamableMap{ let block_id=self.resource_blocks.textures[&texture_id]; textures.push(read_texture(&mut self.file,block_id)?); } - let mut block_ids=Vec::new(); - self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); - //load all regions - let mut models=Vec::new(); - for block_id in block_ids{ - models.append(&mut read_region(&mut self.file,block_id)?); - } Ok(strafesnet_common::map::CompleteMap{ modes:self.modes, attributes:self.attributes, From a00b6a63c9762139587f3ea7eabc9d8fc6481964 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 26 Jul 2024 17:26:57 -0700 Subject: [PATCH 39/55] wow it's wrong again --- src/map.rs | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/map.rs b/src/map.rs index 97e74f5..0a83468 100644 --- a/src/map.rs +++ b/src/map.rs @@ -14,6 +14,7 @@ pub enum Error{ InvalidHeader(binrw::Error), InvalidBlockId(BlockId), InvalidMeshId(model::MeshId), + InvalidModelId(model::ModelId), InvalidTextureId(model::TextureId), InvalidData(binrw::Error), IO(std::io::Error), @@ -168,18 +169,20 @@ struct Region{ //consider including a bvh in the region instead of needing to rebalance the physics bvh on the fly model_count:u32, #[br(count=model_count)] - models:Vec, + models:Vec<(u32,newtypes::model::Model)>, } //code deduplication reused in into_complete_map -fn read_region(file:&mut crate::file::File,block_id:BlockId)->Result,Error>{ +fn read_region(file:&mut crate::file::File,block_id:BlockId)->Result,Error>{ //load region from disk //parse the models and determine what resources need to be loaded //load resources into self.resources //return Region let mut block=file.block_reader(block_id).map_err(Error::File)?; let region:Region=block.read_le().map_err(Error::InvalidData)?; - Ok(region.models.into_iter().map(Into::into).collect()) + Ok(region.models.into_iter().map(|(model_id,model)| + (model::ModelId::new(model_id),model.into()) + ).collect()) } fn read_mesh(file:&mut crate::file::File,block_id:BlockId)->Result{ let mut block=file.block_reader(block_id).map_err(Error::File)?; @@ -251,7 +254,7 @@ impl StreamableMap{ self.bvh.the_tester(aabb,&mut |&block_id|block_ids.push(block_id)); block_ids } - pub fn load_region(&mut self,block_id:BlockId)->Result,Error>{ + pub fn load_region(&mut self,block_id:BlockId)->Result,Error>{ read_region(&mut self.file,block_id) } pub fn load_mesh(&mut self,mesh_id:model::MeshId)->Result{ @@ -263,14 +266,18 @@ impl StreamableMap{ read_texture(&mut self.file,block_id) } pub fn into_complete_map(mut self)->Result{ - let mut block_ids=Vec::new(); - self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); //count on reading the file in sequential order being fastest - block_ids.sort(); + let mut block_ids=std::collections::BinaryHeap::new(); + self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); //load all regions - let mut models=Vec::new(); + let mut model_pairs=HashMap::new(); for block_id in block_ids{ - models.append(&mut read_region(&mut self.file,block_id)?); + model_pairs.extend(read_region(&mut self.file,block_id)?); + } + let mut models=Vec::with_capacity(model_pairs.len()); + for model_id in 0..model_pairs.len() as u32{ + let model_id=model::ModelId::new(model_id); + models.push(model_pairs.remove(&model_id).ok_or(Error::InvalidModelId(model_id))?); } //load all meshes let mut meshes=Vec::with_capacity(self.resource_blocks.meshes.len()); @@ -302,7 +309,7 @@ fn collect_spacial_blocks( block_location:&mut Vec, block_headers:&mut Vec, sequential_block_data:&mut std::io::Cursor<&mut Vec>, - bvh_node:strafesnet_common::bvh::BvhWeightNode + bvh_node:strafesnet_common::bvh::BvhWeightNode )->Result<(),Error>{ //inspect the node weights top-down. //When a node weighs less than the limit, @@ -311,9 +318,9 @@ fn collect_spacial_blocks( let mut models=Vec::new(); let mut model_count=0; let extents=bvh_node.aabb().clone().into(); - bvh_node.into_visitor(&mut |model|{ + bvh_node.into_visitor(&mut |(model_id,model)|{ model_count+=1; - models.push(model); + models.push((model_id.get(),model)); }); let id=BlockId::new(block_headers.len() as u32+1); block_headers.push(SpacialBlockHeader{ @@ -343,14 +350,14 @@ fn collect_spacial_blocks( /// otherwise sort by distance to start zone pub fn write_map(mut writer:W,map:strafesnet_common::map::CompleteMap)->Result<(),Error>{ //serialize models and make a bvh that knows the file size of the branch - let boxen=map.models.into_iter().map(|model|{ + let boxen=map.models.into_iter().enumerate().map(|(model_id,model)|{ //grow your own aabb let mesh=map.meshes.get(model.mesh.get() as usize).ok_or(Error::InvalidMeshId(model.mesh))?; let mut aabb=strafesnet_common::aabb::Aabb::default(); for &pos in &mesh.unique_pos{ aabb.grow(model.transform.transform_point3(pos)); } - Ok((model.into(),aabb)) + Ok(((model::ModelId::new(model_id as u32),model.into()),aabb)) }).collect::,_>>()?; let bvh=strafesnet_common::bvh::generate_bvh(boxen).weigh_contents(&|_|std::mem::size_of::()); //build blocks From 5d254009421e2e2453b5ea9ed65c8d46e36d7318 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Sat, 27 Jul 2024 09:04:51 -0700 Subject: [PATCH 40/55] there's no way that a max heap is better than just sorting --- src/map.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/map.rs b/src/map.rs index 0a83468..55313f9 100644 --- a/src/map.rs +++ b/src/map.rs @@ -266,9 +266,10 @@ impl StreamableMap{ read_texture(&mut self.file,block_id) } pub fn into_complete_map(mut self)->Result{ - //count on reading the file in sequential order being fastest - let mut block_ids=std::collections::BinaryHeap::new(); + let mut block_ids=Vec::new(); self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); + //count on reading the file in sequential order being fastest + block_ids.sort_unstable(); //load all regions let mut model_pairs=HashMap::new(); for block_id in block_ids{ From a1ee34c7a38fdfed4812055167188baf5cde59c5 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 26 Jul 2024 16:57:41 -0700 Subject: [PATCH 41/55] binrw enums --- src/newtypes.rs | 1 + src/newtypes/common.rs | 26 +++++++++ src/newtypes/gameplay_attributes.rs | 55 ++++++++++++++++--- src/newtypes/gameplay_modes.rs | 81 +++++++++++++--------------- src/newtypes/gameplay_style.rs | 82 +++++++++++++++++++++++++---- src/newtypes/model.rs | 8 +++ 6 files changed, 195 insertions(+), 58 deletions(-) create mode 100644 src/newtypes/common.rs diff --git a/src/newtypes.rs b/src/newtypes.rs index 8b12c6b..19e2e59 100644 --- a/src/newtypes.rs +++ b/src/newtypes.rs @@ -1,3 +1,4 @@ +mod common; pub mod aabb; pub mod model; pub mod integer; diff --git a/src/newtypes/common.rs b/src/newtypes/common.rs new file mode 100644 index 0000000..0136b54 --- /dev/null +++ b/src/newtypes/common.rs @@ -0,0 +1,26 @@ +pub const fn flag(b:bool,mask:u8)->u8{ + (-(b as i8) as u8)&mask +} + +#[binrw::binrw] +#[brw(little,repr=u8)] +pub enum Boolio{ + True, + False +} +impl Into for Boolio{ + fn into(self)->bool{ + match self{ + Boolio::True=>true, + Boolio::False=>false, + } + } +} +impl From for Boolio{ + fn from(value:bool)->Self{ + match value{ + true=>Boolio::True, + false=>Boolio::False, + } + } +} diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs index c8039d7..0dd3501 100644 --- a/src/newtypes/gameplay_attributes.rs +++ b/src/newtypes/gameplay_attributes.rs @@ -1,24 +1,22 @@ +use super::common::{flag,Boolio}; use super::integer::{Time,Planar64,Planar64Vec3}; #[binrw::binrw] #[brw(little)] pub struct ContactingLadder{ - pub sticky:Option<()>, + pub sticky:Boolio, } impl Into for ContactingLadder{ fn into(self)->strafesnet_common::gameplay_attributes::ContactingLadder{ strafesnet_common::gameplay_attributes::ContactingLadder{ - sticky:self.sticky.is_some(), + sticky:self.sticky.into(), } } } impl From for ContactingLadder{ fn from(value:strafesnet_common::gameplay_attributes::ContactingLadder)->Self{ Self{ - sticky:match value.sticky{ - true=>Some(()), - false=>None, - } + sticky:value.sticky.into(), } } } @@ -26,10 +24,15 @@ impl From for Contacti #[binrw::binrw] #[brw(little)] pub enum ContactingBehaviour{ + #[brw(magic=0u8)] Surf, + #[brw(magic=1u8)] Ladder(ContactingLadder), + #[brw(magic=2u8)] NoJump, + #[brw(magic=3u8)] Cling, + #[brw(magic=4u8)] Elastic(u32), } impl Into for ContactingBehaviour{ @@ -118,7 +121,9 @@ impl From for Accelerator{ #[binrw::binrw] #[brw(little)] pub enum Booster{ + #[brw(magic=0u8)] Velocity(Planar64Vec3), + #[brw(magic=1u8)] Energy{direction:Planar64Vec3,energy:Planar64}, } impl Into for Booster{ @@ -180,18 +185,24 @@ impl From for Trajecto #[binrw::binrw] #[brw(little)] pub enum SetTrajectory{ + #[brw(magic=0u8)] AirTime(Time), + #[brw(magic=1u8)] Height(Planar64), + #[brw(magic=2u8)] DotVelocity{direction:Planar64Vec3,dot:Planar64}, + #[brw(magic=3u8)] TargetPointTime{ target_point:Planar64Vec3, time:Time, }, + #[brw(magic=4u8)] TargetPointSpeed{ target_point:Planar64Vec3, speed:Planar64, trajectory_choice:TrajectoryChoice, }, + #[brw(magic=5u8)] Velocity(Planar64Vec3), } impl Into for SetTrajectory{ @@ -286,11 +297,22 @@ impl From for Wormhole{ #[binrw::binrw] #[brw(little)] pub struct GeneralAttributes{ + pub header:u8, + #[br(if(header&Self::BOOSTER!=0))] pub booster:Option, + #[br(if(header&Self::TRAJECTORY!=0))] pub trajectory:Option, + #[br(if(header&Self::WORMHOLE!=0))] pub wormhole:Option, + #[br(if(header&Self::ACCELERATOR!=0))] pub accelerator:Option, } +impl GeneralAttributes{ + const BOOSTER:u8=1<<0; + const TRAJECTORY:u8=1<<1; + const WORMHOLE:u8=1<<2; + const ACCELERATOR:u8=1<<3; +} impl Into for GeneralAttributes{ fn into(self)->strafesnet_common::gameplay_attributes::GeneralAttributes{ strafesnet_common::gameplay_attributes::GeneralAttributes{ @@ -303,7 +325,13 @@ impl Into for General } impl From for GeneralAttributes{ fn from(value:strafesnet_common::gameplay_attributes::GeneralAttributes)->Self{ + let header= + flag(value.booster.is_some(),GeneralAttributes::BOOSTER) + |flag(value.trajectory.is_some(),GeneralAttributes::TRAJECTORY) + |flag(value.wormhole.is_some(),GeneralAttributes::WORMHOLE) + |flag(value.accelerator.is_some(),GeneralAttributes::ACCELERATOR); Self{ + header, booster:value.booster.map(Into::into), trajectory:value.trajectory.map(Into::into), wormhole:value.wormhole.map(Into::into), @@ -315,8 +343,13 @@ impl From for General #[binrw::binrw] #[brw(little)] pub struct ContactingAttributes{ + pub header:u8, + #[br(if(header&Self::CONTACTING_BEHAVIOUR!=0))] pub contact_behaviour:Option, } +impl ContactingAttributes{ + const CONTACTING_BEHAVIOUR:u8=1<<0; +} impl Into for ContactingAttributes{ fn into(self)->strafesnet_common::gameplay_attributes::ContactingAttributes{ strafesnet_common::gameplay_attributes::ContactingAttributes{ @@ -327,6 +360,7 @@ impl Into for Cont impl From for ContactingAttributes{ fn from(value:strafesnet_common::gameplay_attributes::ContactingAttributes)->Self{ Self{ + header:flag(value.contact_behaviour.is_some(),ContactingAttributes::CONTACTING_BEHAVIOUR), contact_behaviour:value.contact_behaviour.map(Into::into), } } @@ -335,8 +369,13 @@ impl From for Cont #[binrw::binrw] #[brw(little)] pub struct IntersectingAttributes{ + pub header:u8, + #[br(if(header&Self::INTERSECTING_WATER!=0))] pub water:Option, } +impl IntersectingAttributes{ + const INTERSECTING_WATER:u8=1<<0; +} impl Into for IntersectingAttributes{ fn into(self)->strafesnet_common::gameplay_attributes::IntersectingAttributes{ strafesnet_common::gameplay_attributes::IntersectingAttributes{ @@ -347,6 +386,7 @@ impl Into for In impl From for IntersectingAttributes{ fn from(value:strafesnet_common::gameplay_attributes::IntersectingAttributes)->Self{ Self{ + header:flag(value.water.is_some(),IntersectingAttributes::INTERSECTING_WATER), water:value.water.map(Into::into), } } @@ -355,11 +395,14 @@ impl From for In #[binrw::binrw] #[brw(little)] pub enum CollisionAttributes{ + #[brw(magic=0u8)] Decoration, + #[brw(magic=1u8)] Contact{ contacting:ContactingAttributes, general:GeneralAttributes, }, + #[brw(magic=2u8)] Intersect{ intersecting:IntersectingAttributes, general:GeneralAttributes, diff --git a/src/newtypes/gameplay_modes.rs b/src/newtypes/gameplay_modes.rs index aa7848e..b789427 100644 --- a/src/newtypes/gameplay_modes.rs +++ b/src/newtypes/gameplay_modes.rs @@ -1,65 +1,60 @@ -#[binrw::binrw] -#[brw(little,repr=u8)] -pub enum StageElementBehaviour{ - SpawnAt,//must be standing on top to get effect. except cancollide false - Trigger, - Teleport, - Platform, - //Check(point) acts like a trigger if you haven't hit all the checkpoints on previous stages yet. - //Note that all stage elements act like this, this is just the isolated behaviour. - Check, - Checkpoint,//this is a combined behaviour for Ordered & Unordered in case a model is used multiple times or for both. -} -impl Into for StageElementBehaviour{ - fn into(self)->strafesnet_common::gameplay_modes::StageElementBehaviour{ - match self{ - StageElementBehaviour::SpawnAt=>strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt, - StageElementBehaviour::Trigger=>strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger, - StageElementBehaviour::Teleport=>strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport, - StageElementBehaviour::Platform=>strafesnet_common::gameplay_modes::StageElementBehaviour::Platform, - StageElementBehaviour::Check=>strafesnet_common::gameplay_modes::StageElementBehaviour::Check, - StageElementBehaviour::Checkpoint=>strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint, - } - } -} -impl From for StageElementBehaviour{ - fn from(value:strafesnet_common::gameplay_modes::StageElementBehaviour)->Self{ - match value{ - strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt=>StageElementBehaviour::SpawnAt, - strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger=>StageElementBehaviour::Trigger, - strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport=>StageElementBehaviour::Teleport, - strafesnet_common::gameplay_modes::StageElementBehaviour::Platform=>StageElementBehaviour::Platform, - strafesnet_common::gameplay_modes::StageElementBehaviour::Check=>StageElementBehaviour::Check, - strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint=>StageElementBehaviour::Checkpoint, - } - } -} +use super::common::flag; #[binrw::binrw] #[brw(little)] pub struct StageElement{ - pub stage_id:u32,//which stage spawn to send to - pub behaviour:StageElementBehaviour, + pub header:u8, + pub stage_id:u32, + #[br(if(header&Self::JUMP_LIMIT!=0))] pub jump_limit:Option, - pub force:Option<()>,//allow setting to lower spawn id i.e. 7->3 +} +impl StageElement{ + const BEHAVIOUR:u8=0b00111; + const JUMP_LIMIT:u8=1<<3; + const FORCE:u8=1<<4; + const fn behaviour(&self)->Option{ + match self.header&Self::BEHAVIOUR{ + 0=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt), + 1=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger), + 2=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport), + 3=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Platform), + 4=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Check), + 5=>Some(strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint), + _=>None, + } + } + const fn force(&self)->bool{ + self.header&Self::FORCE!=0 + } } impl Into for StageElement{ fn into(self)->strafesnet_common::gameplay_modes::StageElement{ strafesnet_common::gameplay_modes::StageElement::new( strafesnet_common::gameplay_modes::StageId::new(self.stage_id), - self.force.is_some(), - self.behaviour.into(), + self.force(), + self.behaviour().unwrap(), self.jump_limit, ) } } impl From for StageElement{ fn from(value:strafesnet_common::gameplay_modes::StageElement)->Self{ + let behaviour=match value.behaviour(){ + strafesnet_common::gameplay_modes::StageElementBehaviour::SpawnAt=>0, + strafesnet_common::gameplay_modes::StageElementBehaviour::Trigger=>1, + strafesnet_common::gameplay_modes::StageElementBehaviour::Teleport=>2, + strafesnet_common::gameplay_modes::StageElementBehaviour::Platform=>3, + strafesnet_common::gameplay_modes::StageElementBehaviour::Check=>4, + strafesnet_common::gameplay_modes::StageElementBehaviour::Checkpoint=>5, + }; + let header= + behaviour + |flag(value.jump_limit().is_some(),StageElement::JUMP_LIMIT) + |flag(value.force(),StageElement::FORCE); Self{ + header, stage_id:value.stage_id().get(), - behaviour:value.behaviour().into(), jump_limit:value.jump_limit(), - force:match value.force(){true=>Some(()),false=>None}, } } } diff --git a/src/newtypes/gameplay_style.rs b/src/newtypes/gameplay_style.rs index 1983a22..f7049da 100644 --- a/src/newtypes/gameplay_style.rs +++ b/src/newtypes/gameplay_style.rs @@ -1,3 +1,4 @@ +use super::common::flag; use super::integer::{Time,Ratio64,Planar64,Planar64Vec3}; pub type Controls=u32; @@ -5,19 +6,34 @@ pub type Controls=u32; #[binrw::binrw] #[brw(little)] pub struct StyleModifiers{ + pub header:u8, pub controls_mask:Controls, pub controls_mask_state:Controls, + #[br(if(header&Self::STRAFE!=0))] pub strafe:Option, + #[br(if(header&Self::ROCKET!=0))] pub rocket:Option, + #[br(if(header&Self::JUMP!=0))] pub jump:Option, + #[br(if(header&Self::WALK!=0))] pub walk:Option, + #[br(if(header&Self::LADDER!=0))] pub ladder:Option, + #[br(if(header&Self::SWIM!=0))] pub swim:Option, pub gravity:Planar64Vec3, pub hitbox:Hitbox, pub camera_offset:Planar64Vec3, pub mass:Planar64, } +impl StyleModifiers{ + const STRAFE:u8=1<<0; + const ROCKET:u8=1<<1; + const JUMP:u8=1<<2; + const WALK:u8=1<<3; + const LADDER:u8=1<<4; + const SWIM:u8=1<<5; +} impl Into for StyleModifiers{ fn into(self)->strafesnet_common::gameplay_style::StyleModifiers{ strafesnet_common::gameplay_style::StyleModifiers{ @@ -39,7 +55,15 @@ impl Into for StyleModifiers{ } impl From for StyleModifiers{ fn from(value:strafesnet_common::gameplay_style::StyleModifiers)->Self{ + let header= + flag(value.strafe.is_some(),StyleModifiers::STRAFE) + |flag(value.rocket.is_some(),StyleModifiers::ROCKET) + |flag(value.jump.is_some(),StyleModifiers::JUMP) + |flag(value.walk.is_some(),StyleModifiers::WALK) + |flag(value.ladder.is_some(),StyleModifiers::LADDER) + |flag(value.swim.is_some(),StyleModifiers::SWIM); Self{ + header, controls_mask:value.controls_mask.bits(), controls_mask_state:value.controls_mask_state.bits(), strafe:value.strafe.map(Into::into), @@ -82,8 +106,6 @@ impl From for JumpCalculatio } } -#[binrw::binrw] -#[brw(little)] pub enum JumpImpulse{ FromTime(Time), FromHeight(Planar64), @@ -140,11 +162,16 @@ impl From for ControlsAct #[binrw::binrw] #[brw(little)] pub struct StrafeSettings{ + header:u8, enable:ControlsActivation, mv:Planar64, + #[br(if(header&Self::AIR_ACCEL_LIMIT!=0))] air_accel_limit:Option, tick_rate:Ratio64, } +impl StrafeSettings{ + const AIR_ACCEL_LIMIT:u8=1<<0; +} impl Into for StrafeSettings{ fn into(self)->strafesnet_common::gameplay_style::StrafeSettings{ strafesnet_common::gameplay_style::StrafeSettings::new( @@ -158,7 +185,9 @@ impl Into for StrafeSettings{ impl From for StrafeSettings{ fn from(value:strafesnet_common::gameplay_style::StrafeSettings)->Self{ let (enable,mv,air_accel_limit,tick_rate)=value.into_inner(); + let header=flag(air_accel_limit.is_some(),StrafeSettings::AIR_ACCEL_LIMIT); Self{ + header, enable:enable.into(), mv:mv.get(), air_accel_limit:air_accel_limit.map(|a|a.get()), @@ -190,23 +219,58 @@ impl From for PropulsionS #[binrw::binrw] #[brw(little)] pub struct JumpSettings{ - impulse:JumpImpulse, - calculation:JumpCalculation, + header:u8, + impulse:i64, +} +impl JumpSettings{ + const IMPULSE:u8=0b0011; + const CALCULATION:u8=0b1100; + const fn impulse(&self)->Option{ + match self.header&Self::IMPULSE{ + 0=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromTime(strafesnet_common::integer::Time::raw(self.impulse))), + 1=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromHeight(strafesnet_common::integer::Planar64::raw(self.impulse))), + 2=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(strafesnet_common::integer::Planar64::raw(self.impulse))), + 3=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(strafesnet_common::integer::Planar64::raw(self.impulse))), + _=>None, + } + } + const fn calculation(&self)->Option{ + match (self.header&Self::CALCULATION)>>2{ + 0=>Some(strafesnet_common::gameplay_style::JumpCalculation::Capped), + 1=>Some(strafesnet_common::gameplay_style::JumpCalculation::Energy), + 2=>Some(strafesnet_common::gameplay_style::JumpCalculation::Linear), + _=>None, + } + } } impl Into for JumpSettings{ fn into(self)->strafesnet_common::gameplay_style::JumpSettings{ strafesnet_common::gameplay_style::JumpSettings::new( - self.impulse.into(), - self.calculation.into(), + self.impulse().unwrap(), + self.calculation().unwrap(), ) } } impl From for JumpSettings{ fn from(value:strafesnet_common::gameplay_style::JumpSettings)->Self{ - let (impulse,calculation)=value.into_inner(); + let (impulse_enum,calculation)=value.into_inner(); + let (impulse,impulse_header)=match impulse_enum{ + strafesnet_common::gameplay_style::JumpImpulse::FromTime(impulse)=>(impulse.get(),0), + strafesnet_common::gameplay_style::JumpImpulse::FromHeight(impulse)=>(impulse.get(),1), + strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(impulse)=>(impulse.get(),2), + strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(impulse)=>(impulse.get(),3), + }; + let calculation_header=match calculation{ + strafesnet_common::gameplay_style::JumpCalculation::Capped=>0, + strafesnet_common::gameplay_style::JumpCalculation::Energy=>1, + strafesnet_common::gameplay_style::JumpCalculation::Linear=>2, + }; + let header= + impulse_header + |(calculation_header<<2); Self{ - impulse:impulse.into(), - calculation:calculation.into(), + header, + impulse, } } } diff --git a/src/newtypes/model.rs b/src/newtypes/model.rs index 4d42aa9..6b874d0 100644 --- a/src/newtypes/model.rs +++ b/src/newtypes/model.rs @@ -1,3 +1,4 @@ +use super::common::flag; use strafesnet_common::model::PolygonIter; use super::integer::{Planar64Vec3,Planar64Affine3}; @@ -60,8 +61,13 @@ impl From for PolygonGroup{ #[binrw::binrw] #[brw(little)] pub struct RenderConfig{ + pub header:u8, + #[br(if(header&Self::TEXTURE!=0))] pub texture:Option, } +impl RenderConfig{ + const TEXTURE:u8=1<<0; +} impl Into for RenderConfig{ fn into(self)->strafesnet_common::model::RenderConfig{ strafesnet_common::model::RenderConfig{ @@ -71,7 +77,9 @@ impl Into for RenderConfig{ } impl From for RenderConfig{ fn from(value:strafesnet_common::model::RenderConfig)->Self{ + let header=flag(value.texture.is_some(),RenderConfig::TEXTURE); Self{ + header, texture:value.texture.map(|texture_id|texture_id.get()), } } From e3130661f47d5588e639898f89c5791139d177a0 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 29 Jul 2024 16:38:32 -0700 Subject: [PATCH 42/55] v0.1.0 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 454ea1f..5385d29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,9 +93,9 @@ dependencies = [ [[package]] name = "strafesnet_common" -version = "0.1.3" +version = "0.2.0" source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" -checksum = "10a7e3b69506893bbdde90ce8a9d75cd56d280c0424d2dfdf98f8520179d0c1b" +checksum = "74580c59a09194ce39db49cd814a5c2fc2d61513c88c6b811b5b40c0da6de057" dependencies = [ "bitflags", "glam", diff --git a/Cargo.toml b/Cargo.toml index 846ca41..6ff42e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] binrw = "0.14.0" id = { version = "0.1.0", registry = "strafesnet" } -strafesnet_common = { version = "0.1.3", registry = "strafesnet" } +strafesnet_common = { version = "0.2.0", registry = "strafesnet" } From 05c8db47507d3a2840b76d88f650673c34eb1132 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 29 Jul 2024 18:20:44 -0700 Subject: [PATCH 43/55] don't panic --- src/map.rs | 3 +- src/newtypes/gameplay_modes.rs | 47 +++++++++++----- src/newtypes/gameplay_style.rs | 97 ++++++++++++++++++++++++---------- src/newtypes/integer.rs | 18 +++++-- 4 files changed, 121 insertions(+), 44 deletions(-) diff --git a/src/map.rs b/src/map.rs index 55313f9..1eed566 100644 --- a/src/map.rs +++ b/src/map.rs @@ -12,6 +12,7 @@ use strafesnet_common::gameplay_modes; #[derive(Debug)] pub enum Error{ InvalidHeader(binrw::Error), + InvalidMode(newtypes::gameplay_modes::ModeError), InvalidBlockId(BlockId), InvalidMeshId(model::MeshId), InvalidModelId(model::ModelId), @@ -214,7 +215,7 @@ impl StreamableMap{ pub(crate) fn new(mut file:crate::file::File)->Result{ //assume the file seek is in the right place to start reading a map header let header:MapHeader=file.as_mut().read_le().map_err(Error::InvalidHeader)?; - let modes=header.modes.into_iter().map(Into::into).collect(); + let modes=header.modes.into_iter().map(TryInto::try_into).collect::>().map_err(Error::InvalidMode)?; let attributes=header.attributes.into_iter().map(Into::into).collect(); let render_configs=header.render_configs.into_iter().map(Into::into).collect(); let bvh=header.spacial_blocks.into_iter().map(|spacial_block| diff --git a/src/newtypes/gameplay_modes.rs b/src/newtypes/gameplay_modes.rs index b789427..bda60af 100644 --- a/src/newtypes/gameplay_modes.rs +++ b/src/newtypes/gameplay_modes.rs @@ -27,14 +27,25 @@ impl StageElement{ self.header&Self::FORCE!=0 } } -impl Into for StageElement{ - fn into(self)->strafesnet_common::gameplay_modes::StageElement{ - strafesnet_common::gameplay_modes::StageElement::new( +#[derive(Debug)] +pub enum StageElementError{ + InvalidBehaviour, +} +impl std::fmt::Display for StageElementError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for StageElementError{} +impl TryInto for StageElement{ + type Error=StageElementError; + fn try_into(self)->Result{ + Ok(strafesnet_common::gameplay_modes::StageElement::new( strafesnet_common::gameplay_modes::StageId::new(self.stage_id), self.force(), - self.behaviour().unwrap(), + self.behaviour().ok_or(StageElementError::InvalidBehaviour)?, self.jump_limit, - ) + )) } } impl From for StageElement{ @@ -154,19 +165,31 @@ pub struct Mode{ #[br(count=header.elements)] pub elements:Vec<(u32,StageElement)>, } -impl Into for Mode{ - fn into(self)->strafesnet_common::gameplay_modes::Mode{ - strafesnet_common::gameplay_modes::Mode::new( - self.style.into(), +#[derive(Debug)] +pub enum ModeError{ + StyleModifier(super::gameplay_style::StyleModifierError), + StageElement(StageElementError), +} +impl std::fmt::Display for ModeError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for ModeError{} +impl TryInto for Mode{ + type Error=ModeError; + fn try_into(self)->Result{ + Ok(strafesnet_common::gameplay_modes::Mode::new( + self.style.try_into().map_err(ModeError::StyleModifier)?, strafesnet_common::model::ModelId::new(self.start), self.zones.into_iter().map(|(model_id,zone)| (strafesnet_common::model::ModelId::new(model_id),zone.into()) ).collect(), self.stages.into_iter().map(Into::into).collect(), self.elements.into_iter().map(|(model_id,stage_element)| - (strafesnet_common::model::ModelId::new(model_id),stage_element.into()) - ).collect(), - ) + Ok((strafesnet_common::model::ModelId::new(model_id),stage_element.try_into()?)) + ).collect::>().map_err(ModeError::StageElement)?, + )) } } impl From for Mode{ diff --git a/src/newtypes/gameplay_style.rs b/src/newtypes/gameplay_style.rs index f7049da..bb7cecb 100644 --- a/src/newtypes/gameplay_style.rs +++ b/src/newtypes/gameplay_style.rs @@ -2,6 +2,16 @@ use super::common::flag; use super::integer::{Time,Ratio64,Planar64,Planar64Vec3}; pub type Controls=u32; +#[derive(Debug)] +pub enum ControlsError{ + UnknownBits, +} +impl std::fmt::Display for ControlsError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for ControlsError{} #[binrw::binrw] #[brw(little)] @@ -34,15 +44,27 @@ impl StyleModifiers{ const LADDER:u8=1<<4; const SWIM:u8=1<<5; } -impl Into for StyleModifiers{ - fn into(self)->strafesnet_common::gameplay_style::StyleModifiers{ - strafesnet_common::gameplay_style::StyleModifiers{ - //TODO: fail gracefully in binrw instead of panicing here - controls_mask:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).unwrap(), - controls_mask_state:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask_state).unwrap(), - strafe:self.strafe.map(Into::into), +#[derive(Debug)] +pub enum StyleModifierError{ + Controls(ControlsError), + JumpSettings(JumpSettingsError), + StrafeSettings(StrafeSettingsError), +} +impl std::fmt::Display for StyleModifierError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for StyleModifierError{} +impl TryInto for StyleModifiers{ + type Error=StyleModifierError; + fn try_into(self)->Result{ + Ok(strafesnet_common::gameplay_style::StyleModifiers{ + controls_mask:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).ok_or(StyleModifierError::Controls(ControlsError::UnknownBits))?, + controls_mask_state:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask_state).ok_or(StyleModifierError::Controls(ControlsError::UnknownBits))?, + strafe:self.strafe.map(TryInto::try_into).transpose().map_err(StyleModifierError::StrafeSettings)?, rocket:self.rocket.map(Into::into), - jump:self.jump.map(Into::into), + jump:self.jump.map(TryInto::try_into).transpose().map_err(StyleModifierError::JumpSettings)?, walk:self.walk.map(Into::into), ladder:self.ladder.map(Into::into), swim:self.swim.map(Into::into), @@ -50,7 +72,7 @@ impl Into for StyleModifiers{ hitbox:self.hitbox.into(), camera_offset:strafesnet_common::integer::Planar64Vec3::raw_array(self.camera_offset), mass:strafesnet_common::integer::Planar64::raw(self.mass), - } + }) } } impl From for StyleModifiers{ @@ -140,13 +162,14 @@ pub struct ControlsActivation{ controls_intersects:Controls, controls_contains:Controls, } -impl Into for ControlsActivation{ - fn into(self)->strafesnet_common::gameplay_style::ControlsActivation{ - strafesnet_common::gameplay_style::ControlsActivation::new( - strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).unwrap(), - strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_intersects).unwrap(), - strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_contains).unwrap(), - ) +impl TryInto for ControlsActivation{ + type Error=ControlsError; + fn try_into(self)->Result{ + Ok(strafesnet_common::gameplay_style::ControlsActivation::new( + strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).ok_or(ControlsError::UnknownBits)?, + strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_intersects).ok_or(ControlsError::UnknownBits)?, + strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_contains).ok_or(ControlsError::UnknownBits)?, + )) } } impl From for ControlsActivation{ @@ -172,14 +195,26 @@ pub struct StrafeSettings{ impl StrafeSettings{ const AIR_ACCEL_LIMIT:u8=1<<0; } -impl Into for StrafeSettings{ - fn into(self)->strafesnet_common::gameplay_style::StrafeSettings{ - strafesnet_common::gameplay_style::StrafeSettings::new( - self.enable.into(), +#[derive(Debug)] +pub enum StrafeSettingsError{ + Ratio(super::integer::RatioError), + Controls(ControlsError), +} +impl std::fmt::Display for StrafeSettingsError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for StrafeSettingsError{} +impl TryInto for StrafeSettings{ + type Error=StrafeSettingsError; + fn try_into(self)->Result{ + Ok(strafesnet_common::gameplay_style::StrafeSettings::new( + self.enable.try_into().map_err(StrafeSettingsError::Controls)?, strafesnet_common::integer::Planar64::raw(self.mv), self.air_accel_limit.map(strafesnet_common::integer::Planar64::raw), - self.tick_rate.into(), - ) + self.tick_rate.try_into().map_err(StrafeSettingsError::Ratio)?, + )) } } impl From for StrafeSettings{ @@ -243,12 +278,18 @@ impl JumpSettings{ } } } -impl Into for JumpSettings{ - fn into(self)->strafesnet_common::gameplay_style::JumpSettings{ - strafesnet_common::gameplay_style::JumpSettings::new( - self.impulse().unwrap(), - self.calculation().unwrap(), - ) +#[derive(Debug)] +pub enum JumpSettingsError{ + InvalidImpulseDiscriminant, + InvalidCalculationDiscriminant, +} +impl TryInto for JumpSettings{ + type Error=JumpSettingsError; + fn try_into(self)->Result{ + Ok(strafesnet_common::gameplay_style::JumpSettings::new( + self.impulse().ok_or(JumpSettingsError::InvalidImpulseDiscriminant)?, + self.calculation().ok_or(JumpSettingsError::InvalidCalculationDiscriminant)?, + )) } } impl From for JumpSettings{ diff --git a/src/newtypes/integer.rs b/src/newtypes/integer.rs index f75ba70..0eb7711 100644 --- a/src/newtypes/integer.rs +++ b/src/newtypes/integer.rs @@ -6,9 +6,21 @@ pub struct Ratio64{ num:i64, den:u64, } -impl Into for Ratio64{ - fn into(self)->strafesnet_common::integer::Ratio64{ - strafesnet_common::integer::Ratio64::new(self.num,self.den).unwrap() +#[derive(Debug)] +pub enum RatioError{ + ZeroDenominator, +} +impl std::fmt::Display for RatioError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for RatioError{} +impl TryInto for Ratio64{ + type Error=RatioError; + fn try_into(self)->Result{ + strafesnet_common::integer::Ratio64::new(self.num,self.den) + .ok_or(RatioError::ZeroDenominator) } } impl From for Ratio64{ From d036a335015ddb6beef01f2bb1ba2712358508c0 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 29 Jul 2024 18:22:26 -0700 Subject: [PATCH 44/55] v0.1.1 no panic --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5385d29..ea559a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,7 +104,7 @@ dependencies = [ [[package]] name = "strafesnet_snf" -version = "0.1.0" +version = "0.1.1" dependencies = [ "binrw", "id", diff --git a/Cargo.toml b/Cargo.toml index 6ff42e3..9b20fd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "strafesnet_snf" -version = "0.1.0" +version = "0.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 4b2de6f88cd2dd1f41864d72a8f1a79081ac65a5 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 6 Aug 2024 12:58:44 -0700 Subject: [PATCH 45/55] update deps --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea559a3..fa91cd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,9 +40,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "either" @@ -93,9 +93,9 @@ dependencies = [ [[package]] name = "strafesnet_common" -version = "0.2.0" +version = "0.2.3" source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" -checksum = "74580c59a09194ce39db49cd814a5c2fc2d61513c88c6b811b5b40c0da6de057" +checksum = "e6155b62ce5d118d1aab0d90d6d6981bca1e046c4ca86829bc93215e8b3bb929" dependencies = [ "bitflags", "glam", From 617cae300f798bd3afd7be3c9d26c1d51e87baec Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 6 Aug 2024 13:02:56 -0700 Subject: [PATCH 46/55] name some ids --- src/newtypes/gameplay_modes.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/newtypes/gameplay_modes.rs b/src/newtypes/gameplay_modes.rs index bda60af..4363208 100644 --- a/src/newtypes/gameplay_modes.rs +++ b/src/newtypes/gameplay_modes.rs @@ -1,10 +1,13 @@ use super::common::flag; +pub type ModeId=u32; +pub type StageId=u32; + #[binrw::binrw] #[brw(little)] pub struct StageElement{ pub header:u8, - pub stage_id:u32, + pub stage_id:StageId, #[br(if(header&Self::JUMP_LIMIT!=0))] pub jump_limit:Option, } From 3255b687e5143a64c3477ba65490047621499553 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 7 Aug 2024 18:11:24 -0700 Subject: [PATCH 47/55] refactor JumpCalculation --- src/newtypes/gameplay_attributes.rs | 17 +++ src/newtypes/gameplay_style.rs | 188 ++++++++++++++-------------- 2 files changed, 112 insertions(+), 93 deletions(-) diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs index 0dd3501..192aee8 100644 --- a/src/newtypes/gameplay_attributes.rs +++ b/src/newtypes/gameplay_attributes.rs @@ -125,6 +125,11 @@ pub enum Booster{ Velocity(Planar64Vec3), #[brw(magic=1u8)] Energy{direction:Planar64Vec3,energy:Planar64}, + #[brw(magic=2u8)] + AirTime(Time), + #[brw(magic=3u8)] + Height(Planar64), + } impl Into for Booster{ fn into(self)->strafesnet_common::gameplay_attributes::Booster{ @@ -138,6 +143,14 @@ impl Into for Booster{ direction:strafesnet_common::integer::Planar64Vec3::raw_array(direction), energy:strafesnet_common::integer::Planar64::raw(energy) }, + Booster::AirTime(time)=> + strafesnet_common::gameplay_attributes::Booster::AirTime( + strafesnet_common::integer::Time::raw(time) + ), + Booster::Height(height)=> + strafesnet_common::gameplay_attributes::Booster::Height( + strafesnet_common::integer::Planar64::raw(height) + ), } } } @@ -151,6 +164,10 @@ impl From for Booster{ direction:direction.get().to_array(), energy:energy.get(), }, + strafesnet_common::gameplay_attributes::Booster::AirTime(time)=> + Booster::AirTime(time.get()), + strafesnet_common::gameplay_attributes::Booster::Height(height)=> + Booster::Height(height.get()), } } } diff --git a/src/newtypes/gameplay_style.rs b/src/newtypes/gameplay_style.rs index bb7cecb..64d98b9 100644 --- a/src/newtypes/gameplay_style.rs +++ b/src/newtypes/gameplay_style.rs @@ -105,52 +105,52 @@ impl From for StyleModifiers{ #[binrw::binrw] #[brw(little,repr=u8)] pub enum JumpCalculation{ - Capped, - Energy, - Linear, + Max, + BoostThenJump, + JumpThenBoost, } impl Into for JumpCalculation{ fn into(self)->strafesnet_common::gameplay_style::JumpCalculation{ match self{ - JumpCalculation::Capped=>strafesnet_common::gameplay_style::JumpCalculation::Capped, - JumpCalculation::Energy=>strafesnet_common::gameplay_style::JumpCalculation::Energy, - JumpCalculation::Linear=>strafesnet_common::gameplay_style::JumpCalculation::Linear, + JumpCalculation::Max=>strafesnet_common::gameplay_style::JumpCalculation::Max, + JumpCalculation::BoostThenJump=>strafesnet_common::gameplay_style::JumpCalculation::BoostThenJump, + JumpCalculation::JumpThenBoost=>strafesnet_common::gameplay_style::JumpCalculation::JumpThenBoost, } } } impl From for JumpCalculation{ fn from(value:strafesnet_common::gameplay_style::JumpCalculation)->Self{ match value{ - strafesnet_common::gameplay_style::JumpCalculation::Capped=>JumpCalculation::Capped, - strafesnet_common::gameplay_style::JumpCalculation::Energy=>JumpCalculation::Energy, - strafesnet_common::gameplay_style::JumpCalculation::Linear=>JumpCalculation::Linear, + strafesnet_common::gameplay_style::JumpCalculation::Max=>JumpCalculation::Max, + strafesnet_common::gameplay_style::JumpCalculation::BoostThenJump=>JumpCalculation::BoostThenJump, + strafesnet_common::gameplay_style::JumpCalculation::JumpThenBoost=>JumpCalculation::JumpThenBoost, } } } pub enum JumpImpulse{ - FromTime(Time), - FromHeight(Planar64), - FromDeltaV(Planar64), - FromEnergy(Planar64), + Time(Time), + Height(Planar64), + Linear(Planar64), + Energy(Planar64), } impl Into for JumpImpulse{ fn into(self)->strafesnet_common::gameplay_style::JumpImpulse{ match self{ - JumpImpulse::FromTime(time)=>strafesnet_common::gameplay_style::JumpImpulse::FromTime(strafesnet_common::integer::Time::raw(time)), - JumpImpulse::FromHeight(height)=>strafesnet_common::gameplay_style::JumpImpulse::FromHeight(strafesnet_common::integer::Planar64::raw(height)), - JumpImpulse::FromDeltaV(deltav)=>strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(strafesnet_common::integer::Planar64::raw(deltav)), - JumpImpulse::FromEnergy(energy)=>strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(strafesnet_common::integer::Planar64::raw(energy)), + JumpImpulse::Time(time)=>strafesnet_common::gameplay_style::JumpImpulse::Time(strafesnet_common::integer::Time::raw(time)), + JumpImpulse::Height(height)=>strafesnet_common::gameplay_style::JumpImpulse::Height(strafesnet_common::integer::Planar64::raw(height)), + JumpImpulse::Linear(deltav)=>strafesnet_common::gameplay_style::JumpImpulse::Linear(strafesnet_common::integer::Planar64::raw(deltav)), + JumpImpulse::Energy(energy)=>strafesnet_common::gameplay_style::JumpImpulse::Energy(strafesnet_common::integer::Planar64::raw(energy)), } } } impl From for JumpImpulse{ fn from(value:strafesnet_common::gameplay_style::JumpImpulse)->Self{ match value{ - strafesnet_common::gameplay_style::JumpImpulse::FromTime(time)=>JumpImpulse::FromTime(time.get()), - strafesnet_common::gameplay_style::JumpImpulse::FromHeight(height)=>JumpImpulse::FromHeight(height.get()), - strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(deltav)=>JumpImpulse::FromDeltaV(deltav.get()), - strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(energy)=>JumpImpulse::FromEnergy(energy.get()), + strafesnet_common::gameplay_style::JumpImpulse::Time(time)=>JumpImpulse::Time(time.get()), + strafesnet_common::gameplay_style::JumpImpulse::Height(height)=>JumpImpulse::Height(height.get()), + strafesnet_common::gameplay_style::JumpImpulse::Linear(deltav)=>JumpImpulse::Linear(deltav.get()), + strafesnet_common::gameplay_style::JumpImpulse::Energy(energy)=>JumpImpulse::Energy(energy.get()), } } } @@ -165,19 +165,19 @@ pub struct ControlsActivation{ impl TryInto for ControlsActivation{ type Error=ControlsError; fn try_into(self)->Result{ - Ok(strafesnet_common::gameplay_style::ControlsActivation::new( - strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).ok_or(ControlsError::UnknownBits)?, - strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_intersects).ok_or(ControlsError::UnknownBits)?, - strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_contains).ok_or(ControlsError::UnknownBits)?, - )) + Ok(strafesnet_common::gameplay_style::ControlsActivation{ + controls_mask:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_mask).ok_or(ControlsError::UnknownBits)?, + controls_intersects:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_intersects).ok_or(ControlsError::UnknownBits)?, + controls_contains:strafesnet_common::controls_bitflag::Controls::from_bits(self.controls_contains).ok_or(ControlsError::UnknownBits)?, + }) } } impl From for ControlsActivation{ fn from(value:strafesnet_common::gameplay_style::ControlsActivation)->Self{ Self{ - controls_mask:value.controls_mask().bits(), - controls_intersects:value.controls_intersects().bits(), - controls_contains:value.controls_contains().bits(), + controls_mask:value.controls_mask.bits(), + controls_intersects:value.controls_intersects.bits(), + controls_contains:value.controls_contains.bits(), } } } @@ -209,24 +209,23 @@ impl std::error::Error for StrafeSettingsError{} impl TryInto for StrafeSettings{ type Error=StrafeSettingsError; fn try_into(self)->Result{ - Ok(strafesnet_common::gameplay_style::StrafeSettings::new( - self.enable.try_into().map_err(StrafeSettingsError::Controls)?, - strafesnet_common::integer::Planar64::raw(self.mv), - self.air_accel_limit.map(strafesnet_common::integer::Planar64::raw), - self.tick_rate.try_into().map_err(StrafeSettingsError::Ratio)?, - )) + Ok(strafesnet_common::gameplay_style::StrafeSettings{ + enable:self.enable.try_into().map_err(StrafeSettingsError::Controls)?, + mv:strafesnet_common::integer::Planar64::raw(self.mv), + air_accel_limit:self.air_accel_limit.map(strafesnet_common::integer::Planar64::raw), + tick_rate:self.tick_rate.try_into().map_err(StrafeSettingsError::Ratio)?, + }) } } impl From for StrafeSettings{ fn from(value:strafesnet_common::gameplay_style::StrafeSettings)->Self{ - let (enable,mv,air_accel_limit,tick_rate)=value.into_inner(); - let header=flag(air_accel_limit.is_some(),StrafeSettings::AIR_ACCEL_LIMIT); + let header=flag(value.air_accel_limit.is_some(),StrafeSettings::AIR_ACCEL_LIMIT); Self{ header, - enable:enable.into(), - mv:mv.get(), - air_accel_limit:air_accel_limit.map(|a|a.get()), - tick_rate:tick_rate.into(), + enable:value.enable.into(), + mv:value.mv.get(), + air_accel_limit:value.air_accel_limit.map(|a|a.get()), + tick_rate:value.tick_rate.into(), } } } @@ -238,15 +237,15 @@ pub struct PropulsionSettings{ } impl Into for PropulsionSettings{ fn into(self)->strafesnet_common::gameplay_style::PropulsionSettings{ - strafesnet_common::gameplay_style::PropulsionSettings::new( - strafesnet_common::integer::Planar64::raw(self.magnitude) - ) + strafesnet_common::gameplay_style::PropulsionSettings{ + magnitude:strafesnet_common::integer::Planar64::raw(self.magnitude) + } } } impl From for PropulsionSettings{ fn from(value:strafesnet_common::gameplay_style::PropulsionSettings)->Self{ Self{ - magnitude:value.magnitude().get(), + magnitude:value.magnitude.get(), } } } @@ -258,25 +257,29 @@ pub struct JumpSettings{ impulse:i64, } impl JumpSettings{ - const IMPULSE:u8=0b0011; - const CALCULATION:u8=0b1100; + const IMPULSE:u8=0b00011; + const CALCULATION:u8=0b01100; + const LIMIT_MINIMUM:u8=0b10000; const fn impulse(&self)->Option{ match self.header&Self::IMPULSE{ - 0=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromTime(strafesnet_common::integer::Time::raw(self.impulse))), - 1=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromHeight(strafesnet_common::integer::Planar64::raw(self.impulse))), - 2=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(strafesnet_common::integer::Planar64::raw(self.impulse))), - 3=>Some(strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(strafesnet_common::integer::Planar64::raw(self.impulse))), + 0=>Some(strafesnet_common::gameplay_style::JumpImpulse::Time(strafesnet_common::integer::Time::raw(self.impulse))), + 1=>Some(strafesnet_common::gameplay_style::JumpImpulse::Height(strafesnet_common::integer::Planar64::raw(self.impulse))), + 2=>Some(strafesnet_common::gameplay_style::JumpImpulse::Linear(strafesnet_common::integer::Planar64::raw(self.impulse))), + 3=>Some(strafesnet_common::gameplay_style::JumpImpulse::Energy(strafesnet_common::integer::Planar64::raw(self.impulse))), _=>None, } } const fn calculation(&self)->Option{ match (self.header&Self::CALCULATION)>>2{ - 0=>Some(strafesnet_common::gameplay_style::JumpCalculation::Capped), - 1=>Some(strafesnet_common::gameplay_style::JumpCalculation::Energy), - 2=>Some(strafesnet_common::gameplay_style::JumpCalculation::Linear), + 0=>Some(strafesnet_common::gameplay_style::JumpCalculation::Max), + 1=>Some(strafesnet_common::gameplay_style::JumpCalculation::JumpThenBoost), + 2=>Some(strafesnet_common::gameplay_style::JumpCalculation::BoostThenJump), _=>None, } } + const fn limit_minimum(&self)->bool{ + self.header&Self::LIMIT_MINIMUM!=0 + } } #[derive(Debug)] pub enum JumpSettingsError{ @@ -286,29 +289,30 @@ pub enum JumpSettingsError{ impl TryInto for JumpSettings{ type Error=JumpSettingsError; fn try_into(self)->Result{ - Ok(strafesnet_common::gameplay_style::JumpSettings::new( - self.impulse().ok_or(JumpSettingsError::InvalidImpulseDiscriminant)?, - self.calculation().ok_or(JumpSettingsError::InvalidCalculationDiscriminant)?, - )) + Ok(strafesnet_common::gameplay_style::JumpSettings{ + impulse:self.impulse().ok_or(JumpSettingsError::InvalidImpulseDiscriminant)?, + calculation:self.calculation().ok_or(JumpSettingsError::InvalidCalculationDiscriminant)?, + limit_minimum:self.limit_minimum(), + }) } } impl From for JumpSettings{ fn from(value:strafesnet_common::gameplay_style::JumpSettings)->Self{ - let (impulse_enum,calculation)=value.into_inner(); - let (impulse,impulse_header)=match impulse_enum{ - strafesnet_common::gameplay_style::JumpImpulse::FromTime(impulse)=>(impulse.get(),0), - strafesnet_common::gameplay_style::JumpImpulse::FromHeight(impulse)=>(impulse.get(),1), - strafesnet_common::gameplay_style::JumpImpulse::FromDeltaV(impulse)=>(impulse.get(),2), - strafesnet_common::gameplay_style::JumpImpulse::FromEnergy(impulse)=>(impulse.get(),3), + let (impulse,impulse_header)=match value.impulse{ + strafesnet_common::gameplay_style::JumpImpulse::Time(impulse)=>(impulse.get(),0), + strafesnet_common::gameplay_style::JumpImpulse::Height(impulse)=>(impulse.get(),1), + strafesnet_common::gameplay_style::JumpImpulse::Linear(impulse)=>(impulse.get(),2), + strafesnet_common::gameplay_style::JumpImpulse::Energy(impulse)=>(impulse.get(),3), }; - let calculation_header=match calculation{ - strafesnet_common::gameplay_style::JumpCalculation::Capped=>0, - strafesnet_common::gameplay_style::JumpCalculation::Energy=>1, - strafesnet_common::gameplay_style::JumpCalculation::Linear=>2, + let calculation_header=match value.calculation{ + strafesnet_common::gameplay_style::JumpCalculation::Max=>0, + strafesnet_common::gameplay_style::JumpCalculation::JumpThenBoost=>1, + strafesnet_common::gameplay_style::JumpCalculation::BoostThenJump=>2, }; let header= impulse_header - |(calculation_header<<2); + |(calculation_header<<2) + |((value.limit_minimum as u8)<<4); Self{ header, impulse, @@ -324,17 +328,17 @@ pub struct AccelerateSettings{ } impl Into for AccelerateSettings{ fn into(self)->strafesnet_common::gameplay_style::AccelerateSettings{ - strafesnet_common::gameplay_style::AccelerateSettings::new( - strafesnet_common::integer::Planar64::raw(self.accel), - strafesnet_common::integer::Planar64::raw(self.topspeed), - ) + strafesnet_common::gameplay_style::AccelerateSettings{ + accel:strafesnet_common::integer::Planar64::raw(self.accel), + topspeed:strafesnet_common::integer::Planar64::raw(self.topspeed), + } } } impl From for AccelerateSettings{ fn from(value:strafesnet_common::gameplay_style::AccelerateSettings)->Self{ Self{ - accel:value.accel().get(), - topspeed:value.topspeed().get(), + accel:value.accel.get(), + topspeed:value.topspeed.get(), } } } @@ -349,22 +353,21 @@ pub struct WalkSettings{ } impl Into for WalkSettings{ fn into(self)->strafesnet_common::gameplay_style::WalkSettings{ - strafesnet_common::gameplay_style::WalkSettings::new( - self.accelerate.into(), - strafesnet_common::integer::Planar64::raw(self.static_friction), - strafesnet_common::integer::Planar64::raw(self.kinetic_friction), - strafesnet_common::integer::Planar64::raw(self.surf_dot), - ) + strafesnet_common::gameplay_style::WalkSettings{ + accelerate:self.accelerate.into(), + static_friction:strafesnet_common::integer::Planar64::raw(self.static_friction), + kinetic_friction:strafesnet_common::integer::Planar64::raw(self.kinetic_friction), + surf_dot:strafesnet_common::integer::Planar64::raw(self.surf_dot), + } } } impl From for WalkSettings{ fn from(value:strafesnet_common::gameplay_style::WalkSettings)->Self{ - let (accelerate,static_friction,kinetic_friction,surf_dot)=value.into_inner(); Self{ - accelerate:accelerate.into(), - static_friction:static_friction.get(), - kinetic_friction:kinetic_friction.get(), - surf_dot:surf_dot.get(), + accelerate:value.accelerate.into(), + static_friction:value.static_friction.get(), + kinetic_friction:value.kinetic_friction.get(), + surf_dot:value.surf_dot.get(), } } } @@ -377,18 +380,17 @@ pub struct LadderSettings{ } impl Into for LadderSettings{ fn into(self)->strafesnet_common::gameplay_style::LadderSettings{ - strafesnet_common::gameplay_style::LadderSettings::new( - self.accelerate.into(), - strafesnet_common::integer::Planar64::raw(self.dot), - ) + strafesnet_common::gameplay_style::LadderSettings{ + accelerate:self.accelerate.into(), + dot:strafesnet_common::integer::Planar64::raw(self.dot), + } } } impl From for LadderSettings{ fn from(value:strafesnet_common::gameplay_style::LadderSettings)->Self{ - let (accelerate,dot)=value.into_inner(); Self{ - accelerate:accelerate.into(), - dot:dot.get(), + accelerate:value.accelerate.into(), + dot:value.dot.get(), } } } From a31bb6c09534a46dae461033a2369c0780d0df5b Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 7 Aug 2024 18:15:17 -0700 Subject: [PATCH 48/55] v0.1.2 update common --- Cargo.lock | 13 ++++++++++--- Cargo.toml | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa91cd2..007417e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "binrw" version = "0.14.0" @@ -93,10 +99,11 @@ dependencies = [ [[package]] name = "strafesnet_common" -version = "0.2.3" +version = "0.3.0" source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" -checksum = "e6155b62ce5d118d1aab0d90d6d6981bca1e046c4ca86829bc93215e8b3bb929" +checksum = "1077d45a0b064964906a57de765a5a2bfe47b41f2f807d13b18c70765e76d3dd" dependencies = [ + "arrayvec", "bitflags", "glam", "id", @@ -104,7 +111,7 @@ dependencies = [ [[package]] name = "strafesnet_snf" -version = "0.1.1" +version = "0.1.2" dependencies = [ "binrw", "id", diff --git a/Cargo.toml b/Cargo.toml index 9b20fd0..a4a574a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "strafesnet_snf" -version = "0.1.1" +version = "0.1.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -8,4 +8,4 @@ edition = "2021" [dependencies] binrw = "0.14.0" id = { version = "0.1.0", registry = "strafesnet" } -strafesnet_common = { version = "0.2.0", registry = "strafesnet" } +strafesnet_common = { version = "0.3.0", registry = "strafesnet" } From 6a198ad74609ee460e3f6954a8a4c90fcd8cddbb Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 9 Aug 2024 14:13:10 -0700 Subject: [PATCH 49/55] update common --- Cargo.lock | 4 +- Cargo.toml | 2 +- src/newtypes/gameplay_attributes.rs | 72 ++++++++++++++++++++++------- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 007417e..52cc6b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "strafesnet_common" -version = "0.3.0" +version = "0.4.0" source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" -checksum = "1077d45a0b064964906a57de765a5a2bfe47b41f2f807d13b18c70765e76d3dd" +checksum = "ea4126f6fbf9aecf89c9e319290f0221d177dcaa8659b4b9e3d82acc37829f12" dependencies = [ "arrayvec", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index a4a574a..d0b75ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] binrw = "0.14.0" id = { version = "0.1.0", registry = "strafesnet" } -strafesnet_common = { version = "0.3.0", registry = "strafesnet" } +strafesnet_common = { version = "0.4.0", registry = "strafesnet" } diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs index 192aee8..a0082cd 100644 --- a/src/newtypes/gameplay_attributes.rs +++ b/src/newtypes/gameplay_attributes.rs @@ -409,31 +409,71 @@ impl From for In } } +#[binrw::binrw] +#[brw(little)] +pub struct ContactAttributes{ + contacting:ContactingAttributes, + general:GeneralAttributes, +} +impl Into for ContactAttributes{ + fn into(self)->strafesnet_common::gameplay_attributes::ContactAttributes{ + strafesnet_common::gameplay_attributes::ContactAttributes{ + contacting:self.contacting.into(), + general:self.general.into(), + } + } +} +impl From for ContactAttributes{ + fn from(value:strafesnet_common::gameplay_attributes::ContactAttributes)->Self{ + Self{ + contacting:value.contacting.into(), + general:value.general.into(), + } + } +} + +#[binrw::binrw] +#[brw(little)] +pub struct IntersectAttributes{ + intersecting:IntersectingAttributes, + general:GeneralAttributes, +} +impl Into for IntersectAttributes{ + fn into(self)->strafesnet_common::gameplay_attributes::IntersectAttributes{ + strafesnet_common::gameplay_attributes::IntersectAttributes{ + intersecting:self.intersecting.into(), + general:self.general.into(), + } + } +} +impl From for IntersectAttributes{ + fn from(value:strafesnet_common::gameplay_attributes::IntersectAttributes)->Self{ + Self{ + intersecting:value.intersecting.into(), + general:value.general.into(), + } + } +} + #[binrw::binrw] #[brw(little)] pub enum CollisionAttributes{ #[brw(magic=0u8)] Decoration, #[brw(magic=1u8)] - Contact{ - contacting:ContactingAttributes, - general:GeneralAttributes, - }, + Contact(ContactAttributes), #[brw(magic=2u8)] - Intersect{ - intersecting:IntersectingAttributes, - general:GeneralAttributes, - }, + Intersect(IntersectAttributes), } impl Into for CollisionAttributes{ fn into(self)->strafesnet_common::gameplay_attributes::CollisionAttributes{ match self{ CollisionAttributes::Decoration=> strafesnet_common::gameplay_attributes::CollisionAttributes::Decoration, - CollisionAttributes::Contact{contacting,general}=> - strafesnet_common::gameplay_attributes::CollisionAttributes::Contact{contacting:contacting.into(),general:general.into()}, - CollisionAttributes::Intersect{intersecting,general}=> - strafesnet_common::gameplay_attributes::CollisionAttributes::Intersect{intersecting:intersecting.into(),general:general.into()}, + CollisionAttributes::Contact(attr)=> + strafesnet_common::gameplay_attributes::CollisionAttributes::Contact(attr.into()), + CollisionAttributes::Intersect(attr)=> + strafesnet_common::gameplay_attributes::CollisionAttributes::Intersect(attr.into()), } } } @@ -442,10 +482,10 @@ impl From for Colli match value{ strafesnet_common::gameplay_attributes::CollisionAttributes::Decoration=> CollisionAttributes::Decoration, - strafesnet_common::gameplay_attributes::CollisionAttributes::Contact{contacting,general}=> - CollisionAttributes::Contact{contacting:contacting.into(),general:general.into()}, - strafesnet_common::gameplay_attributes::CollisionAttributes::Intersect{intersecting,general}=> - CollisionAttributes::Intersect{intersecting:intersecting.into(),general:general.into()}, + strafesnet_common::gameplay_attributes::CollisionAttributes::Contact(attr)=> + CollisionAttributes::Contact(attr.into()), + strafesnet_common::gameplay_attributes::CollisionAttributes::Intersect(attr)=> + CollisionAttributes::Intersect(attr.into()), } } } From 4eb8ff192893e8a0bc4432cf66bbdc73c53f66a2 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 9 Aug 2024 14:26:19 -0700 Subject: [PATCH 50/55] v0.1.3 update common --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52cc6b3..18652e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,7 +111,7 @@ dependencies = [ [[package]] name = "strafesnet_snf" -version = "0.1.2" +version = "0.1.3" dependencies = [ "binrw", "id", diff --git a/Cargo.toml b/Cargo.toml index d0b75ba..7138551 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "strafesnet_snf" -version = "0.1.2" +version = "0.1.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 39a7c31d320daac01503f85fe3fd8416cfbc7da3 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 16 Sep 2024 15:46:52 -0700 Subject: [PATCH 51/55] v0.2.0 fixed wide vectors --- Cargo.lock | 56 +++++++++++++++++++++++++---- Cargo.toml | 4 +-- src/map.rs | 2 +- src/newtypes/aabb.rs | 8 ++--- src/newtypes/gameplay_attributes.rs | 46 ++++++++++++------------ src/newtypes/gameplay_style.rs | 44 +++++++++++------------ src/newtypes/model.rs | 28 +++++++-------- 7 files changed, 116 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18652e7..58d2c57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "binrw" @@ -44,6 +44,12 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "bnum" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50202def95bf36cb7d1d7a7962cea1c36a3f8ad42425e5d2b71d7acb8041b5b8" + [[package]] name = "bytemuck" version = "1.16.3" @@ -56,6 +62,18 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "fixed_wide" +version = "0.1.0" +source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" +checksum = "7a8d6e10c51c9df39ead915c62288afbc41d13e00368e526037e530ee5c58e13" +dependencies = [ + "arrayvec", + "bnum", + "paste", + "ratio_ops", +] + [[package]] name = "glam" version = "0.28.0" @@ -73,12 +91,29 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "linear_ops" +version = "0.1.0" +source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" +checksum = "b2e6977ac24f47086d8a7a2d4ae1c720e86dfdc8407cf5e34c18bfa01053c456" +dependencies = [ + "fixed_wide", + "paste", + "ratio_ops", +] + [[package]] name = "owo-colors" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "proc-macro2" version = "1.0.86" @@ -98,20 +133,29 @@ dependencies = [ ] [[package]] -name = "strafesnet_common" -version = "0.4.0" +name = "ratio_ops" +version = "0.1.0" source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" -checksum = "ea4126f6fbf9aecf89c9e319290f0221d177dcaa8659b4b9e3d82acc37829f12" +checksum = "01239195d6afe0509e7e3511b716c0540251dfe7ece0a9a5a27116afb766c42c" + +[[package]] +name = "strafesnet_common" +version = "0.5.0" +source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" +checksum = "d8fcc44793ae84a1d80882f367980913292241c94eb87584de4010bdad4a918d" dependencies = [ "arrayvec", "bitflags", + "fixed_wide", "glam", "id", + "linear_ops", + "ratio_ops", ] [[package]] name = "strafesnet_snf" -version = "0.1.3" +version = "0.2.0" dependencies = [ "binrw", "id", diff --git a/Cargo.toml b/Cargo.toml index 7138551..300777c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "strafesnet_snf" -version = "0.1.3" +version = "0.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -8,4 +8,4 @@ edition = "2021" [dependencies] binrw = "0.14.0" id = { version = "0.1.0", registry = "strafesnet" } -strafesnet_common = { version = "0.4.0", registry = "strafesnet" } +strafesnet_common = { version = "0.5.0", registry = "strafesnet" } diff --git a/src/map.rs b/src/map.rs index 1eed566..02f8868 100644 --- a/src/map.rs +++ b/src/map.rs @@ -357,7 +357,7 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple let mesh=map.meshes.get(model.mesh.get() as usize).ok_or(Error::InvalidMeshId(model.mesh))?; let mut aabb=strafesnet_common::aabb::Aabb::default(); for &pos in &mesh.unique_pos{ - aabb.grow(model.transform.transform_point3(pos)); + aabb.grow(model.transform.transform_point3(pos).fix_1()); } Ok(((model::ModelId::new(model_id as u32),model.into()),aabb)) }).collect::,_>>()?; diff --git a/src/newtypes/aabb.rs b/src/newtypes/aabb.rs index ae8cb52..4443e55 100644 --- a/src/newtypes/aabb.rs +++ b/src/newtypes/aabb.rs @@ -8,16 +8,16 @@ pub struct Aabb{ impl Into for Aabb{ fn into(self)->strafesnet_common::aabb::Aabb{ strafesnet_common::aabb::Aabb::new( - strafesnet_common::integer::Planar64Vec3::raw_array(self.min), - strafesnet_common::integer::Planar64Vec3::raw_array(self.max), + strafesnet_common::integer::vec3::raw_array(self.min), + strafesnet_common::integer::vec3::raw_array(self.max), ) } } impl From for Aabb{ fn from(value:strafesnet_common::aabb::Aabb)->Self{ Self{ - max:value.max().get().to_array(), - min:value.min().get().to_array(), + max:value.max().map(|t|t.to_raw()).to_array(), + min:value.min().map(|t|t.to_raw()).to_array(), } } } diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs index a0082cd..6a758fb 100644 --- a/src/newtypes/gameplay_attributes.rs +++ b/src/newtypes/gameplay_attributes.rs @@ -84,16 +84,16 @@ impl Into for Interse strafesnet_common::gameplay_attributes::IntersectingWater{ viscosity:strafesnet_common::integer::Planar64::raw(self.viscosity), density:strafesnet_common::integer::Planar64::raw(self.density), - velocity:strafesnet_common::integer::Planar64Vec3::raw_array(self.velocity), + velocity:strafesnet_common::integer::vec3::raw_array(self.velocity), } } } impl From for IntersectingWater{ fn from(value:strafesnet_common::gameplay_attributes::IntersectingWater)->Self{ Self{ - viscosity:value.viscosity.get(), - density:value.density.get(), - velocity:value.velocity.get().to_array(), + viscosity:value.viscosity.to_raw(), + density:value.density.to_raw(), + velocity:value.velocity.map(|t|t.to_raw()).to_array(), } } } @@ -106,14 +106,14 @@ pub struct Accelerator{ impl Into for Accelerator{ fn into(self)->strafesnet_common::gameplay_attributes::Accelerator{ strafesnet_common::gameplay_attributes::Accelerator{ - acceleration:strafesnet_common::integer::Planar64Vec3::raw_array(self.acceleration) + acceleration:strafesnet_common::integer::vec3::raw_array(self.acceleration) } } } impl From for Accelerator{ fn from(value:strafesnet_common::gameplay_attributes::Accelerator)->Self{ Self{ - acceleration:value.acceleration.get().to_array(), + acceleration:value.acceleration.map(|t|t.to_raw()).to_array(), } } } @@ -136,11 +136,11 @@ impl Into for Booster{ match self{ Booster::Velocity(velocity)=> strafesnet_common::gameplay_attributes::Booster::Velocity( - strafesnet_common::integer::Planar64Vec3::raw_array(velocity) + strafesnet_common::integer::vec3::raw_array(velocity) ), Booster::Energy{direction,energy}=> strafesnet_common::gameplay_attributes::Booster::Energy{ - direction:strafesnet_common::integer::Planar64Vec3::raw_array(direction), + direction:strafesnet_common::integer::vec3::raw_array(direction), energy:strafesnet_common::integer::Planar64::raw(energy) }, Booster::AirTime(time)=> @@ -158,16 +158,16 @@ impl From for Booster{ fn from(value:strafesnet_common::gameplay_attributes::Booster)->Self{ match value{ strafesnet_common::gameplay_attributes::Booster::Velocity(velocity)=> - Booster::Velocity(velocity.get().to_array()), + Booster::Velocity(velocity.map(|t|t.to_raw()).to_array()), strafesnet_common::gameplay_attributes::Booster::Energy{direction,energy}=> Booster::Energy{ - direction:direction.get().to_array(), - energy:energy.get(), + direction:direction.map(|t|t.to_raw()).to_array(), + energy:energy.to_raw(), }, strafesnet_common::gameplay_attributes::Booster::AirTime(time)=> Booster::AirTime(time.get()), strafesnet_common::gameplay_attributes::Booster::Height(height)=> - Booster::Height(height.get()), + Booster::Height(height.to_raw()), } } } @@ -235,23 +235,23 @@ impl Into for SetTrajecto ), SetTrajectory::DotVelocity{direction,dot}=> strafesnet_common::gameplay_attributes::SetTrajectory::DotVelocity{ - direction:strafesnet_common::integer::Planar64Vec3::raw_array(direction), + direction:strafesnet_common::integer::vec3::raw_array(direction), dot:strafesnet_common::integer::Planar64::raw(dot), }, SetTrajectory::TargetPointTime{target_point,time}=> strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointTime{ - target_point:strafesnet_common::integer::Planar64Vec3::raw_array(target_point), + target_point:strafesnet_common::integer::vec3::raw_array(target_point), time:strafesnet_common::integer::Time::raw(time), }, SetTrajectory::TargetPointSpeed{target_point,speed,trajectory_choice}=> strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointSpeed{ - target_point:strafesnet_common::integer::Planar64Vec3::raw_array(target_point), + target_point:strafesnet_common::integer::vec3::raw_array(target_point), speed:strafesnet_common::integer::Planar64::raw(speed), trajectory_choice:trajectory_choice.into(), }, SetTrajectory::Velocity(velocity)=> strafesnet_common::gameplay_attributes::SetTrajectory::Velocity( - strafesnet_common::integer::Planar64Vec3::raw_array(velocity) + strafesnet_common::integer::vec3::raw_array(velocity) ), } } @@ -265,27 +265,27 @@ impl From for SetTrajecto ), strafesnet_common::gameplay_attributes::SetTrajectory::Height(height)=> SetTrajectory::Height( - height.get() + height.to_raw() ), strafesnet_common::gameplay_attributes::SetTrajectory::DotVelocity{direction,dot}=> SetTrajectory::DotVelocity{ - direction:direction.get().to_array(), - dot:dot.get(), + direction:direction.map(|t|t.to_raw()).to_array(), + dot:dot.to_raw(), }, strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointTime{target_point,time}=> SetTrajectory::TargetPointTime{ - target_point:target_point.get().to_array(), + target_point:target_point.map(|t|t.to_raw()).to_array(), time:time.get(), }, strafesnet_common::gameplay_attributes::SetTrajectory::TargetPointSpeed{target_point,speed,trajectory_choice}=> SetTrajectory::TargetPointSpeed{ - target_point:target_point.get().to_array(), - speed:speed.get(), + target_point:target_point.map(|t|t.to_raw()).to_array(), + speed:speed.to_raw(), trajectory_choice:trajectory_choice.into(), }, strafesnet_common::gameplay_attributes::SetTrajectory::Velocity(velocity)=> SetTrajectory::Velocity( - velocity.get().to_array() + velocity.map(|t|t.to_raw()).to_array() ), } } diff --git a/src/newtypes/gameplay_style.rs b/src/newtypes/gameplay_style.rs index 64d98b9..9033700 100644 --- a/src/newtypes/gameplay_style.rs +++ b/src/newtypes/gameplay_style.rs @@ -68,9 +68,9 @@ impl TryInto for StyleModifie walk:self.walk.map(Into::into), ladder:self.ladder.map(Into::into), swim:self.swim.map(Into::into), - gravity:strafesnet_common::integer::Planar64Vec3::raw_array(self.gravity), + gravity:strafesnet_common::integer::vec3::raw_array(self.gravity), hitbox:self.hitbox.into(), - camera_offset:strafesnet_common::integer::Planar64Vec3::raw_array(self.camera_offset), + camera_offset:strafesnet_common::integer::vec3::raw_array(self.camera_offset), mass:strafesnet_common::integer::Planar64::raw(self.mass), }) } @@ -94,10 +94,10 @@ impl From for StyleModifiers{ walk:value.walk.map(Into::into), ladder:value.ladder.map(Into::into), swim:value.swim.map(Into::into), - gravity:value.gravity.get().to_array(), + gravity:value.gravity.map(|t|t.to_raw()).to_array(), hitbox:value.hitbox.into(), - camera_offset:value.camera_offset.get().to_array(), - mass:value.mass.get(), + camera_offset:value.camera_offset.map(|t|t.to_raw()).to_array(), + mass:value.mass.to_raw(), } } } @@ -148,9 +148,9 @@ impl From for JumpImpulse{ fn from(value:strafesnet_common::gameplay_style::JumpImpulse)->Self{ match value{ strafesnet_common::gameplay_style::JumpImpulse::Time(time)=>JumpImpulse::Time(time.get()), - strafesnet_common::gameplay_style::JumpImpulse::Height(height)=>JumpImpulse::Height(height.get()), - strafesnet_common::gameplay_style::JumpImpulse::Linear(deltav)=>JumpImpulse::Linear(deltav.get()), - strafesnet_common::gameplay_style::JumpImpulse::Energy(energy)=>JumpImpulse::Energy(energy.get()), + strafesnet_common::gameplay_style::JumpImpulse::Height(height)=>JumpImpulse::Height(height.to_raw()), + strafesnet_common::gameplay_style::JumpImpulse::Linear(deltav)=>JumpImpulse::Linear(deltav.to_raw()), + strafesnet_common::gameplay_style::JumpImpulse::Energy(energy)=>JumpImpulse::Energy(energy.to_raw()), } } } @@ -223,8 +223,8 @@ impl From for StrafeSettings{ Self{ header, enable:value.enable.into(), - mv:value.mv.get(), - air_accel_limit:value.air_accel_limit.map(|a|a.get()), + mv:value.mv.to_raw(), + air_accel_limit:value.air_accel_limit.map(|a|a.to_raw()), tick_rate:value.tick_rate.into(), } } @@ -245,7 +245,7 @@ impl Into for PropulsionS impl From for PropulsionSettings{ fn from(value:strafesnet_common::gameplay_style::PropulsionSettings)->Self{ Self{ - magnitude:value.magnitude.get(), + magnitude:value.magnitude.to_raw(), } } } @@ -300,9 +300,9 @@ impl From for JumpSettings{ fn from(value:strafesnet_common::gameplay_style::JumpSettings)->Self{ let (impulse,impulse_header)=match value.impulse{ strafesnet_common::gameplay_style::JumpImpulse::Time(impulse)=>(impulse.get(),0), - strafesnet_common::gameplay_style::JumpImpulse::Height(impulse)=>(impulse.get(),1), - strafesnet_common::gameplay_style::JumpImpulse::Linear(impulse)=>(impulse.get(),2), - strafesnet_common::gameplay_style::JumpImpulse::Energy(impulse)=>(impulse.get(),3), + strafesnet_common::gameplay_style::JumpImpulse::Height(impulse)=>(impulse.to_raw(),1), + strafesnet_common::gameplay_style::JumpImpulse::Linear(impulse)=>(impulse.to_raw(),2), + strafesnet_common::gameplay_style::JumpImpulse::Energy(impulse)=>(impulse.to_raw(),3), }; let calculation_header=match value.calculation{ strafesnet_common::gameplay_style::JumpCalculation::Max=>0, @@ -337,8 +337,8 @@ impl Into for AccelerateS impl From for AccelerateSettings{ fn from(value:strafesnet_common::gameplay_style::AccelerateSettings)->Self{ Self{ - accel:value.accel.get(), - topspeed:value.topspeed.get(), + accel:value.accel.to_raw(), + topspeed:value.topspeed.to_raw(), } } } @@ -365,9 +365,9 @@ impl From for WalkSettings{ fn from(value:strafesnet_common::gameplay_style::WalkSettings)->Self{ Self{ accelerate:value.accelerate.into(), - static_friction:value.static_friction.get(), - kinetic_friction:value.kinetic_friction.get(), - surf_dot:value.surf_dot.get(), + static_friction:value.static_friction.to_raw(), + kinetic_friction:value.kinetic_friction.to_raw(), + surf_dot:value.surf_dot.to_raw(), } } } @@ -390,7 +390,7 @@ impl From for LadderSettings{ fn from(value:strafesnet_common::gameplay_style::LadderSettings)->Self{ Self{ accelerate:value.accelerate.into(), - dot:value.dot.get(), + dot:value.dot.to_raw(), } } } @@ -427,7 +427,7 @@ pub struct Hitbox{ impl Into for Hitbox{ fn into(self)->strafesnet_common::gameplay_style::Hitbox{ strafesnet_common::gameplay_style::Hitbox{ - halfsize:strafesnet_common::integer::Planar64Vec3::raw_array(self.halfsize), + halfsize:strafesnet_common::integer::vec3::raw_array(self.halfsize), mesh:self.mesh.into(), } } @@ -435,7 +435,7 @@ impl Into for Hitbox{ impl From for Hitbox{ fn from(value:strafesnet_common::gameplay_style::Hitbox)->Self{ Self{ - halfsize:value.halfsize.get().to_array(), + halfsize:value.halfsize.map(|t|t.to_raw()).to_array(), mesh:value.mesh.into(), } } diff --git a/src/newtypes/model.rs b/src/newtypes/model.rs index 6b874d0..6d3ce51 100644 --- a/src/newtypes/model.rs +++ b/src/newtypes/model.rs @@ -153,8 +153,8 @@ pub struct Mesh{ impl Into for Mesh{ fn into(self)->strafesnet_common::model::Mesh{ strafesnet_common::model::Mesh{ - unique_pos:self.unique_pos.into_iter().map(strafesnet_common::integer::Planar64Vec3::raw_array).collect(), - unique_normal:self.unique_normal.into_iter().map(strafesnet_common::integer::Planar64Vec3::raw_array).collect(), + unique_pos:self.unique_pos.into_iter().map(strafesnet_common::integer::vec3::raw_array).collect(), + unique_normal:self.unique_normal.into_iter().map(strafesnet_common::integer::vec3::raw_array).collect(), unique_tex:self.unique_tex.into_iter().map(strafesnet_common::model::TextureCoordinate::from_array).collect(), unique_color:self.unique_color.into_iter().map(strafesnet_common::model::Color4::from_array).collect(), unique_vertices:self.unique_vertices.into_iter().map(|vert|strafesnet_common::model::IndexedVertex{ @@ -200,10 +200,10 @@ impl From for Mesh{ physics_groups:value.physics_groups.len() as u32, }, unique_pos:value.unique_pos.into_iter() - .map(|pos|pos.get().to_array()) + .map(|pos|pos.map(|t|t.to_raw()).to_array()) .collect(), unique_normal:value.unique_normal.into_iter() - .map(|normal|normal.get().to_array()) + .map(|normal|normal.map(|t|t.to_raw()).to_array()) .collect(), unique_tex:value.unique_tex.into_iter() .map(|tex|tex.to_array()) @@ -243,12 +243,12 @@ impl Into for Model{ attributes:strafesnet_common::gameplay_attributes::CollisionAttributesId::new(self.attributes), color:strafesnet_common::model::Color4::from_array(self.color), transform:strafesnet_common::integer::Planar64Affine3::new( - strafesnet_common::integer::Planar64Mat3::from_cols( - strafesnet_common::integer::Planar64Vec3::raw_xyz(_0,_1,_2), - strafesnet_common::integer::Planar64Vec3::raw_xyz(_3,_4,_5), - strafesnet_common::integer::Planar64Vec3::raw_xyz(_6,_7,_8) - ), - strafesnet_common::integer::Planar64Vec3::raw_xyz(_9,_a,_b) + strafesnet_common::integer::Planar64Mat3::from_cols([ + strafesnet_common::integer::vec3::raw_xyz(_0,_1,_2), + strafesnet_common::integer::vec3::raw_xyz(_3,_4,_5), + strafesnet_common::integer::vec3::raw_xyz(_6,_7,_8) + ]), + strafesnet_common::integer::vec3::raw_xyz(_9,_a,_b) ), } } @@ -261,10 +261,10 @@ impl From for Model{ [_6,_7,_8], [_9,_a,_b] )=( - value.transform.matrix3.x_axis.get().to_array(), - value.transform.matrix3.y_axis.get().to_array(), - value.transform.matrix3.z_axis.get().to_array(), - value.transform.translation.get().to_array() + value.transform.matrix3.x_axis.map(|t|t.to_raw()).to_array(), + value.transform.matrix3.y_axis.map(|t|t.to_raw()).to_array(), + value.transform.matrix3.z_axis.map(|t|t.to_raw()).to_array(), + value.transform.translation.map(|t|t.to_raw()).to_array() ); Self{ mesh:value.mesh.get(), From 0dc2d1f89e7e2bde553c2d00d33a8ec828a0a07f Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 31 Dec 2024 04:32:25 -0800 Subject: [PATCH 52/55] delete Boolio --- src/newtypes/common.rs | 23 ----------------------- src/newtypes/gameplay_attributes.rs | 6 ++++-- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/src/newtypes/common.rs b/src/newtypes/common.rs index 0136b54..cec7e09 100644 --- a/src/newtypes/common.rs +++ b/src/newtypes/common.rs @@ -1,26 +1,3 @@ pub const fn flag(b:bool,mask:u8)->u8{ (-(b as i8) as u8)&mask } - -#[binrw::binrw] -#[brw(little,repr=u8)] -pub enum Boolio{ - True, - False -} -impl Into for Boolio{ - fn into(self)->bool{ - match self{ - Boolio::True=>true, - Boolio::False=>false, - } - } -} -impl From for Boolio{ - fn from(value:bool)->Self{ - match value{ - true=>Boolio::True, - false=>Boolio::False, - } - } -} diff --git a/src/newtypes/gameplay_attributes.rs b/src/newtypes/gameplay_attributes.rs index 6a758fb..3dcfb81 100644 --- a/src/newtypes/gameplay_attributes.rs +++ b/src/newtypes/gameplay_attributes.rs @@ -1,10 +1,12 @@ -use super::common::{flag,Boolio}; +use super::common::flag; use super::integer::{Time,Planar64,Planar64Vec3}; #[binrw::binrw] #[brw(little)] pub struct ContactingLadder{ - pub sticky:Boolio, + #[br(map=|paused:u8|paused!=0)] + #[bw(map=|paused:&bool|*paused as u8)] + pub sticky:bool, } impl Into for ContactingLadder{ fn into(self)->strafesnet_common::gameplay_attributes::ContactingLadder{ From f8c623cd883143ae391fafe04a3c33710d5ff2f9 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 31 Dec 2024 04:32:39 -0800 Subject: [PATCH 53/55] change api for no reason --- src/file.rs | 4 ++-- src/map.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/file.rs b/src/file.rs index 1cc2d8e..75b89cd 100644 --- a/src/file.rs +++ b/src/file.rs @@ -92,7 +92,7 @@ impl File{ data:input, }) } - pub(crate) fn as_mut(&mut self)->&mut R{ + pub(crate) fn data_mut(&mut self)->&mut R{ &mut self.data } pub(crate) fn block_reader(&mut self,block_id:BlockId)->Result,Error>{ @@ -102,7 +102,7 @@ impl File{ let block_start=self.header.block_location[block_id.get() as usize]; let block_end=self.header.block_location[block_id.get() as usize+1]; self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(Error::Seek)?; - Ok(self.as_mut().take_seek(block_end-block_start)) + Ok(self.data_mut().take_seek(block_end-block_start)) } pub(crate) fn fourcc(&self)->FourCC{ self.header.fourcc diff --git a/src/map.rs b/src/map.rs index 02f8868..a5ef6f7 100644 --- a/src/map.rs +++ b/src/map.rs @@ -214,7 +214,7 @@ pub struct StreamableMap{ impl StreamableMap{ pub(crate) fn new(mut file:crate::file::File)->Result{ //assume the file seek is in the right place to start reading a map header - let header:MapHeader=file.as_mut().read_le().map_err(Error::InvalidHeader)?; + let header:MapHeader=file.data_mut().read_le().map_err(Error::InvalidHeader)?; let modes=header.modes.into_iter().map(TryInto::try_into).collect::>().map_err(Error::InvalidMode)?; let attributes=header.attributes.into_iter().map(Into::into).collect(); let render_configs=header.render_configs.into_iter().map(Into::into).collect(); From 9395d58a2c25857c1287d30e871793ce01b7c6f0 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 31 Dec 2024 04:32:46 -0800 Subject: [PATCH 54/55] spaces --- src/file.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file.rs b/src/file.rs index 75b89cd..fb04c3e 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,6 +1,6 @@ //file format "sniff" -use binrw::{binrw, BinReaderExt, io::TakeSeekExt}; +use binrw::{binrw,BinReaderExt,io::TakeSeekExt}; #[derive(Debug)] pub enum Error{ From 6f958e3edaab7e190054fbbbc7c32f0bf6be0d45 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 2 Jan 2025 19:40:26 -0800 Subject: [PATCH 55/55] snf: move into folder --- .gitignore => lib/snf/.gitignore | 0 Cargo.lock => lib/snf/Cargo.lock | 0 Cargo.toml => lib/snf/Cargo.toml | 0 LICENSE-APACHE => lib/snf/LICENSE-APACHE | 0 LICENSE-MIT => lib/snf/LICENSE-MIT | 0 README.md => lib/snf/README.md | 0 {src => lib/snf/src}/bot.rs | 0 {src => lib/snf/src}/demo.rs | 0 {src => lib/snf/src}/file.rs | 0 {src => lib/snf/src}/lib.rs | 0 {src => lib/snf/src}/map.rs | 0 {src => lib/snf/src}/newtypes.rs | 0 {src => lib/snf/src}/newtypes/aabb.rs | 0 {src => lib/snf/src}/newtypes/common.rs | 0 {src => lib/snf/src}/newtypes/gameplay_attributes.rs | 0 {src => lib/snf/src}/newtypes/gameplay_modes.rs | 0 {src => lib/snf/src}/newtypes/gameplay_style.rs | 0 {src => lib/snf/src}/newtypes/integer.rs | 0 {src => lib/snf/src}/newtypes/model.rs | 0 19 files changed, 0 insertions(+), 0 deletions(-) rename .gitignore => lib/snf/.gitignore (100%) rename Cargo.lock => lib/snf/Cargo.lock (100%) rename Cargo.toml => lib/snf/Cargo.toml (100%) rename LICENSE-APACHE => lib/snf/LICENSE-APACHE (100%) rename LICENSE-MIT => lib/snf/LICENSE-MIT (100%) rename README.md => lib/snf/README.md (100%) rename {src => lib/snf/src}/bot.rs (100%) rename {src => lib/snf/src}/demo.rs (100%) rename {src => lib/snf/src}/file.rs (100%) rename {src => lib/snf/src}/lib.rs (100%) rename {src => lib/snf/src}/map.rs (100%) rename {src => lib/snf/src}/newtypes.rs (100%) rename {src => lib/snf/src}/newtypes/aabb.rs (100%) rename {src => lib/snf/src}/newtypes/common.rs (100%) rename {src => lib/snf/src}/newtypes/gameplay_attributes.rs (100%) rename {src => lib/snf/src}/newtypes/gameplay_modes.rs (100%) rename {src => lib/snf/src}/newtypes/gameplay_style.rs (100%) rename {src => lib/snf/src}/newtypes/integer.rs (100%) rename {src => lib/snf/src}/newtypes/model.rs (100%) diff --git a/.gitignore b/lib/snf/.gitignore similarity index 100% rename from .gitignore rename to lib/snf/.gitignore diff --git a/Cargo.lock b/lib/snf/Cargo.lock similarity index 100% rename from Cargo.lock rename to lib/snf/Cargo.lock diff --git a/Cargo.toml b/lib/snf/Cargo.toml similarity index 100% rename from Cargo.toml rename to lib/snf/Cargo.toml diff --git a/LICENSE-APACHE b/lib/snf/LICENSE-APACHE similarity index 100% rename from LICENSE-APACHE rename to lib/snf/LICENSE-APACHE diff --git a/LICENSE-MIT b/lib/snf/LICENSE-MIT similarity index 100% rename from LICENSE-MIT rename to lib/snf/LICENSE-MIT diff --git a/README.md b/lib/snf/README.md similarity index 100% rename from README.md rename to lib/snf/README.md diff --git a/src/bot.rs b/lib/snf/src/bot.rs similarity index 100% rename from src/bot.rs rename to lib/snf/src/bot.rs diff --git a/src/demo.rs b/lib/snf/src/demo.rs similarity index 100% rename from src/demo.rs rename to lib/snf/src/demo.rs diff --git a/src/file.rs b/lib/snf/src/file.rs similarity index 100% rename from src/file.rs rename to lib/snf/src/file.rs diff --git a/src/lib.rs b/lib/snf/src/lib.rs similarity index 100% rename from src/lib.rs rename to lib/snf/src/lib.rs diff --git a/src/map.rs b/lib/snf/src/map.rs similarity index 100% rename from src/map.rs rename to lib/snf/src/map.rs diff --git a/src/newtypes.rs b/lib/snf/src/newtypes.rs similarity index 100% rename from src/newtypes.rs rename to lib/snf/src/newtypes.rs diff --git a/src/newtypes/aabb.rs b/lib/snf/src/newtypes/aabb.rs similarity index 100% rename from src/newtypes/aabb.rs rename to lib/snf/src/newtypes/aabb.rs diff --git a/src/newtypes/common.rs b/lib/snf/src/newtypes/common.rs similarity index 100% rename from src/newtypes/common.rs rename to lib/snf/src/newtypes/common.rs diff --git a/src/newtypes/gameplay_attributes.rs b/lib/snf/src/newtypes/gameplay_attributes.rs similarity index 100% rename from src/newtypes/gameplay_attributes.rs rename to lib/snf/src/newtypes/gameplay_attributes.rs diff --git a/src/newtypes/gameplay_modes.rs b/lib/snf/src/newtypes/gameplay_modes.rs similarity index 100% rename from src/newtypes/gameplay_modes.rs rename to lib/snf/src/newtypes/gameplay_modes.rs diff --git a/src/newtypes/gameplay_style.rs b/lib/snf/src/newtypes/gameplay_style.rs similarity index 100% rename from src/newtypes/gameplay_style.rs rename to lib/snf/src/newtypes/gameplay_style.rs diff --git a/src/newtypes/integer.rs b/lib/snf/src/newtypes/integer.rs similarity index 100% rename from src/newtypes/integer.rs rename to lib/snf/src/newtypes/integer.rs diff --git a/src/newtypes/model.rs b/lib/snf/src/newtypes/model.rs similarity index 100% rename from src/newtypes/model.rs rename to lib/snf/src/newtypes/model.rs