From 05bd0736ff8954b25d40908ebda64b09fd45bf57 Mon Sep 17 00:00:00 2001 From: bgkillas Date: Thu, 21 Aug 2025 15:44:40 -0400 Subject: [PATCH] fix vanilla error and borrow error --- ewext/src/lib.rs | 29 +++++++++----- ewext/src/modules/entity_sync.rs | 14 +++---- ewext/src/modules/entity_sync/diff_model.rs | 19 ++++++--- .../data/scripts/animals/tiny_ghost_spawn.lua | 39 +++++++++++++++++++ 4 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 quant.ew/data/scripts/animals/tiny_ghost_spawn.lua diff --git a/ewext/src/lib.rs b/ewext/src/lib.rs index 34ebdd56..229ca805 100644 --- a/ewext/src/lib.rs +++ b/ewext/src/lib.rs @@ -8,6 +8,7 @@ use modules::{Module, ModuleCtx, entity_sync::EntitySync}; use net::NetManager; use noita_api::add_lua_fn; use noita_api::addr_grabber::Globals; +use noita_api::noita::types::EntityManager; use noita_api::noita::world::ParticleWorldState; use noita_api::{ EntityID, VariableStorageComponent, @@ -105,17 +106,17 @@ impl ExtState { }) } } - -pub fn ephemerial(entity_id: usize) -> eyre::Result<()> { - ExtState::with_global(|state| { - if let Some(entity) = state.globals.entity_manager_mut().get_entity_mut(entity_id) { - entity.filename_index = 0; - } - }) +pub fn ephemerial(entity_id: usize, em: &mut EntityManager) { + if let Some(entity) = em.get_entity_mut(entity_id) { + entity.filename_index = 0; + } } fn make_ephemerial(lua: LuaState) -> eyre::Result<()> { let entity_id = lua.to_integer(1).cast_unsigned(); - ephemerial(entity_id)?; + ephemerial( + entity_id, + ExtState::with_global(|state| state.globals.entity_manager_mut())?, + ); Ok(()) } @@ -152,8 +153,15 @@ fn netmanager_recv(_lua: LuaState) -> eyre::Result> { NoitaInbound::Ready { .. } => bail!("Unexpected Ready message"), NoitaInbound::ProxyToDes(proxy_to_des) => ExtState::with_global(|state| { let _lock = IN_MODULE_LOCK.lock().unwrap(); - if let Err(e) = state.modules.entity_sync.handle_proxytodes(proxy_to_des) { - let _ = print_error(e); + match state.modules.entity_sync.handle_proxytodes(proxy_to_des) { + Err(e) => { + let _ = print_error(e); + } + Ok(Some(peer)) => { + state.fps_by_player.remove(&peer); + state.player_entity_map.remove_by_left(&peer); + } + Ok(None) => {} } })?, NoitaInbound::RemoteMessage { @@ -168,6 +176,7 @@ fn netmanager_recv(_lua: LuaState) -> eyre::Result> { &state.player_entity_map, &mut state.dont_spawn, &mut state.cam_pos, + state.globals.entity_manager_mut(), ) { Ok(()) => {} Err(s) => { diff --git a/ewext/src/modules/entity_sync.rs b/ewext/src/modules/entity_sync.rs index 1e78181a..04b0f256 100644 --- a/ewext/src/modules/entity_sync.rs +++ b/ewext/src/modules/entity_sync.rs @@ -205,6 +205,7 @@ impl EntitySync { None, *drops_gold, &mut self.entity_manager, + ctx.globals.entity_manager, )?; if let Some(damage) = entity .try_get_first_component::(None)? @@ -324,7 +325,7 @@ impl EntitySync { pub(crate) fn handle_proxytodes( &mut self, proxy_to_des: shared::des::ProxyToDes, - ) -> eyre::Result<()> { + ) -> eyre::Result> { match proxy_to_des { shared::des::ProxyToDes::GotAuthority(full_entity_data) => { self.local_diff_model.got_authority(full_entity_data); @@ -337,18 +338,16 @@ impl EntitySync { remote.remove_entities(&mut self.entity_manager)? } self.interest_tracker.remove_peer(peer); - let _ = crate::ExtState::with_global(|state| { - state.fps_by_player.remove(&peer); - state.player_entity_map.remove_by_left(&peer); - }); + return Ok(Some(peer)); } shared::des::ProxyToDes::DeleteEntity(entity) => { EntityID(entity).kill(); } } - Ok(()) + Ok(None) } + #[allow(clippy::too_many_arguments)] pub(crate) fn handle_remotedes( &mut self, source: PeerId, @@ -357,6 +356,7 @@ impl EntitySync { player_entity_map: &BiHashMap, dont_spawn: &mut FxHashSet, cam_pos: &mut FxHashMap, + em: &mut noita_api::noita::types::EntityManager, ) -> eyre::Result<()> { match remote_des { RemoteDes::ChestOpen(gid, x, y, file, rx, ry) => { @@ -448,7 +448,7 @@ impl EntitySync { self.remote_models .entry(source) .or_insert(RemoteDiffModel::new(source)) - .apply_init(vec, &mut self.entity_manager), + .apply_init(vec, &mut self.entity_manager, em)?, ); } RemoteDes::ExitedInterest => { diff --git a/ewext/src/modules/entity_sync/diff_model.rs b/ewext/src/modules/entity_sync/diff_model.rs index 70653ed4..1e8b52f2 100644 --- a/ewext/src/modules/entity_sync/diff_model.rs +++ b/ewext/src/modules/entity_sync/diff_model.rs @@ -1528,19 +1528,26 @@ impl RemoteDiffModel { &mut self, diff: Vec, entity_manager: &mut EntityManager, - ) -> Vec { + em: &mut noita_api::noita::types::EntityManager, + ) -> eyre::Result> { let mut dont_kill = Vec::with_capacity(self.waiting_for_lid.len()); for info in diff { if let Some(ent) = self.waiting_for_lid.remove(&info.gid) { self.tracked.insert(info.lid, ent); - let _ = - init_remote_entity(ent, Some(info.lid), Some(info.gid), false, entity_manager); + let _ = init_remote_entity( + ent, + Some(info.lid), + Some(info.gid), + false, + entity_manager, + em, + ); dont_kill.push(ent); } self.lid_to_gid.insert(info.lid, info.gid); self.entity_infos.insert(info.lid, info.info); } - dont_kill + Ok(dont_kill) } pub(crate) fn apply_diff( &mut self, @@ -2059,6 +2066,7 @@ impl RemoteDiffModel { self.lid_to_gid.get(lid).copied(), entity_info.drops_gold, entity_manager, + ctx.globals.entity_manager, )?; self.tracked.insert(*lid, entity); } @@ -2187,6 +2195,7 @@ pub fn init_remote_entity( gid: Option, drops_gold: bool, entity_manager: &mut EntityManager, + em: &mut noita_api::noita::types::EntityManager, ) -> eyre::Result<()> { if entity.has_tag("player_unit") { entity.kill(); @@ -2397,7 +2406,7 @@ pub fn init_remote_entity( .try_get_first_component_including_disabled::(ComponentTag::None) .is_none() { - ephemerial(entity.0.get().cast_unsigned())? + ephemerial(entity.0.get().cast_unsigned(), em) } Ok(()) diff --git a/quant.ew/data/scripts/animals/tiny_ghost_spawn.lua b/quant.ew/data/scripts/animals/tiny_ghost_spawn.lua new file mode 100644 index 00000000..dfd813a8 --- /dev/null +++ b/quant.ew/data/scripts/animals/tiny_ghost_spawn.lua @@ -0,0 +1,39 @@ +dofile_once("data/scripts/lib/utilities.lua") + +--function collision_trigger(target_id) +local entity_id = GetUpdatedEntityID() +local x, y = EntityGetTransform(entity_id) +local target_id = EntityGetClosestWithTag(x, y, "enemy") +if not target_id then + return +end + +if not IsPlayer(target_id) and EntityGetIsAlive(target_id) then + --print("ghost added: " .. x .. ", " .. y) + + local children = EntityGetAllChildren(entity_id) + if #children == 0 then + return + end + local ghost_id = children[1] + + -- reduce health of target for balance + component_readwrite( + EntityGetFirstComponent(target_id, "DamageModelComponent"), + { hp = 0, max_hp = 0 }, + function(comp) + comp.max_hp = math.max(comp.max_hp * 0.75, comp.max_hp - 3) + comp.hp = comp.max_hp + end + ) + + -- enable ghost + for _, comp in pairs(EntityGetAllComponents(ghost_id)) do + EntitySetComponentIsEnabled(ghost_id, comp, true) + end + + -- transfer ghost & remove spawner + EntityRemoveFromParent(ghost_id) + EntityAddChild(target_id, ghost_id) + EntityKill(entity_id) +end