more type info

This commit is contained in:
bgkillas 2025-07-18 23:42:15 -04:00
parent d15ccb2f5d
commit d9769e4b24
5 changed files with 119 additions and 90 deletions

View file

@ -33,18 +33,7 @@ pub struct StdString {
size: usize,
capacity: usize,
}
impl<'a> StdString {
pub fn as_str(&'a self) -> &'a str {
let slice: &[u8] = unsafe {
if self.capacity <= 16 {
&self.buffer.sso_buffer
} else {
slice::from_raw_parts(self.buffer.buffer, self.size)
}
};
let actual_len = slice.iter().position(|&b| b == 0).unwrap_or(self.size);
str::from_utf8(&slice[..actual_len]).unwrap()
}
impl StdString {
pub fn get(&self, index: usize) -> u8 {
unsafe {
if self.capacity <= 16 {
@ -55,6 +44,21 @@ impl<'a> StdString {
}
}
}
impl AsRef<str> for StdString {
fn as_ref(&self) -> &str {
let slice: &[u8] = unsafe {
if self.capacity <= 16 {
&self.buffer.sso_buffer
} else {
slice::from_raw_parts(self.buffer.buffer, self.size)
}
};
let actual_len = slice.iter().position(|&b| b == 0).unwrap_or(self.size);
str::from_utf8(&slice[..actual_len]).unwrap_or("UTF8_ERR")
}
}
impl From<&str> for StdString {
fn from(value: &str) -> Self {
let mut res = StdString {
@ -74,18 +78,18 @@ impl From<&str> for StdString {
}
impl Display for StdString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
write!(f, "{}", self.as_ref())
}
}
impl Debug for StdString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("StdString").field(&self.as_str()).finish()
f.debug_tuple("StdString").field(&self.as_ref()).finish()
}
}
impl PartialEq for StdString {
fn eq(&self, other: &Self) -> bool {
if self.size == other.size {
self.as_str() == other.as_str()
self.as_ref() == other.as_ref()
} else {
false
}
@ -132,12 +136,36 @@ impl Debug for CString {
}
}
#[repr(C)]
#[derive(Debug)]
pub struct StdVec<T> {
pub start: *mut T,
pub end: *mut T,
pub cap: *mut T,
}
impl<T: 'static> AsRef<[T]> for StdVec<T> {
fn as_ref(&self) -> &'static [T] {
unsafe { slice::from_raw_parts(self.start, self.len()) }
}
}
impl<T: 'static> AsMut<[T]> for StdVec<T> {
fn as_mut(&mut self) -> &'static mut [T] {
unsafe { slice::from_raw_parts_mut(self.start, self.len()) }
}
}
impl<T: Debug + 'static> Debug for StdVec<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("StdVec")
.field(&format!("{:?}", self.as_ref()))
.finish()
}
}
impl<T> StdVec<T> {
pub fn len(&self) -> usize {
unsafe { self.end.byte_offset_from_unsigned(self.start) }
}
pub fn is_empty(&self) -> bool {
self.start == self.end
}
}
#[repr(C)]
#[derive(Debug)]
@ -153,11 +181,17 @@ pub struct StdMapNode<K, V> {
}
#[repr(C)]
#[derive(Debug)]
pub struct StdMap<K, V> {
pub root: *mut StdMapNode<K, V>,
pub len: u32,
}
impl<K: Debug + 'static, V: Debug + 'static> Debug for StdMap<K, V> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("StdMap")
.field(&format!("{:?}", self.iter().collect::<Vec<_>>()))
.finish()
}
}
#[derive(Debug)]
pub struct StdMapIter<K, V> {

View file

@ -1,5 +1,5 @@
use crate::noita::types::CString;
use crate::noita::types::entity::Entity;
use crate::noita::types::{CString, StdVec};
#[repr(C)]
#[derive(Debug)]
pub struct Component {
@ -30,20 +30,18 @@ pub struct ComponentManager {
pub vtable: *const ComponentManagerVTable,
pub end: isize,
unk: [isize; 2],
pub entity_entry: *mut isize,
unk2: [isize; 8],
pub entity_entry: StdVec<isize>,
unk2: [isize; 6],
pub next: *mut isize,
unk3: isize,
unk4: isize,
pub component_list: *mut *mut Component,
//TODO Unknown
unk3: [isize; 2],
pub component_list: StdVec<*mut Component>,
}
impl ComponentManager {
pub fn iter_components(&self, ent: &'static Entity) -> ComponentIter {
unsafe {
if let Some(off) = self.entity_entry.offset(ent.entry).as_ref() {
if let Some(off) = self.entity_entry.start.offset(ent.entry).as_ref() {
ComponentIter {
component_list: self.component_list as *const *const Component,
component_list: self.component_list.start as *const *const Component,
off: *off,
next: self.next,
end: self.end,
@ -60,9 +58,9 @@ impl ComponentManager {
}
pub fn iter_components_mut(&mut self, ent: &'static Entity) -> ComponentIterMut {
unsafe {
if let Some(off) = self.entity_entry.offset(ent.entry).as_ref() {
if let Some(off) = self.entity_entry.start.offset(ent.entry).as_ref() {
ComponentIterMut {
component_list: self.component_list,
component_list: self.component_list.start,
off: *off,
next: self.next,
end: self.end,

View file

@ -1,64 +1,58 @@
use crate::noita::types::StdString;
use crate::noita::types::component::{Component, ComponentManager};
use crate::noita::types::{StdString, StdVec};
use std::slice;
impl EntityManager {
pub fn get_entity(&self, id: isize) -> Option<&'static Entity> {
unsafe {
let len = self.entity_list_end.offset_from(self.entity_list) as usize;
let o = slice::from_raw_parts(self.entity_list.offset(id), len - id as usize)
let o = self
.entities
.as_ref()
.iter()
.find_map(|c| c.as_ref().map(|c| c.id - c.entry))
.unwrap_or(id);
let start = self.entity_list.offset(id - o);
let list = slice::from_raw_parts(start, len - (id - o) as usize);
let start = self.entities.start.offset(id - o);
let list = slice::from_raw_parts(start, self.entities.len() - (id - o) as usize);
list.iter().find_map(|c| c.as_ref().filter(|c| c.id == id))
}
}
pub fn get_entity_mut(&mut self, id: isize) -> Option<&'static mut Entity> {
unsafe {
let len = self.entity_list_end.offset_from(self.entity_list) as usize;
let o = slice::from_raw_parts(self.entity_list.offset(id), len - id as usize)
let o = self
.entities
.as_ref()
.iter()
.find_map(|c| c.as_ref().map(|c| c.id - c.entry))
.unwrap_or(id);
let start = self.entity_list.offset(id - o);
let list = slice::from_raw_parts(start, len - (id - o) as usize);
let start = self.entities.start.offset(id - o);
let list = slice::from_raw_parts(start, self.entities.len() - (id - o) as usize);
list.iter().find_map(|c| c.as_mut().filter(|c| c.id == id))
}
}
pub fn iter_entities(&self) -> impl Iterator<Item = &'static Entity> {
unsafe {
let len = self.entity_list_end.offset_from(self.entity_list) as usize;
slice::from_raw_parts(self.entity_list, len)
.iter()
.filter_map(|e| e.as_ref())
}
self.entities
.as_ref()
.iter()
.filter_map(|c| unsafe { c.as_ref() })
}
pub fn iter_entities_mut(&mut self) -> impl Iterator<Item = &'static mut Entity> {
unsafe {
let len = self.entity_list_end.offset_from(self.entity_list) as usize;
slice::from_raw_parts(self.entity_list, len)
.iter()
.filter_map(|e| e.as_mut())
}
self.entities
.as_mut()
.iter_mut()
.filter_map(|c| unsafe { c.as_mut() })
}
pub fn iter_component_managers(&self) -> impl Iterator<Item = &'static ComponentManager> {
unsafe {
let len = self.component_list_end.offset_from(self.component_list) as usize;
slice::from_raw_parts(self.component_list, len)
.iter()
.filter_map(|e| e.as_ref())
}
self.component_managers
.as_ref()
.iter()
.filter_map(|c| unsafe { c.as_ref() })
}
pub fn iter_component_managers_mut(
&mut self,
) -> impl Iterator<Item = &'static mut ComponentManager> {
unsafe {
let len = self.component_list_end.offset_from(self.component_list) as usize;
slice::from_raw_parts(self.component_list, len)
.iter()
.filter_map(|e| e.as_mut())
}
self.component_managers
.as_mut()
.iter_mut()
.filter_map(|c| unsafe { c.as_mut() })
}
pub fn iter_all_components(
&self,
@ -88,23 +82,16 @@ pub struct Entity {
tags: [isize; 16],
pub x: f32,
pub y: f32,
unknown19: isize,
pub angle_a: f32,
pub angle: f32,
unknown20: isize,
unknown21: isize,
pub rot90_a: f32,
pub rot90: f32,
pub scale_x: f32,
pub scale_y: f32,
pub children: *mut Child,
pub children: *mut StdVec<*mut Entity>,
pub parent: *mut Entity,
}
#[repr(C)]
#[derive(Debug)]
pub struct Child {
pub start: *mut *mut Entity,
pub end: *mut *mut Entity,
}
impl Entity {
pub fn kill(&mut self) {
self.kill_flag = 1;
@ -247,16 +234,13 @@ impl Iterator for DescendantIterMut {
#[repr(C)]
#[derive(Debug)]
pub struct EntityManager {
unknown1: isize,
max_id: isize,
unknown: [isize; 3],
pub entity_list: *mut *mut Entity,
pub entity_list_end: *mut *mut Entity,
unk1: isize,
unk2: isize,
unk3: isize,
unk4: isize,
pub component_list: *mut *mut ComponentManager,
pub component_list_end: *mut *mut ComponentManager,
//TODO Unknown
pub vtable: *const EntityManagerVTable,
pub next_entity_id: usize,
pub free_ids: StdVec<usize>,
pub entities: StdVec<*mut Entity>,
pub entity_buckets: StdVec<StdVec<*mut Entity>>,
pub component_managers: StdVec<*mut ComponentManager>,
}
pub struct EntityManagerVTable {
//TODO
}

View file

@ -1,9 +1,10 @@
use crate::noita::types::{StdMap, StdString};
use crate::noita::types::{StdMap, StdString, StdVec};
//reference stored at 0x01204b30 or 0x01206fac
#[repr(C)]
#[derive(Debug)]
pub struct TagManager {
unk1: [isize; 3],
pub tags: StdMap<StdString, [u8; 4]>,
//TODO unk
pub tags: StdVec<StdString>,
pub tag_indices: StdMap<StdString, [u8; 4]>,
pub max_tag_count: usize,
pub name: StdString,
}

View file

@ -530,7 +530,11 @@ impl Cell {
#[repr(C)]
#[derive(Debug)]
pub struct GameWorld {
unknown1: [isize; 17],
pub x1: f32,
pub y1: f32,
pub x2: f32,
pub y2: f32,
unknown1: [isize; 13],
pub grid_world: *mut GridWorld,
//likely more data
}
@ -562,6 +566,9 @@ pub struct GameGlobal {
pub m_cell_factory: *mut CellFactory,
unknown2: [isize; 11],
pub pause_state: isize,
unk: [isize; 5],
pub inventory_open: usize,
unk4: [isize; 79],
}
#[repr(C)]
@ -749,7 +756,12 @@ pub struct GridWorldThreaded {
pub struct GridWorld {
pub vtable: &'static GridWorldVTable,
pub rng: isize,
unknown: [isize; 317],
unk: [isize; 292],
pub cam_x: isize,
pub cam_y: isize,
pub cam_w: isize,
pub cam_h: isize,
unknown: [isize; 21],
pub world_update_count: isize,
pub chunk_map: ChunkMap,
unknown2: [isize; 41],