Skip to content

Commit b4a4b7a

Browse files
committed
dont allow duping items, fix poly enemies
1 parent 8a3fea6 commit b4a4b7a

File tree

9 files changed

+114
-14
lines changed

9 files changed

+114
-14
lines changed

ewext/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ewext/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ bimap = "0.6.3"
2828
#enables cross-compilation on older systems (for example, when compiling on ubuntu 20.04)
2929
#due to unresolved bug in rust toolchain
3030
#https://github.com/rust-lang/rust/issues/79609
31-
pre2204 = []
31+
pre2204 = []

ewext/noita_api/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ewext/noita_api/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ eyre = "0.6.12"
88
libloading = "0.8.5"
99
noita_api_macro = {path = "../noita_api_macro"}
1010
shared = {path = "../../shared"}
11-
strum = "0.26.3"
11+
strum = "0.26.3"
12+
base64 = "0.22.1"

ewext/noita_api/src/lib.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::lua::{LuaGetValue, LuaPutValue};
22
use crate::serialize::deserialize_entity;
3+
use base64::Engine;
34
use eyre::{eyre, Context, OptionExt};
5+
use shared::des::Gid;
46
use shared::{GameEffectData, GameEffectEnum};
57
use std::collections::HashMap;
68
use std::{
@@ -13,7 +15,6 @@ pub mod serialize;
1315

1416
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1517
pub struct EntityID(pub NonZero<isize>);
16-
1718
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1819
pub struct ComponentID(pub NonZero<isize>);
1920

@@ -42,6 +43,54 @@ impl EntityID {
4243
raw::entity_get_name(self).map(|s| s.to_string())
4344
}
4445

46+
pub fn handle_poly(&self) -> Option<Gid> {
47+
for ent in self.children(None) {
48+
if let Ok(Some(effect)) =
49+
ent.try_get_first_component_including_disabled::<GameEffectComponent>(None)
50+
{
51+
let name = effect.effect().unwrap();
52+
match name {
53+
GameEffectEnum::Polymorph
54+
| GameEffectEnum::PolymorphRandom
55+
| GameEffectEnum::PolymorphUnstable
56+
| GameEffectEnum::PolymorphCessation => {
57+
if let Ok(data) =
58+
raw::component_get_value::<Cow<str>>(effect.0, "mSerializedData")
59+
{
60+
if data.is_empty() {
61+
return None;
62+
}
63+
if let Ok(data) =
64+
base64::engine::general_purpose::STANDARD.decode(data.to_string())
65+
{
66+
let data = String::from_utf8_lossy(&data)
67+
.chars()
68+
.filter(|c| c.is_ascii_alphanumeric())
69+
.collect::<String>();
70+
let mut data = data.split("VariableStorageComponentewgidlid");
71+
let _ = data.next();
72+
if let Some(data) = data.next() {
73+
let mut gid = String::new();
74+
for c in data.chars() {
75+
if c.is_numeric() {
76+
gid.push(c)
77+
} else {
78+
break;
79+
}
80+
}
81+
return Some(Gid(gid.parse::<u64>().ok()?));
82+
}
83+
}
84+
}
85+
return None;
86+
}
87+
_ => {}
88+
}
89+
}
90+
}
91+
None
92+
}
93+
4594
pub fn add_tag(self, tag: impl AsRef<str>) -> eyre::Result<()> {
4695
raw::entity_add_tag(self, tag.as_ref().into())
4796
}

ewext/src/modules/entity_sync.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use diff_model::{entity_is_item, LocalDiffModel, RemoteDiffModel, DES_TAG};
1111
use eyre::{Context, OptionExt};
1212
use interest::InterestTracker;
1313
use noita_api::serialize::serialize_entity;
14-
use noita_api::{EntityID, ProjectileComponent};
14+
use noita_api::{game_print, EntityID, ProjectileComponent, VariableStorageComponent};
1515
use rustc_hash::{FxHashMap, FxHashSet};
1616
use shared::{
1717
des::{
@@ -47,6 +47,7 @@ pub(crate) struct EntitySync {
4747

4848
pending_fired_projectiles: Arc<Vec<ProjectileFired>>,
4949
dont_kill: FxHashSet<EntityID>,
50+
dont_kill_by_gid: FxHashSet<Gid>,
5051
dont_track: FxHashSet<EntityID>,
5152
}
5253
impl EntitySync {
@@ -78,6 +79,7 @@ impl Default for EntitySync {
7879

7980
pending_fired_projectiles: Vec::new().into(),
8081
dont_kill: Default::default(),
82+
dont_kill_by_gid: Default::default(),
8183
dont_track: Default::default(),
8284
}
8385
}
@@ -145,7 +147,27 @@ impl EntitySync {
145147
if !entity.is_alive() || self.dont_track.remove(&entity) {
146148
continue;
147149
}
148-
if entity.has_tag(DES_TAG) && !self.dont_kill.remove(&entity) {
150+
if let Some(gid) = entity.handle_poly() {
151+
game_print(gid.0.to_string());
152+
game_print(self.local_diff_model.find_by_gid(gid).is_some().to_string());
153+
self.dont_kill_by_gid.insert(gid);
154+
}
155+
if entity.has_tag(DES_TAG)
156+
&& !self.dont_kill.remove(&entity)
157+
&& entity
158+
.iter_all_components_of_type_including_disabled::<VariableStorageComponent>(
159+
None,
160+
)?
161+
.find(|var| var.name().unwrap_or("".into()) == "ew_gid_lid")
162+
.map(|var| {
163+
if let Ok(n) = var.value_string().unwrap().parse::<u64>() {
164+
!self.dont_kill_by_gid.remove(&Gid(n))
165+
} else {
166+
true
167+
}
168+
})
169+
.unwrap_or(true)
170+
{
149171
entity.kill();
150172
continue;
151173
}
@@ -170,6 +192,9 @@ impl EntitySync {
170192
remote.remove_entities()
171193
}
172194
}
195+
shared::des::ProxyToDes::DeleteEntity(entity) => {
196+
EntityID(entity).kill();
197+
}
173198
}
174199
}
175200

ewext/src/modules/entity_sync/diff_model.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl LocalDiffModelTracker {
134134
let entity = self.entity_by_lid(lid)?;
135135

136136
if !entity.is_alive() {
137-
self.untrack_entity(ctx, gid, lid)?;
137+
self.untrack_entity(ctx, gid, lid, None)?;
138138
return Ok(());
139139
}
140140
let item_and_was_picked = info.kind == EntityKind::Item && item_in_inventory(entity)?;
@@ -362,10 +362,11 @@ impl LocalDiffModelTracker {
362362
ctx: &mut ModuleCtx<'_>,
363363
gid: Gid,
364364
lid: Lid,
365+
ent: Option<NonZero<isize>>,
365366
) -> Result<(), eyre::Error> {
366367
self.pending_removal.push(lid);
367368
ctx.net.send(&NoitaOutbound::DesToProxy(
368-
shared::des::DesToProxy::DeleteEntity(gid),
369+
shared::des::DesToProxy::DeleteEntity(gid, ent),
369370
))?;
370371

371372
Ok(())
@@ -378,7 +379,7 @@ impl LocalDiffModelTracker {
378379
lid: Lid,
379380
entity: EntityID,
380381
) -> Result<(), eyre::Error> {
381-
self.untrack_entity(ctx, gid, lid)?;
382+
self.untrack_entity(ctx, gid, lid, Some(entity.0))?;
382383
entity.remove_tag(DES_TAG)?;
383384
with_entity_scripts(entity, |luac| {
384385
luac.set_script_throw_item(
@@ -596,7 +597,7 @@ impl LocalDiffModel {
596597
.wrap_err("Failed to update local entity")
597598
{
598599
print_error(error)?;
599-
self.tracker.untrack_entity(ctx, *gid, lid)?;
600+
self.tracker.untrack_entity(ctx, *gid, lid, None)?;
600601
}
601602
}
602603
Ok(())
@@ -1601,6 +1602,10 @@ fn _safe_wandkill(entity: EntityID) -> eyre::Result<()> {
16011602
lc.set_script_source_file(
16021603
"mods/quant.ew/files/system/entity_sync_helper/scripts/killself.lua".into(),
16031604
)?;
1605+
entity.set_component_enabled(*lc, true)?;
1606+
lc.add_tag("enabled_in_inventory")?;
1607+
lc.add_tag("enabled_in_world")?;
1608+
lc.add_tag("enabled_in_hand")?;
16041609
lc.set_execute_on_added(false)?;
16051610
lc.set_m_next_execution_time(noita_api::raw::game_get_frame_num()? + 1)?;
16061611
Ok(())

noita-proxy/src/net/des.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,14 @@ impl DesManager {
7676
.entities
7777
.insert(full_entity_data.gid, full_entity_data);
7878
}
79-
DesToProxy::DeleteEntity(gid) => {
80-
self.authority.remove(&gid);
81-
self.entity_storage.entities.remove(&gid);
79+
DesToProxy::DeleteEntity(gid, ent) => {
80+
if self.entity_storage.entities.contains_key(&gid) {
81+
self.authority.remove(&gid);
82+
self.entity_storage.entities.remove(&gid);
83+
} else if let Some(ent) = ent {
84+
self.pending_messages
85+
.push((source, ProxyToDes::DeleteEntity(ent)));
86+
}
8287
}
8388
DesToProxy::ReleaseAuthority(gid) => {
8489
self.authority.remove(&gid);

shared/src/des.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::num::NonZero;
12
use std::sync::Arc;
23

34
use crate::{GameEffectData, PeerId, WorldPos};
@@ -44,7 +45,7 @@ pub struct UpdatePosition {
4445
#[derive(Encode, Decode, Clone)]
4546
pub enum DesToProxy {
4647
InitOrUpdateEntity(FullEntityData),
47-
DeleteEntity(Gid),
48+
DeleteEntity(Gid, Option<NonZero<isize>>),
4849
ReleaseAuthority(Gid),
4950
RequestAuthority { pos: WorldPos, radius: i32 },
5051
UpdatePositions(Vec<UpdatePosition>),
@@ -56,8 +57,8 @@ pub enum ProxyToDes {
5657
/// Got authority over entity.
5758
GotAuthority(FullEntityData),
5859
RemoveEntities(PeerId),
60+
DeleteEntity(NonZero<isize>),
5961
}
60-
6162
#[derive(Encode, Decode, Clone)]
6263
pub struct InterestRequest {
6364
pub pos: WorldPos,

0 commit comments

Comments
 (0)