arcane_engine/scripting/
replay_ops.rs1use std::cell::RefCell;
7use std::rc::Rc;
8
9use deno_core::OpState;
10
11use crate::physics::types::*;
12use super::physics_ops::PhysicsState;
13
14#[deno_core::op2]
24#[serde]
25fn op_serialize_physics_state(state: &mut OpState) -> Vec<f64> {
26 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
27 let ps = physics.borrow();
28 let world = match ps.0.as_ref() {
29 Some(w) => w,
30 None => return vec![],
31 };
32
33 let mut result: Vec<f64> = Vec::new();
34
35 let bodies = world.all_bodies();
37 let gravity = world.gravity();
38
39 result.push(bodies.len() as f64);
41 result.push(gravity.0 as f64);
42 result.push(gravity.1 as f64);
43
44 for body in &bodies {
46 result.push(body.id as f64);
47 result.push(match body.body_type {
48 BodyType::Static => 0.0,
49 BodyType::Dynamic => 1.0,
50 BodyType::Kinematic => 2.0,
51 });
52 match &body.shape {
53 Shape::Circle { radius } => {
54 result.push(0.0); result.push(*radius as f64); result.push(0.0); }
58 Shape::AABB { half_w, half_h } => {
59 result.push(1.0); result.push(*half_w as f64); result.push(*half_h as f64); }
63 Shape::Polygon { .. } => {
64 result.push(2.0); result.push(0.0);
66 result.push(0.0);
67 }
68 }
69 result.push(body.x as f64);
70 result.push(body.y as f64);
71 result.push(body.angle as f64);
72 result.push(body.vx as f64);
73 result.push(body.vy as f64);
74 result.push(body.angular_velocity as f64);
75 result.push(body.mass as f64);
76 result.push(body.material.restitution as f64);
77 result.push(body.material.friction as f64);
78 result.push(body.layer as f64);
79 result.push(body.mask as f64);
80 }
81
82 result
83}
84
85#[deno_core::op2]
90fn op_restore_physics_state(state: &mut OpState, #[serde] data: Vec<f64>) {
91 if data.len() < 3 {
92 return;
93 }
94
95 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
96 let mut ps = physics.borrow_mut();
97
98 let body_count = data[0] as usize;
99 let gravity_x = data[1] as f32;
100 let gravity_y = data[2] as f32;
101
102 let mut world = crate::physics::world::PhysicsWorld::new(gravity_x, gravity_y);
104
105 let mut offset = 3;
107 for _ in 0..body_count {
108 if offset + 16 > data.len() {
109 break;
110 }
111
112 let _id = data[offset] as u32;
113 let body_type = match data[offset + 1] as u32 {
114 0 => BodyType::Static,
115 1 => BodyType::Dynamic,
116 2 => BodyType::Kinematic,
117 _ => BodyType::Dynamic,
118 };
119 let shape_type = data[offset + 2] as u32;
120 let shape_p1 = data[offset + 3] as f32;
121 let shape_p2 = data[offset + 4] as f32;
122 let x = data[offset + 5] as f32;
123 let y = data[offset + 6] as f32;
124 let _angle = data[offset + 7] as f32;
125 let vx = data[offset + 8] as f32;
126 let vy = data[offset + 9] as f32;
127 let _angular_velocity = data[offset + 10] as f32;
128 let mass = data[offset + 11] as f32;
129 let restitution = data[offset + 12] as f32;
130 let friction = data[offset + 13] as f32;
131 let layer = data[offset + 14] as u16;
132 let mask = data[offset + 15] as u16;
133
134 let shape = match shape_type {
135 0 => Shape::Circle { radius: shape_p1 },
136 1 => Shape::AABB { half_w: shape_p1, half_h: shape_p2 },
137 _ => Shape::AABB { half_w: shape_p1, half_h: shape_p2 },
138 };
139
140 let id = world.add_body(
141 body_type,
142 shape,
143 x, y,
144 mass,
145 Material { restitution, friction },
146 layer, mask,
147 );
148
149 world.set_velocity(id, vx, vy);
151
152 offset += 16;
153 }
154
155 ps.0 = Some(world);
156}
157
158#[deno_core::op2(fast)]
160fn op_get_physics_body_count(state: &mut OpState) -> u32 {
161 let physics = state.borrow_mut::<Rc<RefCell<PhysicsState>>>();
162 let ps = physics.borrow();
163 match ps.0.as_ref() {
164 Some(world) => world.body_count() as u32,
165 None => 0,
166 }
167}
168
169deno_core::extension!(
170 replay_ext,
171 ops = [
172 op_serialize_physics_state,
173 op_restore_physics_state,
174 op_get_physics_body_count,
175 ],
176);