fix telekenesis crash

This commit is contained in:
bgkillas 2025-01-25 15:13:03 -05:00
parent 1717a46b7a
commit 82256e68e8
9 changed files with 958 additions and 908 deletions

View file

@ -108,13 +108,35 @@ impl EntityID {
pub fn kill(self) { pub fn kill(self) {
// Shouldn't ever error. // Shouldn't ever error.
for (i, id) in raw::physics_body_id_get_from_entity(self, None) let body_id = raw::physics_body_id_get_from_entity(self, None).unwrap_or_default();
if !body_id.is_empty() {
for com in raw::entity_get_with_tag("ew_peer".into())
.unwrap_or_default() .unwrap_or_default()
.iter() .iter()
.enumerate() .filter_map(|e| {
e.map(|e| {
e.try_get_first_component_including_disabled::<TelekinesisComponent>(None)
})
})
.flatten()
.flatten()
{ {
let n = 17000.0 + (64.0 * (self.0.get() as usize + i) as f64); if body_id.contains(&com.get_body_id()) {
let _ = raw::physics_body_id_set_transform(*id, n, n, 0.0, 0.0, 0.0, 0.0); let _ = raw::component_set_value(*com, "mState", 0);
}
}
for (i, id) in body_id.iter().enumerate() {
let n = 17000.0;
let _ = raw::physics_body_id_set_transform(
*id,
n + 64.0 * self.0.get() as f64,
n + 64.0 * i as f64,
0.0,
0.0,
0.0,
0.0,
);
}
} }
let _ = raw::entity_kill(self); let _ = raw::entity_kill(self);
} }
@ -526,6 +548,12 @@ impl StatusEffectDataComponent {
} }
} }
impl TelekinesisComponent {
pub fn get_body_id(self) -> PhysicsBodyID {
raw::component_get_value_old::<PhysicsBodyID>(*self, "mBodyID").unwrap_or(PhysicsBodyID(0))
}
}
pub fn game_print(value: impl AsRef<str>) { pub fn game_print(value: impl AsRef<str>) {
let _ = raw::game_print(value.as_ref().into()); let _ = raw::game_print(value.as_ref().into());
} }
@ -560,6 +588,21 @@ pub mod raw {
ret.wrap_err_with(|| eyre!("Getting {field} for {component:?}")) ret.wrap_err_with(|| eyre!("Getting {field} for {component:?}"))
} }
pub(crate) fn component_get_value_old<T>(component: ComponentID, field: &str) -> eyre::Result<T>
where
T: LuaGetValue,
{
let lua = LuaState::current()?;
lua.get_global(c"ComponentGetValue");
lua.push_integer(component.0.into());
lua.push_string(field);
lua.call(2, T::size_on_stack())
.wrap_err("Failed to call ComponentGetValue")?;
let ret = T::get(lua, -1);
lua.pop_last_n(T::size_on_stack());
ret.wrap_err_with(|| eyre!("Getting {field} for {component:?}"))
}
pub(crate) fn component_object_get_value<T>( pub(crate) fn component_object_get_value<T>(
component: ComponentID, component: ComponentID,
object: &str, object: &str,

View file

@ -1,7 +1,5 @@
-- You're supposed to `dofile_once("path/to/load.lua")` this file. -- You're supposed to `dofile_once("path/to/load.lua")` this file.
local orig_do_mod_appends = do_mod_appends local orig_do_mod_appends = do_mod_appends
do_mod_appends = function(filename, ...) do_mod_appends = function(filename, ...)

View file

@ -85,10 +85,10 @@ end
---@return EncodedArea? encoded_area returns an EncodedArea or nil if the area could not be encoded ---@return EncodedArea? encoded_area returns an EncodedArea or nil if the area could not be encoded
---@see decode ---@see decode
function world.encode_area(chunk_map, start_x, start_y, end_x, end_y, encoded_area) function world.encode_area(chunk_map, start_x, start_y, end_x, end_y, encoded_area)
start_x = ffi.cast('int32_t', start_x) start_x = ffi.cast("int32_t", start_x)
start_y = ffi.cast('int32_t', start_y) start_y = ffi.cast("int32_t", start_y)
end_x = ffi.cast('int32_t', end_x) end_x = ffi.cast("int32_t", end_x)
end_y = ffi.cast('int32_t', end_y) end_y = ffi.cast("int32_t", end_y)
---@cast start_x integer ---@cast start_x integer
---@cast start_y integer ---@cast start_y integer
---@cast end_x integer ---@cast end_x integer
@ -226,7 +226,8 @@ function world.decode(grid_world, header, pixel_runs)
end end
if current_material ~= new_material and new_material ~= 0 then if current_material ~= new_material and new_material ~= 0 then
local pixel = world_ffi.construct_cell(grid_world, x, y, world_ffi.get_material_ptr(new_material), nil) local pixel =
world_ffi.construct_cell(grid_world, x, y, world_ffi.get_material_ptr(new_material), nil)
if pixel == nil then if pixel == nil then
-- TODO: This can happen when the material texture has a -- TODO: This can happen when the material texture has a
-- transparent pixel at the given coordinate. There's -- transparent pixel at the given coordinate. There's

View file

@ -401,8 +401,8 @@ local CellData_ptr = ffi.typeof("struct CellData*")
---``` ---```
function world_ffi.get_material_ptr(id) function world_ffi.get_material_ptr(id)
local game_global = ffi.cast("char*", gg_ptr) local game_global = ffi.cast("char*", gg_ptr)
local cell_factory = ffi.cast('char**', (game_global + 0x18))[0] local cell_factory = ffi.cast("char**", (game_global + 0x18))[0]
local begin = ffi.cast('char**', cell_factory + 0x18)[0] local begin = ffi.cast("char**", cell_factory + 0x18)[0]
local ptr = begin + celldata_size * id local ptr = begin + celldata_size * id
return ffi.cast(CellData_ptr, ptr) --[[@as CellData]] return ffi.cast(CellData_ptr, ptr) --[[@as CellData]]
end end
@ -416,9 +416,9 @@ end
---See: `world_ffi.get_material_ptr` ---See: `world_ffi.get_material_ptr`
function world_ffi.get_material_id(material) function world_ffi.get_material_id(material)
local game_global = ffi.cast("char*", gg_ptr) local game_global = ffi.cast("char*", gg_ptr)
local cell_factory = ffi.cast('char**', (game_global + 0x18))[0] local cell_factory = ffi.cast("char**", (game_global + 0x18))[0]
local begin = ffi.cast('char**', cell_factory + 0x18)[0] local begin = ffi.cast("char**", cell_factory + 0x18)[0]
local offset = ffi.cast('char*', material) - begin local offset = ffi.cast("char*", material) - begin
return offset / celldata_size return offset / celldata_size
end end

View file

@ -1,6 +1,7 @@
local rpc = net.new_rpc_namespace() local rpc = net.new_rpc_namespace()
local tele = {} local tele = {}
local who_has_tele = {} local who_has_tele = {}
local is_holding
rpc.opts_reliable() rpc.opts_reliable()
function rpc.end_tele() function rpc.end_tele()
@ -29,6 +30,12 @@ function rpc.send_tele(body_gid, n, extent, aimangle, bodyangle, distance, mindi
if not table.contains(who_has_tele, ctx.rpc_peer_id) then if not table.contains(who_has_tele, ctx.rpc_peer_id) then
table.insert(who_has_tele, ctx.rpc_peer_id) table.insert(who_has_tele, ctx.rpc_peer_id)
ComponentSetValue2(com, "mState", 1) ComponentSetValue2(com, "mState", 1)
if is_holding == ent then
local mycom = EntityGetFirstComponent(ctx.my_player.entity, "TelekinesisComponent")
if mycom ~= nil then
ComponentSetValue2(mycom, "mState", 0)
end
end
end end
ComponentSetValue(com, "mBodyID", body_id) ComponentSetValue(com, "mBodyID", body_id)
ComponentSetValue2(com, "mStartBodyMaxExtent", extent) ComponentSetValue2(com, "mStartBodyMaxExtent", extent)
@ -92,6 +99,7 @@ function tele.on_world_update()
end end
end end
if gid ~= nil then if gid ~= nil then
is_holding = ent
has_tele = true has_tele = true
rpc.send_tele( rpc.send_tele(
ComponentGetValue2(gid, "value_string"), ComponentGetValue2(gid, "value_string"),