forked from alterware/iw6-mod
Simplified predicted data logic.
This commit is contained in:
@@ -47,7 +47,7 @@ namespace // demo class
|
|||||||
|
|
||||||
void shutdown_watcher();
|
void shutdown_watcher();
|
||||||
void process_network_data(auto old_connstate, auto new_connstate, std::span<const std::uint8_t> network_data);
|
void process_network_data(auto old_connstate, auto new_connstate, std::span<const std::uint8_t> network_data);
|
||||||
void process_predicted_data();
|
void process_predicted_data(auto old_connstate, auto new_connstate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] bool is_auto_recording() const;
|
[[nodiscard]] bool is_auto_recording() const;
|
||||||
@@ -419,38 +419,18 @@ namespace // demo class
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void demo_recording_t::process_predicted_data()
|
void demo_recording_t::process_predicted_data(auto old_connstate, auto new_connstate)
|
||||||
{
|
{
|
||||||
|
if (old_connstate < game::CA_ACTIVE || new_connstate < game::CA_ACTIVE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
process_helo_pilot_turret_fire();
|
process_helo_pilot_turret_fire();
|
||||||
|
|
||||||
if (is_recording())
|
if (is_recording())
|
||||||
{
|
{
|
||||||
// only one predicted data packet is needed per (1000 / sv_fps) msec
|
write_predicted_data(user_file_);
|
||||||
// the best way to limit the amount of predicted data is to attempt to predict the next playerState_t::commandTime
|
|
||||||
// because during demo playback the playerState_t::commandTime determines which predicted data is used
|
|
||||||
|
|
||||||
const auto& cl = *game::mp::cl;
|
|
||||||
const auto cmd_number = static_cast<std::size_t>(cl.cmdNumber);
|
|
||||||
const auto pred_svr_time_delta = cl.cmds[cmd_number % std::size(cl.cmds)].serverTime
|
|
||||||
- cl.cmds[(cmd_number - 1) % std::size(cl.cmds)].serverTime;
|
|
||||||
|
|
||||||
const auto pred_svr_time = cl.cgamePredictedDataServerTime;
|
|
||||||
const auto svr_time_delta = std::clamp(cl.snap.serverTime - cl.oldSnapServerTime, 50, 100);
|
|
||||||
|
|
||||||
const auto cur_cmd_time = cl.snap.ps.commandTime;
|
|
||||||
const auto next_cmd_time = cur_cmd_time + svr_time_delta;
|
|
||||||
const auto threshold = (3 * pred_svr_time_delta) / 2;
|
|
||||||
|
|
||||||
if (pred_svr_time + threshold >= next_cmd_time && next_cmd_time + threshold >= pred_svr_time)
|
|
||||||
{
|
|
||||||
times_.predicted_data_time = cl.serverTime;
|
|
||||||
write_predicted_data(user_file_);
|
|
||||||
}
|
|
||||||
else if (cl.serverTime >= times_.predicted_data_time + svr_time_delta - 5)
|
|
||||||
{
|
|
||||||
times_.predicted_data_time = cl.serverTime;
|
|
||||||
write_predicted_data(user_file_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_auto_recording())
|
if (is_auto_recording())
|
||||||
@@ -494,21 +474,11 @@ namespace // hooks
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
demo.process_predicted_data(old_connstate, new_connstate);
|
||||||
demo.process_network_data(old_connstate, new_connstate,
|
demo.process_network_data(old_connstate, new_connstate,
|
||||||
std::span<const std::uint8_t>(reinterpret_cast<const std::uint8_t*>(msg.data), msg.cursize));
|
std::span<const std::uint8_t>(reinterpret_cast<const std::uint8_t*>(msg.data), msg.cursize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void capture_predicted_data(game::msg_t& msg, std::int32_t value, std::uint32_t bits)
|
|
||||||
{
|
|
||||||
if (!demo_playback::playing())
|
|
||||||
{
|
|
||||||
demo.process_predicted_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
// call MSG_WriteBits that this hook replaces
|
|
||||||
game::MSG_WriteBits(&msg, value, bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
void request_non_delta_data(game::msg_t& msg, std::int32_t value, std::uint32_t bits)
|
void request_non_delta_data(game::msg_t& msg, std::int32_t value, std::uint32_t bits)
|
||||||
{
|
{
|
||||||
if (!demo_playback::playing() && demo.non_delta_data_requested())
|
if (!demo_playback::playing() && demo.non_delta_data_requested())
|
||||||
@@ -715,9 +685,6 @@ namespace demo_recording
|
|||||||
// capture incoming packets
|
// capture incoming packets
|
||||||
CL_ParseServerMessage_hook.create(game::CL_ParseServerMessage, capture_data);
|
CL_ParseServerMessage_hook.create(game::CL_ParseServerMessage, capture_data);
|
||||||
|
|
||||||
// capture client predicted data (in CL_WritePacket)
|
|
||||||
utils::hook::call(0x1402C21B9, capture_predicted_data);
|
|
||||||
|
|
||||||
// request the server for no delta data (in CL_WritePacket)
|
// request the server for no delta data (in CL_WritePacket)
|
||||||
utils::hook::call(0x1402C2026, request_non_delta_data);
|
utils::hook::call(0x1402C2026, request_non_delta_data);
|
||||||
|
|
||||||
|
|||||||
@@ -467,35 +467,35 @@ namespace demo_utils
|
|||||||
write_network_data_(output, network_data);
|
write_network_data_(output, network_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_predicted_player_data_(auto& output, const game::ClientArchiveData& cad,
|
void write_predicted_player_data_(auto& output, const game::mp::playerState_t& ps,
|
||||||
const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id)
|
std::uint8_t cad_index, predicted_data_id id)
|
||||||
{
|
{
|
||||||
write_id_and_size(output, 50, demo_data_id::predicted_data);
|
write_id_and_size(output, 50, demo_data_id::predicted_data);
|
||||||
output.write(reinterpret_cast<const char*>(&id), 1);
|
output.write(reinterpret_cast<const char*>(&id), 1);
|
||||||
output.write(reinterpret_cast<const char*>(&cad_index), 1);
|
output.write(reinterpret_cast<const char*>(&cad_index), 1);
|
||||||
|
|
||||||
output.write(reinterpret_cast<const char*>(&cad.serverTime), 4);
|
output.write(reinterpret_cast<const char*>(&ps.commandTime), 4);
|
||||||
output.write(reinterpret_cast<const char*>(&cad.origin[0]), 12);
|
output.write(reinterpret_cast<const char*>(&ps.origin[0]), 12);
|
||||||
output.write(reinterpret_cast<const char*>(&cad.velocity[0]), 12);
|
output.write(reinterpret_cast<const char*>(&ps.velocity[0]), 12);
|
||||||
output.write(reinterpret_cast<const char*>(&cad.bobCycle), 4);
|
output.write(reinterpret_cast<const char*>(&ps.bobCycle), 4);
|
||||||
output.write(reinterpret_cast<const char*>(&cad.movementDir), 4);
|
output.write(reinterpret_cast<const char*>(&ps.movementDir), 4);
|
||||||
output.write(reinterpret_cast<const char*>(&viewangles[0]), 12);
|
output.write(reinterpret_cast<const char*>(&ps.viewangles[0]), 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_predicted_player_data(buffer_t& output, const game::ClientArchiveData& cad,
|
void write_predicted_player_data(buffer_t& output, const game::mp::playerState_t& ps,
|
||||||
const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id)
|
std::uint8_t cad_index, predicted_data_id id)
|
||||||
{
|
{
|
||||||
write_predicted_player_data_(output, cad, viewangles, cad_index, id);
|
write_predicted_player_data_(output, ps, cad_index, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_predicted_player_data(std::ofstream& output, const game::ClientArchiveData& cad,
|
void write_predicted_player_data(std::ofstream& output, const game::mp::playerState_t& ps,
|
||||||
const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id)
|
std::uint8_t cad_index, predicted_data_id id)
|
||||||
{
|
{
|
||||||
write_predicted_player_data_(output, cad, viewangles, cad_index, id);
|
write_predicted_player_data_(output, ps, cad_index, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_predicted_vehicle_data_(auto& output, const game::ClientArchiveData& cad,
|
void write_predicted_vehicle_data_(auto& output, const game::mp::playerState_t& ps,
|
||||||
const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id)
|
std::uint8_t cad_index, predicted_data_id id)
|
||||||
{
|
{
|
||||||
const auto size = (id != predicted_data_id::vehicle_gryphon) ? 58 : 82;
|
const auto size = (id != predicted_data_id::vehicle_gryphon) ? 58 : 82;
|
||||||
|
|
||||||
@@ -503,10 +503,10 @@ namespace demo_utils
|
|||||||
output.write(reinterpret_cast<const char*>(&id), 1);
|
output.write(reinterpret_cast<const char*>(&id), 1);
|
||||||
output.write(reinterpret_cast<const char*>(&cad_index), 1);
|
output.write(reinterpret_cast<const char*>(&cad_index), 1);
|
||||||
|
|
||||||
const auto& vehicle = cad.playerVehStateClientArchive;
|
const auto& vehicle = ps.vehicleState;
|
||||||
output.write(reinterpret_cast<const char*>(&cad.serverTime), 4);
|
output.write(reinterpret_cast<const char*>(&ps.commandTime), 4);
|
||||||
output.write(reinterpret_cast<const char*>(&cad.origin[0]), 12);
|
output.write(reinterpret_cast<const char*>(&ps.origin[0]), 12);
|
||||||
output.write(reinterpret_cast<const char*>(&viewangles[0]), 12);
|
output.write(reinterpret_cast<const char*>(&ps.viewangles[0]), 12);
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.flags), 4);
|
output.write(reinterpret_cast<const char*>(&vehicle.flags), 4);
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.origin[0]), 12);
|
output.write(reinterpret_cast<const char*>(&vehicle.origin[0]), 12);
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.angles[0]), 12);
|
output.write(reinterpret_cast<const char*>(&vehicle.angles[0]), 12);
|
||||||
@@ -520,16 +520,16 @@ namespace demo_utils
|
|||||||
assert(!vehicle.splineId);
|
assert(!vehicle.splineId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_predicted_vehicle_data(buffer_t& output, const game::ClientArchiveData& cad,
|
void write_predicted_vehicle_data(buffer_t& output, const game::mp::playerState_t& ps,
|
||||||
const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id)
|
std::uint8_t cad_index, predicted_data_id id)
|
||||||
{
|
{
|
||||||
write_predicted_vehicle_data_(output, cad, viewangles, cad_index, id);
|
write_predicted_vehicle_data_(output, ps, cad_index, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_predicted_vehicle_data(std::ofstream& output, const game::ClientArchiveData& cad,
|
void write_predicted_vehicle_data(std::ofstream& output, const game::mp::playerState_t& ps,
|
||||||
const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id)
|
std::uint8_t cad_index, predicted_data_id id)
|
||||||
{
|
{
|
||||||
write_predicted_vehicle_data_(output, cad, viewangles, cad_index, id);
|
write_predicted_vehicle_data_(output, ps, cad_index, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_helo_pilot_turret_fire_(auto& output, std::uint8_t fire_count)
|
void write_helo_pilot_turret_fire_(auto& output, std::uint8_t fire_count)
|
||||||
@@ -675,23 +675,23 @@ namespace demo_utils
|
|||||||
|
|
||||||
void write_predicted_data_(auto& output)
|
void write_predicted_data_(auto& output)
|
||||||
{
|
{
|
||||||
const auto& ps = game::mp::cg->ps;
|
auto& cl = *game::mp::cl;
|
||||||
const auto& viewangles = game::mp::cg->refdefViewAngles;
|
auto& ps = cl.snap.ps;
|
||||||
const auto cad_index = static_cast<std::uint8_t>(game::mp::cl->clientArchiveIndex - 1);
|
const auto& cg = *game::mp::cg;
|
||||||
const auto cad_array = std::span(game::mp::cl->clientArchive);
|
|
||||||
|
|
||||||
if (const auto& cad = cad_array[cad_index]; cad.serverTime)
|
ps.viewangles[0] = cg.refdefViewAngles[0];
|
||||||
|
ps.viewangles[1] = cg.refdefViewAngles[1];
|
||||||
|
ps.viewangles[2] = cg.refdefViewAngles[2];
|
||||||
|
|
||||||
|
const auto vehicle_in_use = (ps.vehicleState.entity && ps.vehicleState.entity != 2047);
|
||||||
|
if (!vehicle_in_use)
|
||||||
{
|
{
|
||||||
const auto vehicle_in_use = (ps.vehicleState.entity && ps.vehicleState.entity != 2047);
|
write_predicted_player_data(output, ps, static_cast<std::uint8_t>(cl.clientArchiveIndex), predicted_data_id::player);
|
||||||
if (!vehicle_in_use)
|
}
|
||||||
{
|
else
|
||||||
write_predicted_player_data(output, cad, viewangles, cad_index, predicted_data_id::player);
|
{
|
||||||
}
|
const auto data_type = get_predicted_vehicle_type(ps);
|
||||||
else
|
write_predicted_vehicle_data(output, ps, static_cast<std::uint8_t>(cl.clientArchiveIndex), data_type);
|
||||||
{
|
|
||||||
const auto data_type = get_predicted_vehicle_type(ps);
|
|
||||||
write_predicted_vehicle_data(output, cad, viewangles, cad_index, data_type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,77 +842,12 @@ namespace demo_utils
|
|||||||
|
|
||||||
namespace serialization_server
|
namespace serialization_server
|
||||||
{
|
{
|
||||||
void sv_write_predicted_player_data_(auto& output, const game::mp::playerState_t& ps,
|
|
||||||
std::uint8_t cad_index, predicted_data_id id)
|
|
||||||
{
|
|
||||||
write_id_and_size(output, 50, demo_data_id::predicted_data);
|
|
||||||
output.write(reinterpret_cast<const char*>(&id), 1);
|
|
||||||
output.write(reinterpret_cast<const char*>(&cad_index), 1);
|
|
||||||
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.commandTime), 4);
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.origin[0]), 12);
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.velocity[0]), 12);
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.bobCycle), 4);
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.movementDir), 4);
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.viewangles[0]), 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sv_write_predicted_player_data(buffer_t& output, const game::mp::playerState_t& ps,
|
|
||||||
std::uint8_t cad_index, predicted_data_id id)
|
|
||||||
{
|
|
||||||
sv_write_predicted_player_data_(output, ps, cad_index, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sv_write_predicted_player_data(std::ofstream& output, const game::mp::playerState_t& ps,
|
|
||||||
std::uint8_t cad_index, predicted_data_id id)
|
|
||||||
{
|
|
||||||
sv_write_predicted_player_data_(output, ps, cad_index, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sv_write_predicted_vehicle_data_(auto& output, const game::mp::playerState_t& ps,
|
|
||||||
std::uint8_t cad_index, predicted_data_id id)
|
|
||||||
{
|
|
||||||
const auto size = (id != predicted_data_id::vehicle_gryphon) ? 58 : 82;
|
|
||||||
|
|
||||||
write_id_and_size(output, size, demo_data_id::predicted_data);
|
|
||||||
output.write(reinterpret_cast<const char*>(&id), 1);
|
|
||||||
output.write(reinterpret_cast<const char*>(&cad_index), 1);
|
|
||||||
|
|
||||||
const auto& vehicle = ps.vehicleState;
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.commandTime), 4);
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.origin[0]), 12);
|
|
||||||
output.write(reinterpret_cast<const char*>(&ps.viewangles[0]), 12);
|
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.flags), 4);
|
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.origin[0]), 12);
|
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.angles[0]), 12);
|
|
||||||
|
|
||||||
if (id == predicted_data_id::vehicle_gryphon)
|
|
||||||
{
|
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.velocity[0]), 12);
|
|
||||||
output.write(reinterpret_cast<const char*>(&vehicle.angVelocity[0]), 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!vehicle.splineId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sv_write_predicted_vehicle_data(buffer_t& output, const game::mp::playerState_t& ps,
|
|
||||||
std::uint8_t cad_index, predicted_data_id id)
|
|
||||||
{
|
|
||||||
sv_write_predicted_vehicle_data_(output, ps, cad_index, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sv_write_predicted_vehicle_data(std::ofstream& output, const game::mp::playerState_t& ps,
|
|
||||||
std::uint8_t cad_index, predicted_data_id id)
|
|
||||||
{
|
|
||||||
sv_write_predicted_vehicle_data_(output, ps, cad_index, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sv_write_predicted_data_(auto& output, const game::mp::playerState_t& ps, std::size_t send_msg_count)
|
void sv_write_predicted_data_(auto& output, const game::mp::playerState_t& ps, std::size_t send_msg_count)
|
||||||
{
|
{
|
||||||
const auto vehicle_in_use = (ps.vehicleState.entity && ps.vehicleState.entity != 2047);
|
const auto vehicle_in_use = (ps.vehicleState.entity && ps.vehicleState.entity != 2047);
|
||||||
if (!vehicle_in_use)
|
if (!vehicle_in_use)
|
||||||
{
|
{
|
||||||
sv_write_predicted_player_data(output, ps, static_cast<std::uint8_t>(send_msg_count), predicted_data_id::player);
|
write_predicted_player_data(output, ps, static_cast<std::uint8_t>(send_msg_count), predicted_data_id::player);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -926,7 +861,7 @@ namespace demo_utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sv_write_predicted_vehicle_data(output, ps, static_cast<std::uint8_t>(send_msg_count), data_type);
|
write_predicted_vehicle_data(output, ps, static_cast<std::uint8_t>(send_msg_count), data_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,15 +143,15 @@ namespace demo_utils
|
|||||||
void write_network_data(buffer_t& output, std::span<const std::uint8_t> network_data);
|
void write_network_data(buffer_t& output, std::span<const std::uint8_t> network_data);
|
||||||
void write_network_data(std::ofstream& output, std::span<const std::uint8_t> network_data);
|
void write_network_data(std::ofstream& output, std::span<const std::uint8_t> network_data);
|
||||||
|
|
||||||
//void write_predicted_player_data(buffer_t& output, const game::ClientArchiveData& cad,
|
//void write_predicted_player_data(buffer_t& output, const game::mp::playerState_t& ps,
|
||||||
//const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id);
|
//std::uint8_t cad_index, predicted_data_id id);
|
||||||
//void write_predicted_player_data(std::ofstream& output, const game::ClientArchiveData& cad,
|
//void write_predicted_player_data(std::ofstream& output, const game::mp::playerState_t& ps,
|
||||||
//const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id);
|
//std::uint8_t cad_index, predicted_data_id id);
|
||||||
|
|
||||||
//void write_predicted_vehicle_data(buffer_t& output, const game::ClientArchiveData& cad,
|
//void write_predicted_vehicle_data(buffer_t& output, const game::mp::playerState_t& ps,
|
||||||
//const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id);
|
//std::uint8_t cad_index, predicted_data_id id);
|
||||||
//void write_predicted_vehicle_data(std::ofstream& output, const game::ClientArchiveData& cad,
|
//void write_predicted_vehicle_data(std::ofstream& output, const game::mp::playerState_t& ps,
|
||||||
//const game::vec3_t& viewangles, std::uint8_t cad_index, predicted_data_id id);
|
//std::uint8_t cad_index, predicted_data_id id);
|
||||||
|
|
||||||
void write_helo_pilot_turret_fire(buffer_t& output, std::uint8_t fire_count);
|
void write_helo_pilot_turret_fire(buffer_t& output, std::uint8_t fire_count);
|
||||||
void write_helo_pilot_turret_fire(std::ofstream& output, std::uint8_t fire_count);
|
void write_helo_pilot_turret_fire(std::ofstream& output, std::uint8_t fire_count);
|
||||||
|
|||||||
Reference in New Issue
Block a user