remove some duplicate code, fix enemys not spawning close to alone polymorphed players

This commit is contained in:
bgkillas 2024-11-17 21:45:07 -05:00
parent 778c11be3e
commit f1347df61e
4 changed files with 135 additions and 178 deletions

View file

@ -389,28 +389,6 @@ local player_fns = {
end,
}
local PhysData = util.make_type({
f32 = {"x", "y", "vx", "vy", "vr", "r"}
})
local function deserialize_phys_component(phys_component, phys_info)
local x, y = GamePosToPhysicsPos(phys_info.x, phys_info.y)
np.PhysBodySetTransform(phys_component, x, y, phys_info.r, phys_info.vx, phys_info.vy, phys_info.vr)
end
local function serialize_phys_component(phys_component)
local px, py, pr, pvx, pvy, pvr = np.PhysBodyGetTransform(phys_component)
px, py = PhysicsPosToGamePos(px, py)
return PhysData {
x = px,
y = py,
r = pr,
vx = pvx,
vy = pvy,
vr = pvr,
}
end
function player_fns.serialize_position(player_data)
local entity = player_data.entity
if not EntityGetIsAlive(entity) then
@ -428,26 +406,6 @@ function player_fns.serialize_position(player_data)
player_data.pos_x = x
player_data.pos_y = y
local phys_info = {}
local phys_info_2 = {}
for _, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBodyComponent") or {}) do
if phys_component ~= nil and phys_component ~= 0 then
local _, info = pcall(serialize_phys_component, phys_component)
table.insert(phys_info, info)
end
end
for _, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBody2Component") or {}) do
if phys_component ~= nil and phys_component ~= 0 then
local initialized = ComponentGetValue2(phys_component, "mInitialized")
if initialized then
local _, info = pcall(serialize_phys_component, phys_component)
table.insert(phys_info_2, info)
else
table.insert(phys_info_2, nil)
end
end
end
local c = CharacterPos{
frames_in_air = ComponentGetValue2(character_platforming_comp, "mFramesInAirCounter"),
x = x,
@ -457,10 +415,10 @@ function player_fns.serialize_position(player_data)
is_on_ground = ComponentGetValue2(character_data, "is_on_ground"),
is_on_slippery_ground = ComponentGetValue2(character_data, "is_on_slippery_ground"),
}
return c, phys_info, phys_info_2
return c, util.get_phys_info(entity, false)
end
function player_fns.deserialize_position(message, phys_infos, phys_infos_2, player_data)
function player_fns.deserialize_position(message, phys_infos, player_data)
player_data.pos_x = message.x
player_data.pos_y = message.y
@ -483,26 +441,7 @@ function player_fns.deserialize_position(message, phys_infos, phys_infos_2, play
ComponentSetValue2(velocity_comp, "gravity_y", 0)
local had_phys = false
for i, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBodyComponent") or {}) do
local phys_info = phys_infos[i]
if phys_component ~= nil and phys_component ~= 0 and phys_info ~= nil then
deserialize_phys_component(phys_component, phys_info)
had_phys = true
end
end
for i, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBody2Component") or {}) do
local phys_info = phys_infos_2[i]
if phys_component ~= nil and phys_component ~= 0 and phys_info ~= nil then
-- A physics body doesn't exist otherwise, causing a crash
local initialized = ComponentGetValue2(phys_component, "mInitialized")
if initialized then
deserialize_phys_component(phys_component, phys_info)
had_phys = true
end
end
end
if not had_phys then
if not util.set_phys_info(entity, phys_infos) then
ComponentSetValue2(character_data, "mVelocity", message.vel_x, message.vel_y)
EntityApplyTransform(entity, message.x, message.y)
end

View file

@ -349,4 +349,107 @@ util.add_cross_call("ew_host_frame_num", function()
end
end)
local FULL_TURN = math.pi * 2
local PhysData = util.make_type({
f32 = {"x", "y", "vx", "vy", "vr"},
-- We should be able to cram rotation into 1 byte.
u8 = {"r"}
})
-- Variant of PhysData for when we don't have any motion.
local PhysDataNoMotion = util.make_type({
f32 = {"x", "y"},
-- We should be able to cram rotation into 1 byte.
u8 = {"r"}
})
local function serialize_phys_component(phys_component)
local px, py, pr, pvx, pvy, pvr = np.PhysBodyGetTransform(phys_component)
px, py = PhysicsPosToGamePos(px, py)
if math.abs(pvx) < 0.01 and math.abs(pvy) < 0.01 and math.abs(pvr) < 0.01 then
return PhysDataNoMotion {
x = px,
y = py,
r = math.floor((pr % FULL_TURN) / FULL_TURN * 255),
}
else
return PhysData {
x = px,
y = py,
r = math.floor((pr % FULL_TURN) / FULL_TURN * 255),
vx = pvx,
vy = pvy,
vr = pvr,
}
end
end
local function deserialize_phys_component(phys_component, phys_info)
local x, y = GamePosToPhysicsPos(phys_info.x, phys_info.y)
if ffi.typeof(phys_info) == PhysDataNoMotion then
np.PhysBodySetTransform(phys_component, x, y, phys_info.r / 255 * FULL_TURN, 0, 0, 0)
else
np.PhysBodySetTransform(phys_component, x, y, phys_info.r / 255 * FULL_TURN, phys_info.vx, phys_info.vy, phys_info.vr)
end
end
function util.get_phys_info(entity, kill)
local phys_info = {}
local phys_info_2 = {}
for _, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBodyComponent") or {}) do
if phys_component ~= nil and phys_component ~= 0 then
local ret, info = pcall(serialize_phys_component, phys_component)
if not ret and kill then
GamePrint("Physics component has no body, deleting entity")
EntityKill(entity)
return nil
end
table.insert(phys_info, info)
end
end
for _, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBody2Component") or {}) do
if phys_component ~= nil and phys_component ~= 0 then
local initialized = ComponentGetValue2(phys_component, "mInitialized")
if initialized then
local ret, info = pcall(serialize_phys_component, phys_component)
if not ret and kill then
GamePrint("Physics component has no body, deleting entity")
EntityKill(entity)
return nil
end
table.insert(phys_info_2, info)
else
table.insert(phys_info_2, nil)
end
end
end
return {phys_info, phys_info_2}
end
function util.set_phys_info(entity, data)
local phys_infos, phys_infos_2 = data[1], data[2]
local has_set = false
for i, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBodyComponent") or {}) do
local phys_info = phys_infos[i]
if phys_component ~= nil and phys_component ~= 0 and phys_info ~= nil then
deserialize_phys_component(phys_component, phys_info)
has_set = true
end
end
for i, phys_component in ipairs(EntityGetComponent(entity, "PhysicsBody2Component") or {}) do
local phys_info = phys_infos_2[i]
if phys_component ~= nil and phys_component ~= 0 and phys_info ~= nil then
-- A physics body doesn't exist otherwise, causing a crash
local initialized = ComponentGetValue2(phys_component, "mInitialized")
if initialized then
deserialize_phys_component(phys_component, phys_info)
has_set = true
end
end
end
return has_set
end
return util

View file

@ -51,19 +51,6 @@ local HpData = util.make_type({
local FULL_TURN = math.pi * 2
local PhysData = util.make_type({
f32 = {"x", "y", "vx", "vy", "vr"},
-- We should be able to cram rotation into 1 byte.
u8 = {"r"}
})
-- Variant of PhysData for when we don't have any motion.
local PhysDataNoMotion = util.make_type({
f32 = {"x", "y"},
-- We should be able to cram rotation into 1 byte.
u8 = {"r"}
})
local frame = 0
local enemy_sync = {}
@ -120,36 +107,6 @@ local function table_extend_filtered(to, from, filter)
end
end
local function serialize_phys_component(phys_component)
local px, py, pr, pvx, pvy, pvr = np.PhysBodyGetTransform(phys_component)
px, py = PhysicsPosToGamePos(px, py)
if math.abs(pvx) < 0.01 and math.abs(pvy) < 0.01 and math.abs(pvr) < 0.01 then
return PhysDataNoMotion {
x = px,
y = py,
r = math.floor((pr % FULL_TURN) / FULL_TURN * 255),
}
else
return PhysData {
x = px,
y = py,
r = math.floor((pr % FULL_TURN) / FULL_TURN * 255),
vx = pvx,
vy = pvy,
vr = pvr,
}
end
end
local function deserialize_phys_component(phys_component, phys_info)
local x, y = GamePosToPhysicsPos(phys_info.x, phys_info.y)
if ffi.typeof(phys_info) == PhysDataNoMotion then
np.PhysBodySetTransform(phys_component, x, y, phys_info.r / 255 * FULL_TURN, 0, 0, 0)
else
np.PhysBodySetTransform(phys_component, x, y, phys_info.r / 255 * FULL_TURN, phys_info.vx, phys_info.vy, phys_info.vr)
end
end
local function get_sync_entities(return_all)
local entities = EntityGetWithTag("enemy") or {}
table_extend(entities, EntityGetWithTag("ew_enemy_sync_extra"))
@ -179,6 +136,7 @@ local function get_sync_entities(return_all)
local has_anyone = EntityHasTag(ent, "worm")
or EntityGetFirstComponent(ent, "BossHealthBarComponent") ~= nil
or #EntityGetInRadiusWithTag(x, y, DISTANCE_LIMIT, "ew_peer") ~= 0
or #EntityGetInRadiusWithTag(x, y, DISTANCE_LIMIT, "polymorphed_player") ~= 0
return has_anyone and not EntityHasTag(ent, "ew_no_enemy_sync")
end)
end
@ -208,37 +166,10 @@ function enemy_sync.host_upload_entities()
end
local hp, max_hp, has_hp = util.get_ent_health(enemy_id)
local phys_info = {}
local phys_info_2 = {}
for _, phys_component in ipairs(EntityGetComponent(enemy_id, "PhysicsBodyComponent") or {}) do
if phys_component ~= nil and phys_component ~= 0 then
local ret, info = pcall(serialize_phys_component, phys_component)
if not ret then
GamePrint("Physics component has no body, deleting entity")
EntityKill(enemy_id)
local phys_info = util.get_phys_info(enemy_id, true)
if phys_info == nil then
goto continue
end
table.insert(phys_info, info)
end
end
for _, phys_component in ipairs(EntityGetComponent(enemy_id, "PhysicsBody2Component") or {}) do
if phys_component ~= nil and phys_component ~= 0 then
local initialized = ComponentGetValue2(phys_component, "mInitialized")
if initialized then
local ret, info = pcall(serialize_phys_component, phys_component)
if not ret then
GamePrint("Physics component has no body, deleting entity")
EntityKill(enemy_id)
goto continue
end
table.insert(phys_info_2, info)
else
table.insert(phys_info_2, nil)
end
end
end
if has_hp then
util.ensure_component_present(enemy_id, "LuaComponent", "ew_death_notify", {
@ -351,7 +282,7 @@ function enemy_sync.host_upload_entities()
local stains = stain_sync.get_stains(enemy_id)
table.insert(enemy_data_list, {filename, en_data, phys_info, phys_info_2, wand,
table.insert(enemy_data_list, {filename, en_data, phys_info, wand,
effect_data, animation, dont_cull, death_triggers, stains})
::continue::
end
@ -437,9 +368,9 @@ local function sync_enemy(enemy_info_raw, force_no_cull)
filename = constants.interned_index_to_filename[filename] or filename
local en_data = enemy_info_raw[2]
local dont_cull = enemy_info_raw[8]
local death_triggers = enemy_info_raw[9]
local stains = enemy_info_raw[10]
local dont_cull = enemy_info_raw[7]
local death_triggers = enemy_info_raw[8]
local stains = enemy_info_raw[9]
local remote_enemy_id = en_data.enemy_id
local x, y = en_data.x, en_data.y
if not force_no_cull and not dont_cull then
@ -469,10 +400,9 @@ local function sync_enemy(enemy_info_raw, force_no_cull)
vx, vy = en_data.vx, en_data.vy
end
local phys_infos = enemy_info_raw[3]
local phys_infos_2 = enemy_info_raw[4]
local gid = enemy_info_raw[5]
local effects = enemy_info_raw[6]
local animation = enemy_info_raw[7]
local gid = enemy_info_raw[4]
local effects = enemy_info_raw[5]
local animation = enemy_info_raw[6]
local has_died = filename == nil
local frame_now = GameGetFrameNum()
@ -557,24 +487,8 @@ local function sync_enemy(enemy_info_raw, force_no_cull)
enemy_data_new.frame = frame_now
local enemy_id = enemy_data_new.id
for i, phys_component in ipairs(EntityGetComponent(enemy_id, "PhysicsBodyComponent") or {}) do
local phys_info = phys_infos[i]
if phys_component ~= nil and phys_component ~= 0 and phys_info ~= nil then
deserialize_phys_component(phys_component, phys_info)
end
end
for i, phys_component in ipairs(EntityGetComponent(enemy_id, "PhysicsBody2Component") or {}) do
local phys_info = phys_infos_2[i]
if phys_component ~= nil and phys_component ~= 0 and phys_info ~= nil then
-- A physics body doesn't exist otherwise, causing a crash
local initialized = ComponentGetValue2(phys_component, "mInitialized")
if initialized then
deserialize_phys_component(phys_component, phys_info)
end
end
end
if not has_died then
if not util.set_phys_info(enemy_id, phys_infos) then
local character_data = EntityGetFirstComponentIncludingDisabled(enemy_id, "CharacterDataComponent")
if character_data ~= nil then
ComponentSetValue2(character_data, "mVelocity", vx, vy)
@ -588,6 +502,7 @@ local function sync_enemy(enemy_info_raw, force_no_cull)
else
EntitySetTransform(enemy_id, x, y)
end
end
local worm = EntityGetFirstComponentIncludingDisabled(enemy_id, "WormAIComponent")
or EntityGetFirstComponentIncludingDisabled(enemy_id, "BossDragonComponent")
if worm ~= nil and ffi.typeof(en_data) == EnemyDataWorm then

View file

@ -18,7 +18,7 @@ function rpc.send_money_and_ingestion(money, ingestion_size)
end
end
function rpc.player_update(input_data, pos_data, phys_info, phys_info_2, current_slot, team)
function rpc.player_update(input_data, pos_data, phys_info, current_slot, team)
local peer_id = ctx.rpc_peer_id
if not player_fns.peer_has_player(peer_id) then
@ -40,7 +40,7 @@ function rpc.player_update(input_data, pos_data, phys_info, phys_info_2, current
player_fns.deserialize_inputs(input_data, player_data)
end
if pos_data ~= nil then
player_fns.deserialize_position(pos_data, phys_info, phys_info_2, player_data)
player_fns.deserialize_position(pos_data, phys_info, player_data)
end
if current_slot ~= nil then
player_fns.set_current_slot(current_slot, player_data)
@ -65,7 +65,7 @@ end
function module.on_world_update()
local input_data = player_fns.serialize_inputs(ctx.my_player)
local pos_data, phys_info, phys_info_2 = player_fns.serialize_position(ctx.my_player)
local pos_data, phys_info = player_fns.serialize_position(ctx.my_player)
local current_slot = player_fns.get_current_slot(ctx.my_player)
if input_data ~= nil or pos_data ~= nil then
local my_team
@ -73,7 +73,7 @@ function module.on_world_update()
my_team = ctx.proxy_opt.friendly_fire_team - 1
end
rpc.player_update(input_data, pos_data, phys_info, phys_info_2, current_slot, my_team)
rpc.player_update(input_data, pos_data, phys_info, current_slot, my_team)
if GameGetFrameNum() % 120 == 0 then
local n = np.GetGameModeNr()
rpc.check_gamemode(np.GetGameModeName(n))