diff --git a/quant.ew/files/core/player_fns.lua b/quant.ew/files/core/player_fns.lua index 4520a67f..74518689 100644 --- a/quant.ew/files/core/player_fns.lua +++ b/quant.ew/files/core/player_fns.lua @@ -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 diff --git a/quant.ew/files/core/util.lua b/quant.ew/files/core/util.lua index c1997692..41c3985b 100644 --- a/quant.ew/files/core/util.lua +++ b/quant.ew/files/core/util.lua @@ -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 \ No newline at end of file diff --git a/quant.ew/files/system/enemy_sync.lua b/quant.ew/files/system/enemy_sync.lua index d18df1d3..7403c087 100644 --- a/quant.ew/files/system/enemy_sync.lua +++ b/quant.ew/files/system/enemy_sync.lua @@ -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,36 +166,9 @@ 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) - 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 + local phys_info = util.get_phys_info(enemy_id, true) + if phys_info == nil then + goto continue end if has_hp then @@ -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,36 +487,21 @@ 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 - local character_data = EntityGetFirstComponentIncludingDisabled(enemy_id, "CharacterDataComponent") - if character_data ~= nil then - ComponentSetValue2(character_data, "mVelocity", vx, vy) - end - local velocity_data = EntityGetFirstComponentIncludingDisabled(enemy_id, "VelocityComponent") - if velocity_data ~= nil then - ComponentSetValue2(velocity_data, "mVelocity", vx, vy) - end - if ffi.typeof(en_data) == EnemyDataFish then - EntitySetTransform(enemy_id, x, y, en_data.r / 255 * FULL_TURN) - else - EntitySetTransform(enemy_id, x, y) + 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) + end + local velocity_data = EntityGetFirstComponentIncludingDisabled(enemy_id, "VelocityComponent") + if velocity_data ~= nil then + ComponentSetValue2(velocity_data, "mVelocity", vx, vy) + end + if ffi.typeof(en_data) == EnemyDataFish then + EntitySetTransform(enemy_id, x, y, en_data.r / 255 * FULL_TURN) + else + EntitySetTransform(enemy_id, x, y) + end end local worm = EntityGetFirstComponentIncludingDisabled(enemy_id, "WormAIComponent") or EntityGetFirstComponentIncludingDisabled(enemy_id, "BossDragonComponent") diff --git a/quant.ew/files/system/player_sync.lua b/quant.ew/files/system/player_sync.lua index 6ed73d4c..98254c7c 100644 --- a/quant.ew/files/system/player_sync.lua +++ b/quant.ew/files/system/player_sync.lua @@ -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))