1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
#pragma once
#include "globalincs/pstypes.h"
#include "network/multi_time_manager.h"
#include "physics/physics_state.h"
struct physics_info;
constexpr int PACKET_INFO_LIMIT = 4; // we should never need more than 4 packets to do interpolation. Overwrite the oldest ones if we do.
typedef struct packet_info {
int frame; // this allows us to directly compare one packet to another.
int remote_missiontime; // the remote timestamp that matches this packet.
physics_snapshot snapshot; // the received physics info translated into the physics snapshot type for easy interpolation
packet_info(int frame_in = 0, int time_in = 0, const vec3d* position_in = &vmd_zero_vector, const vec3d* velocity_in = &vmd_zero_vector,
const vec3d* rotational_velocity_in = &vmd_zero_vector, const vec3d* desired_velocity_in = &vmd_zero_vector, const vec3d* desired_rotational_velocity_in = &vmd_zero_vector,
const angles* angles_in = &vmd_zero_angles)
{
frame = frame_in;
remote_missiontime = time_in;
snapshot.position = *position_in;
snapshot.velocity = *velocity_in;
snapshot.rotational_velocity = *rotational_velocity_in;
snapshot.desired_velocity = *desired_velocity_in;
snapshot.desired_rotational_velocity = *desired_rotational_velocity_in;
vm_angles_2_matrix(&snapshot.orientation, angles_in);
}
} packet_info;
// the real center of the new interpolation code. When a packet is received, its frame is used as the key in the unordered_map _packets
// those keys are kept in _received_frames
class interpolation_manager {
private:
int _upcoming_packet_index; // what packet should we look at as the next packet. -1 if we do not yet have enough packets.
int _prev_packet_index; // what was the last packet? This and Upcoming are both idices into the _packets vector.
int _local_skip_forward; // TODO: Use this? Used on the server if a client is inexplicably ahead of us.
bool _simulation_mode; // are we currently simulating as if this were a normal ship?
bool _packets_expended; // have we used up all packets while interpolating?
SCP_vector<packet_info> _packets; // all the info from the position/orientation portion of packets that we care to keep
int _source_player_index;
void reassess_packet_index(vec3d* pos, matrix* ori, physics_info* pip); // for finding which packets from within _packets we should use
void replace_packet(int index, vec3d* pos, matrix* orient, physics_info* pip); // a function that acts as a workaround, when coming out of simulation_mode
// Frame numbers that helps us figure out if we should ignore new information coming from the server because
// we already received a newer packet than this one for that type of info.
int _hull_comparison_frame; // what frame was the last hull information received?
int _shields_comparison_frame; // what frame was the last shield information received?
SCP_vector<std::pair<int,int>> _subsystems_comparison_frame; // what frame was the last subsystem information received? (for each subsystem) First is health, second is animation
int _ai_comparison_frame; // what frame was the last ai information received?
public:
// adds a new packet, whilst also manually sorting the relevant entries
void add_packet(int objnum, int frame, int time_delta, vec3d* position, vec3d* velocity, vec3d* rotational_velocity, vec3d* desired_velocity, vec3d* desired_rotational_velocity, angles* angles, int player_index);
void interpolate_main(vec3d* pos, matrix* ori, physics_info* pip, vec3d* last_pos, matrix* last_orient, vec3d* gravity, bool player_ship);
void reinterpolate_previous(TIMESTAMP stamp, int prev_packet_index, int next_packet_index, vec3d& position, matrix& orientation, vec3d& velocity, vec3d& rotational_velocity);
int get_hull_comparison_frame() { return _hull_comparison_frame; }
int get_shields_comparison_frame() { return _shields_comparison_frame; }
int get_subsystem_health_frame(int i)
{
if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
return _subsystems_comparison_frame[i].first;
} // if it somehow got passed nonsense, chances are what it is is trying to read is nonsense, and INT_MAX will keep it from doing anything crazy.
else {
return INT_MAX;
}
}
int get_subsystem_animation_frame(int i) {
if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
return _subsystems_comparison_frame[i].second;
} // if it somehow got passed nonsense, chances are what it is is trying to read is nonsense, and INT_MAX will keep it from doing anything crazy.
else {
return INT_MAX;
}
}
int get_ai_comparison_frame() { return _ai_comparison_frame; }
void set_hull_comparison_frame(int frame) { _hull_comparison_frame = frame; }
void set_shields_comparison_frame(int frame) { _shields_comparison_frame = frame; }
void set_subsystem_health_frame(int i, int frame)
{
if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
_subsystems_comparison_frame[i].first = frame;
}
}
void set_subsystem_animation_frame(int i, int frame)
{
if (i < static_cast<int>(_subsystems_comparison_frame.size()) && i >= 0) {
_subsystems_comparison_frame[i].second = frame;
}
}
void set_ai_comparison_frame(int frame) { _ai_comparison_frame = frame; }
void force_interpolation_mode() { _simulation_mode = true; }
void reset(int subsystem_count)
{
if (!(Game_mode & GM_MULTIPLAYER)){
return;
}
_packets.clear();
_packets.reserve(PACKET_INFO_LIMIT * 2);
_upcoming_packet_index = -1;
_prev_packet_index = -1;
_simulation_mode = false;
_packets_expended = false;
_local_skip_forward = 0;
_hull_comparison_frame = -1;
_shields_comparison_frame = -1;
_source_player_index = -1;
_subsystems_comparison_frame.clear();
for (int i = 0; i < subsystem_count; i++) {
_subsystems_comparison_frame.emplace_back(-1, -1);
}
_ai_comparison_frame = -1;
}
void clean_up()
{
_packets.clear();
_packets.shrink_to_fit();
_subsystems_comparison_frame.clear();
_subsystems_comparison_frame.shrink_to_fit();
}
interpolation_manager()
{
_upcoming_packet_index = -1;
_prev_packet_index = -1;
_simulation_mode = false;
_packets_expended = false;
_local_skip_forward = 0;
_hull_comparison_frame = -1;
_shields_comparison_frame = -1;
_ai_comparison_frame = -1;
_source_player_index = -1;
}
};
void multi_interpolate_clear_all();
void multi_interpolate_clear_helper(int objnum);
void interpolate_main_helper(int objnum, vec3d* pos, matrix* ori, physics_info* pip, vec3d* last_pos, matrix* last_orient, vec3d* gravity, bool player_ship);
extern SCP_unordered_map<int, interpolation_manager> Interp_info;
|