mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 15:13:16 +00:00
Update NoitaPatcher to 1.34.0
This commit is contained in:
parent
4fbecb8bfe
commit
ebb66dfb0a
8 changed files with 264 additions and 102 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,7 @@
|
||||||
--- World read / write functionality.
|
---@diagnostic disable: cast-local-type
|
||||||
|
---World read / write functionality.
|
||||||
---@module 'noitapatcher.nsew.world'
|
---@module 'noitapatcher.nsew.world'
|
||||||
|
---@class World
|
||||||
local world = {}
|
local world = {}
|
||||||
|
|
||||||
local ffi = require("ffi")
|
local ffi = require("ffi")
|
||||||
|
@ -10,7 +12,7 @@ local C = ffi.C
|
||||||
ffi.cdef([[
|
ffi.cdef([[
|
||||||
|
|
||||||
enum ENCODE_CONST {
|
enum ENCODE_CONST {
|
||||||
PIXEL_RUN_MAX = 16000,
|
PIXEL_RUN_MAX = 4096,
|
||||||
|
|
||||||
LIQUID_FLAG_STATIC = 1,
|
LIQUID_FLAG_STATIC = 1,
|
||||||
};
|
};
|
||||||
|
@ -37,40 +39,60 @@ struct __attribute__ ((__packed__)) EncodedArea {
|
||||||
|
|
||||||
]])
|
]])
|
||||||
|
|
||||||
world.last_material_id = 0
|
---@class PixelRun
|
||||||
|
---@field flags integer
|
||||||
|
---@field material integer
|
||||||
|
---@field length integer
|
||||||
|
|
||||||
|
---@class EncodedAreaHeader
|
||||||
|
---@field x integer
|
||||||
|
---@field y integer
|
||||||
|
---@field width integer
|
||||||
|
---@field height integer
|
||||||
|
---@field pixel_run_count integer
|
||||||
|
|
||||||
|
---@class EncodedArea
|
||||||
|
---@field header EncodedAreaHeader
|
||||||
|
---@field pixel_runs PixelRun[] a pointer
|
||||||
|
|
||||||
world.EncodedAreaHeader = ffi.typeof("struct EncodedAreaHeader")
|
world.EncodedAreaHeader = ffi.typeof("struct EncodedAreaHeader")
|
||||||
world.PixelRun = ffi.typeof("struct PixelRun")
|
world.PixelRun = ffi.typeof("struct PixelRun")
|
||||||
|
---@type fun(): EncodedArea
|
||||||
|
---@diagnostic disable-next-line: assign-type-mismatch
|
||||||
world.EncodedArea = ffi.typeof("struct EncodedArea")
|
world.EncodedArea = ffi.typeof("struct EncodedArea")
|
||||||
|
|
||||||
local pliquid_cell = ffi.typeof("struct CLiquidCell*")
|
local pliquid_cell = ffi.typeof("struct CLiquidCell*")
|
||||||
|
|
||||||
--- Total bytes taken up by the encoded area
|
---Total bytes taken up by the encoded area
|
||||||
-- @tparam EncodedArea encoded_area
|
---@param encoded_area EncodedArea
|
||||||
-- @treturn int total number of bytes that encodes the area
|
---@return integer total number of bytes that encodes the area
|
||||||
-- @usage
|
---```lua
|
||||||
-- local data = ffi.string(area, world.encoded_size(area))
|
---local data = ffi.string(area, world.encoded_size(area))
|
||||||
-- peer:send(data)
|
---peer:send(data)
|
||||||
|
---```
|
||||||
function world.encoded_size(encoded_area)
|
function world.encoded_size(encoded_area)
|
||||||
return (ffi.sizeof(world.EncodedAreaHeader) + encoded_area.header.pixel_run_count * ffi.sizeof(world.PixelRun))
|
return ffi.sizeof(world.EncodedAreaHeader) + encoded_area.header.pixel_run_count * ffi.sizeof(world.PixelRun)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Encode the given rectangle of the world
|
---Encode the given rectangle of the world
|
||||||
-- The rectangle defined by {`start_x`, `start_y`, `end_x`, `end_y`} must not
|
---The rectangle defined by {`start_x`, `start_y`, `end_x`, `end_y`} must not exceed 256 in width or height.
|
||||||
-- exceed 256 in width or height.
|
---@param chunk_map unknown
|
||||||
-- @param chunk_map
|
---@param start_x integer coordinate
|
||||||
-- @tparam int start_x coordinate
|
---@param start_y integer coordinate
|
||||||
-- @tparam int start_y coordinate
|
---@param end_x integer coordinate
|
||||||
-- @tparam int end_x coordinate
|
---@param end_y integer coordinate
|
||||||
-- @tparam int end_y coordinate
|
---@param encoded_area EncodedArea? memory to use, if nil this function allocates its own memory
|
||||||
-- @tparam EncodedArea encoded_area memory to use, if nil this function allocates its own memory
|
---@return EncodedArea? encoded_area returns an EncodedArea or nil if the area could not be encoded
|
||||||
-- @return returns an EncodedArea or nil if the area could not be encoded
|
---@see decode
|
||||||
-- @see decode
|
|
||||||
function world.encode_area(chunk_map, start_x, start_y, end_x, end_y, encoded_area)
|
function world.encode_area(chunk_map, start_x, start_y, end_x, end_y, encoded_area)
|
||||||
start_x = ffi.cast('int32_t', start_x)
|
start_x = ffi.cast('int32_t', start_x)
|
||||||
start_y = ffi.cast('int32_t', start_y)
|
start_y = ffi.cast('int32_t', start_y)
|
||||||
end_x = ffi.cast('int32_t', end_x)
|
end_x = ffi.cast('int32_t', end_x)
|
||||||
end_y = ffi.cast('int32_t', end_y)
|
end_y = ffi.cast('int32_t', end_y)
|
||||||
|
---@cast start_x integer
|
||||||
|
---@cast start_y integer
|
||||||
|
---@cast end_x integer
|
||||||
|
---@cast end_x integer
|
||||||
|
|
||||||
encoded_area = encoded_area or world.EncodedArea()
|
encoded_area = encoded_area or world.EncodedArea()
|
||||||
|
|
||||||
|
@ -163,13 +185,13 @@ function world.encode_area(chunk_map, start_x, start_y, end_x, end_y, encoded_ar
|
||||||
return encoded_area
|
return encoded_area
|
||||||
end
|
end
|
||||||
|
|
||||||
--local PixelRun_const_ptr = ffi.typeof("struct PixelRun const*")
|
local PixelRun_const_ptr = ffi.typeof("struct PixelRun const*")
|
||||||
|
|
||||||
--- Load an encoded area back into the world.
|
---Load an encoded area back into the world.
|
||||||
-- @param grid_world
|
---@param grid_world unknown
|
||||||
-- @tparam EncodedAreaHeader header header of the encoded area
|
---@param header EncodedAreaHeader header of the encoded area
|
||||||
-- @param received pointer or ffi array of PixelRun from the encoded area
|
---@param pixel_runs PixelRun[] or ffi array of PixelRun from the encoded area
|
||||||
-- @see encode_area
|
---@see encode_area
|
||||||
function world.decode(grid_world, header, pixel_runs)
|
function world.decode(grid_world, header, pixel_runs)
|
||||||
local chunk_map = grid_world.vtable.get_chunk_map(grid_world)
|
local chunk_map = grid_world.vtable.get_chunk_map(grid_world)
|
||||||
|
|
||||||
|
@ -192,19 +214,10 @@ function world.decode(grid_world, header, pixel_runs)
|
||||||
while x < bottom_right_x do
|
while x < bottom_right_x do
|
||||||
if world_ffi.chunk_loaded(chunk_map, x, y) then
|
if world_ffi.chunk_loaded(chunk_map, x, y) then
|
||||||
local ppixel = world_ffi.get_cell(chunk_map, x, y)
|
local ppixel = world_ffi.get_cell(chunk_map, x, y)
|
||||||
|
|
||||||
local current_material = 0
|
local current_material = 0
|
||||||
|
|
||||||
if new_material == -1 then
|
|
||||||
goto next_pixel
|
|
||||||
end
|
|
||||||
|
|
||||||
if ppixel[0] ~= nil then
|
if ppixel[0] ~= nil then
|
||||||
local pixel = ppixel[0]
|
local pixel = ppixel[0]
|
||||||
local cell_type = pixel.vtable.get_cell_type(pixel)
|
|
||||||
if cell_type == C.CELL_TYPE_SOLID then
|
|
||||||
goto next_pixel
|
|
||||||
end
|
|
||||||
current_material = world_ffi.get_material_id(pixel.vtable.get_material(pixel))
|
current_material = world_ffi.get_material_id(pixel.vtable.get_material(pixel))
|
||||||
|
|
||||||
if new_material ~= current_material then
|
if new_material ~= current_material then
|
||||||
|
@ -213,14 +226,7 @@ function world.decode(grid_world, header, pixel_runs)
|
||||||
end
|
end
|
||||||
|
|
||||||
if current_material ~= new_material and new_material ~= 0 then
|
if current_material ~= new_material and new_material ~= 0 then
|
||||||
if new_material > world.last_material_id then
|
local pixel = world_ffi.construct_cell(grid_world, x, y, world_ffi.get_material_ptr(new_material), nil)
|
||||||
goto next_pixel
|
|
||||||
end
|
|
||||||
local mat_ptr = world_ffi.get_material_ptr(new_material)
|
|
||||||
if mat_ptr == nil then
|
|
||||||
goto next_pixel
|
|
||||||
end
|
|
||||||
local pixel = world_ffi.construct_cell(grid_world, x, y, mat_ptr, nil)
|
|
||||||
if pixel == nil then
|
if pixel == nil then
|
||||||
-- TODO: This can happen when the material texture has a
|
-- TODO: This can happen when the material texture has a
|
||||||
-- transparent pixel at the given coordinate. There's
|
-- transparent pixel at the given coordinate. There's
|
||||||
|
@ -228,7 +234,6 @@ function world.decode(grid_world, header, pixel_runs)
|
||||||
-- we skip positions like this.
|
-- we skip positions like this.
|
||||||
goto next_pixel
|
goto next_pixel
|
||||||
end
|
end
|
||||||
|
|
||||||
local cell_type = pixel.vtable.get_cell_type(pixel)
|
local cell_type = pixel.vtable.get_cell_type(pixel)
|
||||||
|
|
||||||
if cell_type == C.CELL_TYPE_LIQUID then
|
if cell_type == C.CELL_TYPE_LIQUID then
|
||||||
|
@ -264,4 +269,4 @@ function world.decode(grid_world, header, pixel_runs)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return world
|
return world
|
||||||
|
|
|
@ -37,6 +37,139 @@ struct AABB {
|
||||||
struct Position bottom_right;
|
struct Position bottom_right;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct std_string { /* VC++ std::string */
|
||||||
|
char *buffer;
|
||||||
|
char sso_buffer[12];
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum cell_type {
|
||||||
|
none=0,
|
||||||
|
liquid=1,
|
||||||
|
gas=2,
|
||||||
|
solid=3,
|
||||||
|
fire=4,
|
||||||
|
invalid=4294967295
|
||||||
|
} cell_type;
|
||||||
|
|
||||||
|
struct CellData {
|
||||||
|
struct std_string name;
|
||||||
|
struct std_string ui_name;
|
||||||
|
int material_type;
|
||||||
|
int id_2;
|
||||||
|
enum cell_type cell_type;
|
||||||
|
int platform_type;
|
||||||
|
unsigned int wang_color;
|
||||||
|
int gfx_glow;
|
||||||
|
unsigned int gfx_glow_color;
|
||||||
|
char unknown1[24];
|
||||||
|
unsigned int default_primary_colour;
|
||||||
|
char unknown2[36];
|
||||||
|
bool cell_holes_in_texture;
|
||||||
|
bool stainable;
|
||||||
|
bool burnable;
|
||||||
|
bool on_fire;
|
||||||
|
int fire_hp;
|
||||||
|
int autoignition_temperature;
|
||||||
|
int _100_minus_autoignition_temp;
|
||||||
|
int temperature_of_fire;
|
||||||
|
int generates_smoke;
|
||||||
|
int generates_flames;
|
||||||
|
bool requires_oxygen;
|
||||||
|
char padding1[3];
|
||||||
|
struct std_string on_fire_convert_to_material;
|
||||||
|
int on_fire_convert_to_material_id;
|
||||||
|
struct std_string on_fire_flame_material;
|
||||||
|
int on_fire_flame_material_id;
|
||||||
|
struct std_string on_fire_smoke_material;
|
||||||
|
int on_fire_smoke_material_id;
|
||||||
|
struct ConfigExplosion *explosion_config;
|
||||||
|
int durability;
|
||||||
|
int crackability;
|
||||||
|
bool electrical_conductivity;
|
||||||
|
bool slippery;
|
||||||
|
char padding2[2];
|
||||||
|
float stickyness;
|
||||||
|
struct std_string cold_freezes_to_material;
|
||||||
|
struct std_string warmth_melts_to_material;
|
||||||
|
int warmth_melts_to_material_id;
|
||||||
|
int cold_freezes_to_material_id;
|
||||||
|
int16_t cold_freezes_chance_rev;
|
||||||
|
int16_t warmth_melts_chance_rev;
|
||||||
|
bool cold_freezes_to_dont_do_reverse_reaction;
|
||||||
|
char padding3[3];
|
||||||
|
int lifetime;
|
||||||
|
int hp;
|
||||||
|
float density;
|
||||||
|
bool liquid_sand;
|
||||||
|
bool liquid_slime;
|
||||||
|
bool liquid_static;
|
||||||
|
bool liquid_stains_self;
|
||||||
|
int liquid_sticks_to_ceiling;
|
||||||
|
float liquid_gravity;
|
||||||
|
int liquid_viscosity;
|
||||||
|
int liquid_stains;
|
||||||
|
unsigned int liquid_stains_custom_color;
|
||||||
|
float liquid_sprite_stain_shaken_drop_chance;
|
||||||
|
float liquid_sprite_stain_ignited_drop_chance;
|
||||||
|
int8_t liquid_sprite_stains_check_offset;
|
||||||
|
char padding4[3];
|
||||||
|
float liquid_sprite_stains_status_threshold;
|
||||||
|
float liquid_damping;
|
||||||
|
float liquid_flow_speed;
|
||||||
|
bool liquid_sand_never_box2d;
|
||||||
|
char unknown7[3];
|
||||||
|
int8_t gas_speed;
|
||||||
|
int8_t gas_upwards_speed;
|
||||||
|
int8_t gas_horizontal_speed;
|
||||||
|
int8_t gas_downwards_speed;
|
||||||
|
float solid_friction;
|
||||||
|
float solid_restitution;
|
||||||
|
float solid_gravity_scale;
|
||||||
|
int solid_static_type;
|
||||||
|
float solid_on_collision_splash_power;
|
||||||
|
bool solid_on_collision_explode;
|
||||||
|
bool solid_on_sleep_convert;
|
||||||
|
bool solid_on_collision_convert;
|
||||||
|
bool solid_on_break_explode;
|
||||||
|
bool solid_go_through_sand;
|
||||||
|
bool solid_collide_with_self;
|
||||||
|
char padding5[2];
|
||||||
|
struct std_string solid_on_collision_material;
|
||||||
|
int solid_on_collision_material_id;
|
||||||
|
struct std_string solid_break_to_type;
|
||||||
|
int solid_break_to_type_id;
|
||||||
|
struct std_string convert_to_box2d_material;
|
||||||
|
int convert_to_box2d_material_id;
|
||||||
|
int vegetation_full_lifetime_growth;
|
||||||
|
struct std_string vegetation_sprite;
|
||||||
|
bool vegetation_random_flip_x_scale;
|
||||||
|
char padding6[3];
|
||||||
|
char unknown11[12];
|
||||||
|
float wang_noise_percent;
|
||||||
|
float wang_curvature;
|
||||||
|
int wang_noise_type;
|
||||||
|
char unknown12[12];
|
||||||
|
bool danger_fire;
|
||||||
|
bool danger_radioactive;
|
||||||
|
bool danger_poison;
|
||||||
|
bool danger_water;
|
||||||
|
char unknown13[24];
|
||||||
|
bool always_ignites_damagemodel;
|
||||||
|
bool ignore_self_reaction_warning;
|
||||||
|
char padding7[2];
|
||||||
|
char unknown14[12];
|
||||||
|
float audio_size_multiplier;
|
||||||
|
bool audio_is_soft;
|
||||||
|
char padding8[3];
|
||||||
|
char unknown15[8];
|
||||||
|
bool show_in_creative_mode;
|
||||||
|
bool is_just_particle_fx;
|
||||||
|
char padding9[2];
|
||||||
|
// struct grid_CosmeticParticleConfig *ParticleEffect;
|
||||||
|
};
|
||||||
|
|
||||||
enum CellType {
|
enum CellType {
|
||||||
CELL_TYPE_NONE = 0,
|
CELL_TYPE_NONE = 0,
|
||||||
CELL_TYPE_LIQUID = 1,
|
CELL_TYPE_LIQUID = 1,
|
||||||
|
@ -58,7 +191,7 @@ struct Cell_vtable {
|
||||||
void* field9_0x24;
|
void* field9_0x24;
|
||||||
void* field10_0x28;
|
void* field10_0x28;
|
||||||
void* field11_0x2c;
|
void* field11_0x2c;
|
||||||
void* (__thiscall *get_material)(void *);
|
struct CellData* (__thiscall *get_material)(void *);
|
||||||
void* field13_0x34;
|
void* field13_0x34;
|
||||||
void* field14_0x38;
|
void* field14_0x38;
|
||||||
void* field15_0x3c;
|
void* field15_0x3c;
|
||||||
|
@ -189,9 +322,28 @@ typedef struct Cell* __thiscall construct_cell_f(struct GridWorld*, int x, int y
|
||||||
|
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
--local function check_celldata_field(f, o)
|
||||||
|
-- local offset = ffi.offsetof("struct CellData", f)
|
||||||
|
-- assert(offset == o, "Expected field " .. f .. " to be at offset " .. o)
|
||||||
|
--end
|
||||||
|
--
|
||||||
|
--check_celldata_field("wang_color", 0x40)
|
||||||
|
--check_celldata_field("generates_flames", 0xa4)
|
||||||
|
--check_celldata_field("durability", 0x104)
|
||||||
|
--check_celldata_field("cold_freezes_to_material", 0x114)
|
||||||
|
--check_celldata_field("liquid_sand", 0x160)
|
||||||
|
--check_celldata_field("liquid_sprite_stain_ignited_drop_chance", 0x17c)
|
||||||
|
--check_celldata_field("gas_horizontal_speed", 0x196)
|
||||||
|
--check_celldata_field("solid_on_sleep_convert", 0x1ad)
|
||||||
|
--check_celldata_field("solid_break_to_type", 0x1d0)
|
||||||
|
--check_celldata_field("vegetation_sprite", 0x20c)
|
||||||
|
--check_celldata_field("wang_noise_type", 0x23c)
|
||||||
|
--check_celldata_field("ignore_self_reaction_warning", 0x269)
|
||||||
|
--check_celldata_field("is_just_particle_fx", 0x289)
|
||||||
|
|
||||||
---@class ChunkMap pointer type
|
---@class ChunkMap pointer type
|
||||||
---@class GridWorld pointer type
|
---@class GridWorld pointer type
|
||||||
---@class Material pointer type
|
---@class CellData pointer type
|
||||||
---@class Cell pointer type
|
---@class Cell pointer type
|
||||||
|
|
||||||
---Access a pixel in the world.
|
---Access a pixel in the world.
|
||||||
|
@ -205,7 +357,7 @@ world_ffi.get_cell = ffi.cast("get_cell_f*", world_info.get_cell)
|
||||||
world_ffi.remove_cell = ffi.cast("remove_cell_f*", world_info.remove_cell)
|
world_ffi.remove_cell = ffi.cast("remove_cell_f*", world_info.remove_cell)
|
||||||
|
|
||||||
---Create a new cell. If memory is null pointer it will allocate its own memory.
|
---Create a new cell. If memory is null pointer it will allocate its own memory.
|
||||||
---@type fun(grid_world: GridWorld, x: integer, y: integer, material: Material, memory: ffi.cdata*)
|
---@type fun(grid_world: GridWorld, x: integer, y: integer, material: CellData, memory: ffi.cdata*)
|
||||||
world_ffi.construct_cell = ffi.cast("construct_cell_f*", world_info.construct_cell)
|
world_ffi.construct_cell = ffi.cast("construct_cell_f*", world_info.construct_cell)
|
||||||
|
|
||||||
---Check if a chunk is loaded. x and y are world coordinates.
|
---Check if a chunk is loaded. x and y are world coordinates.
|
||||||
|
@ -239,10 +391,11 @@ function world_ffi.get_grid_world()
|
||||||
end
|
end
|
||||||
|
|
||||||
local celldata_size = 0x290
|
local celldata_size = 0x290
|
||||||
|
local CellData_ptr = ffi.typeof("struct CellData*")
|
||||||
|
|
||||||
---Turn a standard material id into a material pointer.
|
---Turn a standard material id into a material pointer.
|
||||||
---@param id integer material id that is used in the standard Noita functions
|
---@param id integer material id that is used in the standard Noita functions
|
||||||
---@return Material material to internal material data (aka cell data).
|
---@return CellData material to internal material data (aka cell data).
|
||||||
---```lua
|
---```lua
|
||||||
---local gold_ptr = world_ffi.get_material_ptr(CellFactory_GetType("gold"))
|
---local gold_ptr = world_ffi.get_material_ptr(CellFactory_GetType("gold"))
|
||||||
---```
|
---```
|
||||||
|
@ -251,11 +404,11 @@ function world_ffi.get_material_ptr(id)
|
||||||
local cell_factory = ffi.cast('char**', (game_global + 0x18))[0]
|
local cell_factory = ffi.cast('char**', (game_global + 0x18))[0]
|
||||||
local begin = ffi.cast('char**', cell_factory + 0x18)[0]
|
local begin = ffi.cast('char**', cell_factory + 0x18)[0]
|
||||||
local ptr = begin + celldata_size * id
|
local ptr = begin + celldata_size * id
|
||||||
return ptr
|
return ffi.cast(CellData_ptr, ptr) --[[@as CellData]]
|
||||||
end
|
end
|
||||||
|
|
||||||
---Turn a material pointer into a standard material id.
|
---Turn a material pointer into a standard material id.
|
||||||
---@param material Material to a material (aka cell data)
|
---@param material CellData to a material (aka cell data)
|
||||||
---@return integer material id that is accepted by standard Noita functions such as `CellFactory_GetUIName` and `ConvertMaterialOnAreaInstantly`.
|
---@return integer material id that is accepted by standard Noita functions such as `CellFactory_GetUIName` and `ConvertMaterialOnAreaInstantly`.
|
||||||
---```lua
|
---```lua
|
||||||
---local mat_id = world_ffi.get_material_id(cell.vtable.get_material(cell))
|
---local mat_id = world_ffi.get_material_id(cell.vtable.get_material(cell))
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
---@diagnostic disable: cast-local-type
|
--- World read / write functionality.
|
||||||
---World read / write functionality.
|
|
||||||
---@module 'noitapatcher.nsew.world'
|
---@module 'noitapatcher.nsew.world'
|
||||||
---@class World
|
|
||||||
local world = {}
|
local world = {}
|
||||||
|
|
||||||
local ffi = require("ffi")
|
local ffi = require("ffi")
|
||||||
|
@ -12,7 +10,7 @@ local C = ffi.C
|
||||||
ffi.cdef([[
|
ffi.cdef([[
|
||||||
|
|
||||||
enum ENCODE_CONST {
|
enum ENCODE_CONST {
|
||||||
PIXEL_RUN_MAX = 4096,
|
PIXEL_RUN_MAX = 16000,
|
||||||
|
|
||||||
LIQUID_FLAG_STATIC = 1,
|
LIQUID_FLAG_STATIC = 1,
|
||||||
};
|
};
|
||||||
|
@ -39,60 +37,40 @@ struct __attribute__ ((__packed__)) EncodedArea {
|
||||||
|
|
||||||
]])
|
]])
|
||||||
|
|
||||||
---@class PixelRun
|
world.last_material_id = 0
|
||||||
---@field flags integer
|
|
||||||
---@field material integer
|
|
||||||
---@field length integer
|
|
||||||
|
|
||||||
---@class EncodedAreaHeader
|
|
||||||
---@field x integer
|
|
||||||
---@field y integer
|
|
||||||
---@field width integer
|
|
||||||
---@field height integer
|
|
||||||
---@field pixel_run_count integer
|
|
||||||
|
|
||||||
---@class EncodedArea
|
|
||||||
---@field header EncodedAreaHeader
|
|
||||||
---@field pixel_runs PixelRun[] a pointer
|
|
||||||
|
|
||||||
world.EncodedAreaHeader = ffi.typeof("struct EncodedAreaHeader")
|
world.EncodedAreaHeader = ffi.typeof("struct EncodedAreaHeader")
|
||||||
world.PixelRun = ffi.typeof("struct PixelRun")
|
world.PixelRun = ffi.typeof("struct PixelRun")
|
||||||
---@type fun(): EncodedArea
|
|
||||||
---@diagnostic disable-next-line: assign-type-mismatch
|
|
||||||
world.EncodedArea = ffi.typeof("struct EncodedArea")
|
world.EncodedArea = ffi.typeof("struct EncodedArea")
|
||||||
|
|
||||||
local pliquid_cell = ffi.typeof("struct CLiquidCell*")
|
local pliquid_cell = ffi.typeof("struct CLiquidCell*")
|
||||||
|
|
||||||
---Total bytes taken up by the encoded area
|
--- Total bytes taken up by the encoded area
|
||||||
---@param encoded_area EncodedArea
|
-- @tparam EncodedArea encoded_area
|
||||||
---@return integer total number of bytes that encodes the area
|
-- @treturn int total number of bytes that encodes the area
|
||||||
---```lua
|
-- @usage
|
||||||
---local data = ffi.string(area, world.encoded_size(area))
|
-- local data = ffi.string(area, world.encoded_size(area))
|
||||||
---peer:send(data)
|
-- peer:send(data)
|
||||||
---```
|
|
||||||
function world.encoded_size(encoded_area)
|
function world.encoded_size(encoded_area)
|
||||||
return (ffi.sizeof(world.EncodedAreaHeader) + encoded_area.header.pixel_run_count * ffi.sizeof(world.PixelRun))
|
return (ffi.sizeof(world.EncodedAreaHeader) + encoded_area.header.pixel_run_count * ffi.sizeof(world.PixelRun))
|
||||||
end
|
end
|
||||||
|
|
||||||
---Encode the given rectangle of the world
|
--- Encode the given rectangle of the world
|
||||||
---The rectangle defined by {`start_x`, `start_y`, `end_x`, `end_y`} must not exceed 256 in width or height.
|
-- The rectangle defined by {`start_x`, `start_y`, `end_x`, `end_y`} must not
|
||||||
---@param chunk_map unknown
|
-- exceed 256 in width or height.
|
||||||
---@param start_x integer coordinate
|
-- @param chunk_map
|
||||||
---@param start_y integer coordinate
|
-- @tparam int start_x coordinate
|
||||||
---@param end_x integer coordinate
|
-- @tparam int start_y coordinate
|
||||||
---@param end_y integer coordinate
|
-- @tparam int end_x coordinate
|
||||||
---@param encoded_area EncodedArea? memory to use, if nil this function allocates its own memory
|
-- @tparam int end_y coordinate
|
||||||
---@return EncodedArea? encoded_area returns an EncodedArea or nil if the area could not be encoded
|
-- @tparam EncodedArea encoded_area memory to use, if nil this function allocates its own memory
|
||||||
---@see decode
|
-- @return returns an EncodedArea or nil if the area could not be encoded
|
||||||
|
-- @see decode
|
||||||
function world.encode_area(chunk_map, start_x, start_y, end_x, end_y, encoded_area)
|
function world.encode_area(chunk_map, start_x, start_y, end_x, end_y, encoded_area)
|
||||||
start_x = ffi.cast('int32_t', start_x)
|
start_x = ffi.cast('int32_t', start_x)
|
||||||
start_y = ffi.cast('int32_t', start_y)
|
start_y = ffi.cast('int32_t', start_y)
|
||||||
end_x = ffi.cast('int32_t', end_x)
|
end_x = ffi.cast('int32_t', end_x)
|
||||||
end_y = ffi.cast('int32_t', end_y)
|
end_y = ffi.cast('int32_t', end_y)
|
||||||
---@cast start_x integer
|
|
||||||
---@cast start_y integer
|
|
||||||
---@cast end_x integer
|
|
||||||
---@cast end_x integer
|
|
||||||
|
|
||||||
encoded_area = encoded_area or world.EncodedArea()
|
encoded_area = encoded_area or world.EncodedArea()
|
||||||
|
|
||||||
|
@ -187,11 +165,11 @@ end
|
||||||
|
|
||||||
--local PixelRun_const_ptr = ffi.typeof("struct PixelRun const*")
|
--local PixelRun_const_ptr = ffi.typeof("struct PixelRun const*")
|
||||||
|
|
||||||
---Load an encoded area back into the world.
|
--- Load an encoded area back into the world.
|
||||||
---@param grid_world unknown
|
-- @param grid_world
|
||||||
---@param header EncodedAreaHeader header of the encoded area
|
-- @tparam EncodedAreaHeader header header of the encoded area
|
||||||
---@param pixel_runs PixelRun[] or ffi array of PixelRun from the encoded area
|
-- @param received pointer or ffi array of PixelRun from the encoded area
|
||||||
---@see encode_area
|
-- @see encode_area
|
||||||
function world.decode(grid_world, header, pixel_runs)
|
function world.decode(grid_world, header, pixel_runs)
|
||||||
local chunk_map = grid_world.vtable.get_chunk_map(grid_world)
|
local chunk_map = grid_world.vtable.get_chunk_map(grid_world)
|
||||||
|
|
||||||
|
@ -214,10 +192,19 @@ function world.decode(grid_world, header, pixel_runs)
|
||||||
while x < bottom_right_x do
|
while x < bottom_right_x do
|
||||||
if world_ffi.chunk_loaded(chunk_map, x, y) then
|
if world_ffi.chunk_loaded(chunk_map, x, y) then
|
||||||
local ppixel = world_ffi.get_cell(chunk_map, x, y)
|
local ppixel = world_ffi.get_cell(chunk_map, x, y)
|
||||||
|
|
||||||
local current_material = 0
|
local current_material = 0
|
||||||
|
|
||||||
|
if new_material == -1 then
|
||||||
|
goto next_pixel
|
||||||
|
end
|
||||||
|
|
||||||
if ppixel[0] ~= nil then
|
if ppixel[0] ~= nil then
|
||||||
local pixel = ppixel[0]
|
local pixel = ppixel[0]
|
||||||
|
local cell_type = pixel.vtable.get_cell_type(pixel)
|
||||||
|
if cell_type == C.CELL_TYPE_SOLID then
|
||||||
|
goto next_pixel
|
||||||
|
end
|
||||||
current_material = world_ffi.get_material_id(pixel.vtable.get_material(pixel))
|
current_material = world_ffi.get_material_id(pixel.vtable.get_material(pixel))
|
||||||
|
|
||||||
if new_material ~= current_material then
|
if new_material ~= current_material then
|
||||||
|
@ -226,7 +213,22 @@ function world.decode(grid_world, header, pixel_runs)
|
||||||
end
|
end
|
||||||
|
|
||||||
if current_material ~= new_material and new_material ~= 0 then
|
if current_material ~= new_material and new_material ~= 0 then
|
||||||
local pixel = world_ffi.construct_cell(grid_world, x, y, world_ffi.get_material_ptr(new_material), nil)
|
if new_material > world.last_material_id then
|
||||||
|
goto next_pixel
|
||||||
|
end
|
||||||
|
local mat_ptr = world_ffi.get_material_ptr(new_material)
|
||||||
|
if mat_ptr == nil then
|
||||||
|
goto next_pixel
|
||||||
|
end
|
||||||
|
local pixel = world_ffi.construct_cell(grid_world, x, y, mat_ptr, nil)
|
||||||
|
if pixel == nil then
|
||||||
|
-- TODO: This can happen when the material texture has a
|
||||||
|
-- transparent pixel at the given coordinate. There's
|
||||||
|
-- probably a better way to deal with this, but for now
|
||||||
|
-- we skip positions like this.
|
||||||
|
goto next_pixel
|
||||||
|
end
|
||||||
|
|
||||||
local cell_type = pixel.vtable.get_cell_type(pixel)
|
local cell_type = pixel.vtable.get_cell_type(pixel)
|
||||||
|
|
||||||
if cell_type == C.CELL_TYPE_LIQUID then
|
if cell_type == C.CELL_TYPE_LIQUID then
|
||||||
|
@ -238,6 +240,8 @@ function world.decode(grid_world, header, pixel_runs)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
::next_pixel::
|
||||||
|
|
||||||
left = left - 1
|
left = left - 1
|
||||||
if left <= 0 then
|
if left <= 0 then
|
||||||
current_run_ix = current_run_ix + 1
|
current_run_ix = current_run_ix + 1
|
|
@ -1,5 +1,5 @@
|
||||||
local world_ffi = require("noitapatcher.nsew.world_ffi")
|
local world_ffi = require("noitapatcher.nsew.world_ffi")
|
||||||
local world = require("noitapatcher.nsew.world")
|
local world = dofile_once("mods/quant.ew/files/system/world_sync/world.lua")
|
||||||
local rect = require("noitapatcher.nsew.rect")
|
local rect = require("noitapatcher.nsew.rect")
|
||||||
local ffi = require("ffi")
|
local ffi = require("ffi")
|
||||||
|
|
|
@ -66,7 +66,7 @@ local function load_modules()
|
||||||
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/weather_sync.lua")
|
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/weather_sync.lua")
|
||||||
ctx.load_system("polymorph")
|
ctx.load_system("polymorph")
|
||||||
|
|
||||||
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/world_sync_v2.lua")
|
ctx.load_system("world_sync")
|
||||||
|
|
||||||
ctx.load_system("spawn_hooks")
|
ctx.load_system("spawn_hooks")
|
||||||
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/proxy_info.lua")
|
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/proxy_info.lua")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue