some more noita type definitions

This commit is contained in:
bgkillas 2025-07-13 11:50:02 -04:00
parent 58cac3ba81
commit 4ff165b815
6 changed files with 165 additions and 519 deletions

View file

@ -3,7 +3,6 @@
name="blob_guy"
ui_name="blob guy"
wang_color="AAFFAAAA"
lifetime="1"
cell_type="liquid"
liquid_sand="0"
tags="[static]"

View file

@ -173,47 +173,6 @@ impl Blob {
if !loaded {
return Ok(());
}
for _ in 0..5 {
let mut boundary: FxHashMap<(isize, isize), i8> = FxHashMap::default();
for (a, b) in self.pixels.keys().copied() {
let k = (a - 1, b);
boundary.entry(k).and_modify(|u| *u += 1).or_default();
let k = (a, b - 1);
boundary.entry(k).and_modify(|u| *u += 1).or_default();
let k = (a + 1, b);
boundary.entry(k).and_modify(|u| *u += 1).or_default();
let k = (a, b + 1);
boundary.entry(k).and_modify(|u| *u += 1).or_default();
boundary.insert((a, b), i8::MIN);
}
let mut boundary2: FxHashMap<(isize, isize), i8> = FxHashMap::default();
for ((a, b), p) in boundary {
boundary2.insert((a, b), p);
let k = (a - 1, b);
boundary2.entry(k).and_modify(|u| *u += 1);
let k = (a, b - 1);
boundary2.entry(k).and_modify(|u| *u += 1);
let k = (a + 1, b);
boundary2.entry(k).and_modify(|u| *u += 1);
let k = (a, b + 1);
boundary2.entry(k).and_modify(|u| *u += 1);
}
let mut is_some = false;
for (a, b) in boundary2 {
if b >= 3 {
let temp = Pixel {
pos: Pos::new(a.0 as f32 + 0.5, a.1 as f32 + 0.5),
temp: true,
..Default::default()
};
self.pixels.insert(a, temp);
is_some = true
}
}
if !is_some {
break;
}
}
self.register_pixels(start, map);
Ok(())
}

View file

@ -214,10 +214,13 @@ impl ChunkOps for ParticleWorldState {
};
let x = cx * CHUNK_SIZE as isize;
let y = cy * CHUNK_SIZE as isize;
let blob_cell = Box::new(types::LiquidCell::blob(
&self.material_list[blob as usize],
self.cell_vtable,
));
let blob_cell = unsafe {
Box::new(types::LiquidCell::create(
&self.material_list[blob as usize],
self.cell_vtable,
self.world_ptr,
))
};
for ((i, j), pixel) in (0..CHUNK_SIZE as isize)
.flat_map(|i| (0..CHUNK_SIZE as isize).map(move |j| (i, j)))
.zip(chunk.iter())

View file

@ -5,12 +5,7 @@ use std::arch::asm;
use std::ffi::c_void;
use std::fs::File;
use std::io::Read;
pub fn get_functions() -> eyre::Result<(
types::ConstructPtr,
types::RemovePtr,
&'static types::CellVTable,
*mut types::GameGlobal,
)> {
pub fn get_functions() -> eyre::Result<(&'static types::CellVTable, *mut types::GameGlobal)> {
let exe = std::env::current_exe()?;
let mut file = File::open(exe)?;
let mut vec = Vec::with_capacity(15460864);
@ -18,18 +13,9 @@ pub fn get_functions() -> eyre::Result<(
let obj = object::File::parse(vec.as_slice())?;
let text = obj.section_by_name(".text").wrap_err("obj err")?;
let data = text.data()?;
let construct: &[u8] = &[0x8b, 0x46, 0x38, 0x33, 0xc9, 0x83, 0xf8, 0x01];
let remove: &[u8] = &[
0x8b, 0x06, 0x8b, 0xce, 0xff, 0x90, 0x9c, 0x00, 0x00, 0x00, 0x8b, 0x06, 0x8b, 0xce, 0x6a,
0x01, 0xff, 0x10,
];
let game_global: &[u8] = &[0xe8];
let game_global2 = &[0x8b, 0x40, 0x48, 0x8b, 0x00, 0xc1, 0xe8, 0x02, 0xa8, 0x01];
let start = text.address() as *const c_void;
let construct = find_pattern(data, construct)?;
let remove = find_pattern(data, remove)?;
let construct_ptr = get_function_start(unsafe { start.add(construct) });
let remove_ptr = get_function_start(unsafe { start.add(remove) });
let (game_global, offset) = find_pattern_global(data, game_global, game_global2)?;
let ptr = unsafe { start.add(game_global) };
let game_global_ptr = get_rela_call(ptr, offset);
@ -54,12 +40,7 @@ pub fn get_functions() -> eyre::Result<(
(start.add(find_pattern(data, cellvtable)?) as *const types::CellVTable).as_ref()
}
.wrap_err("cell data err")?;
Ok((
types::ConstructPtr(construct_ptr),
types::RemovePtr(remove_ptr),
cellvtable_ptr,
game_global_ptr,
))
Ok((cellvtable_ptr, game_global_ptr))
}
fn get_global(global: *const c_void) -> *mut types::GameGlobal {
unsafe {
@ -96,20 +77,3 @@ fn get_rela_call(ptr: *const c_void, offset: isize) -> *const c_void {
next_instruction.offset(offset)
}
}
fn get_function_start(func: *const c_void) -> *const c_void {
let mut it = func.cast::<u8>();
loop {
unsafe {
if it as isize % 16 == 0
&& (matches!(it.offset(-1).as_ref(), Some(&0xcc) | Some(&0xc3))
|| it.offset(-3).as_ref() == Some(&0xc2))
&& (it.as_ref() >= Some(&0x50) && it.as_ref() < Some(&0x58))
&& ((it.offset(1).as_ref() >= Some(&0x50) && it.offset(1).as_ref() < Some(&0x58))
|| matches!(it.offset(1).as_ref(), Some(&0x8b) | Some(&0xec)))
{
return it.cast::<c_void>();
}
it = it.offset(-1)
}
}
}

View file

@ -2,8 +2,6 @@
use std::ffi::c_void;
#[cfg(target_arch = "x86")]
use std::arch::asm;
use std::fmt::{Debug, Display, Formatter};
#[repr(C)]
#[derive(Debug, Default, Clone, Copy)]
@ -46,124 +44,6 @@ impl ChunkPtr {
}
}
#[derive(Debug, Clone, Copy)]
pub struct RemovePtr(pub *const c_void);
impl Default for RemovePtr {
fn default() -> Self {
Self(0x71b480 as *const c_void)
}
}
impl RemovePtr {
pub fn remove_cell(self, world: *mut GridWorld, cell: *mut Cell, x: isize, y: isize) {
#[cfg(target_arch = "x86")]
unsafe {
asm!(
"mov ecx, {world}",
"push 0",
"push {y:e}",
"push {x:e}",
"push {cell}",
"call {remove}",
world = in(reg) world,
cell = in(reg) cell,
x = in(reg) x,
y = in(reg) y,
remove = in(reg) self.0,
clobber_abi("C"),
);
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box((x, y, cell, world));
unreachable!()
}
}
pub fn print_bytes(self) {
let mut start = unsafe { self.0.offset(-1).cast::<u8>() };
let mut bytes = String::new();
let end = get_function_end(self.0);
while start != end.cast() {
unsafe {
start = start.offset(1);
bytes += &format!("\\x{:x}", start.read());
}
}
crate::print!("{}", bytes);
}
}
#[derive(Debug, Clone, Copy)]
pub struct ConstructPtr(pub *const c_void);
impl Default for ConstructPtr {
fn default() -> Self {
Self(0x7048c0 as *const c_void)
}
}
impl ConstructPtr {
pub fn create_cell(
self,
world: *mut GridWorld,
x: isize,
y: isize,
material: &CellData,
//_memory: *mut c_void,
) -> *mut Cell {
#[cfg(target_arch = "x86")]
unsafe {
let cell_ptr: *mut Cell;
asm!(
"mov ecx, {world}",
"push 0",
"push {material}",
"push {y:e}",
"push {x:e}",
"call {construct}",
world = in(reg) world,
x = in(reg) x,
y = in(reg) y,
material = in(reg) material,
construct = in(reg) self.0,
clobber_abi("C"),
out("eax") cell_ptr,
);
cell_ptr
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box((x, y, material, world));
unreachable!()
}
}
pub fn print_bytes(self) {
let mut start = unsafe { self.0.offset(-1).cast::<u8>() };
let mut bytes = String::new();
let end = get_function_end(self.0);
while start != end.cast() {
unsafe {
start = start.offset(1);
bytes += &format!("\\x{:x}", start.read());
}
}
crate::print!("{}", bytes);
}
}
fn get_function_end(func: *const c_void) -> *const c_void {
let mut it = func.cast::<u8>();
loop {
unsafe {
if (it.offset(-1).as_ref() >= Some(&0x58) && it.offset(-1).as_ref() < Some(&0x60))
&& matches!(it.as_ref(), Some(&0xc3) | Some(&0xc2))
{
return if it.as_ref() == Some(&0xc3) {
it.offset(1).cast::<c_void>()
} else {
it.offset(3).cast::<c_void>()
};
}
it = it.offset(1)
}
}
}
#[repr(C)]
pub struct ChunkMap {
unknown: [isize; 2],
@ -221,30 +101,11 @@ impl Debug for ChunkMap {
#[repr(C)]
#[derive(Debug)]
pub struct GridWorldVTable {
//ptr is 0x10013bc
unknown: [*const c_void; 3],
pub get_chunk_map: *const c_void,
unknown2: [*const c_void; 30],
}
#[allow(dead_code)]
impl GridWorldVTable {
pub fn get_chunk_map(&self) -> *mut ChunkMap {
#[cfg(target_arch = "x86")]
unsafe {
let ret: *mut ChunkMap;
asm!(
"mov ecx, 0",
"call {fn}",
out("eax") ret,
fn = in(reg) self.get_chunk_map,
clobber_abi("C"),
);
ret
}
#[cfg(target_arch = "x86_64")]
{
unreachable!()
}
}
unknownmagic: *const c_void,
unknown2: [*const c_void; 29],
}
#[repr(C)]
@ -273,7 +134,8 @@ struct GridWorldThreaded {
#[derive(Debug)]
pub struct GridWorld {
pub vtable: &'static GridWorldVTable,
unknown: [isize; 318],
pub rng: isize,
unknown: [isize; 317],
pub world_update_count: isize,
pub chunk_map: ChunkMap,
unknown2: [isize; 41],
@ -352,24 +214,12 @@ pub enum CellType {
pub struct ExplosionConfig {
//TODO find some data maybe
}
#[allow(clippy::derivable_impls)]
impl Default for ExplosionConfig {
fn default() -> Self {
Self {}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct GridCosmeticParticleConfig {
//TODO find some data maybe
}
#[allow(clippy::derivable_impls)]
impl Default for GridCosmeticParticleConfig {
fn default() -> Self {
Self {}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct CellData {
@ -474,7 +324,7 @@ pub struct CellData {
pub danger_radioactive: bool,
pub danger_poison: bool,
pub danger_water: bool,
unknown13: [u8; 23],
unknown13: [u8; 24],
pub always_ignites_damagemodel: bool,
pub ignore_self_reaction_warning: bool,
padding7: [u8; 2],
@ -593,7 +443,7 @@ impl Default for CellData {
danger_poison: false,
danger_water: false,
unknown13: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
],
always_ignites_damagemodel: false,
ignore_self_reaction_warning: false,
@ -612,49 +462,92 @@ impl Default for CellData {
}
#[repr(C)]
#[derive(Debug)]
pub struct CellVTable {
pub struct CellVTables(pub [CellVTable; 5]);
#[repr(C)]
pub union CellVTable {
//ptr is 0xff2040
none: NoneCellVTable,
//ptr is 0x100bb90
liquid: LiquidCellVTable,
gas: GasCellVTable,
//ptr is 0xff8a6c
solid: SolidCellVTable,
fire: FireCellVTable,
}
impl Debug for CellVTable {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self as *const CellVTable)
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct SolidCellVTable {
unknown0: *const c_void,
unknown1: *const c_void,
unknown2: *const c_void,
unknown3: *const c_void,
unknown4: *const c_void,
unknown5: *const c_void,
unknown6: *const c_void,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct NoneCellVTable {
unknown: [*const c_void; 41],
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct GasCellVTable {}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct FireCellVTable {}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct LiquidCellVTable {
pub destroy: *const c_void,
pub get_cell_type: *const c_void,
_field01: *const c_void,
_field02: *const c_void,
_field03: *const c_void,
unknown01: *const c_void,
unknown02: *const c_void,
unknown03: *const c_void,
pub get_color: *const c_void,
_field04: *const c_void,
unknown04: *const c_void,
pub set_color: *const c_void,
_field05: *const c_void,
_field06: *const c_void,
_field07: *const c_void,
_field08: *const c_void,
unknown05: *const c_void,
unknown06: *const c_void,
unknown07: *const c_void,
unknown08: *const c_void,
pub get_material: *const c_void,
_field09: *const c_void,
_field10: *const c_void,
_field11: *const c_void,
_field12: *const c_void,
_field13: *const c_void,
_field14: *const c_void,
_field15: *const c_void,
unknown09: *const c_void,
unknown10: *const c_void,
unknown11: *const c_void,
unknown12: *const c_void,
unknown13: *const c_void,
unknown14: *const c_void,
unknown15: *const c_void,
pub get_position: *const c_void,
_field16: *const c_void,
_field17: *const c_void,
_field18: *const c_void,
_field19: *const c_void,
_field20: *const c_void,
_field21: *const c_void,
_field22: *const c_void,
_field23: *const c_void,
unknown16: *const c_void,
unknown17: *const c_void,
unknown18: *const c_void,
unknown19: *const c_void,
unknown20: *const c_void,
unknown21: *const c_void,
unknown22: *const c_void,
unknown23: *const c_void,
pub is_burning: *const c_void,
_field24: *const c_void,
_field25: *const c_void,
_field26: *const c_void,
unknown24: *const c_void,
unknown25: *const c_void,
unknown26: *const c_void,
pub stop_burning: *const c_void,
_field27: *const c_void,
_field28: *const c_void,
_field29: *const c_void,
_field30: *const c_void,
_field31: *const c_void,
unknown27: *const c_void,
unknown28: *const c_void,
unknown29: *const c_void,
unknown30: *const c_void,
unknown31: *const c_void,
pub remove: *const c_void,
_field32: *const c_void,
unknown32: *const c_void,
}
#[repr(C)]
#[derive(Debug)]
@ -663,242 +556,20 @@ pub struct Position {
pub x: isize,
pub y: isize,
}
impl Default for CellVTable {
//ptr is 0x100bb90
fn default() -> Self {
Self {
destroy: 0x70af20 as *const c_void,
get_cell_type: 0x5b01a0 as *const c_void,
_field01: 0x70b050 as *const c_void,
_field02: 0x70b060 as *const c_void,
_field03: 0x5b01c0 as *const c_void,
get_color: 0x5b01d0 as *const c_void,
_field04: 0x70d090 as *const c_void,
set_color: 0x5b01e0 as *const c_void,
_field05: 0x5b0200 as *const c_void,
_field06: 0x5b01f0 as *const c_void,
_field07: 0x70b070 as *const c_void,
_field08: 0x70b0b0 as *const c_void,
get_material: 0x4ac0d0 as *const c_void,
_field09: 0x70d0b0 as *const c_void,
_field10: 0x4abf60 as *const c_void,
_field11: 0x70d1a0 as *const c_void,
_field12: 0x70d1e0 as *const c_void,
_field13: 0x70d180 as *const c_void,
_field14: 0x70cb40 as *const c_void,
_field15: 0x70cd80 as *const c_void,
get_position: 0x70cdd0 as *const c_void,
_field16: 0x70c6e0 as *const c_void,
_field17: 0x5b01b0 as *const c_void,
_field18: 0x4abf90 as *const c_void,
_field19: 0x4abfa0 as *const c_void,
_field20: 0x70b110 as *const c_void,
_field21: 0x70b120 as *const c_void,
_field22: 0x70b160 as *const c_void,
_field23: 0x70f5b0 as *const c_void,
is_burning: 0x70f5d0 as *const c_void,
_field24: 0x70cdf0 as *const c_void,
_field25: 0x70f750 as *const c_void,
_field26: 0x4ac0e0 as *const c_void,
stop_burning: 0x70f7f0 as *const c_void,
_field27: 0x4ac020 as *const c_void,
_field28: 0x70f160 as *const c_void,
_field29: 0x70eaf0 as *const c_void,
_field30: 0x70ef90 as *const c_void,
_field31: 0x70f360 as *const c_void,
remove: 0x70af50 as *const c_void,
_field32: 0x70b1d0 as *const c_void,
}
}
}
#[allow(dead_code)]
impl CellVTable {
pub fn destroy(&self, cell: *mut Cell) {
#[cfg(target_arch = "x86")]
unsafe {
asm!(
"mov ecx, {cell}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.destroy,
clobber_abi("C"),
);
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
pub fn get_cell_type(&self, cell: *mut Cell) -> CellType {
#[cfg(target_arch = "x86")]
unsafe {
let ret: u32;
asm!(
"mov ecx, {cell}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.get_cell_type,
out("eax") ret,
clobber_abi("C"),
);
std::mem::transmute(ret)
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
pub fn get_color(&self, cell: *mut Cell) -> Color {
#[cfg(target_arch = "x86")]
unsafe {
let ret: u32;
asm!(
"mov ecx, {cell}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.get_color,
out("eax") ret,
clobber_abi("C"),
);
std::mem::transmute(ret)
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
pub fn set_color(&self, cell: *mut Cell, color: Color) {
#[cfg(target_arch = "x86")]
unsafe {
let color: u32 = std::mem::transmute(color);
asm!(
"mov ecx, {cell}",
"push {color}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.set_color,
color = in(reg) color,
clobber_abi("C"),
);
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box((cell, color));
unreachable!()
}
}
pub fn get_material(&self, cell: *mut Cell) -> *mut CellData {
#[cfg(target_arch = "x86")]
unsafe {
let ret: *mut CellData;
asm!(
"mov ecx, {cell}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.get_material,
out("eax") ret,
clobber_abi("C"),
);
ret
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
pub fn get_position(&self, cell: *mut Cell) -> *mut Position {
#[cfg(target_arch = "x86")]
unsafe {
let mut ret: *mut Position;
asm!(
"mov ecx, {cell}",
"push 0",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.get_position,
out("eax") ret,
clobber_abi("C"),
);
ret
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
pub fn is_burning(&self, cell: *mut Cell) -> bool {
#[cfg(target_arch = "x86")]
unsafe {
let ret: u16;
asm!(
"mov ecx, {cell}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.is_burning,
out("eax") ret,
clobber_abi("C"),
);
let ret: [u8; 2] = ret.to_ne_bytes();
ret[0] == 1
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
pub fn stop_burning(&self, cell: *mut Cell) {
#[cfg(target_arch = "x86")]
unsafe {
asm!(
"mov ecx, {cell}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.stop_burning,
clobber_abi("C"),
);
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
pub fn remove(&self, cell: *mut Cell) {
#[cfg(target_arch = "x86")]
unsafe {
asm!(
"mov ecx, {cell}",
"call {fn}",
cell = in(reg) cell,
fn = in(reg) self.remove,
clobber_abi("C"),
);
}
#[cfg(target_arch = "x86_64")]
{
std::hint::black_box(cell);
unreachable!()
}
}
}
#[repr(C)]
#[derive(Debug, Clone)]
#[derive(Clone, Debug)]
pub struct Cell {
pub vtable: &'static CellVTable,
pub hp: isize,
unknown1: [isize; 2],
pub is_burning: bool,
unknown2: [u8; 3],
pub temperature_of_fire: u8,
unknown2: [u8; 2],
pub material: &'static CellData,
}
unsafe impl Sync for Cell {}
unsafe impl Send for Cell {}
@ -906,15 +577,18 @@ unsafe impl Send for Cell {}
pub enum FullCell {
Cell(Cell),
LiquidCell(LiquidCell),
GasCell(GasCell),
FireCell(FireCell),
#[default]
None,
}
impl From<&Cell> for FullCell {
fn from(value: &Cell) -> Self {
if value.material.cell_type == CellType::Liquid {
FullCell::LiquidCell(value.get_liquid().clone())
} else {
FullCell::Cell(value.clone())
match value.material.cell_type {
CellType::Liquid => FullCell::LiquidCell(value.get_liquid().clone()),
CellType::Fire => FullCell::FireCell(value.get_fire().clone()),
CellType::Gas => FullCell::GasCell(value.get_gas().clone()),
CellType::None | CellType::Solid => FullCell::Cell(value.clone()),
}
}
}
@ -923,6 +597,12 @@ impl Cell {
pub fn get_liquid(&self) -> &LiquidCell {
unsafe { std::mem::transmute::<&Cell, &LiquidCell>(self) }
}
pub fn get_fire(&self) -> &FireCell {
unsafe { std::mem::transmute::<&Cell, &FireCell>(self) }
}
pub fn get_gas(&self) -> &GasCell {
unsafe { std::mem::transmute::<&Cell, &GasCell>(self) }
}
}
#[repr(C)]
@ -946,6 +626,36 @@ impl Debug for CellPtr {
unsafe impl Sync for CellPtr {}
unsafe impl Send for CellPtr {}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct FireCell {
pub cell: Cell,
pub x: isize,
pub y: isize,
unknown1: u8,
unknown2: u8,
unknown3: u8,
unknown4: u8,
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct GasCell {
pub cell: Cell,
pub x: isize,
pub y: isize,
unknown1: u8,
unknown2: u8,
unknown3: u8,
unknown4: u8,
unknown5: isize,
unknown6: isize,
unknown7: isize,
pub color: Color,
pub not_color: Color,
lifetime: isize,
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct LiquidCell {
@ -961,39 +671,55 @@ pub struct LiquidCell {
unknown6: isize,
pub color: Color,
pub not_color: Color,
unknown7: isize,
lifetime: isize,
unknown8: isize,
}
impl LiquidCell {
pub fn blob(mat: &'static CellData, vtable: &'static CellVTable) -> Self {
/// # Safety
pub unsafe fn create(
mat: &'static CellData,
vtable: &'static CellVTable,
world: *mut GridWorld,
) -> Self {
let lifetime = if mat.lifetime > 0
&& let Some(world) = (unsafe { world.as_mut() })
{
let life = ((mat.lifetime as f32 * 0.3) as u64).max(1);
world.rng *= 0x343fd;
world.rng += 0x269ec3;
(((world.rng >> 0x10 & 0x7fff) as u64 % (life * 2 + 1)) - life) as isize
} else {
-1
};
Self {
cell: Cell::blob(mat, vtable),
cell: Cell::create(mat, vtable),
x: 0,
y: 0,
unknown1: 3,
unknown2: 0,
is_static: true,
is_static: mat.liquid_static,
unknown3: 0,
unknown4: 0,
unknown5: 0,
unknown6: 0,
color: mat.default_primary_color,
not_color: mat.default_primary_color,
unknown7: 0,
lifetime,
unknown8: 0,
}
}
}
impl Cell {
fn blob(material: &'static CellData, vtable: &'static CellVTable) -> Self {
fn create(material: &'static CellData, vtable: &'static CellVTable) -> Self {
Self {
vtable,
hp: material.hp,
unknown1: [-1000, 0],
is_burning: false,
unknown2: [10, 0, 0],
is_burning: material.on_fire,
temperature_of_fire: material.temperature_of_fire as u8,
unknown2: [0, 0],
material,
}
}

View file

@ -5,8 +5,6 @@ use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIter
pub struct ParticleWorldState {
pub world_ptr: *mut types::GridWorld,
pub material_list: &'static [types::CellData],
pub construct_ptr: types::ConstructPtr,
pub remove_ptr: types::RemovePtr,
pub cell_vtable: &'static types::CellVTable,
}
unsafe impl Sync for ParticleWorldState {}
@ -84,8 +82,7 @@ impl ParticleWorldState {
Ok(())
}
pub fn new() -> eyre::Result<Self> {
let (construct_ptr, remove_ptr, cell_vtable, global_ptr) =
crate::noita::init_data::get_functions()?;
let (cell_vtable, global_ptr) = crate::noita::init_data::get_functions()?;
let global = unsafe { global_ptr.as_mut() }.wrap_err("no global?")?;
let cell_factory =
unsafe { global.m_cell_factory.as_mut() }.wrap_err("no cell factory?")?;
@ -96,8 +93,6 @@ impl ParticleWorldState {
Ok(ParticleWorldState {
world_ptr,
material_list,
construct_ptr,
remove_ptr,
cell_vtable,
})
}