make types a bit nicer

This commit is contained in:
bgkillas 2025-07-23 15:18:41 -04:00
parent 6b15e58202
commit 3fdd72c363
6 changed files with 123 additions and 138 deletions

View file

@ -1,5 +1,4 @@
use crate::chunk::Chunks;
use crate::chunk::SCALE;
use crate::chunk::{CellType, ChunkPos, Pos};
use crate::{CHUNK_AMOUNT, State};
#[cfg(target_arch = "x86")]
@ -24,16 +23,14 @@ impl State {
let mean = blob.mean();
blob.update_pos()?;
let start = Pos::new(mean.0, mean.1).to_chunk();
if !unsafe { self.particle_world_state.assume_init_ref() }
.exists::<SCALE>(start.x, start.y)
|| self
.world
.read(
unsafe { self.particle_world_state.assume_init_ref() },
self.blob_guy,
start,
)
.is_err()
if self
.world
.read(
unsafe { self.particle_world_state.assume_init_ref() },
self.blob_guy,
start,
)
.is_err()
{
blob.update(start, &mut self.world, mean, false)?;
continue 'upper;

View file

@ -154,7 +154,6 @@ impl ChunkOps for ParticleWorldState {
let Some(pixel_array) = unsafe { self.world_ptr.as_mut() }
.wrap_err("no world")?
.chunk_map
.chunk_array
.get(x >> SCALE, y >> SCALE)
else {
return Err(eyre!("chunk not loaded"));
@ -164,7 +163,7 @@ impl ChunkOps for ParticleWorldState {
.flat_map(|i| (0..CHUNK_SIZE as isize).map(move |j| (i, j)))
.zip(chunk.iter_mut())
{
*pixel = if let Some(cell) = pixel_array.data.get(shift_x + i, shift_y + j) {
*pixel = if let Some(cell) = pixel_array.get(shift_x + i, shift_y + j) {
match cell.material.cell_type {
types::CellType::Liquid => {
if cell.material.material_type as u16 == blob {
@ -206,7 +205,6 @@ impl ChunkOps for ParticleWorldState {
let Some(pixel_array) = unsafe { self.world_ptr.as_mut() }
.wrap_err("no world")?
.chunk_map
.chunk_array
.get_mut(cx >> SCALE, cy >> SCALE)
else {
return Err(eyre!("chunk not loaded"));
@ -229,17 +227,15 @@ impl ChunkOps for ParticleWorldState {
CellType::Blob => {
let world_x = x + i;
let world_y = y + j;
if let Some(cell) = pixel_array.data.get_mut(shift_x + i, shift_y + j) {
let new = Box::leak(blob_cell.clone());
new.x = world_x;
new.y = world_y;
cell.0 = (new as *mut types::LiquidCell).cast();
}
let cell = pixel_array.get_mut_raw(shift_x + i, shift_y + j);
let new = Box::leak(blob_cell.clone());
new.x = world_x;
new.y = world_y;
*cell = (new as *mut types::LiquidCell).cast();
}
CellType::Remove => {
if let Some(cell) = pixel_array.data.get_mut(shift_x + i, shift_y + j) {
cell.0 = std::ptr::null_mut()
}
let cell = pixel_array.get_mut_raw(shift_x + i, shift_y + j);
*cell = std::ptr::null_mut();
}
_ => {}
}

View file

@ -10,7 +10,7 @@ use noita_api::add_lua_fn;
use noita_api::addr_grabber::Globals;
use noita_api::noita::world::ParticleWorldState;
use noita_api::{
DamageModelComponent, EntityID, VariableStorageComponent,
EntityID, VariableStorageComponent,
lua::{
LUA, LuaGetValue, LuaState, RawString,
lua_bindings::{LUA_REGISTRYINDEX, lua_State},
@ -27,7 +27,6 @@ use std::{
cell::RefCell,
ffi::c_int,
sync::{LazyLock, Mutex, OnceLock, TryLockError},
time::Instant,
};
use std::{num::NonZero, sync::MutexGuard};
mod modules;
@ -281,7 +280,7 @@ fn module_on_projectile_fired(lua: LuaState) -> eyre::Result<()> {
})
}
fn bench_fn(_lua: LuaState) -> eyre::Result<()> {
/*fn bench_fn(_lua: LuaState) -> eyre::Result<()> {
let start = Instant::now();
let iters = 10000;
for _ in 0..iters {
@ -297,9 +296,9 @@ fn bench_fn(_lua: LuaState) -> eyre::Result<()> {
));
Ok(())
}
}*/
fn test_fn(_lua: LuaState) -> eyre::Result<()> {
/*fn test_fn(_lua: LuaState) -> eyre::Result<()> {
let player = EntityID::get_closest_with_tag(0.0, 0.0, "player_unit")?;
let damage_model: DamageModelComponent = player.get_first_component(None)?;
let hp = damage_model.hp()?;
@ -319,16 +318,16 @@ fn test_fn(_lua: LuaState) -> eyre::Result<()> {
// noita::api::raw::entity_set_transform(player, 0.0, 0.0, 0.0, 1.0, 1.0)?;
Ok(())
}
}*/
fn probe(_lua: LuaState) {
/*fn probe(_lua: LuaState) {
backtrace::trace(|frame| {
let _ip = frame.ip() as usize;
#[cfg(debug_assertions)]
println!("Probe: 0x{_ip:x}");
false
});
}
}*/
pub(crate) fn print_error(error: eyre::Report) -> eyre::Result<()> {
let lua = LuaState::current()?;
@ -376,9 +375,9 @@ pub unsafe extern "C" fn luaopen_ewext(lua: *mut lua_State) -> c_int {
add_lua_fn!(make_ephemerial);
add_lua_fn!(set_world_num);
add_lua_fn!(test_fn);
add_lua_fn!(bench_fn);
add_lua_fn!(probe);
//add_lua_fn!(test_fn);
//add_lua_fn!(bench_fn);
//add_lua_fn!(probe);
add_lua_fn!(netmanager_connect);
add_lua_fn!(netmanager_recv);

View file

@ -68,7 +68,6 @@ impl WorldData for ParticleWorldState {
let Some(pixel_array) = unsafe { self.world_ptr.as_mut() }
.wrap_err("no world")?
.chunk_map
.chunk_array
.get(cx >> SCALE, cy >> SCALE)
else {
return Err(eyre!("chunk not loaded"));
@ -78,7 +77,7 @@ impl WorldData for ParticleWorldState {
.flat_map(|i| (shift_y..shift_y + CHUNK_SIZE as isize).map(move |j| (i, j)))
.zip(chunk.iter_mut())
{
*p = pixel_array.data.get_compact_pixel(i, j);
*p = pixel_array.get_compact_pixel(i, j);
}
Ok(())
}
@ -88,7 +87,6 @@ impl WorldData for ParticleWorldState {
let Some(pixel_array) = unsafe { self.world_ptr.as_mut() }
.wrap_err("no world")?
.chunk_map
.chunk_array
.get_mut(cx >> SCALE, cy >> SCALE)
else {
return Err(eyre!("chunk not loaded"));
@ -100,50 +98,49 @@ impl WorldData for ParticleWorldState {
let mut y = 0;
for run in chunk.runs {
for _ in 0..run.length {
if let Some(cell) = pixel_array.data.get_mut(shift_x + x, shift_y + y) {
let xs = start_x + x;
let ys = start_y + y;
let mat = &self
.material_list
.get_static(run.data.material as usize)
.unwrap();
match mat.cell_type {
CellType::None => {
cell.0 = ptr::null_mut();
}
CellType::Liquid => {
let liquid = Box::leak(Box::new(unsafe {
LiquidCell::create(mat, self.cell_vtables.liquid(), self.world_ptr)
}));
liquid.x = xs;
liquid.y = ys;
cell.0 = (liquid as *mut LiquidCell).cast();
}
CellType::Gas => {
let gas = Box::leak(Box::new(unsafe {
GasCell::create(mat, self.cell_vtables.gas(), self.world_ptr)
}));
gas.x = xs;
gas.y = ys;
cell.0 = (gas as *mut GasCell).cast();
}
CellType::Solid => {}
CellType::Fire => {
let fire = Box::leak(Box::new(unsafe {
FireCell::create(mat, self.cell_vtables.fire(), self.world_ptr)
}));
fire.x = xs;
fire.y = ys;
cell.0 = (fire as *mut FireCell).cast();
}
let cell = pixel_array.get_mut_raw(shift_x + x, shift_y + y);
let xs = start_x + x;
let ys = start_y + y;
let mat = &self
.material_list
.get_static(run.data.material as usize)
.unwrap();
match mat.cell_type {
CellType::None => {
*cell = ptr::null_mut();
}
CellType::Liquid => {
let liquid = Box::leak(Box::new(unsafe {
LiquidCell::create(mat, self.cell_vtables.liquid(), self.world_ptr)
}));
liquid.x = xs;
liquid.y = ys;
*cell = (liquid as *mut LiquidCell).cast();
}
CellType::Gas => {
let gas = Box::leak(Box::new(unsafe {
GasCell::create(mat, self.cell_vtables.gas(), self.world_ptr)
}));
gas.x = xs;
gas.y = ys;
*cell = (gas as *mut GasCell).cast();
}
CellType::Solid => {}
CellType::Fire => {
let fire = Box::leak(Box::new(unsafe {
FireCell::create(mat, self.cell_vtables.fire(), self.world_ptr)
}));
fire.x = xs;
fire.y = ys;
*cell = (fire as *mut FireCell).cast();
}
}
if x == CHUNK_SIZE as isize {
x = 0;
y += 1;
} else {
x += 1;
}
}
if x == CHUNK_SIZE as isize {
x = 0;
y += 1;
} else {
x += 1;
}
}
Ok(())

View file

@ -318,12 +318,6 @@ impl Cell {
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct CellPtr(pub *mut Cell);
unsafe impl Sync for CellPtr {}
unsafe impl Send for CellPtr {}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct FireCell {
@ -641,30 +635,20 @@ pub struct Color {
pub a: u8,
}
#[derive(Debug)]
#[repr(transparent)]
pub struct CellArray(pub *mut CellPtr);
unsafe impl Sync for CellArray {}
unsafe impl Send for CellArray {}
impl CellArray {
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &CellPtr> {
unsafe { slice::from_raw_parts(self.0, 512 * 512) }.iter()
}
impl Chunk {
#[inline]
pub fn get(&self, x: isize, y: isize) -> Option<&Cell> {
let index = (y << 9) | x;
unsafe { self.0.offset(index).as_ref()?.0.as_ref() }
unsafe { self.data[index.cast_unsigned()].as_ref() }
}
#[inline]
pub fn get_mut(&mut self, x: isize, y: isize) -> Option<&mut CellPtr> {
pub fn get_mut(&mut self, x: isize, y: isize) -> Option<&mut Cell> {
unsafe { self.get_mut_raw(x, y).as_mut() }
}
#[inline]
pub fn get_mut_raw(&mut self, x: isize, y: isize) -> *mut CellPtr {
pub fn get_mut_raw(&mut self, x: isize, y: isize) -> &mut *mut Cell {
let index = (y << 9) | x;
unsafe { self.0.offset(index) }
&mut self.data[index.cast_unsigned()]
}
#[inline]
pub fn get_raw_pixel(&self, x: isize, y: isize) -> RawPixel {
@ -713,53 +697,72 @@ impl CellArray {
}
#[repr(C)]
#[derive(Debug)]
pub struct ChunkMap {
pub len: usize,
unknown: isize,
pub chunk_array: ChunkArrayPtr,
pub chunk_array: &'static mut [*mut Chunk; 512 * 512],
pub chunk_count: usize,
pub min_chunk: Vec2i,
pub max_chunk: Vec2i,
pub min_pixel: Vec2i,
pub max_pixel: Vec2i,
}
impl Debug for ChunkMap {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ChunkMap")
.field("len", &self.len)
.field("unknown", &self.unknown)
.field(
"chunk_array",
&self
.chunk_array
.iter()
.enumerate()
.filter_map(|(i, a)| unsafe {
a.as_ref().map(|a| (i % 512 - 256, i / 512 - 256, a))
})
.collect::<Vec<_>>(),
)
.field("chunk_count", &self.chunk_count)
.field("min_chunk", &self.min_chunk)
.field("max_chunk", &self.max_chunk)
.field("min_pixel", &self.min_pixel)
.field("max_pixel", &self.max_pixel)
.finish()
}
}
#[repr(C)]
#[derive(Debug)]
pub struct Chunk {
pub data: CellArray,
//thought it might make sense if more data but seems like garbage
pub data: &'static mut [*mut Cell; 512 * 512],
}
impl Debug for Chunk {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Chunk")
.field(
&self
.data
.iter()
.enumerate()
.filter_map(|(i, a)| {
unsafe { a.as_ref() }.map(|a| (i % 512, i / 512, a.material.material_type))
})
.collect::<Vec<_>>(),
)
.finish()
}
}
unsafe impl Sync for Chunk {}
unsafe impl Send for Chunk {}
#[repr(transparent)]
#[derive(Debug)]
pub struct ChunkPtr(pub *mut Chunk);
unsafe impl Sync for ChunkPtr {}
unsafe impl Send for ChunkPtr {}
#[repr(transparent)]
#[derive(Debug)]
pub struct ChunkArrayPtr(pub *mut ChunkPtr);
unsafe impl Sync for ChunkArrayPtr {}
unsafe impl Send for ChunkArrayPtr {}
impl ChunkArrayPtr {
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &ChunkPtr> {
self.slice().iter()
}
#[inline]
pub fn slice(&self) -> &'static [ChunkPtr] {
unsafe { slice::from_raw_parts(self.0, 512 * 512) }
}
impl ChunkMap {
#[inline]
pub fn get(&self, x: isize, y: isize) -> Option<&Chunk> {
let index = (((y - 256) & 511) << 9) | ((x - 256) & 511);
unsafe { self.0.offset(index).as_ref()?.0.as_ref() }
unsafe { self.chunk_array[index.cast_unsigned()].as_ref() }
}
#[inline]
pub fn get_mut(&mut self, x: isize, y: isize) -> Option<&mut Chunk> {
let index = (((y - 256) & 511) << 9) | ((x - 256) & 511);
unsafe { self.0.offset(index).as_mut()?.0.as_mut() }
unsafe { self.chunk_array[index.cast_unsigned()].as_mut() }
}
}

View file

@ -1,7 +1,6 @@
use crate::noita::types;
use crate::noita::types::StdVec;
use eyre::ContextCompat;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
#[derive(Debug)]
pub struct ParticleWorldState {
pub world_ptr: *mut types::GridWorld,
@ -20,11 +19,7 @@ impl ParticleWorldState {
let Some(world) = (unsafe { self.world_ptr.as_mut() }) else {
return false;
};
world
.chunk_map
.chunk_array
.get(cx >> SCALE, cy >> SCALE)
.is_some()
world.chunk_map.get(cx >> SCALE, cy >> SCALE).is_some()
}
///# Safety
#[allow(clippy::type_complexity)]
@ -35,11 +30,10 @@ impl ParticleWorldState {
world
.chunk_map
.chunk_array
.slice()
.par_iter()
.iter()
.enumerate()
.filter_map(|(i, c)| {
unsafe { c.0.as_ref() }.map(|c| {
unsafe { c.as_ref() }.map(|c| {
let x = i as isize % 512 - 256;
let y = i as isize / 512 - 256;
(
@ -47,7 +41,7 @@ impl ParticleWorldState {
c.data
.iter()
.map(|p| {
unsafe { p.0.as_ref() }
unsafe { p.as_ref() }
.map(types::FullCell::from)
.unwrap_or_default()
})
@ -65,10 +59,9 @@ impl ParticleWorldState {
if let Some(pixel_array) = unsafe { self.world_ptr.as_mut() }
.wrap_err("no world")?
.chunk_map
.chunk_array
.get_mut(x.div_euclid(512), y.div_euclid(512))
{
if let Some(cell) = pixel_array.data.get(x.rem_euclid(512), y.rem_euclid(512)) {
if let Some(cell) = pixel_array.get(x.rem_euclid(512), y.rem_euclid(512)) {
let full = types::FullCell::from(cell);
crate::print!("{full:?}");
} else {