complete a bunch of entity functions

This commit is contained in:
bgkillas 2025-07-22 12:45:49 -04:00
parent b7ccd4d9ec
commit 9819ffb9a0
3 changed files with 177 additions and 50 deletions

View file

@ -49,7 +49,7 @@ pub struct GlobalsRef {
pub platform: &'static Platform, pub platform: &'static Platform,
pub global_stats: &'static GlobalStats, pub global_stats: &'static GlobalStats,
pub filenames: &'static StdVec<StdString>, pub filenames: &'static StdVec<StdString>,
pub wand_pickup: &'static Inventory, pub inventory: &'static Inventory,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct GlobalsMut { pub struct GlobalsMut {
@ -64,7 +64,7 @@ pub struct GlobalsMut {
pub platform: &'static mut Platform, pub platform: &'static mut Platform,
pub global_stats: &'static mut GlobalStats, pub global_stats: &'static mut GlobalStats,
pub filenames: &'static mut StdVec<StdString>, pub filenames: &'static mut StdVec<StdString>,
pub wand_pickup: &'static mut Inventory, pub inventory: &'static mut Inventory,
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -80,7 +80,7 @@ pub struct Globals {
pub platform: *mut Platform, pub platform: *mut Platform,
pub global_stats: *mut GlobalStats, pub global_stats: *mut GlobalStats,
pub filenames: *mut StdVec<StdString>, pub filenames: *mut StdVec<StdString>,
pub wand_pickup: *mut Inventory, pub inventory: *mut Inventory,
} }
#[allow(clippy::mut_from_ref)] #[allow(clippy::mut_from_ref)]
impl Globals { impl Globals {
@ -123,8 +123,8 @@ impl Globals {
pub fn filenames(&self) -> &'static StdVec<StdString> { pub fn filenames(&self) -> &'static StdVec<StdString> {
unsafe { self.filenames.as_ref().unwrap() } unsafe { self.filenames.as_ref().unwrap() }
} }
pub fn wand_pickup(&self) -> &'static Inventory { pub fn inventory(&self) -> &'static Inventory {
unsafe { self.wand_pickup.as_ref().unwrap() } unsafe { self.inventory.as_ref().unwrap() }
} }
pub fn world_seed_mut(&self) -> &'static mut usize { pub fn world_seed_mut(&self) -> &'static mut usize {
unsafe { self.world_seed.as_mut().unwrap() } unsafe { self.world_seed.as_mut().unwrap() }
@ -165,8 +165,8 @@ impl Globals {
pub fn filenames_mut(&self) -> &'static mut StdVec<StdString> { pub fn filenames_mut(&self) -> &'static mut StdVec<StdString> {
unsafe { self.filenames.as_mut().unwrap() } unsafe { self.filenames.as_mut().unwrap() }
} }
pub fn wand_pickup_mut(&self) -> &'static mut Inventory { pub fn inventory_mut(&self) -> &'static mut Inventory {
unsafe { self.wand_pickup.as_mut().unwrap() } unsafe { self.inventory.as_mut().unwrap() }
} }
pub fn as_ref(&self) -> GlobalsRef { pub fn as_ref(&self) -> GlobalsRef {
GlobalsRef { GlobalsRef {
@ -181,7 +181,7 @@ impl Globals {
platform: self.platform(), platform: self.platform(),
global_stats: self.global_stats(), global_stats: self.global_stats(),
filenames: self.filenames(), filenames: self.filenames(),
wand_pickup: self.wand_pickup(), inventory: self.inventory(),
} }
} }
pub fn as_mut(&self) -> GlobalsMut { pub fn as_mut(&self) -> GlobalsMut {
@ -197,7 +197,7 @@ impl Globals {
platform: self.platform_mut(), platform: self.platform_mut(),
global_stats: self.global_stats_mut(), global_stats: self.global_stats_mut(),
filenames: self.filenames_mut(), filenames: self.filenames_mut(),
wand_pickup: self.wand_pickup_mut(), inventory: self.inventory_mut(),
} }
} }
pub fn new(lua: LuaState) -> Self { pub fn new(lua: LuaState) -> Self {
@ -217,7 +217,7 @@ impl Globals {
let translation_manager = 0x1207c28 as *mut TranslationManager; let translation_manager = 0x1207c28 as *mut TranslationManager;
let platform = 0x1221bc0 as *mut Platform; let platform = 0x1221bc0 as *mut Platform;
let filenames = 0x1207bd4 as *mut StdVec<StdString>; let filenames = 0x1207bd4 as *mut StdVec<StdString>;
let wand_pickup = 0x12224f0 as *mut Inventory; let inventory = 0x12224f0 as *mut Inventory;
Self { Self {
world_seed, world_seed,
new_game_count, new_game_count,
@ -230,7 +230,7 @@ impl Globals {
platform, platform,
global_stats, global_stats,
filenames, filenames,
wand_pickup, inventory,
} }
} }
} }

View file

@ -1,6 +1,5 @@
use crate::noita::types::component::{ComponentData, ComponentManager}; use crate::noita::types::component::{ComponentData, ComponentManager};
use crate::noita::types::{StdMap, StdString, StdVec, Vec2}; use crate::noita::types::{StdMap, StdString, StdVec, Vec2};
use std::cmp::Ordering;
use std::slice; use std::slice;
impl EntityManager { impl EntityManager {
pub fn get_entity_with_tag( pub fn get_entity_with_tag(
@ -24,38 +23,18 @@ impl EntityManager {
} }
} }
pub fn get_entity(&self, id: usize) -> Option<&'static Entity> { pub fn get_entity(&self, id: usize) -> Option<&'static Entity> {
for ent in self self.entities
.entities
.as_ref() .as_ref()
.iter() .iter()
.filter_map(|c| unsafe { c.as_ref() }) .filter_map(|c| unsafe { c.as_ref() })
{ .find(|ent| ent.id == id)
match ent.id.cmp(&id) {
Ordering::Less => {}
Ordering::Equal => return Some(ent),
Ordering::Greater => {
return None;
}
}
}
None
} }
pub fn get_entity_mut(&mut self, id: usize) -> Option<&'static mut Entity> { pub fn get_entity_mut(&mut self, id: usize) -> Option<&'static mut Entity> {
for ent in self self.entities
.entities .as_mut()
.as_ref() .iter_mut()
.iter()
.filter_map(|c| unsafe { c.as_mut() }) .filter_map(|c| unsafe { c.as_mut() })
{ .find(|ent| ent.id == id)
match ent.id.cmp(&id) {
Ordering::Less => {}
Ordering::Equal => return Some(ent),
Ordering::Greater => {
return None;
}
}
}
None
} }
pub fn iter_entities_with_tag( pub fn iter_entities_with_tag(
&self, &self,
@ -63,15 +42,13 @@ impl EntityManager {
tag: &StdString, tag: &StdString,
) -> impl Iterator<Item = &'static Entity> { ) -> impl Iterator<Item = &'static Entity> {
unsafe { unsafe {
if let Some(n) = tag_manager.tag_indices.get(tag).copied() { if let Some(n) = tag_manager.tag_indices.get(tag).copied()
if let Some(v) = self.entity_buckets.get(n as usize) { && let Some(v) = self.entity_buckets.get(n as usize)
{
v.as_ref() v.as_ref()
} else { } else {
&[] &[]
} }
} else {
&[]
}
.iter() .iter()
.filter_map(|e| e.as_ref()) .filter_map(|e| e.as_ref())
} }
@ -82,15 +59,13 @@ impl EntityManager {
tag: &StdString, tag: &StdString,
) -> impl Iterator<Item = &'static mut Entity> { ) -> impl Iterator<Item = &'static mut Entity> {
unsafe { unsafe {
if let Some(n) = tag_manager.tag_indices.get(tag).copied() { if let Some(n) = tag_manager.tag_indices.get(tag).copied()
if let Some(v) = self.entity_buckets.get_mut(n as usize) { && let Some(v) = self.entity_buckets.get_mut(n as usize)
{
v.as_mut() v.as_mut()
} else { } else {
&mut [] &mut []
} }
} else {
&mut []
}
.iter_mut() .iter_mut()
.filter_map(|e| e.as_mut()) .filter_map(|e| e.as_mut())
} }
@ -135,6 +110,118 @@ impl EntityManager {
self.iter_component_managers_mut() self.iter_component_managers_mut()
.flat_map(move |c| c.iter_components_mut(ent)) .flat_map(move |c| c.iter_components_mut(ent))
} }
pub fn get_in_radius(&self, pos: Vec2, radius: f32) -> impl Iterator<Item = &'static Entity> {
self.entities
.as_ref()
.iter()
.filter_map(|e| unsafe { e.as_ref() })
.filter(move |e| pos.abs2(&e.transform.pos) < radius * radius)
}
pub fn get_in_radius_with_tag(
&self,
tag_manager: &TagManager<u16>,
pos: Vec2,
radius: f32,
tag: &StdString,
) -> impl Iterator<Item = &'static Entity> {
if let Some(tag) = tag_manager.tag_indices.get(tag).copied()
&& let Some(ents) = self.entity_buckets.get(tag as usize)
{
ents.as_ref()
} else {
&[]
}
.iter()
.filter_map(|e| unsafe { e.as_ref() })
.filter(move |e| pos.abs2(&e.transform.pos) < radius * radius)
}
pub fn get_in_radius_mut(
&mut self,
pos: Vec2,
radius: f32,
) -> impl Iterator<Item = &'static mut Entity> {
self.entities
.as_mut()
.iter_mut()
.filter_map(|e| unsafe { e.as_mut() })
.filter(move |e| pos.abs2(&e.transform.pos) < radius * radius)
}
pub fn get_in_radius_with_tag_mut(
&mut self,
tag_manager: &TagManager<u16>,
pos: Vec2,
radius: f32,
tag: &StdString,
) -> impl Iterator<Item = &'static mut Entity> {
if let Some(tag) = tag_manager.tag_indices.get(tag).copied()
&& let Some(ents) = self.entity_buckets.get_mut(tag as usize)
{
ents.as_mut()
} else {
&mut []
}
.iter_mut()
.filter_map(|e| unsafe { e.as_mut() })
.filter(move |e| pos.abs2(&e.transform.pos) < radius * radius)
}
pub fn get_with_name(&self, name: StdString) -> Option<&'static Entity> {
self.entities.as_ref().iter().find_map(|e| {
unsafe { e.as_ref() }.and_then(|e| if e.name == name { Some(e) } else { None })
})
}
pub fn get_closest(&self, pos: Vec2) -> Option<&'static Entity> {
self.entities
.as_ref()
.iter()
.filter_map(|e| unsafe { e.as_ref().map(|e| (pos.abs2(&e.transform.pos), e)) })
.min_by(|(a, _), (b, _)| a.total_cmp(b))
.map(|(_, e)| e)
}
pub fn get_closest_with_tag(
&self,
tag_manager: &TagManager<u16>,
pos: Vec2,
tag: &StdString,
) -> Option<&'static Entity> {
tag_manager.tag_indices.get(tag).copied().and_then(|tag| {
self.entity_buckets.get(tag as usize).and_then(|b| {
b.as_ref()
.iter()
.filter_map(|e| unsafe { e.as_ref().map(|e| (pos.abs2(&e.transform.pos), e)) })
.min_by(|(a, _), (b, _)| a.total_cmp(b))
.map(|(_, e)| e)
})
})
}
pub fn get_with_name_mut(&mut self, name: StdString) -> Option<&'static mut Entity> {
self.entities.as_mut().iter_mut().find_map(|e| {
unsafe { e.as_mut() }.and_then(|e| if e.name == name { Some(e) } else { None })
})
}
pub fn get_closest_mut(&mut self, pos: Vec2) -> Option<&'static mut Entity> {
self.entities
.as_mut()
.iter_mut()
.filter_map(|e| unsafe { e.as_mut().map(|e| (pos.abs2(&e.transform.pos), e)) })
.min_by(|(a, _), (b, _)| a.total_cmp(b))
.map(|(_, e)| e)
}
pub fn get_closest_with_tag_mut(
&mut self,
tag_manager: &TagManager<u16>,
pos: Vec2,
tag: &StdString,
) -> Option<&'static mut Entity> {
tag_manager.tag_indices.get(tag).copied().and_then(|tag| {
self.entity_buckets.get_mut(tag as usize).and_then(|b| {
b.as_mut()
.iter_mut()
.filter_map(|e| unsafe { e.as_mut().map(|e| (pos.abs2(&e.transform.pos), e)) })
.min_by(|(a, _), (b, _)| a.total_cmp(b))
.map(|(_, e)| e)
})
})
}
} }
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
@ -156,6 +243,13 @@ impl BitSet<16> {
self.0[out_index as usize] &= !(1 << in_index) self.0[out_index as usize] &= !(1 << in_index)
} }
} }
pub fn count(&self) -> usize {
let mut n = 0;
for s in self.0 {
n += s.count_ones()
}
n as usize
}
} }
impl BitSet<8> { impl BitSet<8> {
#[inline] #[inline]
@ -174,6 +268,13 @@ impl BitSet<8> {
self.0[out_index as usize] &= !(1 << in_index) self.0[out_index as usize] &= !(1 << in_index)
} }
} }
pub fn count(&self) -> usize {
let mut n = 0;
for s in self.0 {
n += s.count_ones()
}
n as usize
}
} }
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
@ -204,6 +305,13 @@ impl Entity {
self.kill_flag = 1; self.kill_flag = 1;
self.iter_children_mut().for_each(|e| e.kill()); self.iter_children_mut().for_each(|e| e.kill());
} }
pub fn kill_safe(&mut self, inventory: &mut Inventory) {
if inventory.wand_pickup == self {
inventory.wand_pickup = std::ptr::null_mut();
inventory.pickup_state = 0;
}
self.kill();
}
pub fn iter_children(&self) -> impl DoubleEndedIterator<Item = &'static Entity> { pub fn iter_children(&self) -> impl DoubleEndedIterator<Item = &'static Entity> {
unsafe { unsafe {
if let Some(child) = self.children.as_ref() { if let Some(child) = self.children.as_ref() {
@ -314,6 +422,15 @@ impl Entity {
self.tags.set(n, false) self.tags.set(n, false)
} }
} }
pub fn get_tags(
&'static self,
tag_manager: &TagManager<u16>,
) -> impl Iterator<Item = &'static StdString> {
tag_manager
.tag_indices
.iter()
.filter_map(|(a, b)| if self.tags.get(*b) { Some(a) } else { None })
}
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -303,6 +303,16 @@ pub struct Vec2 {
pub x: f32, pub x: f32,
pub y: f32, pub y: f32,
} }
impl Vec2 {
pub fn abs(&self, other: &Vec2) -> f32 {
(self.y - other.y).hypot(self.x - other.x)
}
pub fn abs2(&self, other: &Vec2) -> f32 {
let dy = self.y - other.y;
let dx = self.x - other.x;
dx * dx + dy * dy
}
}
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
pub struct Vec2i { pub struct Vec2i {