Added basic server reconcilliation
This commit is contained in:
parent
9af376bcb1
commit
5e7bff96d0
|
@ -18,6 +18,7 @@
|
||||||
#include "../cspt-state.h"
|
#include "../cspt-state.h"
|
||||||
#include "../cspt-message.h"
|
#include "../cspt-message.h"
|
||||||
#define ENABLE_CLIENT_SIDE_PREDICTION
|
#define ENABLE_CLIENT_SIDE_PREDICTION
|
||||||
|
#define ENABLE_SERVER_RECONCILLIATION
|
||||||
|
|
||||||
uint8_t colours[16][3] =
|
uint8_t colours[16][3] =
|
||||||
{
|
{
|
||||||
|
@ -43,6 +44,7 @@ struct threadParameters
|
||||||
bool * keepRunning;
|
bool * keepRunning;
|
||||||
struct gameState * state;
|
struct gameState * state;
|
||||||
struct clientInput * message;
|
struct clientInput * message;
|
||||||
|
struct inputHistory * inputBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
void DrawCircle(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius)
|
void DrawCircle(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius)
|
||||||
|
@ -110,18 +112,73 @@ void * networkHandler(void * parameters)
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Send our input, recieve the state:
|
// Send our input, recieve the state:
|
||||||
sendto(udpSocket, arguments->message, sizeof(struct clientInput), 0, (struct sockaddr *)&serverAddress, sizeof(struct sockaddr_in));
|
sendto(udpSocket, arguments->message, sizeof(struct clientInput), 0,
|
||||||
|
(struct sockaddr *)&serverAddress, sizeof(struct sockaddr_in));
|
||||||
recvfrom(udpSocket, updatedState, sizeof(struct gameState), 0, NULL, NULL);
|
recvfrom(udpSocket, updatedState, sizeof(struct gameState), 0, NULL, NULL);
|
||||||
|
|
||||||
// Only update the state if the given state is more recent than the current state:
|
// Only update the state if the given state is more recent than the current state:
|
||||||
if(updatedState->timestamp.tv_sec > arguments->state->timestamp.tv_sec)
|
if(updatedState->timestamp.tv_sec > arguments->state->timestamp.tv_sec)
|
||||||
{
|
{
|
||||||
memcpy(arguments->state, updatedState, sizeof(struct gameState));
|
memcpy(arguments->state, updatedState, sizeof(struct gameState));
|
||||||
|
#ifdef ENABLE_SERVER_RECONCILLIATION
|
||||||
|
// Throw away any already acknowledged inputs:
|
||||||
|
while (arguments->inputBuffer->start != -1 &&
|
||||||
|
arguments->inputBuffer->inputs[arguments->inputBuffer->start].tickNumber < arguments->state->tickNumber)
|
||||||
|
{
|
||||||
|
arguments->inputBuffer->start = (arguments->inputBuffer->start + 1) % 256;
|
||||||
|
if(arguments->inputBuffer->start == arguments->inputBuffer->end)
|
||||||
|
{
|
||||||
|
arguments->inputBuffer->start = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t currentMessage = arguments->inputBuffer->start;
|
||||||
|
uint64_t lastTickNumber = arguments->inputBuffer->inputs[arguments->inputBuffer->start].tickNumber;
|
||||||
|
|
||||||
|
// Re-apply the currently unused messages:
|
||||||
|
while (currentMessage != 1 &&
|
||||||
|
currentMessage != arguments->inputBuffer->end)
|
||||||
|
{
|
||||||
|
updateInput(arguments->state, &arguments->inputBuffer->inputs[currentMessage]);
|
||||||
|
currentMessage = (currentMessage + 1) % 256;
|
||||||
|
if (arguments->inputBuffer->inputs[currentMessage].tickNumber != lastTickNumber)
|
||||||
|
{
|
||||||
|
doGameTick(arguments->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if(updatedState->timestamp.tv_sec == arguments->state->timestamp.tv_sec &&
|
else if(updatedState->timestamp.tv_sec == arguments->state->timestamp.tv_sec &&
|
||||||
updatedState->timestamp.tv_usec > arguments->state->timestamp.tv_usec)
|
updatedState->timestamp.tv_usec > arguments->state->timestamp.tv_usec)
|
||||||
{
|
{
|
||||||
memcpy(arguments->state, updatedState, sizeof(struct gameState));
|
memcpy(arguments->state, updatedState, sizeof(struct gameState));
|
||||||
|
#ifdef ENABLE_SERVER_RECONCILLIATION
|
||||||
|
// Throw away any already acknowledged inputs:
|
||||||
|
while (arguments->inputBuffer->start != -1 &&
|
||||||
|
arguments->inputBuffer->inputs[arguments->inputBuffer->start].tickNumber < arguments->state->tickNumber)
|
||||||
|
{
|
||||||
|
arguments->inputBuffer->start = (arguments->inputBuffer->start + 1) % 256;
|
||||||
|
if(arguments->inputBuffer->start == arguments->inputBuffer->end)
|
||||||
|
{
|
||||||
|
arguments->inputBuffer->start = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t currentMessage = arguments->inputBuffer->start;
|
||||||
|
uint64_t lastTickNumber = arguments->inputBuffer->inputs[arguments->inputBuffer->start].tickNumber;
|
||||||
|
|
||||||
|
// Re-apply the currently unused messages:
|
||||||
|
while (currentMessage != 1 &&
|
||||||
|
currentMessage != arguments->inputBuffer->end)
|
||||||
|
{
|
||||||
|
updateInput(arguments->state, &arguments->inputBuffer->inputs[currentMessage]);
|
||||||
|
currentMessage = (currentMessage + 1) % 256;
|
||||||
|
if (arguments->inputBuffer->inputs[currentMessage].tickNumber != lastTickNumber)
|
||||||
|
{
|
||||||
|
doGameTick(arguments->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,11 +191,23 @@ void * gameThreadHandler(void * parameters)
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
updateInput(arguments->state, arguments->message);
|
updateInput(arguments->state, arguments->message);
|
||||||
|
#ifdef ENABLE_SERVER_RECONCILLIATION
|
||||||
|
if(arguments->inputBuffer->start = -1)
|
||||||
|
{
|
||||||
|
memcpy(&arguments->inputBuffer->inputs[0], arguments->message, sizeof(struct clientInput));
|
||||||
|
arguments->inputBuffer->start = 0;
|
||||||
|
arguments->inputBuffer->end = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(&arguments->inputBuffer->inputs[arguments->inputBuffer->end], arguments->message, sizeof(struct clientInput));
|
||||||
|
arguments->inputBuffer->end = (arguments->inputBuffer->end + 1) % 256;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
doGameTick(arguments->state);
|
doGameTick(arguments->state);
|
||||||
usleep(15625);
|
usleep(15625);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void * graphicsThreadHandler(void * parameters)
|
void * graphicsThreadHandler(void * parameters)
|
||||||
|
@ -329,6 +398,9 @@ int main(int argc, char ** argv)
|
||||||
parameters.message = clientInput;
|
parameters.message = clientInput;
|
||||||
parameters.ipAddress = ipAddress;
|
parameters.ipAddress = ipAddress;
|
||||||
parameters.keepRunning = &keepRunning;
|
parameters.keepRunning = &keepRunning;
|
||||||
|
parameters.inputBuffer = calloc(1, sizeof(struct inputHistory));
|
||||||
|
parameters.inputBuffer->start = -1;
|
||||||
|
parameters.inputBuffer->end = -1;
|
||||||
|
|
||||||
// Create all of our threads:
|
// Create all of our threads:
|
||||||
pthread_create(&gameThread, NULL, gameThreadHandler, ¶meters);
|
pthread_create(&gameThread, NULL, gameThreadHandler, ¶meters);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include "cspt-state.h"
|
#include "cspt-state.h"
|
||||||
|
|
||||||
void updateInput(struct gameState * state, struct clientInput * message)
|
void updateInput(struct gameState * state, struct clientInput * message)
|
||||||
{
|
{
|
||||||
if(message->clientNumber < 16 && message->clientNumber >= 0)
|
if(message->clientNumber < 16 && message->clientNumber >= 0)
|
||||||
|
@ -49,6 +51,7 @@ void doGameTick(struct gameState * state)
|
||||||
{
|
{
|
||||||
state->clients[index].yVelocity *= 0.9;
|
state->clients[index].yVelocity *= 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do movement:
|
// Do movement:
|
||||||
state->clients[index].xPosition += state->clients[index].xVelocity;
|
state->clients[index].xPosition += state->clients[index].xVelocity;
|
||||||
state->clients[index].yPosition += state->clients[index].yVelocity;
|
state->clients[index].yPosition += state->clients[index].yVelocity;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
struct clientMovement
|
struct clientMovement
|
||||||
{
|
{
|
||||||
double xPosition, yPosition, xVelocity, yVelocity;
|
double xPosition, yPosition, xVelocity, yVelocity;
|
||||||
|
@ -30,6 +31,12 @@ struct networkThreadArguments
|
||||||
struct gameState * state;
|
struct gameState * state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct inputHistory
|
||||||
|
{
|
||||||
|
uint8_t start, end;
|
||||||
|
struct clientInput inputs[256];
|
||||||
|
};
|
||||||
|
|
||||||
void updateInput(struct gameState * state, struct clientInput * message);
|
void updateInput(struct gameState * state, struct clientInput * message);
|
||||||
|
|
||||||
void doGameTick(struct gameState * state);
|
void doGameTick(struct gameState * state);
|
||||||
|
|
Loading…
Reference in New Issue