diff --git a/src/pc/djui/djui_chat_message.c b/src/pc/djui/djui_chat_message.c index 17573263..16c39ad8 100644 --- a/src/pc/djui/djui_chat_message.c +++ b/src/pc/djui/djui_chat_message.c @@ -1,5 +1,6 @@ #include #include "pc/network/network.h" +#include "pc/utils/misc.h" #include "audio_defines.h" #include "audio/external.h" #include "game/mario_misc.h" @@ -11,7 +12,7 @@ static void djui_chat_message_render(struct DjuiBase* base) { struct DjuiChatMessage* chatMessage = (struct DjuiChatMessage*)base; struct DjuiBase* ctBase = &chatMessage->message->base; - f32 seconds = (clock() - chatMessage->createTime) / (f32)CLOCKS_PER_SEC; + f32 seconds = clock_elapsed() - chatMessage->createTime; f32 f = 1.0f; if (seconds >= (DJUI_CHAT_LIFE_TIME - 1)) { f = fmax(1.0f - (seconds - (DJUI_CHAT_LIFE_TIME - 1)), 0.0f); @@ -72,7 +73,7 @@ struct DjuiChatMessage* djui_chat_message_create(char* message) { djui_text_set_alignment(chatText, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP); djui_text_set_drop_shadow(chatText, 0, 0, 0, 200); chatMessage->message = chatText; - chatMessage->createTime = clock(); + chatMessage->createTime = clock_elapsed(); // figure out chat message height chatText->base.comp.width = maxTextWidth; diff --git a/src/pc/djui/djui_chat_message.h b/src/pc/djui/djui_chat_message.h index 7b8b3cd8..777901e4 100644 --- a/src/pc/djui/djui_chat_message.h +++ b/src/pc/djui/djui_chat_message.h @@ -1,13 +1,12 @@ #pragma once #include "djui.h" -#include #pragma pack(1) struct DjuiChatMessage { struct DjuiBase base; struct DjuiText* message; f32 messageWidth; - clock_t createTime; + f32 createTime; }; struct DjuiChatMessage* djui_chat_message_create_from(u8 globalIndex, char* message); diff --git a/src/pc/djui/djui_interactable.c b/src/pc/djui/djui_interactable.c index 2d6dec3b..2fc78949 100644 --- a/src/pc/djui/djui_interactable.c +++ b/src/pc/djui/djui_interactable.c @@ -1,10 +1,10 @@ #include -#include #include "djui.h" #include "src/pc/controller/controller_sdl.h" #include "src/pc/controller/controller_mouse.h" #include "src/pc/controller/controller_keyboard.h" +#include "src/pc/utils/misc.h" #include "audio_defines.h" #include "audio/external.h" @@ -247,7 +247,7 @@ void djui_interactable_update_pad(void) { pad->button |= sKeyboardButtons; static enum PadHoldDirection lastPadHoldDirection = PAD_HOLD_DIR_NONE; - static clock_t padHoldTimer = 0; + static f32 padHoldTimer = 0; enum PadHoldDirection padHoldDirection = sKeyboardHoldDirection; if (padHoldDirection != PAD_HOLD_DIR_NONE) { @@ -270,10 +270,10 @@ void djui_interactable_update_pad(void) { if (padHoldDirection == PAD_HOLD_DIR_NONE) { // nothing to do } else if (padHoldDirection != lastPadHoldDirection) { - padHoldTimer = clock() + CLOCKS_PER_SEC * 0.25f; + padHoldTimer = clock_elapsed() + 0.25f; validPadHold = true; - } else if (clock() > padHoldTimer) { - padHoldTimer = clock() + CLOCKS_PER_SEC * 0.10f; + } else if (clock_elapsed() > padHoldTimer) { + padHoldTimer = clock_elapsed() + 0.10f; validPadHold = true; } @@ -347,6 +347,7 @@ void djui_interactable_update(void) { sHovered = NULL; djui_interactable_cursor_update_active(&gDjuiRoot->base); if (lastHovered != sHovered) { + // FIXME: THIS CAN CAUSE A SEGFAULT! djui_interactable_on_hover_end(lastHovered); play_sound(SOUND_MENU_MESSAGE_NEXT_PAGE, gDefaultSoundArgs); } diff --git a/src/pc/djui/djui_popup.c b/src/pc/djui/djui_popup.c index de4d47f1..4f267863 100644 --- a/src/pc/djui/djui_popup.c +++ b/src/pc/djui/djui_popup.c @@ -1,4 +1,3 @@ -#include #include "djui.h" #include "audio_defines.h" #include "audio/external.h" @@ -9,7 +8,7 @@ struct DjuiPopupList { struct DjuiPopup* popup; - clock_t createTime; + f32 createTime; struct DjuiPopupList* next; }; @@ -19,7 +18,7 @@ static f32 sPopupListY = 0; static void djui_popup_add_to_list(struct DjuiPopup* popup) { struct DjuiPopupList* node = malloc(sizeof(struct DjuiPopupList)); node->popup = popup; - node->createTime = clock(); + node->createTime = clock_elapsed(); node->next = sPopupListHead; sPopupListHead = node; } @@ -70,7 +69,7 @@ void djui_popup_update(void) { djui_base_set_location(&node->popup->base, 4, y); y += node->popup->base.height.value + 4; if (gNetworkType != NT_NONE && gNetworkPlayerLocal != NULL) { - f32 elapsed = (clock() - node->createTime) / (f32)CLOCKS_PER_SEC; + f32 elapsed = (clock_elapsed() - node->createTime); // fade out f32 alpha = fmin(DJUI_POPUP_LIFETIME - elapsed, 1.0f); @@ -92,7 +91,7 @@ void djui_popup_update(void) { } } else { // prevent popups from fading out when we're not connected - node->createTime = clock(); + node->createTime = clock_elapsed(); } // iterate diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 5e60cb7a..25ccd740 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -11,6 +11,7 @@ #include "pc/configfile.h" #include "pc/cheats.h" #include "pc/djui/djui.h" +#include "pc/utils/misc.h" #include "pc/debuglog.h" // Mario 64 specific externs @@ -173,8 +174,8 @@ void network_send_to(u8 localIndex, struct Packet* p) { bool tooManyPackets = false; int maxPacketsPerSecond = (gNetworkType == NT_SERVER) ? (MAX_PACKETS_PER_SECOND_PER_PLAYER * (u16)network_player_connected_count()) : MAX_PACKETS_PER_SECOND_PER_PLAYER; static int sPacketsPerSecond[MAX_PLAYERS] = { 0 }; - static clock_t sPacketsPerSecondTime[MAX_PLAYERS] = { 0 }; - clock_t currentTime = time(NULL); + static f32 sPacketsPerSecondTime[MAX_PLAYERS] = { 0 }; + f32 currentTime = clock_elapsed(); if ((currentTime - sPacketsPerSecondTime[localIndex]) > 0) { if (sPacketsPerSecond[localIndex] > maxPacketsPerSecond) { LOG_ERROR("Too many packets sent to localIndex %d! Attempted %d. Connected count %d.", localIndex, sPacketsPerSecond[localIndex], network_player_connected_count()); @@ -195,7 +196,7 @@ void network_send_to(u8 localIndex, struct Packet* p) { } p->sent = true; - gNetworkPlayers[localIndex].lastSent = clock(); + gNetworkPlayers[localIndex].lastSent = clock_elapsed(); } void network_send(struct Packet* p) { @@ -240,7 +241,7 @@ void network_receive(u8 localIndex, u8* data, u16 dataLength) { memcpy(p.buffer, data, dataLength); if (localIndex != UNKNOWN_LOCAL_INDEX && localIndex != 0) { - gNetworkPlayers[localIndex].lastReceived = clock(); + gNetworkPlayers[localIndex].lastReceived = clock_elapsed(); } // subtract and check hash @@ -255,7 +256,6 @@ void network_receive(u8 localIndex, u8* data, u16 dataLength) { } void network_update(void) { - // check for level loaded event if (networkLoadingLevel < LOADING_LEVEL_THRESHOLD) { networkLoadingLevel++; diff --git a/src/pc/network/network.h b/src/pc/network/network.h index 5d5fa437..258d91c5 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -46,7 +46,7 @@ struct SyncObject { struct Object* o; float maxSyncDistance; bool owned; - clock_t clockSinceUpdate; + f32 clockSinceUpdate; void* behavior; u16 txEventId; u16 rxEventId[MAX_PLAYERS]; diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index 48acfbca..f639b9f6 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -4,6 +4,7 @@ #include "reservation_area.h" #include "pc/djui/djui.h" #include "pc/debuglog.h" +#include "pc/utils/misc.h" struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 }; struct NetworkPlayer* gNetworkPlayerLocal = NULL; @@ -86,13 +87,13 @@ void network_player_update(void) { for (int i = 1; i < MAX_PLAYERS; i++) { struct NetworkPlayer* np = &gNetworkPlayers[i]; if (!np->connected) { continue; } - float elapsed = (clock() - np->lastReceived) / (float)CLOCKS_PER_SEC; + float elapsed = (clock_elapsed() - np->lastReceived); if (elapsed > NETWORK_PLAYER_TIMEOUT) { LOG_INFO("dropping player %d", i); network_player_disconnected(i); continue; } - elapsed = (clock() - np->lastSent) / (float)CLOCKS_PER_SEC; + elapsed = (clock_elapsed() - np->lastSent); if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) { network_send_keep_alive(np->localIndex); } @@ -100,14 +101,14 @@ void network_player_update(void) { } else if (gNetworkType == NT_CLIENT) { struct NetworkPlayer* np = gNetworkPlayerServer; if (!np->connected) { return; } - float elapsed = (clock() - np->lastReceived) / (float)CLOCKS_PER_SEC; + float elapsed = (clock_elapsed() - np->lastReceived); if (elapsed > NETWORK_PLAYER_TIMEOUT * 1.5f) { LOG_INFO("dropping due to no server connectivity"); network_shutdown(false); } - elapsed = (clock() - np->lastSent) / (float)CLOCKS_PER_SEC; + elapsed = (clock_elapsed() - np->lastSent); if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) { network_send_keep_alive(np->localIndex); } @@ -152,8 +153,8 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) { if (!np->connected) { continue; } if (np->globalIndex != globalIndex) { continue; } np->localIndex = i; - np->lastReceived = clock(); - np->lastSent = clock(); + np->lastReceived = clock_elapsed(); + np->lastSent = clock_elapsed(); if (gNetworkType == NT_SERVER || type == NPT_SERVER) { gNetworkSystem->save_id(i, 0); } LOG_ERROR("player connected, reusing local %d, global %d, duplicate event?", i, globalIndex); return i; @@ -178,8 +179,8 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) { np->localIndex = i; np->globalIndex = (gNetworkType == NT_SERVER) ? i : globalIndex; np->type = type; - np->lastReceived = clock(); - np->lastSent = clock(); + np->lastReceived = clock_elapsed(); + np->lastSent = clock_elapsed(); if (gNetworkType == NT_SERVER || type == NPT_SERVER) { gNetworkSystem->save_id(i, 0); } for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; } if (type == NPT_SERVER) { diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index 294a1430..ea9048c6 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -22,8 +22,8 @@ struct NetworkPlayer { enum NetworkPlayerType type; u8 localIndex; u8 globalIndex; - clock_t lastReceived; - clock_t lastSent; + f32 lastReceived; + f32 lastSent; u16 currLevelAreaSeqId; s16 currCourseNum; s16 currActNum; diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index b1d206c4..95da6f01 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -10,6 +10,7 @@ #include "src/game/object_helpers.h" #include "src/game/obj_behaviors.h" #include "pc/debuglog.h" +#include "pc/utils/misc.h" struct SyncObject gSyncObjects[MAX_SYNC_OBJECTS] = { 0 }; struct Packet sLastSyncEntReliablePacket[MAX_SYNC_OBJECTS] = { 0 }; @@ -80,7 +81,7 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance) so->o = o; so->maxSyncDistance = maxSyncDistance; so->owned = false; - so->clockSinceUpdate = clock(); + so->clockSinceUpdate = clock_elapsed(); so->extraFieldCount = 0; so->behavior = (BehaviorScript*)o->behavior; for (int i = 0; i < MAX_PLAYERS; i++) { @@ -235,7 +236,7 @@ static struct SyncObject* packet_read_object_header(struct Packet* p, u8* fromLo return NULL; } gCurrentObject = tmp; - so->clockSinceUpdate = clock(); + so->clockSinceUpdate = clock_elapsed(); // make sure this is the newest event possible u16 eventId = 0; @@ -423,7 +424,7 @@ void network_send_object_reliability(struct Object* o, bool reliable) { // always send a new event ID so->txEventId++; - so->clockSinceUpdate = clock(); + so->clockSinceUpdate = clock_elapsed(); // write the packet data struct Packet p; @@ -565,7 +566,7 @@ void network_update_objects(void) { if (updateRate < so->minUpdateRate) { updateRate = so->minUpdateRate; } // see if we should update - float timeSinceUpdate = ((float)clock() - (float)so->clockSinceUpdate) / (float)CLOCKS_PER_SEC; + float timeSinceUpdate = (clock_elapsed() - so->clockSinceUpdate); if (timeSinceUpdate < updateRate) { continue; } // update! diff --git a/src/pc/network/packets/packet_ordered.c b/src/pc/network/packets/packet_ordered.c index 8db53068..98e8fcde 100644 --- a/src/pc/network/packets/packet_ordered.c +++ b/src/pc/network/packets/packet_ordered.c @@ -1,5 +1,6 @@ #include #include "../network.h" +#include "pc/utils/misc.h" #define DISABLE_MODULE_LOG 1 #include "pc/debuglog.h" @@ -14,7 +15,7 @@ struct OrderedPacketTable { u8 fromGlobalId; u8 groupId; u8 processSeqId; - clock_t lastReceived; + f32 lastReceived; struct OrderedPacketList* packets; struct OrderedPacketTable* next; }; @@ -113,7 +114,7 @@ static void packet_ordered_add_to_table(struct OrderedPacketTable* opt, struct P opl->next = NULL; LOG_INFO("added to list for (%d, %d, %d)", opt->fromGlobalId, opt->groupId, p->orderedSeqId); - opt->lastReceived = clock(); + opt->lastReceived = clock_elapsed(); packet_ordered_check_for_processing(opt); } @@ -151,7 +152,7 @@ void packet_ordered_add(struct Packet* p) { opt->processSeqId = 1; opt->packets = NULL; opt->next = NULL; - opt->lastReceived = clock(); + opt->lastReceived = clock_elapsed(); LOG_INFO("created table for (%d, %d)", opt->fromGlobalId, opt->groupId); // add the packet to the table @@ -219,13 +220,13 @@ void packet_ordered_clear(u8 globalIndex) { } void packet_ordered_update(void) { - clock_t currentClock = clock(); + f32 currentClock = clock_elapsed(); // check all ordered tables for a time out for (int i = 0; i < MAX_PLAYERS; i++) { struct OrderedPacketTable* opt = orderedPacketTable[i]; while (opt != NULL) { struct OrderedPacketTable* optNext = opt->next; - float elapsed = (currentClock - opt->lastReceived) / (float)CLOCKS_PER_SEC; + float elapsed = (currentClock - opt->lastReceived); if (elapsed > PACKET_ORDERED_TIMEOUT) { // too much time has elapsed since we last received a packet for this group, forget the table! diff --git a/src/pc/network/packets/packet_reliable.c b/src/pc/network/packets/packet_reliable.c index b3f9644f..a95b7784 100644 --- a/src/pc/network/packets/packet_reliable.c +++ b/src/pc/network/packets/packet_reliable.c @@ -1,5 +1,6 @@ #include #include "../network.h" +#include "pc/utils/misc.h" #include "pc/debuglog.h" // two-player hack: the localIndex for resending packets can be 0... this means reply to last person received from. THIS WILL NOT WORK with more than two players @@ -9,7 +10,7 @@ struct PacketLinkedList { struct Packet p; - clock_t lastSend; + f32 lastSend; int sendAttempts; struct PacketLinkedList* prev; struct PacketLinkedList* next; @@ -75,7 +76,7 @@ void network_remember_reliable(struct Packet* p) { struct PacketLinkedList* node = malloc(sizeof(struct PacketLinkedList)); node->p = *p; node->p.sent = true; - node->lastSend = clock(); + node->lastSend = clock_elapsed(); node->sendAttempts = 1; node->prev = NULL; node->next = NULL; @@ -98,7 +99,7 @@ void network_remember_reliable(struct Packet* p) { void network_update_reliable(void) { struct PacketLinkedList* node = head; while (node != NULL) { - float elapsed = (clock() - node->lastSend) / CLOCKS_PER_SEC; + float elapsed = (clock_elapsed() - node->lastSend); float maxElapsed = (node->sendAttempts * node->sendAttempts * RELIABLE_RESEND_RATE) / ((float)MAX_RESEND_ATTEMPTS); if (elapsed > maxElapsed) { if (node->p.packetType == PACKET_JOIN_REQUEST && gNetworkPlayerServer != NULL) { @@ -108,7 +109,7 @@ void network_update_reliable(void) { node->p.sent = true; network_send_to(node->p.localIndex, &node->p); - node->lastSend = clock(); + node->lastSend = clock_elapsed(); node->sendAttempts++; if (node->sendAttempts >= MAX_RESEND_ATTEMPTS) { struct PacketLinkedList* next = node->next; diff --git a/src/pc/utils/misc.c b/src/pc/utils/misc.c index 3917583d..3d3cfca8 100644 --- a/src/pc/utils/misc.c +++ b/src/pc/utils/misc.c @@ -1,4 +1,7 @@ #include +#include +#include + #include "misc.h" #include "course_table.h" @@ -18,4 +21,18 @@ void update_all_mario_stars(void) { for (int i = 0; i < MAX_PLAYERS; i++) { gMarioStates[i].numStars = numStars; } +} + +f32 clock_elapsed(void) { + static bool sClockInitialized = false; + static struct timespec clock_start; + if (!sClockInitialized) { + clock_gettime(CLOCK_MONOTONIC, &clock_start); + sClockInitialized = true; + } + + struct timespec clock_current; + clock_gettime(CLOCK_MONOTONIC, &clock_current); + return (clock_current.tv_sec - clock_start.tv_sec) + + ((clock_current.tv_nsec - clock_start.tv_nsec) / 1000000000.0f); } \ No newline at end of file diff --git a/src/pc/utils/misc.h b/src/pc/utils/misc.h index 75f8602e..04bfd82a 100644 --- a/src/pc/utils/misc.h +++ b/src/pc/utils/misc.h @@ -3,5 +3,6 @@ float smoothstep(float edge0, float edge1, float x); void update_all_mario_stars(void); +f32 clock_elapsed(void); #endif \ No newline at end of file