forked from StrafesNET/roblox-bot-player
168 lines
5.0 KiB
Rust
168 lines
5.0 KiB
Rust
use wasm_bindgen::prelude::wasm_bindgen;
|
|
use wasm_bindgen::JsValue;
|
|
use strafesnet_roblox_bot_file::v0;
|
|
use strafesnet_roblox_bot_player::{bot,head,time,graphics};
|
|
use strafesnet_graphics::setup;
|
|
use strafesnet_common::physics::Time as PhysicsTime;
|
|
|
|
mod ratio;
|
|
|
|
// Hack to keep the code compiling,
|
|
// SurfaceTarget::Canvas is not available in IDE for whatever reason.
|
|
struct ToSurfaceTarget(web_sys::HtmlCanvasElement);
|
|
impl From<ToSurfaceTarget> for wgpu::SurfaceTarget<'static>{
|
|
fn from(ToSurfaceTarget(canvas):ToSurfaceTarget)->Self{
|
|
#[cfg(target_arch = "wasm32")]
|
|
let target=wgpu::SurfaceTarget::Canvas(canvas);
|
|
#[expect(unused)]
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
let target=panic!("{canvas:?}");
|
|
#[allow(unused)]
|
|
target
|
|
}
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct Graphics{
|
|
graphics:graphics::Graphics,
|
|
surface:wgpu::Surface<'static>,
|
|
}
|
|
#[wasm_bindgen]
|
|
pub async fn setup_graphics(canvas:web_sys::HtmlCanvasElement)->Graphics{
|
|
let size=(canvas.width(),canvas.height());
|
|
|
|
let instance=setup::step1::create_instance();
|
|
let surface=setup::step2::create_surface(&instance,ToSurfaceTarget(canvas)).unwrap();
|
|
let adapter=setup::step3::pick_adapter(&instance,&surface).await.expect("No suitable GPU adapters found on the system!");
|
|
let (device,queue)=setup::step4::request_device(&adapter).await;
|
|
let config=setup::step5::configure_surface(&adapter,&device,&surface,size);
|
|
Graphics{
|
|
graphics:graphics::Graphics::new(device,queue,config),
|
|
surface:surface,
|
|
}
|
|
}
|
|
#[wasm_bindgen]
|
|
impl Graphics{
|
|
#[wasm_bindgen]
|
|
pub fn render(&mut self,bot:&CompleteBot,head:&PlaybackHead,time:f64){
|
|
let time=time::from_float(time).unwrap();
|
|
let (pos,angles)=head.head.get_position_angles(&bot.bot,time);
|
|
self.graphics.render(&self.surface,pos,angles);
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn resize(&mut self,width:u32,height:u32){
|
|
self.graphics.resize(&self.surface,[width,height].into());
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn change_map(&mut self,map:&CompleteMap){
|
|
self.graphics.change_map(&map.map);
|
|
}
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct CompleteBot{
|
|
bot:bot::CompleteBot,
|
|
}
|
|
#[wasm_bindgen]
|
|
impl CompleteBot{
|
|
#[wasm_bindgen(constructor)]
|
|
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{
|
|
bot:bot::CompleteBot::new(timelines),
|
|
})
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn duration(&self)->f64{
|
|
self.bot.duration().get() as f64/PhysicsTime::ONE_SECOND.get() as f64
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn run_duration(&self,mode_id:u32)->Option<f64>{
|
|
let mode=v0::ModeID(mode_id);
|
|
Some(self.bot.run_duration(mode)?.get() as f64/PhysicsTime::ONE_SECOND.get() as f64)
|
|
}
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct CompleteMap{
|
|
map:strafesnet_common::map::CompleteMap,
|
|
}
|
|
#[wasm_bindgen]
|
|
impl CompleteMap{
|
|
#[wasm_bindgen(constructor)]
|
|
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{
|
|
map,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct PlaybackHead{
|
|
head:head::PlaybackHead,
|
|
}
|
|
#[wasm_bindgen]
|
|
impl PlaybackHead{
|
|
#[wasm_bindgen(constructor)]
|
|
pub fn new(time:f64)->Result<Self,JsValue>{
|
|
let time=time::from_float(time).unwrap();
|
|
Ok(Self{
|
|
head:head::PlaybackHead::new(time),
|
|
})
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn advance_time(&mut self,bot:&CompleteBot,time:f64){
|
|
let time=time::from_float(time).unwrap();
|
|
self.head.advance_time(&bot.bot,time);
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn get_run_time(&self,bot:&CompleteBot,time:f64,mode_id:u32)->Option<f64>{
|
|
let time=time::from_float(time).unwrap();
|
|
let time=self.head.time(&bot.bot,time);
|
|
let mode=v0::ModeID(mode_id);
|
|
let run_time=self.head.state().get_run(mode)?.time(time);
|
|
Some(run_time.get() as f64/strafesnet_common::run::Time::ONE_SECOND.get() as f64)
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn is_run_in_progress(&self,mode_id:u32)->Option<bool>{
|
|
let mode=v0::ModeID(mode_id);
|
|
Some(self.head.state().get_run(mode)?.is_in_progress())
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn is_run_finished(&self,mode_id:u32)->Option<bool>{
|
|
let mode=v0::ModeID(mode_id);
|
|
Some(self.head.state().get_run(mode)?.is_finished())
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn set_paused(&mut self,time:f64,paused:bool){
|
|
let time=time::from_float(time).unwrap();
|
|
self.head.set_paused(time,paused);
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn set_scale(&mut self,time:f64,scale:f64){
|
|
let time=time::from_float(time).unwrap();
|
|
let scale=crate::ratio::ratio_from_float(scale).unwrap();
|
|
self.head.set_scale(time,scale);
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn seek_to(&mut self,time:f64,new_time:f64){
|
|
let time=time::from_float(time).unwrap();
|
|
let new_time=time::from_float(new_time).unwrap();
|
|
self.head.seek_to(time,new_time);
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn seek_forward(&mut self,time_offset:f64){
|
|
let time_offset=time::from_float(time_offset).unwrap();
|
|
self.head.seek_forward(time_offset);
|
|
}
|
|
#[wasm_bindgen]
|
|
pub fn seek_backward(&mut self,time_offset:f64){
|
|
let time_offset=time::from_float(time_offset).unwrap();
|
|
self.head.seek_backward(time_offset);
|
|
}
|
|
}
|