newnet: Replace use of NETMSG with NetQueue. Breaks multiplayer, which never really worked, anyway. Compiles, links and runs, but freezes in multiplayer.

master
Cyp 2010-02-09 18:43:53 +01:00
parent a336d6455d
commit 8991ed6e76
22 changed files with 1098 additions and 1114 deletions

View File

@ -190,7 +190,7 @@ BOOL NETstopLogging(void)
return true;
}
void NETlogPacket(NETMSG *msg, BOOL received)
/*void NETlogPacket(NETMSG *msg, BOOL received)
{
if (msg->type >= NUM_GAME_PACKETS)
{
@ -198,7 +198,7 @@ void NETlogPacket(NETMSG *msg, BOOL received)
}
packetcount[received][msg->type]++;
packetsize[received][msg->type] += msg->size;
}
}*/
BOOL NETlogEntry(const char *str,UDWORD a,UDWORD b)
{

View File

@ -32,7 +32,7 @@ extern "C"
BOOL NETstartLogging(void);
BOOL NETstopLogging(void);
BOOL NETlogEntry( const char *str, UDWORD a, UDWORD b );
void NETlogPacket(NETMSG *msg, BOOL received);
//void NETlogPacket(NETMSG *msg, BOOL received);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -121,7 +121,7 @@ typedef enum
NET_POSITIONREQUEST, //65 position in GUI player list
NET_DATA_CHECK, //66 Data integrity check
NET_HOST_DROPPED, //67 Host has dropped
NET_FUTURE1, //68 future use
NET_SEND_TO_PLAYER, //68 Was future use, now actually using! (Normally, things marked "for future use" never ever get used.)
NET_FUTURE2, //69 "
NET_FUTURE3, //70 "
NET_FILE_REQUESTED, //71 Player has requested a file (map/mod/?)
@ -141,6 +141,9 @@ typedef enum
#define SESSION_JOINDISABLED 1
#define MAX_CONNECTED_PLAYERS 8
#define MAX_TMP_SOCKETS 16
typedef struct { //Available game storage... JUST FOR REFERENCE!
int32_t dwSize;
int32_t dwFlags;
@ -202,14 +205,14 @@ typedef struct {
uint64_t unsentisMPDirtyBit;
} SYNC_COUNTER;
typedef struct {
/*typedef struct {
uint16_t size; // used size of body
uint8_t type; // type of packet
uint8_t destination; // player to send to, or NET_ALL_PLAYERS
uint8_t source; // player it is sent from
char body[MaxMsgSize]; // msg buffer
BOOL status; // If the packet compiled or not (this is _not_ sent!)
} NETMSG;
} NETMSG;*/
typedef struct
{
@ -278,7 +281,7 @@ typedef struct {
// variables
extern NETPLAY NetPlay;
extern NETMSG NetMsg;
//extern NETMSG NetMsg;
extern SYNC_COUNTER sync_counter;
// update flags
extern bool netPlayersUpdated;
@ -287,12 +290,12 @@ extern int mapDownloadProgress;
// ////////////////////////////////////////////////////////////////////////
// functions available to you.
extern int NETinit(BOOL bFirstCall); // init
extern BOOL NETsend(NETMSG *msg, UDWORD player); // send to player
extern BOOL NETbcast(NETMSG *msg); // broadcast to everyone
extern BOOL NETrecv(uint8_t *type); // recv a message if possible
BOOL NETsend(uint8_t player, const uint8_t *rawData, ssize_t rawLen); ///< send to player, or broadcast if player == NET_ALL_PLAYERS.
extern BOOL NETrecvNet(NETQUEUE *queue, uint8_t *type); ///< recv a message from the net queues if possible.
extern BOOL NETrecvGame(NETQUEUE *queue, uint8_t *type); ///< recv a message from the game queues if possible.
extern UBYTE NETsendFile(char *fileName, UDWORD player); // send file chunk.
extern UBYTE NETrecvFile(void); // recv file chunk
extern UBYTE NETrecvFile(NETQUEUE queue); // recv file chunk
extern int NETclose(void); // close current game
extern int NETshutdown(void); // leave the game in play.

View File

@ -1,14 +1,12 @@
#include "netqueue.h"
#include "lib/framework/frame.h"
#include <cstring>
#ifdef USE_ZLIB
#include "zlib.h"
#endif //USE_ZLIB
NetQueue multiQueues[MAX_PLAYERS];
NetQueue::NetQueue(UsagePattern p)
: deserialiseUnderflow(false)
, isCompressed(false)
, readOffset(0)
, readSuccessOffset(0)
, netOffset(0)
@ -18,13 +16,16 @@ NetQueue::NetQueue(UsagePattern p)
{
switch (p)
{
case Unused: canSerialise = false; canDeserialise = false; canWriteRaw = false; canReadRaw = false; canCompress = false; break;
case NetSend: canSerialise = true; canDeserialise = false; canWriteRaw = false; canReadRaw = true; canCompress = true; break;
case NetReceive: canSerialise = false; canDeserialise = true; canWriteRaw = true; canReadRaw = false; canCompress = true; break;
case GameSend: canSerialise = true; canDeserialise = true; canWriteRaw = false; canReadRaw = true; canCompress = false; break;
case GameReceive: canSerialise = false; canDeserialise = true; canWriteRaw = true; canReadRaw = false; canCompress = false; break;
case GameSolo: canSerialise = true; canDeserialise = true; canWriteRaw = false; canReadRaw = false; canCompress = false; break;
}
ASSERT(canSerialise == !canWriteRaw, "Can't insert both objects and raw data into the same NetQueue.");
ASSERT(!canSerialise || !canWriteRaw, "Can't insert both objects and raw data into the same NetQueue.");
ASSERT(!canWriteRaw || canDeserialise, "No point being able to write data into the NetQueue if we can't deserialise it.");
}
@ -133,6 +134,14 @@ void NetQueue::popRawData(size_t netLen)
popOldData();
}
void NetQueue::endSerialiseLength()
{
uint32_t len = data.size() - beginSerialiseOffset - 4;
data[beginSerialiseOffset ] = len>>24 & 0xFF;
data[beginSerialiseOffset+1] = len>>16 & 0xFF;
data[beginSerialiseOffset+2] = len>> 8 & 0xFF;
data[beginSerialiseOffset+3] = len & 0xFF;
}
bool NetQueue::endDeserialise()
{
@ -157,6 +166,29 @@ bool NetQueue::isDeserialiseError() const
return deserialiseUnderflow;
}
void NetQueue::serialiseLength()
{
beginSerialiseOffset = data.size();
// Reserve room for length.
data.resize(data.size() + 4);
}
bool NetQueue::deserialiseHaveLength()
{
if (readOffset + 4 > data.size())
{
return false;
}
uint32_t len = data[readOffset]<<24 | data[readOffset+1]<<16 | data[readOffset+2]<<8 | data[readOffset+3];
return len < data.size() && readOffset + 4 <= data.size() - len;
}
uint8_t NetQueue::deserialiseGetType()
{
return readOffset + 5 > data.size() ? 0 : data[readOffset+4];
}
void NetQueue::popOldData()
{
if (!canDeserialise)
@ -197,7 +229,7 @@ void NetQueue::deserialise(uint8_t &v)
}
// Deserialise.
if (readOffset >= data.size())
if (readOffset + 1 > data.size())
{
deserialiseUnderflow = true;
return; // Not enough data.
@ -206,16 +238,22 @@ void NetQueue::deserialise(uint8_t &v)
v = data[readOffset++];
}
#ifdef USE_ZLIB
void NetQueue::setCompression()
void NetQueue::setCompression(uint32_t compressionMask)
{
ASSERT(canCompress, "Wrong NetQueue type for setCompression.");
if (stream != NULL)
{
//debug(LOG_WARNING, "Already called setCompression on this NetQueue.");
return; // Been there, done that.
}
#ifdef USE_ZLIB
if (!isCompressed && (compressionMask & CompressionZlib) != 0)
{
setCompressionZlib();
isCompressed = true;
}
#endif //USE_ZLIB
}
#ifdef USE_ZLIB
void NetQueue::setCompressionZlib()
{
stream = new z_stream;
stream->zalloc = NULL;
stream->zfree = NULL;
@ -247,93 +285,6 @@ void NetQueue::setCompression()
}
#endif //USE_ZLIB
///////////////////
template<class Q>
void queue(const Q &q, uint8_t &v)
{
q.byte(v);
}
template<class Q>
void queue(const Q &q, uint16_t &v)
{
uint8_t b[2] = {v>>8, v};
queue(q, b[0]);
queue(q, b[1]);
v = b[0]<<8 | b[1];
}
template<class Q>
void queue(const Q &q, uint32_t &v)
{
uint16_t b[2] = {v>>16, v};
queue(q, b[0]);
queue(q, b[1]);
v = b[0]<<16 | b[1];
}
template<class Q>
void queue(const Q &q, uint64_t &v)
{
uint32_t b[2] = {v>>32, v};
queue(q, b[0]);
queue(q, b[1]);
v = uint64_t(b[0])<<32 | b[1];
}
template<class Q>
void queue(const Q &q, int8_t &v)
{
uint8_t b = v;
queue(q, b);
v = b;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
template<class Q>
void queue(const Q &q, int16_t &v)
{
uint16_t b = v;
queue(q, b);
v = b;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
template<class Q>
void queue(const Q &q, int32_t &v)
{
uint32_t b = v;
queue(q, b);
v = b;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
template<class Q>
void queue(const Q &q, int64_t &v)
{
uint64_t b = v;
queue(q, b);
v = b;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
template<class Q>
void queue(const Q &q, float &v)
{
uint32_t b;
std::memcpy(&b, &v, sizeof(b));
queue(q, b);
std::memcpy(&v, &b, sizeof(b));
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
#if 0
extern "C" void testNetQueue()
{
@ -353,7 +304,7 @@ extern "C" void testNetQueue()
}
if (testString[i] == ' ')
{
write.setCompression();
write.setCompression(CompressionMask);
}
printf("%c", testString[i]);
}
@ -384,7 +335,7 @@ extern "C" void testNetQueue()
}
if (result == ' ')
{
read.setCompression();
read.setCompression(CompressionMask);
}
printf("%c", result);
}

View File

@ -4,7 +4,16 @@
#include "lib/framework/types.h"
// TODO Add zlib to build scripts and use it.
//#define USE_ZLIB
// TODO But first move it directly on top of the sockets, seems it didn't really belong here. NetQueue
// was originally intended to be just a stream of bytes, which would be synchronised among all players.
// It ended up being a stream of messages prefixed with message size. And thanks to the need for
// broadcasting, the message streams can get mixed together, which isn't good if the message streams are
// individually zlib-compressed. While it would be possible to enable compression if being careful which
// queues it's enabled on, the compression code doesn't belong here anymore. Leaving it here for now,
// since the compression code is tested, and works. At the time of writing, the compression code is the
// only part of the code which is currently known to work well. It should be moved to a CompressPipe
// class, or something similar.
//#don't define USE_ZLIB
#ifdef __cplusplus
#include <vector>
@ -26,6 +35,8 @@ class NetQueue
public:
enum UsagePattern
{
Unused, ///< NetQueue is not used for anything.
NetSend, ///< For use with outgoing sockets. Will serialise and read raw data.
NetReceive, ///< For use with incoming sockets. Will write raw data and deserialise.
@ -33,27 +44,38 @@ public:
GameReceive, ///< For use as a game order queue. Will deserialise and write raw data.
GameSolo ///< For use as a game order queue. Will serialise and deserialise.
};
enum Compression
{
CompressionZlib = 0x00000001, ///< Zlib compression.
// TODO? CompressionLzma = 0x00000002, ///< Lzma compression.
CompressionMask = 0x00000000 ///< All compression types we support.
#ifdef USE_ZLIB
| CompressionZlib
#endif //USE_ZLIB
};
class Writer
{
public:
enum { Read, Write, Direction = Write };
Writer(NetQueue &q) : queue(q) {}
void byte(uint8_t v) const { queue.serialise(v); }
NetQueue &queue;
Writer(NetQueue *q = NULL) : queue(q) {}
Writer(NetQueue &q) : queue(&q) {}
void byte(uint8_t v) const { queue->serialise(v); }
NetQueue *queue;
};
class Reader
{
public:
enum { Read, Write, Direction = Read };
Reader(NetQueue &q) : queue(q) {}
void byte(uint8_t &v) const { queue.deserialise(v); }
NetQueue &queue;
Reader(NetQueue *q = NULL) : queue(q) {}
Reader(NetQueue &q) : queue(&q) {}
void byte(uint8_t &v) const { queue->deserialise(v); }
NetQueue *queue;
};
NetQueue(UsagePattern p = NetReceive);
NetQueue(UsagePattern p = Unused);
~NetQueue();
// Network related
@ -62,38 +84,58 @@ public:
void popRawData(size_t netLen); ///< Pops the extracted data, so that future readRawData calls do not return that data.
// Serialise/deserialise related. All game clients should deserialise all queues, including their own.
Writer beginSerialise() { return Writer(*this); } ///< No matching endSerialise.
Reader beginDeserialise() { return Reader(*this); }
void endSerialiseLength(); ///< Must call after serialiseLength, but not call otherwise.
bool endDeserialise(); ///< Returns true if deserialise succeeded, data has been consumed. Returns false if deserialise failed, due to not enough data yet.
bool isDeserialiseError() const; ///< Returns true if deserialise has failed.
void serialiseLength(); ///< Do not call readRawData or beginDeserialise before calling endSerialiseLength! Makes room for the length, which will actually be serialised there when calling endSerialise.
bool deserialiseHaveLength(); ///< Checks the length, and returns true iff that much data is available. Length will still be returned by deserialise.
uint8_t deserialiseGetType(); ///< Returns the byte immediately after the length.
void serialise(uint8_t v); ///< Serialise a byte.
void deserialise(uint8_t &v); ///< Deserialise a byte.
#ifdef USE_ZLIB
void setCompression(); ///< Enable compression. Should call after serialising or deserialising an appropriate message.
#endif //USE_ZLIB
void setCompression(uint32_t compressionMask); ///< Enable compression if possible. Should call after serialising or deserialising an appropriate message.
private:
#ifdef USE_ZLIB
void setCompressionZlib(); ///< Enable zlib compression.
#endif //USE_ZLIB
void popOldData(); ///< Pops any data that is no longer needed.
// Disable copy constructor and assignment operator.
NetQueue(const NetQueue &);
void operator =(const NetQueue &);
bool canSerialise; ///< True if we are the producer of data for this NetQueue.
bool canDeserialise; ///< True if we are the producer of data for this NetQueue.
bool canWriteRaw; ///< True if we will call getDataForNetwork.
bool canReadRaw; ///< True if we will call getDataForNetwork.
bool deserialiseUnderflow; ///< We ran out of data when deserialising.
bool canCompress; ///< True if this is a NetQueue for a socket.
bool isCompressed; ///< True if we turned compression on already.
unsigned readOffset; ///< Offset in data for reading.
unsigned readSuccessOffset; ///< Offset in data for reading, when success was last called.
unsigned netOffset; ///< Offset in data for writing to network.
std::vector<uint8_t> data; ///< Decompressed serialised data.
unsigned beginSerialiseOffset; ///< Offset in data when serialiseLength was called.
std::vector<uint8_t> data; ///< Decompressed serialised data.
std::vector<uint8_t> compressedData; ///< Compressed data.
#ifdef USE_ZLIB
std::vector<uint8_t> compressedData; ///< Compressed data.
struct z_stream_s *stream; ///< Non-null iff we are using compression.
struct z_stream_s *stream; ///< Non-null iff we are using zlib compression.
#endif //USE_ZLIB
};
class NetQueuePair
{
public:
NetQueuePair() : send(NetQueue::NetSend), receive(NetQueue::NetReceive) {}
NetQueue send;
NetQueue receive;
};
extern "C"
{
#else
#error There isn''t currently any C interface to this.
#endif //__cplusplus
#ifdef __cplusplus

View File

@ -1,6 +1,6 @@
/*
This file is part of Warzone 2100.
Copyright (C) 2007-2009 Warzone Resurrection Project
Copyright (C) 2007-2010 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,233 +32,118 @@
#include "../framework/frame.h"
#include "netplay.h"
#include "nettypes.h"
#include "netqueue.h"
#include <cstring>
static NetQueue *gameQueues[MAX_PLAYERS + 1] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; // The game queues should be used, even in single-player. The +1 is for AIs that don't want to (TODO fix this) use their own queue.
static NetQueuePair *netQueues[MAX_CONNECTED_PLAYERS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static NetQueuePair *tmpQueues[MAX_TMP_SOCKETS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static NetQueue *broadcastQueue = NULL;
static NetQueue::Writer writer;
static NetQueue::Reader reader;
static int writeSocketIndex = -1;
static PACKETDIR NetDir;
static void NETsetPacketDir(PACKETDIR dir)
{
NetDir = dir;
// Can't put STATIC_ASSERT in global scope, arbitrarily putting it here.
STATIC_ASSERT(MAX_PLAYERS == MAX_CONNECTED_PLAYERS); // Things might break if each connected player doesn't correspond to a player of the same index.
}
PACKETDIR NETgetPacketDir()
{
return NetDir;
}
/*
* Begin & End functions
*/
void NETbeginEncode(uint8_t type, uint8_t player)
{
NETsetPacketDir(PACKET_ENCODE);
NetMsg.type = type;
NetMsg.size = 0;
NetMsg.status = true;
NetMsg.destination = player;
memset(&NetMsg.body, '\0', sizeof(NetMsg.body));
}
void NETbeginDecode(uint8_t type)
template<class Q>
static void queue(const Q &q, uint8_t &v)
{
NETsetPacketDir(PACKET_DECODE);
assert(type == NetMsg.type);
NetMsg.size = 0;
NetMsg.status = true;
q.byte(v);
}
BOOL NETend(void)
template<class Q>
static void queue(const Q &q, uint16_t &v)
{
assert(NETgetPacketDir() != PACKET_INVALID);
// If we are decoding just return true
if (NETgetPacketDir() == PACKET_DECODE)
{
return true;
}
// If the packet is invalid or failed to compile
if (NETgetPacketDir() != PACKET_ENCODE || !NetMsg.status)
{
return false;
}
// We have sent the packet, so make it invalid (to prevent re-sending)
NETsetPacketDir(PACKET_INVALID);
// Send the packet, updating the send functions is on my todo list!
if (NetMsg.destination == NET_ALL_PLAYERS)
{
return NETbcast(&NetMsg);
}
else
{
return NETsend(&NetMsg, NetMsg.destination);
}
uint8_t b[2] = {v>>8, v};
queue(q, b[0]);
queue(q, b[1]);
v = b[0]<<8 | b[1];
}
/*
* Primitive functions (ints and strings). Due to the lack of C++ and the fact
* that I hate macros this is a lot longer than it should be.
*/
BOOL NETint8_t(int8_t *ip)
template<class Q>
static void queue(const Q &q, uint32_t &v)
{
int8_t *store = (int8_t *) &NetMsg.body[NetMsg.size];
// Make sure there is enough data/space left in the packet
if (sizeof(int8_t) + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
{
return NetMsg.status = false;
}
// 8-bit (1 byte) integers need no endian-swapping!
if (NETgetPacketDir() == PACKET_ENCODE)
{
*store = *ip;
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
*ip = *store;
}
// Increment the size of the message
NetMsg.size += sizeof(int8_t);
return true;
uint16_t b[2] = {v>>16, v};
queue(q, b[0]);
queue(q, b[1]);
v = b[0]<<16 | b[1];
}
BOOL NETuint8_t(uint8_t *ip)
template<class Q>
static void queue(const Q &q, uint64_t &v)
{
uint8_t *store = (uint8_t *) &NetMsg.body[NetMsg.size];
// Make sure there is enough data/space left in the packet
if (sizeof(uint8_t) + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
{
return NetMsg.status = false;
}
// 8-bit (1 byte) integers need no endian-swapping!
if (NETgetPacketDir() == PACKET_ENCODE)
{
*store = *ip;
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
*ip = *store;
}
// Increment the size of the message
NetMsg.size += sizeof(uint8_t);
return true;
uint32_t b[2] = {v>>32, v};
queue(q, b[0]);
queue(q, b[1]);
v = uint64_t(b[0])<<32 | b[1];
}
BOOL NETint16_t(int16_t *ip)
template<class Q>
static void queue(const Q &q, char &v)
{
int16_t *store = (int16_t *) &NetMsg.body[NetMsg.size];
uint8_t b = v;
queue(q, b);
v = b;
// Make sure there is enough data/space left in the packet
if (sizeof(int16_t) + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
{
return NetMsg.status = false;
}
// Convert the integer into the network byte order (big endian)
if (NETgetPacketDir() == PACKET_ENCODE)
{
*store = SDL_SwapBE16(*ip);
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
*ip = SDL_SwapBE16(*store);
}
// Increment the size of the message
NetMsg.size += sizeof(int16_t);
return true;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
BOOL NETuint16_t(uint16_t *ip)
template<class Q>
static void queue(const Q &q, int8_t &v)
{
uint16_t *store = (uint16_t *) &NetMsg.body[NetMsg.size];
uint8_t b = v;
queue(q, b);
v = b;
// Make sure there is enough data/space left in the packet
if (sizeof(uint16_t) + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
{
return NetMsg.status = false;
}
// Convert the integer into the network byte order (big endian)
if (NETgetPacketDir() == PACKET_ENCODE)
{
*store = SDL_SwapBE16(*ip);
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
*ip = SDL_SwapBE16(*store);
}
// Increment the size of the message
NetMsg.size += sizeof(uint16_t);
return true;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
BOOL NETint32_t(int32_t *ip)
template<class Q>
static void queue(const Q &q, int16_t &v)
{
int32_t *store = (int32_t *) &NetMsg.body[NetMsg.size];
uint16_t b = v;
queue(q, b);
v = b;
// Make sure there is enough data/space left in the packet
if (sizeof(int32_t) + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
{
return NetMsg.status = false;
}
// Convert the integer into the network byte order (big endian)
if (NETgetPacketDir() == PACKET_ENCODE)
{
*store = SDL_SwapBE32(*ip);
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
*ip = SDL_SwapBE32(*store);
}
// Increment the size of the message
NetMsg.size += sizeof(int32_t);
return true;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
BOOL NETuint32_t(uint32_t *ip)
template<class Q>
static void queue(const Q &q, int32_t &v)
{
uint32_t *store = (uint32_t *) &NetMsg.body[NetMsg.size];
uint32_t b = v;
queue(q, b);
v = b;
// Make sure there is enough data/space left in the packet
if (sizeof(uint32_t) + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
{
return NetMsg.status = false;
}
// Convert the integer into the network byte order (big endian)
if (NETgetPacketDir() == PACKET_ENCODE)
{
*store = SDL_SwapBE32(*ip);
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
*ip = SDL_SwapBE32(*store);
}
// Increment the size of the message
NetMsg.size += sizeof(uint32_t);
return true;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
BOOL NETfloat(float *fp)
template<class Q>
static void queue(const Q &q, int64_t &v)
{
uint64_t b = v;
queue(q, b);
v = b;
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
template<class Q>
void queue(const Q &q, float &v)
{
/*
* NB: Not portable.
@ -277,34 +162,283 @@ BOOL NETfloat(float *fp)
// IEEE754 floating point numbers can be treated the same as 32-bit integers
// with regards to endian conversion
STATIC_ASSERT(sizeof(float) == sizeof(int32_t));
uint32_t b;
std::memcpy(&b, &v, sizeof(b));
queue(q, b);
std::memcpy(&v, &b, sizeof(b));
return NETint32_t((int32_t *) fp);
STATIC_ASSERT(sizeof(b) == sizeof(v));
}
BOOL NETbool(BOOL *bp)
template<class Q>
static void queue(const Q &q, Vector3uw &v)
{
// Bools are converted to uint8_ts
uint8_t tmp = (uint8_t) *bp;
NETuint8_t(&tmp);
queue(q, v.x);
queue(q, v.y);
queue(q, v.z);
}
// If we are decoding and managed to extract the value set it
if (NETgetPacketDir() == PACKET_DECODE && NetMsg.status)
// Queue selection functions
static NetQueue *sendQueue(NETQUEUE queue)
{
return queue.isPair ? &(*static_cast<NetQueuePair **>(queue.queue))->send : static_cast<NetQueue *>(queue.queue);
}
static NetQueue *receiveQueue(NETQUEUE queue)
{
return queue.isPair ? &(*static_cast<NetQueuePair **>(queue.queue))->receive : static_cast<NetQueue *>(queue.queue);
}
static NetQueuePair *&pairQueue(NETQUEUE queue)
{
ASSERT(queue.isPair, "Huh?");
return *static_cast<NetQueuePair **>(queue.queue);
}
NETQUEUE NETnetTmpQueue(unsigned tmpPlayer)
{
NETQUEUE ret;
ASSERT(tmpPlayer < MAX_TMP_SOCKETS, "Huh?");
NetQueuePair **queue = &tmpQueues[tmpPlayer];
ret.queue = queue;
ret.isPair = true;
ret.index = tmpPlayer;
ret.queueType = QUEUE_TMP;
return ret;
}
NETQUEUE NETnetQueue(unsigned player)
{
NETQUEUE ret;
if (player == NET_ALL_PLAYERS)
{
*bp = (BOOL) tmp;
return NETbroadcastQueue();
}
return NetMsg.status;
ASSERT(player < MAX_CONNECTED_PLAYERS, "Huh?");
NetQueuePair **queue = &netQueues[player];
ret.queue = queue;
ret.isPair = true;
ret.index = player;
ret.queueType = QUEUE_NET;
return ret;
}
NETQUEUE NETgameQueue(unsigned player)
{
NETQUEUE ret;
ASSERT(player < MAX_CONNECTED_PLAYERS + 1, "Huh?"); // + 1 for AIs that don't use their own queue.
NetQueue *queue = gameQueues[player];
ret.queue = queue;
ret.isPair = false;
ret.index = player;
ret.queueType = QUEUE_GAME;
return ret;
}
NETQUEUE NETbroadcastQueue()
{
NETQUEUE ret;
NetQueue *queue = broadcastQueue;
ret.queue = queue;
ret.isPair = false;
ret.index = NET_ALL_PLAYERS;
ret.queueType = QUEUE_BROADCAST;
return ret;
}
void NETinsertRawData(NETQUEUE queue, uint8_t *data, size_t dataLen)
{
receiveQueue(queue)->writeRawData(data, dataLen);
}
BOOL NETisMessageReady(NETQUEUE queue)
{
return receiveQueue(queue)->deserialiseHaveLength();
}
uint8_t NETmessageType(NETQUEUE queue)
{
return receiveQueue(queue)->deserialiseGetType();
}
/*
* Begin & End functions
*/
void NETinitQueue(NETQUEUE queue)
{
if (queue.queueType == QUEUE_BROADCAST)
{
delete broadcastQueue;
broadcastQueue = new NetQueue(NetQueue::NetSend);
return;
}
else if (queue.queueType == QUEUE_GAME)
{
delete gameQueues[queue.index];
gameQueues[queue.index] = new NetQueue(NetQueue::GameSolo); // TODO Should sometimes be NetQueue::GameSend or NetQueue::GameReceive.
return;
}
else
{
delete pairQueue(queue);
pairQueue(queue) = new NetQueuePair;
}
}
void NETmoveQueue(NETQUEUE src, NETQUEUE dst)
{
ASSERT(src.isPair, "Huh?");
ASSERT(dst.isPair, "Huh?");
delete pairQueue(dst);
pairQueue(dst) = NULL;
std::swap(pairQueue(src), pairQueue(dst));
}
void NETbeginEncode(NETQUEUE cqueue, uint8_t type)
{
NETsetPacketDir(PACKET_ENCODE);
writer = sendQueue(cqueue);
if (cqueue.queueType == QUEUE_NET || cqueue.queueType == QUEUE_BROADCAST)
{
writeSocketIndex = cqueue.index;
}
else
{
writeSocketIndex = -1;
}
writer.queue->serialiseLength();
queue(writer, type);
}
void NETbeginDecode(NETQUEUE cqueue, uint8_t type)
{
NETsetPacketDir(PACKET_DECODE);
reader = receiveQueue(cqueue);
uint32_t len;
uint8_t readType;
queue(reader, len);
queue(reader, readType);
assert(type == readType);
}
BOOL NETend()
{
assert(NETgetPacketDir() != PACKET_INVALID);
// If we are encoding just return true
if (NETgetPacketDir() == PACKET_ENCODE)
{
writer.queue->endSerialiseLength();
if (writeSocketIndex >= 0)
{
const uint8_t *data;
size_t dataLen;
NetQueue *queue = writeSocketIndex == NET_ALL_PLAYERS ? broadcastQueue : &netQueues[writeSocketIndex]->send;
queue->readRawData(&data, &dataLen);
NETsend(writeSocketIndex, data, dataLen);
queue->popRawData(dataLen);
}
NETsetPacketDir(PACKET_INVALID);
return true;
}
bool ret = reader.queue->endDeserialise();
// We have ended the deserialisation, so mark the direction invalid
NETsetPacketDir(PACKET_INVALID);
return ret;
/*
// If the packet is invalid or failed to compile
if (NETgetPacketDir() != PACKET_ENCODE || !NetMsg.status)
{
return false;
}
// Send the packet, updating the send functions is on my todo list!
if (NetMsg.destination == NET_ALL_PLAYERS)
{
return NETbcast(&NetMsg);
}
else
{
return NETsend(&NetMsg, NetMsg.destination);
}
*/
}
template<class T>
static void queueAuto(T &v)
{
if (NETgetPacketDir() == PACKET_ENCODE)
{
queue(writer, v);
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
queue(reader, v);
}
}
void NETint8_t(int8_t *ip)
{
queueAuto(*ip);
}
void NETuint8_t(uint8_t *ip)
{
queueAuto(*ip);
}
void NETint16_t(int16_t *ip)
{
queueAuto(*ip);
}
void NETuint16_t(uint16_t *ip)
{
queueAuto(*ip);
}
void NETint32_t(int32_t *ip)
{
queueAuto(*ip);
}
void NETuint32_t(uint32_t *ip)
{
queueAuto(*ip);
}
void NETfloat(float *fp)
{
queueAuto(*fp);
}
void NETbool(BOOL *bp)
{
uint8_t i = !!*bp;
queueAuto(i);
*bp = !!i;
}
/*
* NETnull should be used to either add 4 bytes of padding to a message, or to
* discard 4 bytes of data from a message.
*/
BOOL NETnull()
void NETnull()
{
uint32_t zero = 0;
return NETuint32_t(&zero);
NETuint32_t(&zero);
}
/** Sends or receives a string to or from the current network package.
@ -321,103 +455,65 @@ BOOL NETnull()
* string being decoded, the resulting string (in \c str) will be
* truncated.
*/
BOOL NETstring(char *str, uint16_t maxlen)
void NETstring(char *str, uint16_t maxlen)
{
/*
* Strings sent over the network are prefixed with their length, sent as an
* unsigned 16-bit integer.
* unsigned 16-bit integer, not including \0 termination.
*/
// Work out the length of the string if we are encoding
uint16_t len = (NETgetPacketDir() == PACKET_ENCODE) ? strnlen1(str, maxlen) : 0;
char *store;
uint16_t len = NETgetPacketDir() == PACKET_ENCODE ? strnlen1(str, maxlen) - 1 : 0;
queueAuto(len);
// Add/fetch the length from the packet
NETuint16_t(&len);
// Map store to the message buffer
store = (char *) &NetMsg.body[NetMsg.size];
// Make sure there is enough data/space left in the packet
if (len + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
// Truncate length if necessary
if (len > maxlen - 1)
{
return NetMsg.status = false;
debug(LOG_ERROR, "NETstring: %s packet, length %u truncated at %u", NETgetPacketDir() == PACKET_ENCODE ? "Encoding" : "Decoding", len, maxlen);
len = maxlen - 1;
}
if (NETgetPacketDir() == PACKET_ENCODE)
for (unsigned i = 0; i < len; ++i)
{
memcpy(store, str, len);
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
// Truncate length if necessary
if (len > maxlen)
{
debug(LOG_ERROR, "NETstring: Decoding packet type %d from %d, buffer size %u truncated at %u",
NetMsg.type, NetMsg.source, len, maxlen);
len = maxlen;
}
memcpy(str, store, len);
// Guarantee NUL-termination
str[len - 1] = '\0';
queueAuto(str[i]);
}
// Increment the size of the message
NetMsg.size += sizeof(len) + len;
return true;
if (NETgetPacketDir() == PACKET_DECODE)
{
// NUL-terminate
str[len] = '\0';
}
}
BOOL NETbin(char *str, uint16_t maxlen)
void NETbin(uint8_t *str, uint16_t maxlen)
{
/*
* Strings sent over the network are prefixed with their length, sent as an
* Bins sent over the network are prefixed with their length, sent as an
* unsigned 16-bit integer.
*/
// Work out the length of the string if we are encoding
uint16_t len = (NETgetPacketDir() == PACKET_ENCODE) ? maxlen : 0;
char *store;
// Work out the length of the bin if we are encoding
uint16_t len = NETgetPacketDir() == PACKET_ENCODE ? maxlen : 0;
queueAuto(len);
// Add/fetch the length from the packet
NETuint16_t(&len);
// Map store to the message buffer
store = (char *) &NetMsg.body[NetMsg.size];
// Make sure there is enough data/space left in the packet
if (len + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
// Truncate length if necessary
if (len > maxlen)
{
return NetMsg.status = false;
debug(LOG_ERROR, "NETbin: Decoding packet, buffer size %u truncated at %u", len, maxlen);
len = maxlen;
}
if (NETgetPacketDir() == PACKET_ENCODE)
for (unsigned i = 0; i < len; ++i)
{
memcpy(store, str, len);
}
else if (NETgetPacketDir() == PACKET_DECODE)
{
// Truncate length if necessary
if (len > maxlen)
{
debug(LOG_ERROR, "NETbin: Decoding packet type %d from %d, buffer size %u truncated at %u",
NetMsg.type, NetMsg.source, len, maxlen);
len = maxlen;
}
memcpy(str, store, len);
queueAuto(str[i]);
}
// Increment the size of the message
NetMsg.size += sizeof(len) + len;
return true;
// Throw away length...
//maxlen = len;
}
BOOL NETVector3uw(Vector3uw* vp)
void NETVector3uw(Vector3uw *vp)
{
return (NETuint16_t(&vp->x)
&& NETuint16_t(&vp->y)
&& NETuint16_t(&vp->z));
queueAuto(*vp);
}
typedef enum
@ -428,7 +524,7 @@ typedef enum
static void NETcoder(PACKETDIR dir)
{
static const char original[] = "THIS IS A TEST STRING";
/* static const char original[] = "THIS IS A TEST STRING";
char str[sizeof(original)];
BOOL b = true;
uint32_t u32 = 32;
@ -442,9 +538,9 @@ static void NETcoder(PACKETDIR dir)
sstrcpy(str, original);
if (dir == PACKET_ENCODE)
NETbeginEncode(0, 0);
NETbeginEncodeNet(0, 0);
else
NETbeginDecode(0);
NETbeginDecodeNet(0, 0);
NETbool(&b); assert(b == true);
NETuint32_t(&u32); assert(u32 == 32);
NETuint16_t(&u16); assert(u16 == 16);
@ -453,12 +549,12 @@ static void NETcoder(PACKETDIR dir)
NETint16_t(&i16); assert(i16 == -16);
NETint8_t(&i8); assert(i8 == -8);
NETstring(str, sizeof(str)); assert(strncmp(str, original, sizeof(str) - 1) == 0);
NETenum(&te); assert(te == test_b);
NETenum(&te); assert(te == test_b);*/
}
void NETtest()
{
NETMSG cmp;
/*NETMSG cmp;
memset(&cmp, 0, sizeof(cmp));
memset(&NetMsg, 0, sizeof(NetMsg));
@ -466,10 +562,11 @@ void NETtest()
memcpy(&cmp, &NetMsg, sizeof(cmp));
NETcoder(PACKET_DECODE);
ASSERT(memcmp(&cmp, &NetMsg, sizeof(cmp)) == 0, "nettypes unit test failed");
fprintf(stdout, "\tNETtypes self-test: PASSED\n");
fprintf(stdout, "\tNETtypes self-test: PASSED\n");*/
ASSERT(false, "nettypes test disabled, since it doesn't compile anymore.");
}
int NETgetSource()
/*int NETgetSource()
{
return NetMsg.source;
}
}*/

View File

@ -40,20 +40,49 @@ typedef enum packetDirectionEnum
PACKET_INVALID
} PACKETDIR;
void NETbeginEncode(uint8_t type, uint8_t player);
void NETbeginDecode(uint8_t type);
typedef enum QueueType
{
QUEUE_TMP,
QUEUE_NET,
QUEUE_GAME,
QUEUE_BROADCAST,
} QUEUETYPE;
typedef struct _netqueue
{
void *queue; ///< Is either a (NetQueuePair **) or a (NetQueue *). (Note different numbers of *.)
BOOL isPair;
uint8_t index;
uint8_t queueType;
} NETQUEUE;
NETQUEUE NETnetTmpQueue(unsigned tmpPlayer); ///< One of the temp queues from before a client has joined the game.
NETQUEUE NETnetQueue(unsigned player); ///< The queue pair used for sending and receiving data directly from another client.
NETQUEUE NETgameQueue(unsigned player); ///< The game action queue.
NETQUEUE NETbroadcastQueue(void); ///< The queue for sending data directly to all clients, not just a specific one.
void NETinsertRawData(NETQUEUE queue, uint8_t *data, size_t dataLen); /// Dump raw data from sockets and raw data sent via host here.
BOOL NETisMessageReady(NETQUEUE queue);
uint8_t NETmessageType(NETQUEUE queue);
void NETinitQueue(NETQUEUE queue);
void NETmoveQueue(NETQUEUE src, NETQUEUE dst);
void NETbeginEncode(NETQUEUE queue, uint8_t type);
void NETbeginDecode(NETQUEUE queue, uint8_t type);
BOOL NETend(void);
BOOL NETint8_t(int8_t *ip);
BOOL NETuint8_t(uint8_t *ip);
BOOL NETint16_t(int16_t *ip);
BOOL NETuint16_t(uint16_t *ip);
BOOL NETint32_t(int32_t *ip);
BOOL NETuint32_t(uint32_t *ip);
BOOL NETfloat(float* fp);
BOOL NETbool(BOOL *bp);
BOOL NETnull(void);
BOOL NETstring(char *str, uint16_t maxlen);
BOOL NETbin(char *str, uint16_t maxlen);
void NETint8_t(int8_t *ip);
void NETuint8_t(uint8_t *ip);
void NETint16_t(int16_t *ip);
void NETuint16_t(uint16_t *ip);
void NETint32_t(int32_t *ip);
void NETuint32_t(uint32_t *ip);
void NETfloat(float* fp);
void NETbool(BOOL *bp);
void NETnull(void);
void NETstring(char *str, uint16_t maxlen);
void NETbin(uint8_t *str, uint16_t maxlen);
PACKETDIR NETgetPacketDir(void);
@ -91,13 +120,13 @@ do \
} while(0)
#endif
BOOL NETVector3uw(Vector3uw* vp);
void NETVector3uw(Vector3uw* vp);
/**
* Get player who is the source of the current packet.
* @see selectedPlayer
*/
int NETgetSource(void);
//int NETgetSource(void);
void NETtest(void);

View File

@ -73,7 +73,7 @@ BOOL sendHappyVtol(const DROID* psDroid)
return false;
}
NETbeginEncode(NET_VTOL, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_VTOL);
{
uint8_t player = psDroid->player;
uint32_t droid = psDroid->id;
@ -84,12 +84,12 @@ BOOL sendHappyVtol(const DROID* psDroid)
return NETend();
}
BOOL recvHappyVtol()
BOOL recvHappyVtol(NETQUEUE queue)
{
DROID* pD;
unsigned int i;
NETbeginDecode(NET_VTOL);
NETbeginDecode(queue, NET_VTOL);
{
uint8_t player;
uint32_t droid;
@ -127,7 +127,7 @@ BOOL sendDroidSecondary(const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STA
if (!bMultiMessages)
return true;
NETbeginEncode(NET_SECONDARY, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_SECONDARY);
{
uint8_t player = psDroid->player;
uint32_t droid = psDroid->id;
@ -145,7 +145,7 @@ BOOL sendDroidSecondary(const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STA
}
// recv
BOOL recvDroidSecondary()
BOOL recvDroidSecondary(NETQUEUE queue)
{
DROID* psDroid;
SECONDARY_ORDER sec = DSO_ATTACK_RANGE;
@ -153,7 +153,7 @@ BOOL recvDroidSecondary()
uint32_t body;
Vector3uw pos;
NETbeginDecode(NET_SECONDARY);
NETbeginDecode(queue, NET_SECONDARY);
{
uint8_t player;
uint32_t droid;
@ -198,7 +198,7 @@ BOOL sendDroidSecondaryAll(const DROID* psDroid)
if (!bMultiMessages)
return true;
NETbeginEncode(NET_SECONDARY_ALL, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_SECONDARY_ALL);
{
uint8_t player = psDroid->player;
uint32_t droid = psDroid->id;
@ -211,11 +211,11 @@ BOOL sendDroidSecondaryAll(const DROID* psDroid)
return NETend();
}
BOOL recvDroidSecondaryAll()
BOOL recvDroidSecondaryAll(NETQUEUE queue)
{
DROID* psDroid;
NETbeginDecode(NET_SECONDARY_ALL);
NETbeginDecode(queue, NET_SECONDARY_ALL);
{
uint8_t player;
uint32_t droid, secOrder;
@ -249,7 +249,7 @@ BOOL sendDroidEmbark(const DROID* psDroid, const DROID* psTransporter)
if (!bMultiMessages)
return true;
NETbeginEncode(NET_DROIDEMBARK, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_DROIDEMBARK);
{
uint8_t player = psDroid->player;
uint32_t droidID = psDroid->id;
@ -266,13 +266,13 @@ BOOL sendDroidEmbark(const DROID* psDroid, const DROID* psTransporter)
*
* \sa sendDroidEmbark(),sendDroidDisEmbark(),recvDroidDisEmbark()
*/
BOOL recvDroidEmbark()
BOOL recvDroidEmbark(NETQUEUE queue)
{
DROID* psDroid;
DROID* psTransporterDroid;
BOOL bDroidRemoved;
NETbeginDecode(NET_DROIDEMBARK);
NETbeginDecode(queue, NET_DROIDEMBARK);
{
uint8_t player;
uint32_t droidID;
@ -336,7 +336,7 @@ BOOL sendDroidDisEmbark(const DROID* psDroid, const DROID* psTransporter)
if (!bMultiMessages)
return true;
NETbeginEncode(NET_DROIDDISEMBARK, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_DROIDDISEMBARK);
{
uint8_t player = psDroid->player;
uint32_t droidID = psDroid->id;
@ -355,12 +355,12 @@ BOOL sendDroidDisEmbark(const DROID* psDroid, const DROID* psTransporter)
*
* \sa sendDroidEmbark(),recvDroidEmbark(),sendDroidDisEmbark()
*/
BOOL recvDroidDisEmbark()
BOOL recvDroidDisEmbark(NETQUEUE queue)
{
DROID *psFoundDroid = NULL, *psTransporterDroid = NULL;
DROID *psCheckDroid = NULL;
NETbeginDecode(NET_DROIDDISEMBARK);
NETbeginDecode(queue, NET_DROIDDISEMBARK);
{
uint8_t player;
uint32_t droidID;
@ -450,7 +450,7 @@ BOOL SendDroidMove(const DROID* psDroid, uint32_t x, uint32_t y, BOOL formation)
return true;
}
NETbeginEncode(NET_DROIDMOVE, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_DROIDMOVE);
{
uint8_t player = psDroid->player;
uint32_t droid = psDroid->id;
@ -465,13 +465,13 @@ BOOL SendDroidMove(const DROID* psDroid, uint32_t x, uint32_t y, BOOL formation)
}
// recv and updated droid position
BOOL recvDroidMove()
BOOL recvDroidMove(NETQUEUE queue)
{
DROID* psDroid;
uint32_t x, y;
BOOL formation;
NETbeginDecode(NET_DROIDMOVE);
NETbeginDecode(queue, NET_DROIDMOVE);
{
uint8_t player;
uint32_t droid;
@ -487,14 +487,14 @@ BOOL recvDroidMove()
if ((x == 0 && y == 0) || x > world_coord(mapWidth) || y > world_coord(mapHeight))
{
/* Probably an invalid droid position */
debug(LOG_ERROR, "Received an invalid droid position from %d, [%s : p%d]", NETgetSource(),
debug(LOG_ERROR, "Received an invalid droid position from %d, [%s : p%d]", queue.index,
isHumanPlayer(player) ? "Human" : "AI", player);
return false;
}
if (!IdToDroid(droid, player, &psDroid))
{
debug(LOG_ERROR, "Packet from %d refers to non-existent droid %u, [%s : p%d]",
NETgetSource(), droid, isHumanPlayer(player) ? "Human" : "AI", player);
queue.index, droid, isHumanPlayer(player) ? "Human" : "AI", player);
return false;
}
}
@ -537,7 +537,7 @@ BOOL SendDroid(const DROID_TEMPLATE* pTemplate, uint32_t x, uint32_t y, uint8_t
}
debug(LOG_SYNC, "Droid sent with id of %u", id);
NETbeginEncode(NET_DROID, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_DROID);
{
Vector3uw pos = { x, y, 0 };
uint32_t templateID = pTemplate->multiPlayerID;
@ -556,7 +556,7 @@ BOOL SendDroid(const DROID_TEMPLATE* pTemplate, uint32_t x, uint32_t y, uint8_t
// ////////////////////////////////////////////////////////////////////////////
// receive droid creation information from other players
BOOL recvDroid()
BOOL recvDroid(NETQUEUE queue)
{
DROID_TEMPLATE* pT;
DROID* psDroid;
@ -567,7 +567,7 @@ BOOL recvDroid()
uint32_t templateID;
uint32_t power;
NETbeginDecode(NET_DROID);
NETbeginDecode(queue, NET_DROID);
{
NETuint8_t(&player);
NETuint32_t(&id);
@ -586,7 +586,7 @@ BOOL recvDroid()
if ((pos.x == 0 && pos.y == 0) || pos.x > world_coord(mapWidth) || pos.y > world_coord(mapHeight))
{
debug(LOG_ERROR, "Received bad droid position (%d, %d) from %d about p%d (%s)", (int)pos.x, (int)pos.y,
NETgetSource(), player, isHumanPlayer(player) ? "Human" : "AI");
queue.index, player, isHumanPlayer(player) ? "Human" : "AI");
return false;
}
@ -594,7 +594,7 @@ BOOL recvDroid()
if (!pT)
{
debug(LOG_ERROR, "Packet from %d refers to non-existent template %u, [%s : p%d]",
NETgetSource(), templateID, isHumanPlayer(player) ? "Human" : "AI", player);
queue.index, templateID, isHumanPlayer(player) ? "Human" : "AI", player);
return false;
}
@ -616,7 +616,7 @@ BOOL recvDroid()
}
else
{
debug(LOG_ERROR, "Packet from %d cannot create droid for p%d (%s)!", NETgetSource(),
debug(LOG_ERROR, "Packet from %d cannot create droid for p%d (%s)!", queue.index,
player, isHumanPlayer(player) ? "Human" : "AI");
#ifdef DEBUG
CONPRINTF(ConsoleString, (ConsoleString, "MULTIPLAYER: Couldn't build a remote droid, relying on checking to resync"));
@ -648,7 +648,7 @@ BOOL SendGroupOrderSelected(uint8_t player, uint32_t x, uint32_t y, const BASE_O
if (!bMultiMessages)
return true;
NETbeginEncode(NET_GROUPORDER, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_GROUPORDER);
{
DROID_ORDER order = (altOrder?DORDER_UNKNOWN_ALT:DORDER_UNKNOWN);
BOOL subType = (psObj) ? true : false, cmdOrder = false;
@ -722,7 +722,7 @@ BOOL SendGroupOrderGroup(const DROID_GROUP* psGroup, DROID_ORDER order, uint32_t
if (!bMultiMessages)
return true;
NETbeginEncode(NET_GROUPORDER, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_GROUPORDER);
{
BOOL subType = (psObj) ? true : false, cmdOrder = false;
DROID *psDroid;
@ -777,7 +777,7 @@ BOOL SendGroupOrderGroup(const DROID_GROUP* psGroup, DROID_ORDER order, uint32_t
// ////////////////////////////////////////////////////////////////////////////
// receive a group order.
BOOL recvGroupOrder()
BOOL recvGroupOrder(NETQUEUE queue)
{
DROID_ORDER order = DORDER_NONE;
BOOL subType, cmdOrder;
@ -790,7 +790,7 @@ BOOL recvGroupOrder()
uint32_t *droidBodies;
Vector3uw *droidPositions;
NETbeginDecode(NET_GROUPORDER);
NETbeginDecode(queue, NET_GROUPORDER);
{
NETuint8_t(&player); // FYI: anything over MAX_PLAYERS means this is a ai player
NETenum(&order);
@ -826,14 +826,7 @@ BOOL recvGroupOrder()
for (i = 0; i < droidCount; ++i)
{
// Retrieve the id number for the current droid
if (!NETuint32_t(&droidIDs[i]))
{
// If somehow we fail assume the message got truncated prematurely
debug(LOG_SYNC, "Error retrieving droid ID number; while there are (supposed to be) still %u droids left for p%d",
(unsigned int)(droidCount - i), player);
NETend();
return false;
}
NETuint32_t(&droidIDs[i]);
// Get the body points of the droid
NETuint32_t(&droidBodies[i]);
@ -842,12 +835,18 @@ BOOL recvGroupOrder()
NETVector3uw(&droidPositions[i]);
}
}
NETend();
if (!NETend())
{
// If somehow we fail assume the message got truncated prematurely
debug(LOG_SYNC, "Error retrieving droid ID number; while there are (supposed to be) still %u droids left for p%d",
(unsigned int)droidCount, player);
return false;
}
/* Check if the order is valid */
if (order != DORDER_UNKNOWN && order != DORDER_UNKNOWN_ALT && ((subType && !validOrderForObj(order)) || (!subType && !validOrderForLoc(order))))
{
debug(LOG_ERROR, "Invalid group order received from %d, [%s : p%d]", NETgetSource(),
debug(LOG_ERROR, "Invalid group order received from %d, [%s : p%d]", queue.index,
isHumanPlayer(player) ? "Human" : "AI", player);
return false;
}
@ -863,7 +862,7 @@ BOOL recvGroupOrder()
if (!IdToDroid(droidIDs[i], ANYPLAYER, &psDroid))
{
debug(LOG_ERROR, "Packet from %d refers to non-existent droid %u, [%s : p%d]",
NETgetSource(), droidIDs[i], isHumanPlayer(player) ? "Human" : "AI", player);
queue.index, droidIDs[i], isHumanPlayer(player) ? "Human" : "AI", player);
continue; // continue working on next droid; crossing fingers...
}
@ -919,7 +918,7 @@ BOOL SendDroidInfo(const DROID* psDroid, DROID_ORDER order, uint32_t x, uint32_t
return true;
}
NETbeginEncode(NET_DROIDINFO, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_DROIDINFO);
{
uint32_t droidId = psDroid->id;
BOOL subType = (psObj) ? true : false;
@ -952,9 +951,9 @@ BOOL SendDroidInfo(const DROID* psDroid, DROID_ORDER order, uint32_t x, uint32_t
// ////////////////////////////////////////////////////////////////////////////
// receive droid information form other players.
BOOL recvDroidInfo()
BOOL recvDroidInfo(NETQUEUE queue)
{
NETbeginDecode(NET_DROIDINFO);
NETbeginDecode(queue, NET_DROIDINFO);
{
uint32_t droidId;
DROID* psDroid;
@ -968,7 +967,7 @@ BOOL recvDroidInfo()
if (!IdToDroid(droidId, ANYPLAYER, &psDroid))
{
debug(LOG_ERROR, "Packet from %d refers to non-existent droid %u, [%s : p%d]",
NETgetSource(), droidId, isHumanPlayer(player) ? "Human" : "AI", player);
queue.index, droidId, isHumanPlayer(player) ? "Human" : "AI", player);
return false;
}
@ -1101,7 +1100,7 @@ BOOL SendDestroyDroid(const DROID* psDroid)
return true;
}
NETbeginEncode(NET_DROIDDEST, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_DROIDDEST);
{
uint32_t id = psDroid->id;
@ -1114,11 +1113,11 @@ BOOL SendDestroyDroid(const DROID* psDroid)
// ////////////////////////////////////////////////////////////////////////////
// Accept a droid which was destroyed on another machine
BOOL recvDestroyDroid()
BOOL recvDestroyDroid(NETQUEUE queue)
{
DROID* psDroid;
NETbeginDecode(NET_DROIDDEST);
NETbeginDecode(queue, NET_DROIDDEST);
{
uint32_t id;
@ -1127,7 +1126,7 @@ BOOL recvDestroyDroid()
if (!IdToDroid(id, ANYPLAYER, &psDroid))
{
debug(LOG_DEATH, "droid %d on request from player %d can't be found? Must be dead already?",
id, NETgetSource() );
id, queue.index );
return false;
}
}
@ -1137,13 +1136,13 @@ BOOL recvDestroyDroid()
if(!psDroid->died)
{
turnOffMultiMsg(true);
debug(LOG_DEATH, "Killing droid %d on request from player %d", psDroid->id, NETgetSource());
debug(LOG_DEATH, "Killing droid %d on request from player %d", psDroid->id, queue.index);
destroyDroid(psDroid);
turnOffMultiMsg(false);
}
else
{
debug(LOG_DEATH, "droid %d on request from player %d is dead already?", psDroid->id, NETgetSource());
debug(LOG_DEATH, "droid %d on request from player %d is dead already?", psDroid->id, queue.index);
}
return true;

View File

@ -65,13 +65,13 @@ static void giftResearch (uint8_t from, uint8_t to, BOOL send);
///////////////////////////////////////////////////////////////////////////////
// gifts..
BOOL recvGift(void)
BOOL recvGift(NETQUEUE queue)
{
uint8_t type, from, to;
int audioTrack;
uint32_t droidID;
NETbeginDecode(NET_GIFT);
NETbeginDecode(queue, NET_GIFT);
NETuint8_t(&type);
NETuint8_t(&from);
NETuint8_t(&to);
@ -158,7 +158,7 @@ void giftRadar(uint8_t from, uint8_t to, BOOL send)
{
uint8_t subType = RADAR_GIFT;
NETbeginEncode(NET_GIFT, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_GIFT);
NETuint8_t(&subType);
NETuint8_t(&from);
NETuint8_t(&to);
@ -244,7 +244,7 @@ static void sendGiftDroids(uint8_t from, uint8_t to)
}
if (psD->selected)
{
NETbeginEncode(NET_GIFT, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_GIFT);
NETuint8_t(&giftType);
NETuint8_t(&from);
NETuint8_t(&to);
@ -289,7 +289,7 @@ static void giftResearch(uint8_t from, uint8_t to, BOOL send)
{
uint8_t giftType = RESEARCH_GIFT;
NETbeginEncode(NET_GIFT, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_GIFT);
NETuint8_t(&giftType);
NETuint8_t(&from);
NETuint8_t(&to);
@ -327,7 +327,7 @@ void giftPower(uint8_t from, uint8_t to, BOOL send)
{
uint8_t giftType = POWER_GIFT;
NETbeginEncode(NET_GIFT, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_GIFT);
NETuint8_t(&giftType);
NETuint8_t(&from);
NETuint8_t(&to);
@ -470,7 +470,7 @@ void formAlliance(uint8_t p1, uint8_t p2, BOOL prop, BOOL allowAudio, BOOL allow
void sendAlliance(uint8_t from, uint8_t to, uint8_t state, int32_t value)
{
NETbeginEncode(NET_ALLIANCE, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_ALLIANCE);
NETuint8_t(&from);
NETuint8_t(&to);
NETuint8_t(&state);
@ -478,12 +478,12 @@ void sendAlliance(uint8_t from, uint8_t to, uint8_t state, int32_t value)
NETend();
}
BOOL recvAlliance(BOOL allowAudio)
BOOL recvAlliance(NETQUEUE queue, BOOL allowAudio)
{
uint8_t to, from, state;
int32_t value;
NETbeginDecode(NET_ALLIANCE);
NETbeginDecode(queue, NET_ALLIANCE);
NETuint8_t(&from);
NETuint8_t(&to);
NETuint8_t(&state);
@ -546,7 +546,7 @@ void technologyGiveAway(const STRUCTURE *pS)
pF->player = pS->player;
}
NETbeginEncode(NET_ARTIFACTS, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_ARTIFACTS);
{
/* Make sure that we don't have to violate the constness of pS.
* Since the nettype functions aren't const correct when sending
@ -572,7 +572,7 @@ void technologyGiveAway(const STRUCTURE *pS)
*/
void sendMultiPlayerFeature(FEATURE_TYPE subType, uint32_t x, uint32_t y, uint32_t id)
{
NETbeginEncode(NET_FEATURES, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_FEATURES);
{
NETenum(&subType);
NETuint32_t(&x);
@ -582,13 +582,13 @@ void sendMultiPlayerFeature(FEATURE_TYPE subType, uint32_t x, uint32_t y, uint32
NETend();
}
void recvMultiPlayerFeature()
void recvMultiPlayerFeature(NETQUEUE queue)
{
FEATURE_TYPE subType;
uint32_t x, y, id;
unsigned int i;
NETbeginDecode(NET_FEATURES);
NETbeginDecode(queue, NET_FEATURES);
{
NETenum(&subType);
NETuint32_t(&x);
@ -637,7 +637,7 @@ void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
uint8_t player = ANYPLAYER;
debug(LOG_FEATURE, "Sending %u artifact(s) type: (%s)", quantity, feature_names[type]);
NETbeginEncode(NET_ARTIFACTS, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_ARTIFACTS);
NETuint8_t(&quantity);
NETenum(&type);
@ -702,7 +702,7 @@ BOOL addOilDrum(uint8_t count)
// ///////////////////////////////////////////////////////////////
// receive splattered artifacts
void recvMultiPlayerRandomArtifacts()
void recvMultiPlayerRandomArtifacts(NETQUEUE queue)
{
int count, i;
uint8_t quantity, player;
@ -711,7 +711,7 @@ void recvMultiPlayerRandomArtifacts()
FEATURE_TYPE type;
FEATURE *pF;
NETbeginDecode(NET_ARTIFACTS);
NETbeginDecode(queue, NET_ARTIFACTS);
NETuint8_t(&quantity);
NETenum(&type);

View File

@ -33,17 +33,17 @@ extern void requestAlliance (uint8_t from, uint8_t to, BOOL prop, BOOL allowAud
extern void breakAlliance (uint8_t p1, uint8_t p2, BOOL prop, BOOL allowAudio);
extern void formAlliance (uint8_t p1, uint8_t p2, BOOL prop, BOOL allowAudio, BOOL allowNotification);
extern void sendAlliance (uint8_t from, uint8_t to, uint8_t state, int32_t value);
extern BOOL recvAlliance (BOOL allowAudio);
extern BOOL recvAlliance (NETQUEUE queue, BOOL allowAudio); // Was declared in multirecv.h, too.
extern void createTeamAlliances (void);
extern BOOL sendGift (uint8_t type, uint8_t to);
extern BOOL recvGift (void);
extern BOOL recvGift (NETQUEUE queue);
extern void technologyGiveAway (const STRUCTURE* pS);
extern void recvMultiPlayerRandomArtifacts (void);
extern void recvMultiPlayerRandomArtifacts (NETQUEUE queue);
extern void addMultiPlayerRandomArtifacts (uint8_t quantity, FEATURE_TYPE type);
extern void processMultiPlayerArtifacts (void);
extern void recvMultiPlayerFeature(void);
extern void recvMultiPlayerFeature (NETQUEUE queue);
extern void sendMultiPlayerFeature(FEATURE_TYPE type, uint32_t x, uint32_t y, uint32_t id);
extern void giftArtifact (UDWORD owner,UDWORD x,UDWORD y);

View File

@ -88,6 +88,7 @@
#include "multirecv.h"
#include "multimenu.h"
#include "multilimit.h"
#include "multigifts.h"
#include "warzoneconfig.h"
@ -1595,7 +1596,7 @@ static BOOL SendTeamRequest(UBYTE player, UBYTE chosenTeam)
}
else
{
NETbeginEncode(NET_TEAMREQUEST, NET_HOST_ONLY);
NETbeginEncode(NETnetQueue(NET_HOST_ONLY), NET_TEAMREQUEST);
NETuint8_t(&player);
NETuint8_t(&chosenTeam);
@ -1606,7 +1607,7 @@ static BOOL SendTeamRequest(UBYTE player, UBYTE chosenTeam)
return true;
}
BOOL recvTeamRequest()
BOOL recvTeamRequest(NETQUEUE queue)
{
UBYTE player, team;
@ -1615,7 +1616,7 @@ BOOL recvTeamRequest()
return true;
}
NETbeginDecode(NET_TEAMREQUEST);
NETbeginDecode(queue, NET_TEAMREQUEST);
NETuint8_t(&player);
NETuint8_t(&team);
NETend();
@ -1623,7 +1624,7 @@ BOOL recvTeamRequest()
if (player > MAX_PLAYERS || team > MAX_PLAYERS)
{
debug(LOG_ERROR, "Invalid NET_TEAMREQUEST from player %d: Tried to change player %d (team %d)",
NETgetSource(), (int)player, (int)team);
queue.index, (int)player, (int)team);
return false;
}
@ -1644,7 +1645,7 @@ static BOOL SendReadyRequest(UBYTE player, BOOL bReady)
}
else
{
NETbeginEncode(NET_READY_REQUEST, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_READY_REQUEST);
NETuint8_t(&player);
NETbool(&bReady);
NETend();
@ -1652,7 +1653,7 @@ static BOOL SendReadyRequest(UBYTE player, BOOL bReady)
return true;
}
BOOL recvReadyRequest()
BOOL recvReadyRequest(NETQUEUE queue)
{
UBYTE player;
BOOL bReady;
@ -1662,7 +1663,7 @@ BOOL recvReadyRequest()
return true;
}
NETbeginDecode(NET_READY_REQUEST);
NETbeginDecode(queue, NET_READY_REQUEST);
NETuint8_t(&player);
NETbool(&bReady);
NETend();
@ -1670,7 +1671,7 @@ BOOL recvReadyRequest()
if (player > MAX_PLAYERS)
{
debug(LOG_ERROR, "Invalid NET_READY_REQUEST from player %d: player id = %d",
NETgetSource(), (int)player);
queue.index, (int)player);
return false;
}
@ -1766,7 +1767,7 @@ static BOOL SendColourRequest(UBYTE player, UBYTE col)
else
{
// clients tell the host which color they want
NETbeginEncode(NET_COLOURREQUEST, NET_HOST_ONLY);
NETbeginEncode(NETnetQueue(NET_HOST_ONLY), NET_COLOURREQUEST);
NETuint8_t(&player);
NETuint8_t(&col);
NETend();
@ -1784,7 +1785,7 @@ static BOOL SendPositionRequest(UBYTE player, UBYTE position)
{
debug(LOG_NET, "Requesting the host to change our position. From %d to %d", player, position);
// clients tell the host which position they want
NETbeginEncode(NET_POSITIONREQUEST, NET_HOST_ONLY);
NETbeginEncode(NETnetQueue(NET_HOST_ONLY), NET_POSITIONREQUEST);
NETuint8_t(&player);
NETuint8_t(&position);
NETend();
@ -1792,7 +1793,7 @@ static BOOL SendPositionRequest(UBYTE player, UBYTE position)
return true;
}
BOOL recvColourRequest()
BOOL recvColourRequest(NETQUEUE queue)
{
UBYTE player, col;
@ -1801,7 +1802,7 @@ BOOL recvColourRequest()
return true;
}
NETbeginDecode(NET_COLOURREQUEST);
NETbeginDecode(queue, NET_COLOURREQUEST);
NETuint8_t(&player);
NETuint8_t(&col);
NETend();
@ -1809,7 +1810,7 @@ BOOL recvColourRequest()
if (player > MAX_PLAYERS)
{
debug(LOG_ERROR, "Invalid NET_COLOURREQUEST from player %d: Tried to change player %d to colour %d",
NETgetSource(), (int)player, (int)col);
queue.index, (int)player, (int)col);
return false;
}
@ -1818,7 +1819,7 @@ BOOL recvColourRequest()
return changeColour(player, col);
}
BOOL recvPositionRequest()
BOOL recvPositionRequest(NETQUEUE queue)
{
UBYTE player, position;
@ -1827,7 +1828,7 @@ BOOL recvPositionRequest()
return true;
}
NETbeginDecode(NET_POSITIONREQUEST);
NETbeginDecode(queue, NET_POSITIONREQUEST);
NETuint8_t(&player);
NETuint8_t(&position);
NETend();
@ -1835,7 +1836,7 @@ BOOL recvPositionRequest()
if (player > MAX_PLAYERS || position > MAX_PLAYERS)
{
debug(LOG_ERROR, "Invalid NET_POSITIONREQUEST from player %d: Tried to change player %d to %d",
NETgetSource(), (int)player, (int)position);
queue.index, (int)player, (int)position);
return false;
}
@ -2152,7 +2153,7 @@ UDWORD addPlayerBox(BOOL players)
*/
static void SendFireUp(void)
{
NETbeginEncode(NET_FIREUP, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_FIREUP);
// no payload necessary
NETend();
}
@ -2161,7 +2162,7 @@ static void SendFireUp(void)
void kickPlayer(uint32_t player_id, const char *reason, LOBBY_ERROR_TYPES type)
{
// send a kick msg
NETbeginEncode(NET_KICK, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_KICK);
NETuint32_t(&player_id);
NETstring( (char *) reason, MAX_KICK_REASON);
NETenum(&type);
@ -2293,7 +2294,7 @@ static void stopJoining(void)
{
// annouce we are leaving...
debug(LOG_NET, "Host is quitting game...");
NETbeginEncode(NET_HOST_DROPPED, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_HOST_DROPPED);
NETend();
sendLeavingMsg(); // say goodbye
NETclose(); // quit running game.
@ -2883,20 +2884,21 @@ void startMultiplayerGame(void)
void frontendMultiMessages(void)
{
NETQUEUE queue;
uint8_t type;
while(NETrecv(&type))
while (NETrecvNet(&queue, &type))
{
// Copy the message to the global one used by the new NET API
switch(type)
{
case NET_FILE_REQUESTED:
recvMapFileRequested();
recvMapFileRequested(queue);
break;
case NET_FILE_PAYLOAD:
widgSetButtonState(psWScreen, MULTIOP_MAP_BUT, 1); // turn preview button off
if (recvMapFileData())
if (recvMapFileData(queue))
{
widgSetButtonState(psWScreen, MULTIOP_MAP_BUT, 0); // turn it back on again
}
@ -2907,7 +2909,7 @@ void frontendMultiMessages(void)
uint32_t reason;
uint32_t victim;
NETbeginDecode(NET_FILE_CANCELLED);
NETbeginDecode(queue, NET_FILE_CANCELLED);
NETuint32_t(&victim);
NETuint32_t(&reason);
NETend();
@ -2931,7 +2933,7 @@ void frontendMultiMessages(void)
break;
case NET_OPTIONS: // incoming options file.
recvOptions();
recvOptions(queue);
ingame.localOptionsReceived = true;
if(titleMode == MULTIOPTION)
@ -2943,23 +2945,23 @@ void frontendMultiMessages(void)
break;
case NET_ALLIANCE:
recvAlliance(false);
recvAlliance(queue, false);
break;
case NET_COLOURREQUEST:
recvColourRequest();
recvColourRequest(queue);
break;
case NET_POSITIONREQUEST:
recvPositionRequest();
recvPositionRequest(queue);
break;
case NET_TEAMREQUEST:
recvTeamRequest();
recvTeamRequest(queue);
break;
case NET_READY_REQUEST:
recvReadyRequest();
recvReadyRequest(queue);
// if hosting try to start the game if everyone is ready
if(NetPlay.isHost && multiplayPlayersReady(false))
@ -2969,7 +2971,7 @@ void frontendMultiMessages(void)
break;
case NET_PING: // diagnostic ping msg.
recvPing();
recvPing(queue);
break;
case NET_PLAYER_DROPPED: // remote player got disconnected
@ -2979,7 +2981,7 @@ void frontendMultiMessages(void)
resetReadyStatus(false);
NETbeginDecode(NET_PLAYER_DROPPED);
NETbeginDecode(queue, NET_PLAYER_DROPPED);
{
NETuint32_t(&player_id);
NETbool(&host);
@ -3002,7 +3004,7 @@ void frontendMultiMessages(void)
resetReadyStatus(false);
NETbeginDecode(NET_PLAYERRESPONDING);
NETbeginDecode(queue, NET_PLAYERRESPONDING);
// the player that has just responded
NETuint32_t(&player_id);
NETend();
@ -3037,7 +3039,7 @@ void frontendMultiMessages(void)
char reason[MAX_KICK_REASON];
LOBBY_ERROR_TYPES KICK_TYPE = ERROR_NOERROR;
NETbeginDecode(NET_KICK);
NETbeginDecode(queue, NET_KICK);
NETuint32_t(&player_id);
NETstring( reason, MAX_KICK_REASON);
NETenum(&KICK_TYPE);
@ -3060,7 +3062,7 @@ void frontendMultiMessages(void)
break;
}
case NET_HOST_DROPPED:
NETbeginDecode(NET_HOST_DROPPED);
NETbeginDecode(queue, NET_HOST_DROPPED);
NETend();
stopJoining();
debug(LOG_NET, "The host has quit!");
@ -3070,7 +3072,7 @@ void frontendMultiMessages(void)
case NET_TEXTMSG: // Chat message
if(ingame.localOptionsReceived)
{
recvTextMessage();
recvTextMessage(queue);
}
break;
}

View File

@ -278,7 +278,7 @@ bool sendDataCheck(void)
int i = 0;
uint32_t player = selectedPlayer;
NETbeginEncode(NET_DATA_CHECK, NET_HOST_ONLY); // only need to send to HOST
NETbeginEncode(NETnetQueue(NET_HOST_ONLY), NET_DATA_CHECK); // only need to send to HOST
for(i = 0; i < DATA_MAXDATA; i++)
{
NETuint32_t(&DataHash[i]);
@ -289,13 +289,13 @@ bool sendDataCheck(void)
return true;
}
bool recvDataCheck(void)
bool recvDataCheck(NETQUEUE queue)
{
int i = 0;
uint32_t player;
uint32_t tempBuffer[DATA_MAXDATA] = {0};
NETbeginDecode(NET_DATA_CHECK);
NETbeginDecode(queue, NET_DATA_CHECK);
for(i = 0; i < DATA_MAXDATA; i++)
{
NETuint32_t(&tempBuffer[i]);

View File

@ -46,7 +46,7 @@ typedef struct {
extern DROIDSTORE *tempDroidList;
extern void ShowMOTD(void);
extern bool recvDataCheck(void);
extern bool recvDataCheck(NETQUEUE queue);
extern bool sendDataCheck(void);
#ifdef __cplusplus

View File

@ -68,7 +68,7 @@ void sendOptions()
{
unsigned int i;
NETbeginEncode(NET_OPTIONS, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_OPTIONS);
// First send information about the game
NETuint8_t(&game.type);
@ -137,11 +137,11 @@ static BOOL checkGameWdg(const char *nm)
// ////////////////////////////////////////////////////////////////////////////
// options for a game. (usually recvd in frontend)
void recvOptions()
void recvOptions(NETQUEUE queue)
{
unsigned int i;
NETbeginDecode(NET_OPTIONS);
NETbeginDecode(queue, NET_OPTIONS);
// Get general information about the game
NETuint8_t(&game.type);
@ -221,7 +221,7 @@ void recvOptions()
debug(LOG_NET, "Map was not found, requesting map %s from host.", game.map);
// Request the map from the host
NETbeginEncode(NET_FILE_REQUESTED, NET_HOST_ONLY);
NETbeginEncode(NETnetQueue(NET_HOST_ONLY), NET_FILE_REQUESTED);
NETuint32_t(&player);
NETend();
@ -312,7 +312,7 @@ BOOL joinCampaign(UDWORD gameNumber, char *sPlayer)
BOOL sendLeavingMsg(void)
{
debug(LOG_NET, "We are leaving 'nicely'");
NETbeginEncode(NET_PLAYER_LEAVING, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_PLAYER_LEAVING);
{
BOOL host = NetPlay.isHost;
uint32_t id = selectedPlayer;
@ -518,6 +518,12 @@ static BOOL gameInit(void)
{
UDWORD player;
// Setup game queues.
for (player = 0; player < MAX_PLAYERS; ++player)
{
NETinitQueue(NETgameQueue(player));
}
scriptInit();
// If this is from a savegame, stop here!
@ -575,7 +581,7 @@ void playerResponding(void)
cameraToHome(selectedPlayer, false);
// Tell the world we're here
NETbeginEncode(NET_PLAYERRESPONDING, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_PLAYERRESPONDING);
NETuint32_t(&selectedPlayer);
NETend();
}

View File

@ -107,9 +107,9 @@ extern PLAYER_RESEARCH* asPlayerResList[MAX_PLAYERS];
// ////////////////////////////////////////////////////////////////////////////
// Local Prototypes
static BOOL recvBeacon(void);
static BOOL recvDestroyTemplate(void);
static BOOL recvResearch(void);
static BOOL recvBeacon(NETQUEUE queue);
static BOOL recvDestroyTemplate(NETQUEUE queue);
static BOOL recvResearch(NETQUEUE queue);
bool multiplayPlayersReady (bool bNotifyStatus);
void startMultiplayerGame (void);
@ -582,9 +582,11 @@ Vector3i cameraToHome(UDWORD player,BOOL scroll)
// Recv Messages. Get a message and dispatch to relevant function.
BOOL recvMessage(void)
{
NETQUEUE queue;
uint8_t type;
while(NETrecv(&type)) // for all incoming messages.
// TODO Figure out which messages belong in the game queues, and which are net related.
while(NETrecvNet(&queue, &type) || NETrecvGame(&queue, &type)) // for all incoming messages.
{
// messages only in game.
if(!ingame.localJoiningInProgress)
@ -592,72 +594,72 @@ BOOL recvMessage(void)
switch(type)
{
case NET_DROID: // new droid of known type
recvDroid();
recvDroid(queue);
break;
case NET_DROIDINFO: //droid update info
recvDroidInfo();
recvDroidInfo(queue);
break;
case NET_DROIDDEST: // droid destroy
recvDestroyDroid();
recvDestroyDroid(queue);
break;
case NET_DROIDMOVE: // move a droid to x,y command.
recvDroidMove();
recvDroidMove(queue);
break;
case NET_GROUPORDER: // an order for more than 1 droid.
recvGroupOrder();
recvGroupOrder(queue);
break;
case NET_CHECK_DROID: // droid damage and position checks
recvDroidCheck();
recvDroidCheck(queue);
break;
case NET_CHECK_STRUCT: // structure damage checks.
recvStructureCheck();
recvStructureCheck(queue);
break;
case NET_CHECK_POWER: // Power level syncing.
recvPowerCheck();
recvPowerCheck(queue);
break;
case NET_TEXTMSG: // simple text message
recvTextMessage();
recvTextMessage(queue);
break;
case NET_DATA_CHECK:
recvDataCheck();
recvDataCheck(queue);
break;
case NET_AITEXTMSG: //multiplayer AI text message
recvTextMessageAI();
recvTextMessageAI(queue);
break;
case NET_BEACONMSG: //beacon (blip) message
recvBeacon();
recvBeacon(queue);
break;
case NET_BUILD: // a build order has been sent.
recvBuildStarted();
recvBuildStarted(queue);
break;
case NET_BUILDFINISHED: // a building is complete
recvBuildFinished();
recvBuildFinished(queue);
break;
case NET_STRUCTDEST: // structure destroy
recvDestroyStructure();
recvDestroyStructure(queue);
break;
case NET_SECONDARY: // set a droids secondary order level.
recvDroidSecondary();
recvDroidSecondary(queue);
break;
case NET_SECONDARY_ALL: // set a droids secondary order level.
recvDroidSecondaryAll();
recvDroidSecondaryAll(queue);
break;
case NET_DROIDEMBARK:
recvDroidEmbark(); //droid has embarked on a Transporter
recvDroidEmbark(queue); //droid has embarked on a Transporter
break;
case NET_DROIDDISEMBARK:
recvDroidDisEmbark(); //droid has disembarked from a Transporter
recvDroidDisEmbark(queue); //droid has disembarked from a Transporter
break;
case NET_GIFT: // an alliance gift from one player to another.
recvGift();
recvGift(queue);
break;
case NET_SCORESUBMIT: // a score update from another player [UNUSED] see NET_PLAYER_STATS
break;
case NET_VTOL:
recvHappyVtol();
recvHappyVtol(queue);
break;
case NET_LASSAT:
recvLasSat();
recvLasSat(queue);
break;
default:
break;
@ -668,25 +670,25 @@ BOOL recvMessage(void)
switch(type)
{
case NET_TEMPLATE: // new template
recvTemplate();
recvTemplate(queue);
break;
case NET_TEMPLATEDEST: // template destroy
recvDestroyTemplate();
recvDestroyTemplate(queue);
break;
case NET_FEATUREDEST: // feature destroy
recvDestroyFeature();
recvDestroyFeature(queue);
break;
case NET_PING: // diagnostic ping msg.
recvPing();
recvPing(queue);
break;
case NET_DEMOLISH: // structure demolished.
recvDemolishFinished();
recvDemolishFinished(queue);
break;
case NET_RESEARCH: // some research has been done.
recvResearch();
recvResearch(queue);
break;
case NET_OPTIONS:
recvOptions();
recvOptions(queue);
break;
case NET_PLAYERRESPONDING: // remote player is now playing
{
@ -694,7 +696,7 @@ BOOL recvMessage(void)
resetReadyStatus(false);
NETbeginDecode(NET_PLAYERRESPONDING);
NETbeginDecode(queue, NET_PLAYERRESPONDING);
// the player that has just responded
NETuint32_t(&player_id);
NETend();
@ -709,16 +711,16 @@ BOOL recvMessage(void)
}
// FIXME: the next 4 cases might not belong here --check (we got two loops for this)
case NET_COLOURREQUEST:
recvColourRequest();
recvColourRequest(queue);
break;
case NET_POSITIONREQUEST:
recvPositionRequest();
recvPositionRequest(queue);
break;
case NET_TEAMREQUEST:
recvTeamRequest();
recvTeamRequest(queue);
break;
case NET_READY_REQUEST:
recvReadyRequest();
recvReadyRequest(queue);
// if hosting try to start the game if everyone is ready
if(NetPlay.isHost && multiplayPlayersReady(false))
@ -727,13 +729,13 @@ BOOL recvMessage(void)
}
break;
case NET_ARTIFACTS:
recvMultiPlayerRandomArtifacts();
recvMultiPlayerRandomArtifacts(queue);
break;
case NET_FEATURES:
recvMultiPlayerFeature();
recvMultiPlayerFeature(queue);
break;
case NET_ALLIANCE:
recvAlliance(true);
recvAlliance(queue, true);
break;
case NET_KICK:
{
@ -741,7 +743,7 @@ BOOL recvMessage(void)
uint32_t player_id;
char reason[MAX_KICK_REASON];
NETbeginDecode(NET_KICK);
NETbeginDecode(queue, NET_KICK);
NETuint32_t(&player_id);
NETstring( reason, MAX_KICK_REASON);
NETend();
@ -761,10 +763,10 @@ BOOL recvMessage(void)
debug(LOG_NET, "NET_FIREUP was received (frontend only?)");
break;
case NET_RESEARCHSTATUS:
recvResearchStatus();
recvResearchStatus(queue);
break;
case NET_PLAYER_STATS:
recvMultiStats();
recvMultiStats(queue);
break;
default:
break;
@ -783,7 +785,7 @@ BOOL SendResearch(uint8_t player, uint32_t index, bool trigger)
PLAYER_RESEARCH *pPlayerRes;
// Send the player that is researching the topic and the topic itself
NETbeginEncode(NET_RESEARCH, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_RESEARCH);
NETuint8_t(&player);
NETuint32_t(&index);
NETend();
@ -816,7 +818,7 @@ BOOL SendResearch(uint8_t player, uint32_t index, bool trigger)
}
// recv a research topic that is now complete.
static BOOL recvResearch()
static BOOL recvResearch(NETQUEUE queue)
{
uint8_t player;
uint32_t index;
@ -824,7 +826,7 @@ static BOOL recvResearch()
PLAYER_RESEARCH *pPlayerRes;
RESEARCH *pResearch;
NETbeginDecode(NET_RESEARCH);
NETbeginDecode(queue, NET_RESEARCH);
NETuint8_t(&player);
NETuint32_t(&index);
NETend();
@ -880,7 +882,7 @@ BOOL sendReseachStatus(STRUCTURE *psBuilding, uint32_t index, uint8_t player, BO
return true;
}
NETbeginEncode(NET_RESEARCHSTATUS, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_RESEARCHSTATUS);
NETuint8_t(&player);
NETbool(&bStart);
@ -901,7 +903,7 @@ BOOL sendReseachStatus(STRUCTURE *psBuilding, uint32_t index, uint8_t player, BO
return true;
}
BOOL recvResearchStatus()
BOOL recvResearchStatus(NETQUEUE queue)
{
STRUCTURE *psBuilding;
PLAYER_RESEARCH *pPlayerRes;
@ -911,7 +913,7 @@ BOOL recvResearchStatus()
BOOL bStart;
uint32_t index, structRef;
NETbeginDecode(NET_RESEARCHSTATUS);
NETbeginDecode(queue, NET_RESEARCHSTATUS);
NETuint8_t(&player);
NETbool(&bStart);
NETuint32_t(&structRef);
@ -1099,7 +1101,7 @@ BOOL sendTextMessage(const char *pStr, BOOL all)
if (all) //broadcast
{
NETbeginEncode(NET_TEXTMSG, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_TEXTMSG);
NETuint32_t(&selectedPlayer); // who this msg is from
NETstring(msg,MAX_CONSOLE_STRING_LENGTH); // the message to send
NETend();
@ -1112,7 +1114,7 @@ BOOL sendTextMessage(const char *pStr, BOOL all)
{
if (isHumanPlayer(i))
{
NETbeginEncode(NET_TEXTMSG, i);
NETbeginEncode(NETnetQueue(i), NET_TEXTMSG);
NETuint32_t(&selectedPlayer); // who this msg is from
NETstring(msg,MAX_CONSOLE_STRING_LENGTH); // the message to send
NETend();
@ -1132,7 +1134,7 @@ BOOL sendTextMessage(const char *pStr, BOOL all)
{
if (isHumanPlayer(i))
{
NETbeginEncode(NET_TEXTMSG, i);
NETbeginEncode(NETnetQueue(i), NET_TEXTMSG);
NETuint32_t(&selectedPlayer); // who this msg is from
NETstring(display, MAX_CONSOLE_STRING_LENGTH); // the message to send
NETend();
@ -1198,7 +1200,7 @@ BOOL sendAIMessage(char *pStr, UDWORD player, UDWORD to)
}
//send to the player who is hosting 'to' player (might be himself if human and not AI)
NETbeginEncode(NET_AITEXTMSG, sendPlayer);
NETbeginEncode(NETnetQueue(sendPlayer), NET_AITEXTMSG);
NETuint32_t(&player); //save the actual sender
//save the actual player that is to get this msg on the source machine (source can host many AIs)
NETuint32_t(&to); //save the actual receiver (might not be the same as the one we are actually sending to, in case of AIs)
@ -1227,8 +1229,8 @@ BOOL sendBeacon(int32_t locX, int32_t locY, int32_t forPlayer, int32_t sender, c
}
// I assume this is correct, looks like it sends it to ONLY that person, and the routine
// kf_AddHelpBlip() itterates for each player it needs.
NETbeginEncode(NET_BEACONMSG, sendPlayer); // send to the player who is hosting 'to' player (might be himself if human and not AI)
// kf_AddHelpBlip() iterates for each player it needs.
NETbeginEncode(NETnetQueue(sendPlayer), NET_BEACONMSG); // send to the player who is hosting 'to' player (might be himself if human and not AI)
NETint32_t(&sender); // save the actual sender
// save the actual player that is to get this msg on the source machine (source can host many AIs)
@ -1258,7 +1260,7 @@ void displayAIMessage(char *pStr, SDWORD from, SDWORD to)
}
// Write a message to the console.
BOOL recvTextMessage()
BOOL recvTextMessage(NETQUEUE queue)
{
UDWORD playerIndex;
char msg[MAX_CONSOLE_STRING_LENGTH];
@ -1267,7 +1269,7 @@ BOOL recvTextMessage()
memset(msg, 0x0, sizeof(msg));
memset(newmsg, 0x0, sizeof(newmsg));
NETbeginDecode(NET_TEXTMSG);
NETbeginDecode(queue, NET_TEXTMSG);
// Who this msg is from
NETuint32_t(&playerIndex);
// The message to send
@ -1309,13 +1311,13 @@ BOOL recvTextMessage()
}
//AI multiplayer message - received message from AI (from scripts)
BOOL recvTextMessageAI()
BOOL recvTextMessageAI(NETQUEUE queue)
{
UDWORD sender, receiver;
char msg[MAX_CONSOLE_STRING_LENGTH];
char newmsg[MAX_CONSOLE_STRING_LENGTH];
NETbeginDecode(NET_AITEXTMSG);
NETbeginDecode(queue, NET_AITEXTMSG);
NETuint32_t(&sender); //in-game player index ('normal' one)
NETuint32_t(&receiver); //in-game player index
NETstring(newmsg,MAX_CONSOLE_STRING_LENGTH);
@ -1352,7 +1354,7 @@ BOOL sendTemplate(DROID_TEMPLATE *pTempl)
ASSERT(pTempl != NULL, "sendTemplate: Old Pumpkin bug");
if (!pTempl) return true; /* hack */
NETbeginEncode(NET_TEMPLATE, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_TEMPLATE);
NETuint8_t(&player);
NETuint32_t(&pTempl->ref);
NETstring(pTempl->aName, sizeof(pTempl->aName));
@ -1381,14 +1383,14 @@ BOOL sendTemplate(DROID_TEMPLATE *pTempl)
}
// receive a template created by another player
BOOL recvTemplate()
BOOL recvTemplate(NETQUEUE queue)
{
uint8_t player;
DROID_TEMPLATE *psTempl;
DROID_TEMPLATE t, *pT = &t;
int i;
NETbeginDecode(NET_TEMPLATE);
NETbeginDecode(queue, NET_TEMPLATE);
NETuint8_t(&player);
ASSERT(player < MAX_PLAYERS, "recvtemplate: invalid player size: %d", player);
@ -1447,7 +1449,7 @@ BOOL SendDestroyTemplate(DROID_TEMPLATE *t)
{
uint8_t player = selectedPlayer;
NETbeginEncode(NET_TEMPLATEDEST, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_TEMPLATEDEST);
NETuint8_t(&player);
NETuint32_t(&t->multiPlayerID);
NETend();
@ -1456,13 +1458,13 @@ BOOL SendDestroyTemplate(DROID_TEMPLATE *t)
}
// acknowledge another player no longer has a template
static BOOL recvDestroyTemplate()
static BOOL recvDestroyTemplate(NETQUEUE queue)
{
uint8_t player;
uint32_t templateID;
DROID_TEMPLATE *psTempl, *psTempPrev = NULL;
NETbeginDecode(NET_TEMPLATEDEST);
NETbeginDecode(queue, NET_TEMPLATEDEST);
NETuint8_t(&player);
NETuint32_t(&templateID);
NETend();
@ -1506,18 +1508,18 @@ static BOOL recvDestroyTemplate()
// send a destruct feature message.
BOOL SendDestroyFeature(FEATURE *pF)
{
NETbeginEncode(NET_FEATUREDEST, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_FEATUREDEST);
NETuint32_t(&pF->id);
return NETend();
}
// process a destroy feature msg.
BOOL recvDestroyFeature()
BOOL recvDestroyFeature(NETQUEUE queue)
{
FEATURE *pF;
uint32_t id;
NETbeginDecode(NET_FEATUREDEST);
NETbeginDecode(queue, NET_FEATUREDEST);
NETuint32_t(&id);
NETend();
@ -1539,7 +1541,7 @@ BOOL recvDestroyFeature()
// ////////////////////////////////////////////////////////////////////////////
// Network File packet processor.
BOOL recvMapFileRequested()
BOOL recvMapFileRequested(NETQUEUE queue)
{
char mapStr[256],mapName[256],fixedname[256];
uint32_t player;
@ -1554,7 +1556,7 @@ BOOL recvMapFileRequested()
}
// Check to see who wants the file
NETbeginDecode(NET_FILE_REQUESTED);
NETbeginDecode(queue, NET_FILE_REQUESTED);
NETuint32_t(&player);
NETend();
@ -1599,7 +1601,7 @@ BOOL recvMapFileRequested()
// NOTE: if we get here, then the game is basically over, The host can't send the file for whatever reason...
// Which also means, that we can't continue.
debug(LOG_NET, "***Host has a file issue, and is being forced to quit!***");
NETbeginEncode(NET_HOST_DROPPED, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_HOST_DROPPED);
NETend();
abort();
}
@ -1640,9 +1642,9 @@ void sendMap(void)
}
// Another player is broadcasting a map, recv a chunk. Returns false if not yet done.
BOOL recvMapFileData()
BOOL recvMapFileData(NETQUEUE queue)
{
mapDownloadProgress = NETrecvFile();
mapDownloadProgress = NETrecvFile(queue);
if (mapDownloadProgress == 100)
{
addConsoleMessage("MAP DOWNLOADED!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
@ -1915,12 +1917,12 @@ BOOL msgStackFireTop(void)
return true;
}
static BOOL recvBeacon(void)
static BOOL recvBeacon(NETQUEUE queue)
{
int32_t sender, receiver,locX, locY;
char msg[MAX_CONSOLE_STRING_LENGTH];
NETbeginDecode(NET_BEACONMSG);
NETbeginDecode(queue, NET_BEACONMSG);
NETint32_t(&sender); // the actual sender
NETint32_t(&receiver); // the actual receiver (might not be the same as the one we are actually sending to, in case of AIs)
NETint32_t(&locX);

View File

@ -32,43 +32,43 @@ extern "C"
{
#endif //__cplusplus
extern BOOL recvDroid (void);
extern BOOL recvDroidInfo (void);
extern BOOL recvDestroyDroid (void);
extern BOOL recvGroupOrder (void);
extern BOOL recvDroidMove (void);
extern BOOL recvDestroyStructure (void);
extern BOOL recvBuildStarted (void);
extern BOOL recvBuildFinished (void);
extern BOOL recvTemplate (void);
extern BOOL recvDestroyFeature (void);
extern BOOL recvDemolishFinished (void);
extern BOOL recvPing (void);
extern BOOL recvRequestDroid (void);
extern BOOL recvTextMessage (void);
extern BOOL recvDroidSecondary (void);
extern BOOL recvDroidSecondaryAll (void);
extern BOOL recvDroidEmbark (void);
extern BOOL recvDroidDisEmbark (void);
extern BOOL recvDroidCheck (void);
extern BOOL recvStructureCheck (void);
extern BOOL recvPowerCheck (void);
extern BOOL recvAlliance (BOOL allowAudio);
extern BOOL recvColourRequest (void);
extern BOOL recvPositionRequest (void);
extern void recvOptions (void);
extern void sendOptions (void);
extern BOOL recvDroid (NETQUEUE queue);
extern BOOL recvDroidInfo (NETQUEUE queue);
extern BOOL recvDestroyDroid (NETQUEUE queue);
extern BOOL recvGroupOrder (NETQUEUE queue);
extern BOOL recvDroidMove (NETQUEUE queue);
extern BOOL recvDestroyStructure (NETQUEUE queue);
extern BOOL recvBuildStarted (NETQUEUE queue);
extern BOOL recvBuildFinished (NETQUEUE queue);
extern BOOL recvTemplate (NETQUEUE queue);
extern BOOL recvDestroyFeature (NETQUEUE queue);
extern BOOL recvDemolishFinished (NETQUEUE queue);
extern BOOL recvPing (NETQUEUE queue);
extern BOOL recvRequestDroid (NETQUEUE queue);
extern BOOL recvTextMessage (NETQUEUE queue);
extern BOOL recvDroidSecondary (NETQUEUE queue);
extern BOOL recvDroidSecondaryAll (NETQUEUE queue);
extern BOOL recvDroidEmbark (NETQUEUE queue);
extern BOOL recvDroidDisEmbark (NETQUEUE queue);
extern BOOL recvDroidCheck (NETQUEUE queue);
extern BOOL recvStructureCheck (NETQUEUE queue);
extern BOOL recvPowerCheck (NETQUEUE queue);
//extern BOOL recvAlliance (NETQUEUE queue, BOOL allowAudio); // Was declared in multigifts.h, too.
extern BOOL recvColourRequest (NETQUEUE queue);
extern BOOL recvPositionRequest (NETQUEUE queue);
extern void recvOptions (NETQUEUE queue);
extern void sendOptions (void);
extern BOOL recvHappyVtol (void);
extern BOOL recvResearchStatus (void);
extern BOOL recvLasSat (void);
extern BOOL recvMapFileData (void);
extern BOOL recvMapFileRequested (void);
extern BOOL recvHappyVtol (NETQUEUE queue);
extern BOOL recvResearchStatus (NETQUEUE queue);
extern BOOL recvLasSat (NETQUEUE queue);
extern BOOL recvMapFileData (NETQUEUE queue);
extern BOOL recvMapFileRequested (NETQUEUE queue);
extern BOOL recvTextMessageAI (void); //AI multiplayer message
extern BOOL recvTeamRequest (void);
extern BOOL recvReadyRequest (void);
extern BOOL recvTextMessageAI (NETQUEUE queue); //AI multiplayer message
extern BOOL recvTeamRequest (NETQUEUE queue);
extern BOOL recvReadyRequest (NETQUEUE queue);
#ifdef __cplusplus
}

View File

@ -73,7 +73,7 @@ BOOL setMultiStats(SDWORD player, PLAYERSTATS plStats, BOOL bLocal)
if (!bLocal)
{
// Now send it to all other players
NETbeginEncode(NET_PLAYER_STATS, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_PLAYER_STATS);
// Send the ID of the player's stats we're updating
NETuint32_t(&playerIndex);
@ -93,11 +93,11 @@ BOOL setMultiStats(SDWORD player, PLAYERSTATS plStats, BOOL bLocal)
return true;
}
void recvMultiStats()
void recvMultiStats(NETQUEUE queue)
{
uint32_t playerIndex;
NETbeginDecode(NET_PLAYER_STATS);
NETbeginDecode(queue, NET_PLAYER_STATS);
// Retrieve the ID number of the player for which we need to
// update the stats
NETuint32_t(&playerIndex);

View File

@ -25,6 +25,8 @@
#ifndef __INCLUDED_SRC_MULTISTATS_H__
#define __INCLUDED_SRC_MULTISTATS_H__
#include "lib/netplay/netplay.h"
#ifdef __cplusplus
extern "C"
{
@ -56,7 +58,7 @@ extern void updateMultiStatsWins (void);
extern void updateMultiStatsLoses (void);
extern void updateMultiStatsKills (BASE_OBJECT *psKilled,UDWORD player);
extern void recvMultiStats(void);
extern void recvMultiStats(NETQUEUE queue);
#ifdef __cplusplus
}

View File

@ -54,7 +54,7 @@
// INFORM others that a building has been started, and base plate should be put down.
BOOL sendBuildStarted(STRUCTURE *psStruct, DROID *psDroid)
{
NETbeginEncode(NET_BUILD, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_BUILD);
// Who is building it
NETuint8_t(&psDroid->player);
@ -94,7 +94,7 @@ BOOL sendBuildStarted(STRUCTURE *psStruct, DROID *psDroid)
// ////////////////////////////////////////////////////////////////////////////
// put down a base plate and start droid building it!
BOOL recvBuildStarted()
BOOL recvBuildStarted(NETQUEUE queue)
{
STRUCTURE_STATS *psStats;
DROID *psDroid;
@ -105,7 +105,7 @@ BOOL recvBuildStarted()
int32_t order;
uint32_t structRef, structId, targetId,droidID;
NETbeginDecode(NET_BUILD);
NETbeginDecode(queue, NET_BUILD);
NETuint8_t(&player);
NETuint32_t(&structRef);
NETuint16_t(&x);
@ -177,7 +177,7 @@ BOOL SendBuildFinished(STRUCTURE *psStruct)
uint8_t player = psStruct->player;
ASSERT( player < MAX_PLAYERS, "invalid player %u", player);
NETbeginEncode(NET_BUILDFINISHED, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_BUILDFINISHED);
NETuint32_t(&power); // send how much power we got.
NETuint32_t(&psStruct->id); // ID of building
@ -191,7 +191,7 @@ BOOL SendBuildFinished(STRUCTURE *psStruct)
}
// ////////////////////////////////////////////////////////////////////////////
BOOL recvBuildFinished()
BOOL recvBuildFinished(NETQUEUE queue)
{
uint32_t structId;
STRUCTURE *psStruct;
@ -200,7 +200,7 @@ BOOL recvBuildFinished()
uint8_t player;
uint32_t power;
NETbeginDecode(NET_BUILDFINISHED);
NETbeginDecode(queue, NET_BUILDFINISHED);
NETuint32_t(&power); // get the player's power level
NETuint32_t(&structId); // get the struct id.
NETuint32_t(&type); // Kind of building.
@ -278,7 +278,7 @@ BOOL recvBuildFinished()
// demolish message.
BOOL SendDemolishFinished(STRUCTURE *psStruct, DROID *psDroid)
{
NETbeginEncode(NET_DEMOLISH, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_DEMOLISH);
// Send what is being demolish and who is doing it
NETuint32_t(&psStruct->id);
@ -287,13 +287,13 @@ BOOL SendDemolishFinished(STRUCTURE *psStruct, DROID *psDroid)
return NETend();
}
BOOL recvDemolishFinished()
BOOL recvDemolishFinished(NETQUEUE queue)
{
STRUCTURE *psStruct;
DROID *psDroid;
uint32_t structID, droidID;
NETbeginDecode(NET_DEMOLISH);
NETbeginDecode(queue, NET_DEMOLISH);
NETuint32_t(&structID);
NETuint32_t(&droidID);
NETend();
@ -325,7 +325,7 @@ BOOL recvDemolishFinished()
BOOL SendDestroyStructure(STRUCTURE *s)
{
technologyGiveAway(s);
NETbeginEncode(NET_STRUCTDEST, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_STRUCTDEST);
// Struct to destroy
NETuint32_t(&s->id);
@ -335,12 +335,12 @@ BOOL SendDestroyStructure(STRUCTURE *s)
// ////////////////////////////////////////////////////////////////////////////
// acknowledge the destruction of a structure, from another player.
BOOL recvDestroyStructure()
BOOL recvDestroyStructure(NETQUEUE queue)
{
uint32_t structID;
STRUCTURE *psStruct;
NETbeginDecode(NET_STRUCTDEST);
NETbeginDecode(queue, NET_STRUCTDEST);
NETuint32_t(&structID);
NETend();
@ -365,7 +365,7 @@ BOOL recvDestroyStructure()
BOOL sendLasSat(UBYTE player, STRUCTURE *psStruct, BASE_OBJECT *psObj)
{
NETbeginEncode(NET_LASSAT, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_LASSAT);
NETuint8_t(&player);
NETuint32_t(&psStruct->id);
@ -376,14 +376,15 @@ BOOL sendLasSat(UBYTE player, STRUCTURE *psStruct, BASE_OBJECT *psObj)
}
// recv lassat info on the receiving end.
BOOL recvLasSat()
BOOL recvLasSat(NETQUEUE queue)
{
BASE_OBJECT *psObj;
UBYTE player,targetplayer;
STRUCTURE *psStruct;
uint32_t id,targetid;
NETbeginDecode(NET_LASSAT);
// TODO Add some kind of checking, so that things don't get lasatted by bunkers.
NETbeginDecode(queue, NET_LASSAT);
NETuint8_t(&player);
NETuint32_t(&id);
NETuint32_t(&targetid);

View File

@ -258,7 +258,7 @@ BOOL ForceDroidSync(const DROID* droidToSend)
debug(LOG_SYNC, "Force sync of droid %u from player %u", droidToSend->id, droidToSend->player);
NETbeginEncode(NET_CHECK_DROID, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_CHECK_DROID);
NETuint8_t(&count);
packageCheck(droidToSend);
return NETend();
@ -286,7 +286,7 @@ static BOOL sendDroidCheck(void)
lastSent = gameTime;
NETbeginEncode(NET_CHECK_DROID, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_CHECK_DROID);
// Allocate space for the list of droids to send
ppD = alloca(sizeof(DROID *) * toSend);
@ -378,12 +378,12 @@ static void packageCheck(const DROID* pD)
// ////////////////////////////////////////////////////////////////////////////
// receive a check and update the local world state accordingly
BOOL recvDroidCheck()
BOOL recvDroidCheck(NETQUEUE queue)
{
uint8_t count;
int i;
NETbeginDecode(NET_CHECK_DROID);
NETbeginDecode(queue, NET_CHECK_DROID);
// Get the number of droids to expect
NETuint8_t(&count);
@ -709,7 +709,7 @@ static BOOL sendStructureCheck(void)
// Only send info about complete buildings
if (pS && (pS->status == SS_BUILT))
{
NETbeginEncode(NET_CHECK_STRUCT, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_CHECK_STRUCT);
NETuint8_t(&pS->player);
NETuint32_t(&pS->id);
NETuint32_t(&pS->body);
@ -745,7 +745,7 @@ static BOOL sendStructureCheck(void)
}
// receive checking info about a structure and update local world state
BOOL recvStructureCheck()
BOOL recvStructureCheck(NETQUEUE queue)
{
STRUCTURE *pS;
STRUCTURE_STATS *psStats;
@ -757,7 +757,7 @@ BOOL recvStructureCheck()
uint16_t x, y, z;
uint32_t ref, type;
NETbeginDecode(NET_CHECK_STRUCT);
NETbeginDecode(queue, NET_CHECK_STRUCT);
NETuint8_t(&player);
NETuint32_t(&ref);
NETuint32_t(&body);
@ -934,18 +934,18 @@ static BOOL sendPowerCheck()
lastsent = gameTime;
NETbeginEncode(NET_CHECK_POWER, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_CHECK_POWER);
NETuint8_t(&player);
NETuint32_t(&power);
return NETend();
}
BOOL recvPowerCheck()
BOOL recvPowerCheck(NETQUEUE queue)
{
uint8_t player;
uint32_t power, power2;
NETbeginDecode(NET_CHECK_POWER);
NETbeginDecode(queue, NET_CHECK_POWER);
NETuint8_t(&player);
NETuint32_t(&power);
NETend();
@ -1098,7 +1098,7 @@ BOOL sendPing(void)
}
}
NETbeginEncode(NET_PING, NET_ALL_PLAYERS);
NETbeginEncode(NETbroadcastQueue(), NET_PING);
NETuint8_t(&player);
NETbool(&isNew);
NETend();
@ -1113,12 +1113,12 @@ BOOL sendPing(void)
}
// accept and process incoming ping messages.
BOOL recvPing()
BOOL recvPing(NETQUEUE queue)
{
BOOL isNew;
uint8_t sender, us = selectedPlayer;
NETbeginDecode(NET_PING);
NETbeginDecode(queue, NET_PING);
NETuint8_t(&sender);
NETbool(&isNew);
NETend();
@ -1132,7 +1132,7 @@ BOOL recvPing()
// If this is a new ping, respond to it
if (isNew)
{
NETbeginEncode(NET_PING, sender);
NETbeginEncode(NETnetQueue(sender), NET_PING);
// We are responding to a new ping
isNew = false;

View File

@ -6381,7 +6381,7 @@ BOOL electronicDamage(BASE_OBJECT *psTarget, UDWORD damage, UBYTE attackPlayer)
{
uint8_t giftType = DROID_GIFT, droid_count = 1;
NETbeginEncode(NET_GIFT, NET_ALL_PLAYERS);
NETbeginEncode(NETgameQueue(selectedPlayer), NET_GIFT);
{
// We need to distinguish between gift types
NETuint8_t(&giftType);