Skip to content

Commit

Permalink
MOAR
Browse files Browse the repository at this point in the history
  • Loading branch information
gafferongames committed Dec 25, 2023
1 parent 747613f commit f05e7c0
Show file tree
Hide file tree
Showing 3 changed files with 325 additions and 257 deletions.
259 changes: 2 additions & 257 deletions yojimbo.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include "yojimbo_reliable_ordered_channel.h"
#include "yojimbo_unreliable_unordered_channel.h"
#include "yojimbo_connection.h"
#include "yojimbo_network_simulator.h"
#include "yojimbo_adaptor.h"

/** @file */

Expand Down Expand Up @@ -78,263 +80,6 @@ void ShutdownYojimbo();

namespace yojimbo
{
/**
Simulates packet loss, latency, jitter and duplicate packets.
This is useful during development, so your game is tested and played under real world conditions, instead of ideal LAN conditions.
This simulator works on packet send. This means that if you want 125ms of latency (round trip), you must to add 125/2 = 62.5ms of latency to each side.
*/

class NetworkSimulator
{
public:

/**
Create a network simulator.
Initial network conditions are set to:
Latency: 0ms
Jitter: 0ms
Packet Loss: 0%
Duplicates: 0%
@param allocator The allocator to use.
@param numPackets The maximum number of packets that can be stored in the simulator at any time.
@param time The initial time value in seconds.
*/

NetworkSimulator( Allocator & allocator, int numPackets, double time );

/**
Network simulator destructor.
Any packet data still in the network simulator is destroyed.
*/

~NetworkSimulator();

/**
Set the latency in milliseconds.
This latency is added on packet send. To simulate a round trip time of 100ms, add 50ms of latency to both sides of the connection.
@param milliseconds The latency to add in milliseconds.
*/

void SetLatency( float milliseconds );

/**
Set the packet jitter in milliseconds.
Jitter is applied +/- this amount in milliseconds. To be truly effective, jitter must be applied together with some latency.
@param milliseconds The amount of jitter to add in milliseconds (+/-).
*/

void SetJitter( float milliseconds );

/**
Set the amount of packet loss to apply on send.
@param percent The packet loss percentage. 0% = no packet loss. 100% = all packets are dropped.
*/

void SetPacketLoss( float percent );

/**
Set percentage chance of packet duplicates.
If the duplicate chance succeeds, a duplicate packet is added to the queue with a random delay of up to 1 second.
@param percent The percentage chance of a packet duplicate being sent. 0% = no duplicate packets. 100% = all packets have a duplicate sent.
*/

void SetDuplicates( float percent );

/**
Is the network simulator active?
The network simulator is active when packet loss, latency, duplicates or jitter are non-zero values.
This is used by the transport to know whether it should shunt packets through the simulator, or send them directly to the network. This is a minor optimization.
*/

bool IsActive() const;

/**
Queue a packet to send.
IMPORTANT: Ownership of the packet data pointer is *not* transferred to the network simulator. It makes a copy of the data instead.
@param to The slot index the packet should be sent to.
@param packetData The packet data.
@param packetBytes The packet size (bytes).
*/

void SendPacket( int to, uint8_t * packetData, int packetBytes );

/**
Receive packets sent to any address.
IMPORTANT: You take ownership of the packet data you receive and are responsible for freeing it. See NetworkSimulator::GetAllocator.
@param maxPackets The maximum number of packets to receive.
@param packetData Array of packet data pointers to be filled [out].
@param packetBytes Array of packet sizes to be filled [out].
@param to Array of to indices to be filled [out].
@returns The number of packets received.
*/

int ReceivePackets( int maxPackets, uint8_t * packetData[], int packetBytes[], int to[] );

/**
Discard all packets in the network simulator.
This is useful if the simulator needs to be reset and used for another purpose.
*/

void DiscardPackets();

/**
Discard packets sent to a particular client index.
This is called when a client disconnects from the server.
*/

void DiscardClientPackets( int clientIndex );

/**
Advance network simulator time.
You must pump this regularly otherwise the network simulator won't work.
@param time The current time value. Please make sure you use double values for time so you retain sufficient precision as time increases.
*/

void AdvanceTime( double time );

/**
Get the allocator to use to free packet data.
@returns The allocator that packet data is allocated with.
*/

Allocator & GetAllocator() { yojimbo_assert( m_allocator ); return *m_allocator; }

protected:

/**
Helper function to update the active flag whenever network settings are changed.
Active is set to true if any of the network conditions are non-zero. This allows you to quickly check if the network simulator is active and would actually do something.
*/

void UpdateActive();

private:

Allocator * m_allocator; ///< The allocator passed in to the constructor. It's used to allocate and free packet data.
float m_latency; ///< Latency in milliseconds
float m_jitter; ///< Jitter in milliseconds +/-
float m_packetLoss; ///< Packet loss percentage.
float m_duplicates; ///< Duplicate packet percentage
bool m_active; ///< True if network simulator is active, eg. if any of the network settings above are enabled.

/// A packet buffered in the network simulator.

struct PacketEntry
{
PacketEntry()
{
to = 0;
deliveryTime = 0.0;
packetData = NULL;
packetBytes = 0;
}

int to; ///< To index this packet should be sent to (for server -> client packets).
double deliveryTime; ///< Delivery time for this packet (seconds).
uint8_t * packetData; ///< Packet data (owns this pointer).
int packetBytes; ///< Size of packet in bytes.
};

double m_time; ///< Current time from last call to advance time.
int m_currentIndex; ///< Current index in the packet entry array. New packets are inserted here.
int m_numPacketEntries; ///< Number of elements in the packet entry array.
PacketEntry * m_packetEntries; ///< Pointer to dynamically allocated packet entries. This is where buffered packets are stored.
};

/**
Specifies the message factory and callbacks for clients and servers.
An instance of this class is passed into the client and server constructors.
You can share the same adapter across a client/server pair if you have local multiplayer, eg. loopback.
*/

class Adapter
{
public:

virtual ~Adapter() {}

/**
Override this function to specify your own custom allocator class.
@param allocator The base allocator that must be used to allocate your allocator instance.
@param memory The block of memory backing your allocator.
@param bytes The number of bytes of memory available to your allocator.
@returns A pointer to the allocator instance you created.
*/

virtual Allocator * CreateAllocator( Allocator & allocator, void * memory, size_t bytes )
{
return YOJIMBO_NEW( allocator, TLSF_Allocator, memory, bytes );
}

/**
You must override this method to create the message factory used by the client and server.
@param allocator The allocator that must be used to create your message factory instance via YOJIMBO_NEW
@returns The message factory pointer you created.
*/

virtual MessageFactory * CreateMessageFactory( Allocator & allocator )
{
(void) allocator;
yojimbo_assert( false );
return NULL;
}

/**
Override this callback to process packets sent from client to server over loopback.
@param clientIndex The client index in range [0,maxClients-1]
@param packetData The packet data (raw) to be sent to the server.
@param packetBytes The number of packet bytes in the server.
@param packetSequence The sequence number of the packet.
@see Client::ConnectLoopback
*/

virtual void ClientSendLoopbackPacket( int clientIndex, const uint8_t * packetData, int packetBytes, uint64_t packetSequence )
{
(void) clientIndex;
(void) packetData;
(void) packetBytes;
(void) packetSequence;
yojimbo_assert( false );
}

/**
Override this callback to process packets sent from client to server over loopback.
@param clientIndex The client index in range [0,maxClients-1]
@param packetData The packet data (raw) to be sent to the server.
@param packetBytes The number of packet bytes in the server.
@param packetSequence The sequence number of the packet.
@see Server::ConnectLoopbackClient
*/

virtual void ServerSendLoopbackPacket( int clientIndex, const uint8_t * packetData, int packetBytes, uint64_t packetSequence )
{
(void) clientIndex;
(void) packetData;
(void) packetBytes;
(void) packetSequence;
yojimbo_assert( false );
}

/**
Override this to get a callback when a client connects on the server.
*/

virtual void OnServerClientConnected( int clientIndex )
{
(void) clientIndex;
}

/**
Override this to get a callback when a client disconnects from the server.
*/

virtual void OnServerClientDisconnected( int clientIndex )
{
(void) clientIndex;
}
};

/**
Network information for a connection.
Contains statistics like round trip time (RTT), packet loss %, bandwidth estimates, number of packets sent, received and acked.
Expand Down
Loading

0 comments on commit f05e7c0

Please sign in to comment.