Remove GAME_SECONDARY in favour of GAME_DROIDINFO, which is sent more efficiently for multiple droids.
Instead of one message per droid, it sends one message for all droids, with the list of droids encoded as droid ID deltas.master
parent
31c6586f9c
commit
239eebec00
|
@ -168,9 +168,9 @@ unsigned NET_PlayerConnectionStatus[CONNECTIONSTATUS_NORMAL][MAX_PLAYERS];
|
||||||
** ie ("trunk", "2.1.3", "3.0", ...)
|
** ie ("trunk", "2.1.3", "3.0", ...)
|
||||||
************************************************************************************
|
************************************************************************************
|
||||||
**/
|
**/
|
||||||
char VersionString[VersionStringSize] = "master, netcode 4.1009";
|
char VersionString[VersionStringSize] = "master, netcode 4.1010";
|
||||||
static int NETCODE_VERSION_MAJOR = 4;
|
static int NETCODE_VERSION_MAJOR = 4;
|
||||||
static int NETCODE_VERSION_MINOR = 1009;
|
static int NETCODE_VERSION_MINOR = 1010;
|
||||||
|
|
||||||
bool NETisCorrectVersion(uint32_t game_version_major, uint32_t game_version_minor)
|
bool NETisCorrectVersion(uint32_t game_version_major, uint32_t game_version_minor)
|
||||||
{
|
{
|
||||||
|
@ -3267,7 +3267,6 @@ const char *messageTypeToString(unsigned messageType_)
|
||||||
case GAME_FEATUREDEST: return "GAME_FEATUREDEST";
|
case GAME_FEATUREDEST: return "GAME_FEATUREDEST";
|
||||||
case GAME_RESEARCH: return "GAME_RESEARCH";
|
case GAME_RESEARCH: return "GAME_RESEARCH";
|
||||||
case GAME_FEATURES: return "GAME_FEATURES";
|
case GAME_FEATURES: return "GAME_FEATURES";
|
||||||
case GAME_SECONDARY: return "GAME_SECONDARY";
|
|
||||||
case GAME_ALLIANCE: return "GAME_ALLIANCE";
|
case GAME_ALLIANCE: return "GAME_ALLIANCE";
|
||||||
case GAME_GIFT: return "GAME_GIFT";
|
case GAME_GIFT: return "GAME_GIFT";
|
||||||
case GAME_ARTIFACTS: return "GAME_ARTIFACTS";
|
case GAME_ARTIFACTS: return "GAME_ARTIFACTS";
|
||||||
|
|
|
@ -97,7 +97,6 @@ enum MESSAGE_TYPES
|
||||||
GAME_FEATUREDEST, ///< destroy a game feature.
|
GAME_FEATUREDEST, ///< destroy a game feature.
|
||||||
GAME_RESEARCH, ///< Research has been completed.
|
GAME_RESEARCH, ///< Research has been completed.
|
||||||
GAME_FEATURES, ///< information regarding features.
|
GAME_FEATURES, ///< information regarding features.
|
||||||
GAME_SECONDARY, ///< set a droids secondary order
|
|
||||||
GAME_ALLIANCE, ///< alliance data.
|
GAME_ALLIANCE, ///< alliance data.
|
||||||
GAME_GIFT, ///< a luvly gift between players.
|
GAME_GIFT, ///< a luvly gift between players.
|
||||||
GAME_ARTIFACTS, ///< artifacts randomly placed.
|
GAME_ARTIFACTS, ///< artifacts randomly placed.
|
||||||
|
|
253
src/multibot.cpp
253
src/multibot.cpp
|
@ -48,6 +48,11 @@
|
||||||
|
|
||||||
#define ANYPLAYER 99
|
#define ANYPLAYER 99
|
||||||
|
|
||||||
|
enum SubType
|
||||||
|
{
|
||||||
|
ObjOrder, LocOrder, SecondaryOrder
|
||||||
|
};
|
||||||
|
|
||||||
struct QueuedDroidInfo
|
struct QueuedDroidInfo
|
||||||
{
|
{
|
||||||
/// Sorts by order, then finally by droid id, to group multiple droids with the same order.
|
/// Sorts by order, then finally by droid id, to group multiple droids with the same order.
|
||||||
|
@ -61,46 +66,59 @@ struct QueuedDroidInfo
|
||||||
int orderCompare(QueuedDroidInfo const &z) const
|
int orderCompare(QueuedDroidInfo const &z) const
|
||||||
{
|
{
|
||||||
if (player != z.player) return player < z.player ? -1 : 1;
|
if (player != z.player) return player < z.player ? -1 : 1;
|
||||||
if (order != z.order) return order < z.order ? -1 : 1;
|
|
||||||
if (subType != z.subType) return subType < z.subType ? -1 : 1;
|
if (subType != z.subType) return subType < z.subType ? -1 : 1;
|
||||||
if (subType)
|
switch (subType)
|
||||||
{
|
{
|
||||||
if (destId != z.destId) return destId < z.destId ? -1 : 1;
|
case ObjOrder:
|
||||||
if (destType != z.destType) return destType < z.destType ? -1 : 1;
|
case LocOrder:
|
||||||
|
if (order != z.order) return order < z.order ? -1 : 1;
|
||||||
|
if (subType == ObjOrder)
|
||||||
|
{
|
||||||
|
if (destId != z.destId) return destId < z.destId ? -1 : 1;
|
||||||
|
if (destType != z.destType) return destType < z.destType ? -1 : 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x != z.x) return x < z.x ? -1 : 1;
|
||||||
|
if (y != z.y) return y < z.y ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (order == DORDER_BUILD || order == DORDER_LINEBUILD)
|
||||||
|
{
|
||||||
|
if (structRef != z.structRef) return structRef < z.structRef ? -1 : 1;
|
||||||
|
if (direction != z.direction) return direction < z.direction ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (order == DORDER_LINEBUILD)
|
||||||
|
{
|
||||||
|
if (x2 != z.x2) return x2 < z.x2 ? -1 : 1;
|
||||||
|
if (y2 != z.y2) return y2 < z.y2 ? -1 : 1;
|
||||||
|
}
|
||||||
|
if (add != z.add) return add < z.add ? -1 : 1;
|
||||||
|
break;
|
||||||
|
case SecondaryOrder:
|
||||||
|
if (secOrder != z.secOrder) return secOrder < z.secOrder ? -1 : 1;
|
||||||
|
if (secState != z.secState) return secState < z.secState ? -1 : 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (x != z.x) return x < z.x ? -1 : 1;
|
|
||||||
if (y != z.y) return y < z.y ? -1 : 1;
|
|
||||||
}
|
|
||||||
if (order == DORDER_BUILD || order == DORDER_LINEBUILD)
|
|
||||||
{
|
|
||||||
if (structRef != z.structRef) return structRef < z.structRef ? -1 : 1;
|
|
||||||
if (direction != z.direction) return direction < z.direction ? -1 : 1;
|
|
||||||
}
|
|
||||||
if (order == DORDER_LINEBUILD)
|
|
||||||
{
|
|
||||||
if (x2 != z.x2) return x2 < z.x2 ? -1 : 1;
|
|
||||||
if (y2 != z.y2) return y2 < z.y2 ? -1 : 1;
|
|
||||||
}
|
|
||||||
if (add != z.add) return add < z.add ? -1 : 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t player;
|
uint8_t player;
|
||||||
uint32_t droidId;
|
uint32_t droidId;
|
||||||
DROID_ORDER order;
|
SubType subType;
|
||||||
BOOL subType;
|
// subType == ObjOrder || subType == LocOrder
|
||||||
uint32_t destId; // if (subType)
|
DROID_ORDER order;
|
||||||
OBJECT_TYPE destType; // if (subType)
|
uint32_t destId; // if (subType == ObjOrder)
|
||||||
uint32_t x; // if (!subType)
|
OBJECT_TYPE destType; // if (subType == ObjOrder)
|
||||||
uint32_t y; // if (!subType)
|
uint32_t x; // if (subType == LocOrder)
|
||||||
uint32_t structRef; // if (order == DORDER_BUILD || order == DORDER_LINEBUILD)
|
uint32_t y; // if (subType == LocOrder)
|
||||||
uint16_t direction; // if (order == DORDER_BUILD || order == DORDER_LINEBUILD)
|
uint32_t structRef; // if (order == DORDER_BUILD || order == DORDER_LINEBUILD)
|
||||||
uint32_t x2; // if (order == DORDER_LINEBUILD)
|
uint16_t direction; // if (order == DORDER_BUILD || order == DORDER_LINEBUILD)
|
||||||
uint32_t y2; // if (order == DORDER_LINEBUILD)
|
uint32_t x2; // if (order == DORDER_LINEBUILD)
|
||||||
|
uint32_t y2; // if (order == DORDER_LINEBUILD)
|
||||||
BOOL add;
|
bool add;
|
||||||
|
// subType == SecondaryOrder
|
||||||
|
SECONDARY_ORDER secOrder;
|
||||||
|
SECONDARY_STATE secState;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<QueuedDroidInfo> queuedOrders;
|
static std::vector<QueuedDroidInfo> queuedOrders;
|
||||||
|
@ -128,50 +146,17 @@ BOOL sendDroidSecondary(const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STA
|
||||||
if (!bMultiMessages)
|
if (!bMultiMessages)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_SECONDARY);
|
QueuedDroidInfo info;
|
||||||
{
|
memset(&info, 0x00, sizeof(info)); // Suppress uninitialised warnings. (The uninitialised values in the queue would be ignored when reading the queue.)
|
||||||
uint8_t player = psDroid->player;
|
|
||||||
uint32_t droid = psDroid->id;
|
|
||||||
|
|
||||||
NETuint8_t(&player);
|
info.player = psDroid->player;
|
||||||
NETuint32_t(&droid);
|
info.droidId = psDroid->id;
|
||||||
NETenum(&sec);
|
info.subType = SecondaryOrder;
|
||||||
NETenum(&state);
|
info.secOrder = sec;
|
||||||
}
|
info.secState = state;
|
||||||
return NETend();
|
|
||||||
}
|
|
||||||
|
|
||||||
// recv
|
// Send later, grouped by order, so multiple droids with the same order can be encoded to much less data.
|
||||||
BOOL recvDroidSecondary(NETQUEUE queue)
|
queuedOrders.push_back(info);
|
||||||
{
|
|
||||||
DROID* psDroid;
|
|
||||||
SECONDARY_ORDER sec = DSO_ATTACK_RANGE;
|
|
||||||
SECONDARY_STATE state = DSS_NONE;
|
|
||||||
|
|
||||||
NETbeginDecode(queue, GAME_SECONDARY);
|
|
||||||
{
|
|
||||||
uint8_t player;
|
|
||||||
uint32_t droid;
|
|
||||||
|
|
||||||
NETuint8_t(&player);
|
|
||||||
NETuint32_t(&droid);
|
|
||||||
NETenum(&sec);
|
|
||||||
NETenum(&state);
|
|
||||||
|
|
||||||
// If we can not find the droid should we not ask for it?
|
|
||||||
psDroid = IdToDroid(droid, player);
|
|
||||||
if (!psDroid)
|
|
||||||
{
|
|
||||||
NETend();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NETend();
|
|
||||||
|
|
||||||
// Set the droids secondary order
|
|
||||||
turnOffMultiMsg(true);
|
|
||||||
secondarySetState(psDroid, sec, state);
|
|
||||||
turnOffMultiMsg(false);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -503,29 +488,39 @@ BOOL recvDroid(NETQUEUE queue)
|
||||||
static void NETQueuedDroidInfo(QueuedDroidInfo *info)
|
static void NETQueuedDroidInfo(QueuedDroidInfo *info)
|
||||||
{
|
{
|
||||||
NETuint8_t(&info->player);
|
NETuint8_t(&info->player);
|
||||||
NETenum(&info->order);
|
NETenum(&info->subType);
|
||||||
NETbool(&info->subType);
|
switch (info->subType)
|
||||||
if (info->subType)
|
|
||||||
{
|
{
|
||||||
NETuint32_t(&info->destId);
|
case ObjOrder:
|
||||||
NETenum(&info->destType);
|
case LocOrder:
|
||||||
|
NETenum(&info->order);
|
||||||
|
if (info->subType == ObjOrder)
|
||||||
|
{
|
||||||
|
NETuint32_t(&info->destId);
|
||||||
|
NETenum(&info->destType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NETuint32_t(&info->x);
|
||||||
|
NETuint32_t(&info->y);
|
||||||
|
}
|
||||||
|
if (info->order == DORDER_BUILD || info->order == DORDER_LINEBUILD)
|
||||||
|
{
|
||||||
|
NETuint32_t(&info->structRef);
|
||||||
|
NETuint16_t(&info->direction);
|
||||||
|
}
|
||||||
|
if (info->order == DORDER_LINEBUILD)
|
||||||
|
{
|
||||||
|
NETuint32_t(&info->x2);
|
||||||
|
NETuint32_t(&info->y2);
|
||||||
|
}
|
||||||
|
NETbool(&info->add);
|
||||||
|
break;
|
||||||
|
case SecondaryOrder:
|
||||||
|
NETenum(&info->secOrder);
|
||||||
|
NETenum(&info->secState);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
NETuint32_t(&info->x);
|
|
||||||
NETuint32_t(&info->y);
|
|
||||||
}
|
|
||||||
if (info->order == DORDER_BUILD || info->order == DORDER_LINEBUILD)
|
|
||||||
{
|
|
||||||
NETuint32_t(&info->structRef);
|
|
||||||
NETuint16_t(&info->direction);
|
|
||||||
}
|
|
||||||
if (info->order == DORDER_LINEBUILD)
|
|
||||||
{
|
|
||||||
NETuint32_t(&info->x2);
|
|
||||||
NETuint32_t(&info->y2);
|
|
||||||
}
|
|
||||||
NETbool(&info->add);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually send the droid info.
|
// Actually send the droid info.
|
||||||
|
@ -596,9 +591,9 @@ bool sendDroidInfo(DROID *psDroid, DROID_ORDER order, uint32_t x, uint32_t y, co
|
||||||
|
|
||||||
info.player = psDroid->player;
|
info.player = psDroid->player;
|
||||||
info.droidId = psDroid->id;
|
info.droidId = psDroid->id;
|
||||||
|
info.subType = psObj != NULL? ObjOrder : LocOrder;
|
||||||
info.order = order;
|
info.order = order;
|
||||||
info.subType = psObj != NULL;
|
if (info.subType == ObjOrder)
|
||||||
if (info.subType)
|
|
||||||
{
|
{
|
||||||
info.destId = psObj->id;
|
info.destId = psObj->id;
|
||||||
info.destType = psObj->type;
|
info.destType = psObj->type;
|
||||||
|
@ -646,7 +641,7 @@ BOOL recvDroidInfo(NETQUEUE queue)
|
||||||
NETQueuedDroidInfo(&info);
|
NETQueuedDroidInfo(&info);
|
||||||
|
|
||||||
STRUCTURE_STATS *psStats = NULL;
|
STRUCTURE_STATS *psStats = NULL;
|
||||||
if (info.order == DORDER_BUILD || info.order == DORDER_LINEBUILD)
|
if (info.subType == LocOrder && (info.order == DORDER_BUILD || info.order == DORDER_LINEBUILD))
|
||||||
{
|
{
|
||||||
// Find structure target
|
// Find structure target
|
||||||
for (unsigned typeIndex = 0; typeIndex < numStructureStats; typeIndex++)
|
for (unsigned typeIndex = 0; typeIndex < numStructureStats; typeIndex++)
|
||||||
|
@ -659,16 +654,14 @@ BOOL recvDroidInfo(NETQUEUE queue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.subType)
|
switch (info.subType)
|
||||||
{
|
{
|
||||||
syncDebug("Order=%s,%d(%d)", getDroidOrderName(info.order), info.destId, info.destType);
|
case ObjOrder: syncDebug("Order=%s,%d(%d)", getDroidOrderName(info.order), info.destId, info.destType); break;
|
||||||
}
|
case LocOrder: syncDebug("Order=%s,(%d,%d)", getDroidOrderName(info.order), info.x, info.y); break;
|
||||||
else
|
case SecondaryOrder: syncDebug("SecondaryOrder=%d,%08X", (int)info.secOrder, (int)info.secState); break;
|
||||||
{
|
|
||||||
syncDebug("Order=%s,(%d,%d)", getDroidOrderName(info.order), info.x, info.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DROID_ORDER_DATA sOrder = infoToOrderData(info, (BASE_STATS *)psStats);
|
DROID_ORDER_DATA sOrder = infoToOrderData(info, psStats);
|
||||||
|
|
||||||
uint32_t num = 0;
|
uint32_t num = 0;
|
||||||
NETuint32_t(&num);
|
NETuint32_t(&num);
|
||||||
|
@ -680,7 +673,7 @@ BOOL recvDroidInfo(NETQUEUE queue)
|
||||||
NETuint32_t(&deltaDroidId);
|
NETuint32_t(&deltaDroidId);
|
||||||
info.droidId += deltaDroidId;
|
info.droidId += deltaDroidId;
|
||||||
|
|
||||||
DROID *psDroid = IdToDroid(info.droidId, ANYPLAYER);
|
DROID *psDroid = IdToDroid(info.droidId, info.player);
|
||||||
if (!psDroid)
|
if (!psDroid)
|
||||||
{
|
{
|
||||||
debug(LOG_NEVER, "Packet from %d refers to non-existent droid %u, [%s : p%d]",
|
debug(LOG_NEVER, "Packet from %d refers to non-existent droid %u, [%s : p%d]",
|
||||||
|
@ -693,26 +686,38 @@ BOOL recvDroidInfo(NETQUEUE queue)
|
||||||
|
|
||||||
syncDebugDroid(psDroid, '<');
|
syncDebugDroid(psDroid, '<');
|
||||||
|
|
||||||
/*
|
switch (info.subType)
|
||||||
* If the current order not is a command order and we are not a
|
|
||||||
* commander yet are in the commander group remove us from it.
|
|
||||||
*/
|
|
||||||
if (hasCommander(psDroid))
|
|
||||||
{
|
{
|
||||||
psDroid->psGroup->remove(psDroid);
|
case ObjOrder:
|
||||||
}
|
case LocOrder:
|
||||||
|
/*
|
||||||
|
* If the current order not is a command order and we are not a
|
||||||
|
* commander yet are in the commander group remove us from it.
|
||||||
|
*/
|
||||||
|
if (hasCommander(psDroid))
|
||||||
|
{
|
||||||
|
psDroid->psGroup->remove(psDroid);
|
||||||
|
}
|
||||||
|
|
||||||
if (sOrder.psObj != TargetMissing) // Only do order if the target didn't die.
|
if (sOrder.psObj != TargetMissing) // Only do order if the target didn't die.
|
||||||
{
|
{
|
||||||
if (!info.add)
|
if (!info.add)
|
||||||
{
|
{
|
||||||
orderDroidListEraseRange(psDroid, 0, psDroid->listSize + 1); // Clear all non-pending orders, plus the first pending order (which is probably the order we just received).
|
orderDroidListEraseRange(psDroid, 0, psDroid->listSize + 1); // Clear all non-pending orders, plus the first pending order (which is probably the order we just received).
|
||||||
orderDroidBase(psDroid, &sOrder); // Execute the order immediately (even if in the middle of another order.
|
orderDroidBase(psDroid, &sOrder); // Execute the order immediately (even if in the middle of another order.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
orderDroidAdd(psDroid, &sOrder); // Add the order to the (non-pending) list. Will probably overwrite the corresponding pending order, assuming all pending orders were written to the list.
|
orderDroidAdd(psDroid, &sOrder); // Add the order to the (non-pending) list. Will probably overwrite the corresponding pending order, assuming all pending orders were written to the list.
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SecondaryOrder:
|
||||||
|
// Set the droids secondary order
|
||||||
|
turnOffMultiMsg(true);
|
||||||
|
secondarySetState(psDroid, info.secOrder, info.secState);
|
||||||
|
turnOffMultiMsg(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
syncDebugDroid(psDroid, '>');
|
syncDebugDroid(psDroid, '>');
|
||||||
|
|
|
@ -612,9 +612,6 @@ BOOL recvMessage(void)
|
||||||
case GAME_STRUCTDEST: // structure destroy
|
case GAME_STRUCTDEST: // structure destroy
|
||||||
recvDestroyStructure(queue);
|
recvDestroyStructure(queue);
|
||||||
break;
|
break;
|
||||||
case GAME_SECONDARY: // set a droids secondary order level.
|
|
||||||
recvDroidSecondary(queue);
|
|
||||||
break;
|
|
||||||
case GAME_DROIDEMBARK:
|
case GAME_DROIDEMBARK:
|
||||||
recvDroidEmbark(queue); //droid has embarked on a Transporter
|
recvDroidEmbark(queue); //droid has embarked on a Transporter
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -39,13 +39,11 @@ extern BOOL recvDemolishFinished (NETQUEUE queue);
|
||||||
extern BOOL recvPing (NETQUEUE queue);
|
extern BOOL recvPing (NETQUEUE queue);
|
||||||
extern BOOL recvRequestDroid (NETQUEUE queue);
|
extern BOOL recvRequestDroid (NETQUEUE queue);
|
||||||
extern BOOL recvTextMessage (NETQUEUE queue);
|
extern BOOL recvTextMessage (NETQUEUE queue);
|
||||||
extern BOOL recvDroidSecondary (NETQUEUE queue);
|
|
||||||
extern BOOL recvDroidEmbark (NETQUEUE queue);
|
extern BOOL recvDroidEmbark (NETQUEUE queue);
|
||||||
extern BOOL recvDroidDisEmbark (NETQUEUE queue);
|
extern BOOL recvDroidDisEmbark (NETQUEUE queue);
|
||||||
extern BOOL recvDroidCheck (NETQUEUE queue);
|
extern BOOL recvDroidCheck (NETQUEUE queue);
|
||||||
extern BOOL recvStructureCheck (NETQUEUE queue);
|
extern BOOL recvStructureCheck (NETQUEUE queue);
|
||||||
extern BOOL recvPowerCheck (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 recvColourRequest (NETQUEUE queue);
|
||||||
extern BOOL recvPositionRequest (NETQUEUE queue);
|
extern BOOL recvPositionRequest (NETQUEUE queue);
|
||||||
extern void recvOptions (NETQUEUE queue);
|
extern void recvOptions (NETQUEUE queue);
|
||||||
|
|
Loading…
Reference in New Issue