implement file drag drop for native player
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1678,7 +1678,6 @@ dependencies = [
|
|||||||
"strafesnet_common",
|
"strafesnet_common",
|
||||||
"strafesnet_graphics",
|
"strafesnet_graphics",
|
||||||
"strafesnet_roblox_bot_file",
|
"strafesnet_roblox_bot_file",
|
||||||
"strafesnet_snf",
|
|
||||||
"wgpu",
|
"wgpu",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1705,6 +1704,7 @@ dependencies = [
|
|||||||
"strafesnet_graphics",
|
"strafesnet_graphics",
|
||||||
"strafesnet_roblox_bot_file",
|
"strafesnet_roblox_bot_file",
|
||||||
"strafesnet_roblox_bot_player",
|
"strafesnet_roblox_bot_player",
|
||||||
|
"strafesnet_snf",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ python3 -m http.server
|
|||||||
How to run the native player:
|
How to run the native player:
|
||||||
```
|
```
|
||||||
cd native-player
|
cd native-player
|
||||||
cargo run --release
|
cargo run --release -- ../web-demo/bhop_marble_5692093612.snfm ../web-demo/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d.qbot
|
||||||
```
|
```
|
||||||
|
You can drag and drop map files and bot files to load them.
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ glam = "0.31.0"
|
|||||||
strafesnet_common.workspace = true
|
strafesnet_common.workspace = true
|
||||||
strafesnet_graphics.workspace = true
|
strafesnet_graphics.workspace = true
|
||||||
strafesnet_roblox_bot_file.workspace = true
|
strafesnet_roblox_bot_file.workspace = true
|
||||||
strafesnet_snf.workspace = true
|
|
||||||
wgpu = "28.0.0"
|
wgpu = "28.0.0"
|
||||||
|
|||||||
@@ -11,16 +11,15 @@ pub struct CompleteBot{
|
|||||||
impl CompleteBot{
|
impl CompleteBot{
|
||||||
pub(crate) const CAMERA_OFFSET:glam::Vec3=glam::vec3(0.0,2.0,0.0);
|
pub(crate) const CAMERA_OFFSET:glam::Vec3=glam::vec3(0.0,2.0,0.0);
|
||||||
pub fn new(
|
pub fn new(
|
||||||
data:&[u8],
|
timelines:v0::Block,
|
||||||
)->Result<Self,v0::Error>{
|
)->Self{
|
||||||
let timelines=v0::read_all_to_block(std::io::Cursor::new(data))?;
|
|
||||||
let first=timelines.output_events.first().unwrap();
|
let first=timelines.output_events.first().unwrap();
|
||||||
let last=timelines.output_events.last().unwrap();
|
let last=timelines.output_events.last().unwrap();
|
||||||
Ok(Self{
|
Self{
|
||||||
time_base:crate::time::from_float(first.time).unwrap(),
|
time_base:crate::time::from_float(first.time).unwrap(),
|
||||||
duration:crate::time::from_float(last.time-first.time).unwrap(),
|
duration:crate::time::from_float(last.time-first.time).unwrap(),
|
||||||
timelines,
|
timelines,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
pub const fn time_base(&self)->PhysicsTime{
|
pub const fn time_base(&self)->PhysicsTime{
|
||||||
self.time_base
|
self.time_base
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ impl Graphics{
|
|||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn change_map(&mut self,map:&crate::map::CompleteMap){
|
pub fn change_map(&mut self,map:&strafesnet_common::map::CompleteMap){
|
||||||
self.graphics.clear();
|
self.graphics.clear();
|
||||||
self.graphics.generate_models(&self.device,&self.queue,map.map());
|
self.graphics.generate_models(&self.device,&self.queue,map);
|
||||||
}
|
}
|
||||||
pub fn resize(&mut self,surface:&wgpu::Surface<'_>,size:glam::UVec2){
|
pub fn resize(&mut self,surface:&wgpu::Surface<'_>,size:glam::UVec2){
|
||||||
self.config.width=size.x.max(1);
|
self.config.width=size.x.max(1);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
pub mod bot;
|
pub mod bot;
|
||||||
pub mod map;
|
|
||||||
pub mod head;
|
pub mod head;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
#[derive(Debug)]
|
|
||||||
pub enum Error{
|
|
||||||
File(strafesnet_snf::Error),
|
|
||||||
Map(strafesnet_snf::map::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 struct CompleteMap{
|
|
||||||
complete_map:strafesnet_common::map::CompleteMap,
|
|
||||||
}
|
|
||||||
impl CompleteMap{
|
|
||||||
pub fn new(
|
|
||||||
data:&[u8],
|
|
||||||
)->Result<Self,Error>{
|
|
||||||
let complete_map=strafesnet_snf::read_map(std::io::Cursor::new(data))
|
|
||||||
.map_err(Error::File)?
|
|
||||||
.into_complete_map()
|
|
||||||
.map_err(Error::Map)?;
|
|
||||||
Ok(Self{complete_map})
|
|
||||||
}
|
|
||||||
pub const fn map(&self)->&strafesnet_common::map::CompleteMap{
|
|
||||||
&self.complete_map
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,11 @@
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
#[cfg(any(feature="roblox",feature="source"))]
|
|
||||||
use strafesnet_deferred_loader::deferred_loader::LoadFailureMode;
|
|
||||||
|
|
||||||
#[expect(dead_code)]
|
#[expect(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ReadError{
|
pub enum ReadError{
|
||||||
#[cfg(feature="roblox")]
|
|
||||||
Roblox(strafesnet_rbx_loader::ReadError),
|
|
||||||
#[cfg(feature="source")]
|
|
||||||
Source(strafesnet_bsp_loader::ReadError),
|
|
||||||
#[cfg(feature="snf")]
|
|
||||||
StrafesNET(strafesnet_snf::Error),
|
StrafesNET(strafesnet_snf::Error),
|
||||||
#[cfg(feature="snf")]
|
|
||||||
StrafesNETMap(strafesnet_snf::map::Error),
|
StrafesNETMap(strafesnet_snf::map::Error),
|
||||||
#[cfg(feature="snf")]
|
RobloxBot(strafesnet_roblox_bot_file::v0::Error),
|
||||||
StrafesNETBot(strafesnet_snf::bot::Error),
|
|
||||||
Io(std::io::Error),
|
Io(std::io::Error),
|
||||||
UnknownFileFormat,
|
UnknownFileFormat,
|
||||||
}
|
}
|
||||||
@@ -27,14 +17,8 @@ impl std::fmt::Display for ReadError{
|
|||||||
impl std::error::Error for ReadError{}
|
impl std::error::Error for ReadError{}
|
||||||
|
|
||||||
pub enum ReadFormat{
|
pub enum ReadFormat{
|
||||||
#[cfg(feature="roblox")]
|
|
||||||
Roblox(strafesnet_rbx_loader::Model),
|
|
||||||
#[cfg(feature="source")]
|
|
||||||
Source(strafesnet_bsp_loader::Bsp),
|
|
||||||
#[cfg(feature="snf")]
|
|
||||||
SNFM(strafesnet_common::map::CompleteMap),
|
SNFM(strafesnet_common::map::CompleteMap),
|
||||||
#[cfg(feature="snf")]
|
QBOT(strafesnet_roblox_bot_file::v0::Block),
|
||||||
SNFB(strafesnet_snf::bot::Segment),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<R:Read+std::io::Seek>(input:R)->Result<ReadFormat,ReadError>{
|
pub fn read<R:Read+std::io::Seek>(input:R)->Result<ReadFormat,ReadError>{
|
||||||
@@ -45,19 +29,12 @@ pub fn read<R:Read+std::io::Seek>(input:R)->Result<ReadFormat,ReadError>{
|
|||||||
buf.read_to_end(&mut entire_file).map_err(ReadError::Io)?;
|
buf.read_to_end(&mut entire_file).map_err(ReadError::Io)?;
|
||||||
let cursor=std::io::Cursor::new(entire_file);
|
let cursor=std::io::Cursor::new(entire_file);
|
||||||
match peek.as_slice(){
|
match peek.as_slice(){
|
||||||
#[cfg(feature="roblox")]
|
|
||||||
b"<rob"=>Ok(ReadFormat::Roblox(strafesnet_rbx_loader::read(cursor).map_err(ReadError::Roblox)?)),
|
|
||||||
#[cfg(feature="source")]
|
|
||||||
b"VBSP"=>Ok(ReadFormat::Source(strafesnet_bsp_loader::read(cursor).map_err(ReadError::Source)?)),
|
|
||||||
#[cfg(feature="snf")]
|
|
||||||
b"SNFM"=>Ok(ReadFormat::SNFM(
|
b"SNFM"=>Ok(ReadFormat::SNFM(
|
||||||
strafesnet_snf::read_map(cursor).map_err(ReadError::StrafesNET)?
|
strafesnet_snf::read_map(cursor).map_err(ReadError::StrafesNET)?
|
||||||
.into_complete_map().map_err(ReadError::StrafesNETMap)?
|
.into_complete_map().map_err(ReadError::StrafesNETMap)?
|
||||||
)),
|
)),
|
||||||
#[cfg(feature="snf")]
|
b"qbot"=>Ok(ReadFormat::QBOT(
|
||||||
b"SNFB"=>Ok(ReadFormat::SNFB(
|
strafesnet_roblox_bot_file::v0::read_all_to_block(cursor).map_err(ReadError::RobloxBot)?
|
||||||
strafesnet_snf::read_bot(cursor).map_err(ReadError::StrafesNET)?
|
|
||||||
.read_all().map_err(ReadError::StrafesNETBot)?
|
|
||||||
)),
|
)),
|
||||||
_=>Err(ReadError::UnknownFileFormat),
|
_=>Err(ReadError::UnknownFileFormat),
|
||||||
}
|
}
|
||||||
@@ -68,10 +45,6 @@ pub fn read<R:Read+std::io::Seek>(input:R)->Result<ReadFormat,ReadError>{
|
|||||||
pub enum LoadError{
|
pub enum LoadError{
|
||||||
ReadError(ReadError),
|
ReadError(ReadError),
|
||||||
File(std::io::Error),
|
File(std::io::Error),
|
||||||
#[cfg(feature="roblox")]
|
|
||||||
LoadRoblox(strafesnet_rbx_loader::LoadError),
|
|
||||||
#[cfg(feature="source")]
|
|
||||||
LoadSource(strafesnet_bsp_loader::LoadError),
|
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for LoadError{
|
impl std::fmt::Display for LoadError{
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
@@ -81,36 +54,15 @@ impl std::fmt::Display for LoadError{
|
|||||||
impl std::error::Error for LoadError{}
|
impl std::error::Error for LoadError{}
|
||||||
|
|
||||||
pub enum LoadFormat{
|
pub enum LoadFormat{
|
||||||
#[cfg(any(feature="snf",feature="roblox",feature="source"))]
|
|
||||||
Map(strafesnet_common::map::CompleteMap),
|
Map(strafesnet_common::map::CompleteMap),
|
||||||
#[cfg(feature="snf")]
|
Bot(strafesnet_roblox_bot_file::v0::Block),
|
||||||
Bot(strafesnet_snf::bot::Segment),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load<P:AsRef<std::path::Path>>(path:P)->Result<LoadFormat,LoadError>{
|
pub fn load<P:AsRef<std::path::Path>>(path:P)->Result<LoadFormat,LoadError>{
|
||||||
//blocking because it's simpler...
|
//blocking because it's simpler...
|
||||||
let file=std::fs::File::open(path).map_err(LoadError::File)?;
|
let file=std::fs::File::open(path).map_err(LoadError::File)?;
|
||||||
match read(file).map_err(LoadError::ReadError)?{
|
match read(file).map_err(LoadError::ReadError)?{
|
||||||
#[cfg(feature="snf")]
|
ReadFormat::QBOT(bot)=>Ok(LoadFormat::Bot(bot)),
|
||||||
ReadFormat::SNFB(bot)=>Ok(LoadFormat::Bot(bot)),
|
|
||||||
#[cfg(feature="snf")]
|
|
||||||
ReadFormat::SNFM(map)=>Ok(LoadFormat::Map(map)),
|
ReadFormat::SNFM(map)=>Ok(LoadFormat::Map(map)),
|
||||||
#[cfg(feature="roblox")]
|
|
||||||
ReadFormat::Roblox(model)=>{
|
|
||||||
let mut place=strafesnet_rbx_loader::Place::from(model);
|
|
||||||
let script_errors=place.run_scripts().unwrap();
|
|
||||||
for error in script_errors{
|
|
||||||
println!("Script error: {error}");
|
|
||||||
}
|
|
||||||
let (map,errors)=place.to_snf(LoadFailureMode::DefaultToNone).map_err(LoadError::LoadRoblox)?;
|
|
||||||
if errors.count()!=0{
|
|
||||||
print!("Errors encountered while loading the map:\n{}",errors);
|
|
||||||
}
|
|
||||||
Ok(LoadFormat::Map(map))
|
|
||||||
},
|
|
||||||
#[cfg(feature="source")]
|
|
||||||
ReadFormat::Source(bsp)=>Ok(LoadFormat::Map(
|
|
||||||
bsp.to_snf(LoadFailureMode::DefaultToNone,&[]).map_err(LoadError::LoadSource)?
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,25 +17,26 @@ pub enum Instruction{
|
|||||||
SessionPlayback(SessionPlaybackInstruction),
|
SessionPlayback(SessionPlaybackInstruction),
|
||||||
Render,
|
Render,
|
||||||
Resize(winit::dpi::PhysicalSize<u32>),
|
Resize(winit::dpi::PhysicalSize<u32>),
|
||||||
|
ChangeMap(strafesnet_common::map::CompleteMap),
|
||||||
|
LoadReplay(strafesnet_roblox_bot_file::v0::Block),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PlayerWorker<'a>{
|
pub struct PlayerWorker<'a>{
|
||||||
surface:wgpu::Surface<'a>,
|
surface:wgpu::Surface<'a>,
|
||||||
graphics_thread:Graphics,
|
graphics_thread:Graphics,
|
||||||
bot:CompleteBot,
|
bot:Option<CompleteBot>,
|
||||||
playback_head:PlaybackHead,
|
playback_head:PlaybackHead,
|
||||||
}
|
}
|
||||||
impl<'a> PlayerWorker<'a>{
|
impl<'a> PlayerWorker<'a>{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
surface:wgpu::Surface<'a>,
|
surface:wgpu::Surface<'a>,
|
||||||
bot:CompleteBot,
|
|
||||||
graphics_thread:Graphics,
|
graphics_thread:Graphics,
|
||||||
)->Self{
|
)->Self{
|
||||||
let playback_head=PlaybackHead::new(SessionTime::ZERO);
|
let playback_head=PlaybackHead::new(SessionTime::ZERO);
|
||||||
Self{
|
Self{
|
||||||
surface,
|
surface,
|
||||||
graphics_thread,
|
graphics_thread,
|
||||||
bot,
|
bot:None,
|
||||||
playback_head,
|
playback_head,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,14 +44,20 @@ impl<'a> PlayerWorker<'a>{
|
|||||||
match ins.instruction{
|
match ins.instruction{
|
||||||
Instruction::SessionControl(session_control_instruction)=>{},
|
Instruction::SessionControl(session_control_instruction)=>{},
|
||||||
Instruction::SessionPlayback(session_playback_instruction)=>{},
|
Instruction::SessionPlayback(session_playback_instruction)=>{},
|
||||||
Instruction::Render=>{
|
Instruction::Render=>if let Some(bot)=&self.bot{
|
||||||
self.playback_head.advance_time(&self.bot,ins.time);
|
self.playback_head.advance_time(bot,ins.time);
|
||||||
let (pos,angles)=self.playback_head.get_position_angles(&self.bot,ins.time);
|
let (pos,angles)=self.playback_head.get_position_angles(bot,ins.time);
|
||||||
self.graphics_thread.render(&self.surface,pos,angles);
|
self.graphics_thread.render(&self.surface,pos,angles);
|
||||||
},
|
},
|
||||||
Instruction::Resize(physical_size)=>{
|
Instruction::Resize(physical_size)=>{
|
||||||
self.graphics_thread.resize(&self.surface,glam::uvec2(physical_size.width,physical_size.height));
|
self.graphics_thread.resize(&self.surface,glam::uvec2(physical_size.width,physical_size.height));
|
||||||
},
|
},
|
||||||
|
Instruction::ChangeMap(complete_map)=>{
|
||||||
|
self.graphics_thread.change_map(&complete_map);
|
||||||
|
},
|
||||||
|
Instruction::LoadReplay(bot)=>{
|
||||||
|
self.bot=Some(CompleteBot::new(bot));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ impl WindowContext<'_>{
|
|||||||
match event{
|
match event{
|
||||||
winit::event::WindowEvent::DroppedFile(path)=>{
|
winit::event::WindowEvent::DroppedFile(path)=>{
|
||||||
match crate::file::load(path.as_path()){
|
match crate::file::load(path.as_path()){
|
||||||
// Ok(LoadFormat::Map(map))=>self.physics_thread.send(TimedInstruction{time,instruction:PhysicsWorkerInstruction::ChangeMap(map)}),
|
Ok(LoadFormat::Map(map))=>self.physics_thread.send(TimedInstruction{time,instruction:PhysicsWorkerInstruction::ChangeMap(map)}),
|
||||||
// Ok(LoadFormat::Bot(bot))=>self.physics_thread.send(TimedInstruction{time,instruction:PhysicsWorkerInstruction::LoadReplay(bot)}),
|
Ok(LoadFormat::Bot(bot))=>self.physics_thread.send(TimedInstruction{time,instruction:PhysicsWorkerInstruction::LoadReplay(bot)}),
|
||||||
Err(e)=>println!("Failed to load file: {e}"),
|
Err(e)=>println!("Failed to load file: {e}"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -149,12 +149,7 @@ impl WindowContext<'_>{
|
|||||||
config:wgpu::SurfaceConfiguration,
|
config:wgpu::SurfaceConfiguration,
|
||||||
)->WindowContext<'a>{
|
)->WindowContext<'a>{
|
||||||
let screen_size=glam::uvec2(config.width,config.height);
|
let screen_size=glam::uvec2(config.width,config.height);
|
||||||
let bot=include_bytes!("../../web-demo/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d.qbot");
|
let graphics=strafesnet_roblox_bot_player::graphics::Graphics::new(device,queue,config);
|
||||||
let map=include_bytes!("../../web-demo/bhop_marble_5692093612.snfm");
|
|
||||||
let bot=strafesnet_roblox_bot_player::bot::CompleteBot::new(bot).unwrap();
|
|
||||||
let map=strafesnet_roblox_bot_player::map::CompleteMap::new(map).unwrap();
|
|
||||||
let mut graphics=strafesnet_roblox_bot_player::graphics::Graphics::new(device,queue,config);
|
|
||||||
graphics.change_map(&map);
|
|
||||||
WindowContext{
|
WindowContext{
|
||||||
simulation_paused:false,
|
simulation_paused:false,
|
||||||
//make sure to update this!!!!!
|
//make sure to update this!!!!!
|
||||||
@@ -162,7 +157,6 @@ impl WindowContext<'_>{
|
|||||||
window,
|
window,
|
||||||
physics_thread:crate::player::PlayerWorker::new(
|
physics_thread:crate::player::PlayerWorker::new(
|
||||||
surface,
|
surface,
|
||||||
bot,
|
|
||||||
graphics,
|
graphics,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ strafesnet_roblox_bot_player = { version = "0.1.0", path = "../lib" }
|
|||||||
strafesnet_common.workspace = true
|
strafesnet_common.workspace = true
|
||||||
strafesnet_graphics.workspace = true
|
strafesnet_graphics.workspace = true
|
||||||
strafesnet_roblox_bot_file.workspace = true
|
strafesnet_roblox_bot_file.workspace = true
|
||||||
|
strafesnet_snf.workspace = true
|
||||||
wasm-bindgen = "0.2.108"
|
wasm-bindgen = "0.2.108"
|
||||||
wasm-bindgen-futures = "0.4.58"
|
wasm-bindgen-futures = "0.4.58"
|
||||||
web-sys = { version = "0.3.85", features = ["HtmlCanvasElement"] }
|
web-sys = { version = "0.3.85", features = ["HtmlCanvasElement"] }
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use wasm_bindgen::prelude::wasm_bindgen;
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
use strafesnet_roblox_bot_file::v0;
|
use strafesnet_roblox_bot_file::v0;
|
||||||
use strafesnet_roblox_bot_player::{bot,map,head,time,graphics};
|
use strafesnet_roblox_bot_player::{bot,head,time,graphics};
|
||||||
use strafesnet_graphics::setup;
|
use strafesnet_graphics::setup;
|
||||||
use strafesnet_common::physics::Time as PhysicsTime;
|
use strafesnet_common::physics::Time as PhysicsTime;
|
||||||
|
|
||||||
@@ -65,8 +65,9 @@ pub struct CompleteBot{
|
|||||||
impl CompleteBot{
|
impl CompleteBot{
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(data:&[u8])->Result<Self,JsValue>{
|
pub fn new(data:&[u8])->Result<Self,JsValue>{
|
||||||
|
let timelines=v0::read_all_to_block(std::io::Cursor::new(data)).map_err(|e|JsValue::from_str(&e.to_string()))?;
|
||||||
Ok(Self{
|
Ok(Self{
|
||||||
bot:bot::CompleteBot::new(data).map_err(|e|JsValue::from_str(&e.to_string()))?,
|
bot:bot::CompleteBot::new(timelines),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@@ -82,14 +83,18 @@ impl CompleteBot{
|
|||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct CompleteMap{
|
pub struct CompleteMap{
|
||||||
map:map::CompleteMap,
|
map:strafesnet_common::map::CompleteMap,
|
||||||
}
|
}
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
impl CompleteMap{
|
impl CompleteMap{
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(data:&[u8])->Result<Self,JsValue>{
|
pub fn new(data:&[u8])->Result<Self,JsValue>{
|
||||||
|
let map=strafesnet_snf::read_map(std::io::Cursor::new(data))
|
||||||
|
.map_err(|e|JsValue::from_str(&e.to_string()))?
|
||||||
|
.into_complete_map()
|
||||||
|
.map_err(|e|JsValue::from_str(&e.to_string()))?;
|
||||||
Ok(Self{
|
Ok(Self{
|
||||||
map:map::CompleteMap::new(data).map_err(|e|JsValue::from_str(&e.to_string()))?,
|
map,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user