Skip to content

Commit 463f9d9

Browse files
authoredJan 20, 2025
Merge pull request #24 from HeatXD/netstats
Netstats and free network polling from the main loop.
2 parents 88b9099 + 6334d87 commit 463f9d9

File tree

12 files changed

+327
-107
lines changed

12 files changed

+327
-107
lines changed
 

‎Examples/LocalSession/LocalSession.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,15 @@ int main(int argc, char* args[])
177177
int count = 0;
178178
auto events = gekko_session_events(sess, &count);
179179
for (int i = 0; i < count; i++) {
180-
printf("ev: %d\n", events[i]->type);
180+
printf("s ev: %d\n", events[i]->type);
181181
}
182182

183183
count = 0;
184184
auto updates = gekko_update_session(sess, &count);
185185
for (int i = 0; i < count; i++)
186186
{
187187
auto ev = updates[i];
188-
188+
printf("g ev: %d\n", ev->type);
189189
switch (ev->type)
190190
{
191191
case AdvanceEvent:

‎Examples/OnlineSession/OnlineSession.cpp

+82-69
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,15 @@ GInput get_key_inputs() {
157157
return input;
158158
}
159159

160-
micro GetFrameTime(float frames_ahead) {
161-
if (frames_ahead >= 1.0f) {
162-
return std::chrono::duration_cast<micro>(slow_frame(1));
160+
float GetFrameTime(float frames_ahead) {
161+
if (frames_ahead >= 1.f) {
162+
return std::chrono::duration<float>(slow_frame(1)).count();
163163
}
164-
else if (frames_ahead <= -1.0f) {
165-
return std::chrono::duration_cast<micro>(fast_frame(1));
164+
else if (frames_ahead <= -1.f) {
165+
return std::chrono::duration<float>(fast_frame(1)).count();
166166
}
167167
else {
168-
return std::chrono::duration_cast<micro>(normal_frame(1));
168+
return std::chrono::duration<float>(normal_frame(1)).count();
169169
}
170170

171171
}
@@ -229,90 +229,103 @@ int main(int argc, char* args[])
229229
}
230230

231231
gekko_set_local_delay(sess, localplayer, 1);
232-
// timing
233-
234-
gtime_point start_time(gclock::now());
235-
gtime_point end_time(gclock::now());
236232

237233
int current = 0;
238234

235+
// timing
236+
auto curr_time = gclock::now();
237+
auto prev_time(gclock::now());
238+
239+
float delta_time = 0.f;
240+
float accumulator = 0.f;
241+
float frame_time = 0.f;
242+
float frames_ahead = 0.f;
243+
239244
while (running) {
240-
start_time = gclock::now();
245+
curr_time = gclock::now();
241246

242-
auto frame_time = GetFrameTime(gekko_frames_ahead(sess));
247+
frames_ahead = gekko_frames_ahead(sess);
248+
frame_time = GetFrameTime(frames_ahead);
243249

244-
std::cout << "ft: " << frame_time.count() << std::endl;
250+
delta_time = std::chrono::duration<float>(curr_time - prev_time).count();
251+
prev_time = curr_time;
245252

246-
process_events();
253+
accumulator += delta_time;
247254

248-
//add local inputs to the session
249-
auto input = get_key_inputs();
250-
gekko_add_local_input(sess, localplayer, &input);
255+
gekko_network_poll(sess);
251256

252-
int count = 0;
253-
auto events = gekko_session_events(sess, &count);
254-
for (int i = 0; i < count; i++) {
255-
auto event = events[i];
257+
while (accumulator >= frame_time) {
256258

257-
printf("EV: %d\n", event->type);
259+
GekkoNetworkStats stats{};
260+
gekko_network_stats(sess, localplayer == 0 ? 1 : 0, &stats);
258261

259-
if (event->type == DesyncDetected) {
260-
auto desync = event->data.desynced;
261-
printf("desync detected, f:%d, rh:%d, lc:%u, rc:%u\n", desync.frame, desync.remote_handle, desync.local_checksum, desync.remote_checksum);
262-
}
262+
std::cout << "ping: " << stats.last_ping
263+
<< " avg ping: " << stats.avg_ping
264+
<< " jitter: " << stats.jitter
265+
<< " ft: " << frame_time
266+
<< " fa: " << frames_ahead
267+
<< std::endl;
263268

264-
if (event->type == PlayerDisconnected) {
265-
auto disco = event->data.disconnected;
266-
printf("disconnect detected, player: %d\n", disco.handle);
267-
}
268-
}
269+
process_events();
269270

270-
count = 0;
271-
auto updates = gekko_update_session(sess, &count);
272-
for (int i = 0; i < count; i++) {
273-
auto ev = updates[i];
271+
//add local inputs to the session
272+
auto input = get_key_inputs();
273+
gekko_add_local_input(sess, localplayer, &input);
274274

275-
switch (ev->type) {
276-
case SaveEvent:
277-
printf("Save frame:%d\n", ev->data.save.frame);
278-
save_state(&state, ev);
279-
break;
280-
case LoadEvent:
281-
printf("Load frame:%d\n", ev->data.load.frame);
282-
load_state(&state, ev);
283-
break;
284-
case AdvanceEvent:
285-
// on advance event, advance the gamestate using the given inputs
286-
inputs[0].input.value = ev->data.adv.inputs[0];
287-
inputs[1].input.value = ev->data.adv.inputs[1];
288-
current = ev->data.adv.frame;
289-
printf("F:%d, P1:%d P2:%d\n", current, inputs[0].input.value, inputs[1].input.value);
290-
// now we can use them to update state.
291-
update_state(state, inputs, num_players);
292-
break;
293-
default:
294-
printf("Unknown Event: %d\n", ev->type);
295-
break;
275+
int count = 0;
276+
auto events = gekko_session_events(sess, &count);
277+
for (int i = 0; i < count; i++) {
278+
auto event = events[i];
279+
280+
printf("EV: %d\n", event->type);
281+
282+
if (event->type == DesyncDetected) {
283+
auto desync = event->data.desynced;
284+
printf("desync detected, f:%d, rh:%d, lc:%u, rc:%u\n", desync.frame, desync.remote_handle, desync.local_checksum, desync.remote_checksum);
285+
}
286+
287+
if (event->type == PlayerDisconnected) {
288+
auto disco = event->data.disconnected;
289+
printf("disconnect detected, player: %d\n", disco.handle);
290+
}
296291
}
297-
}
298292

293+
count = 0;
294+
auto updates = gekko_update_session(sess, &count);
295+
for (int i = 0; i < count; i++) {
296+
auto ev = updates[i];
297+
298+
switch (ev->type) {
299+
case SaveEvent:
300+
printf("Save frame:%d\n", ev->data.save.frame);
301+
save_state(&state, ev);
302+
break;
303+
case LoadEvent:
304+
printf("Load frame:%d\n", ev->data.load.frame);
305+
load_state(&state, ev);
306+
break;
307+
case AdvanceEvent:
308+
// on advance event, advance the gamestate using the given inputs
309+
inputs[0].input.value = ev->data.adv.inputs[0];
310+
inputs[1].input.value = ev->data.adv.inputs[1];
311+
current = ev->data.adv.frame;
312+
printf("F:%d, P1:%d P2:%d\n", current, inputs[0].input.value, inputs[1].input.value);
313+
// now we can use them to update state.
314+
update_state(state, inputs, num_players);
315+
break;
316+
default:
317+
printf("Unknown Event: %d\n", ev->type);
318+
break;
319+
}
320+
}
321+
// frame done.
322+
accumulator -= frame_time;
323+
}
299324
// draw the state every iteration
300325
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
301326
SDL_RenderClear(renderer);
302327
render_state(state);
303328
SDL_RenderPresent(renderer);
304-
305-
end_time = gclock::now();
306-
307-
auto work_time = std::chrono::duration_cast<micro>(end_time - start_time);
308-
// std::cout << "wt: " << work_time.count() << std::endl;
309-
310-
auto adjusted_sleep = frame_time - work_time;
311-
// std::cout << "st: " << adjusted_sleep.count() << std::endl;
312-
313-
if (adjusted_sleep.count() > 0) {
314-
std::this_thread::sleep_for(adjusted_sleep);
315-
}
316329
}
317330

318331
del_window();

‎GekkoLib/include/backend.h

+10-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ namespace Gekko {
4545

4646
NetAddress address;
4747

48-
std::map<Frame, u32> health;
48+
std::map<Frame, u32> session_health;
4949

5050
private:
5151
GekkoPlayerType _type;
@@ -103,7 +103,9 @@ namespace Gekko {
103103

104104
bool CheckStatusActors();
105105

106-
void SendHealthCheck(Frame frame, u32 checksum);
106+
void SendSessionHealth(Frame frame, u32 checksum);
107+
108+
void SendNetworkHealth();
107109

108110
public:
109111
std::vector<std::unique_ptr<Player>> locals;
@@ -149,7 +151,9 @@ namespace Gekko {
149151

150152
void OnInputAck(NetAddress& addr, NetPacket& pkt);
151153

152-
void OnHealthCheck(NetAddress& addr, NetPacket& pkt);
154+
void OnSessionHealth(NetAddress& addr, NetPacket& pkt);
155+
156+
void OnNetworkHealth(NetAddress& addr, NetPacket& pkt);
153157

154158
private:
155159
const u32 MAX_PLAYER_SEND_SIZE = 32;
@@ -175,7 +179,7 @@ namespace Gekko {
175179
std::vector<u8> _bin_buffer;
176180

177181
struct InputSendCache {
178-
static const u64 INPUT_RESEND_DELAY = std::chrono::microseconds(200).count();
182+
static const u64 INPUT_RESEND_DELAY = std::chrono::milliseconds(200).count();
179183

180184
u64 last_send_time = 0;
181185
Frame frame = -1;
@@ -185,5 +189,7 @@ namespace Gekko {
185189
InputSendCache _last_sent_input;
186190

187191
InputSendCache _last_sent_spectator_input;
192+
193+
u64 _last_sent_network_check;
188194
};
189195
}

‎GekkoLib/include/event.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ namespace Gekko {
1616
void Reset();
1717

1818
private:
19-
u32 _input_size;
19+
u32 _input_size = 0;
2020

21-
u16 _index_others;
21+
u16 _index_others = 0;
2222

23-
u16 _index_advance;
23+
u16 _index_advance = 0;
2424

2525
std::vector<std::unique_ptr<GekkoGameEvent>> _buffer_advance;
2626

‎GekkoLib/include/gekko.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ struct GekkoSession {
2020
virtual GekkoGameEvent** UpdateSession(i32* count) = 0;
2121
virtual GekkoSessionEvent** Events(i32* count) = 0;
2222
virtual f32 FramesAhead() = 0;
23+
virtual void NetworkStats(i32 player, GekkoNetworkStats* stats) = 0;
24+
virtual void NetworkPoll() = 0;
2325
};
2426

2527
namespace Gekko {
@@ -44,6 +46,10 @@ namespace Gekko {
4446

4547
virtual f32 FramesAhead();
4648

49+
virtual void NetworkStats(i32 player, GekkoNetworkStats* stats);
50+
51+
virtual void NetworkPoll();
52+
4753
private:
4854
void Poll();
4955

@@ -77,7 +83,9 @@ namespace Gekko {
7783

7884
bool ShouldDelaySpectator();
7985

80-
void SendHealthCheck();
86+
void SendSessionHealthCheck();
87+
88+
void SendNetworkHealthCheck();
8189

8290
void SessionIntegrityCheck();
8391

‎GekkoLib/include/gekkonet.h

+12
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ typedef struct GekkoSessionEvent {
159159
} data;
160160
} GekkoSessionEvent;
161161

162+
typedef struct GekkoNetworkStats {
163+
// unsigned int bytes_received;
164+
// unsigned int bytes_sent;
165+
unsigned short last_ping;
166+
float avg_ping;
167+
float jitter;
168+
} GekkoNetworkStats;
169+
162170
// Public Facing API
163171
GEKKONET_API bool gekko_create(GekkoSession** session);
164172

@@ -180,6 +188,10 @@ GEKKONET_API GekkoSessionEvent** gekko_session_events(GekkoSession* session, int
180188

181189
GEKKONET_API float gekko_frames_ahead(GekkoSession* session);
182190

191+
GEKKONET_API void gekko_network_stats(GekkoSession* session, int player, GekkoNetworkStats* stats);
192+
193+
GEKKONET_API void gekko_network_poll(GekkoSession* session);
194+
183195
#ifndef GEKKONET_NO_ASIO
184196

185197
GEKKONET_API GekkoNetAdapter* gekko_default_adapter(unsigned short port);

‎GekkoLib/include/net.h

+22-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ namespace Gekko {
3131
InputAck,
3232
SyncRequest,
3333
SyncResponse,
34-
HealthCheck,
34+
SessionHealth,
35+
NetworkHealth
3536
};
3637

3738
struct MsgHeader {
@@ -88,7 +89,7 @@ namespace Gekko {
8889
}
8990
};
9091

91-
struct HealthCheckMsg : MsgBody {
92+
struct SessionHealthMsg : MsgBody {
9293
Frame frame;
9394
u32 checksum;
9495

@@ -98,6 +99,16 @@ namespace Gekko {
9899
}
99100
};
100101

102+
struct NetworkHealthMsg : MsgBody {
103+
u64 send_time;
104+
bool received;
105+
106+
template <typename Archive, typename Self>
107+
static void serialize(Archive& a, Self& s) {
108+
a(s.send_time, s.received);
109+
}
110+
};
111+
101112
struct NetPacket {
102113
MsgHeader header;
103114
std::unique_ptr<MsgBody> body;
@@ -109,13 +120,20 @@ namespace Gekko {
109120
};
110121

111122
struct NetStats {
112-
static const u64 DISCONNECT_TIMEOUT = std::chrono::microseconds(2000).count();
113-
static const u64 SYNC_MSG_DELAY = std::chrono::microseconds(200).count();
123+
static const u64 DISCONNECT_TIMEOUT = std::chrono::milliseconds(2000).count();
124+
static const u64 SYNC_MSG_DELAY = std::chrono::milliseconds(200).count();
125+
static const u64 NET_CHECK_DELAY = std::chrono::milliseconds(1000).count();
114126

115127
Frame last_acked_frame;
116128
u64 last_sent_sync_message;
117129
u64 last_received_message = -1;
118130
u64 last_received_frame = 0;
131+
132+
std::vector<u16> rtt;
133+
134+
float CalculateJitter();
135+
float CalculateAvgRTT();
136+
u32 LastRTT();
119137
};
120138

121139
struct NetInputData {

0 commit comments

Comments
 (0)
Failed to load comments.