Example #1
0
/// Does not read/write info->droidId!
static void NETQueuedDroidInfo(QueuedDroidInfo *info)
{
	NETuint8_t(&info->player);
	NETenum(&info->subType);
	switch (info->subType)
	{
		case ObjOrder:
		case LocOrder:
			NETenum(&info->order);
			if (info->subType == ObjOrder)
			{
				NETuint32_t(&info->destId);
				NETenum(&info->destType);
			}
			else
			{
				NETauto(&info->pos);
			}
			if (info->order == DORDER_BUILD || info->order == DORDER_LINEBUILD)
			{
				NETuint32_t(&info->structRef);
				NETuint16_t(&info->direction);
			}
			if (info->order == DORDER_LINEBUILD)
			{
				NETauto(&info->pos2);
			}
			if (info->order == DORDER_BUILDMODULE)
			{
				NETauto(&info->index);
			}
			NETbool(&info->add);
			break;
		case SecondaryOrder:
			NETenum(&info->secOrder);
			NETenum(&info->secState);
			break;
	}
}
Example #2
0
/** Force a droid to be synced
 *
 *  Call this when you need to update the given droid right now.
 */
bool ForceDroidSync(const DROID* droidToSend)
{
	uint8_t count = 1;		// *always* one
	PACKAGED_CHECK pc = packageCheck(droidToSend);

	ASSERT(droidToSend != NULL, "NULL pointer passed");

	debug(LOG_SYNC, "Force sync of droid %u from player %u", droidToSend->id, droidToSend->player);

	NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_DROID);
		NETuint8_t(&count);
		NETuint32_t(&gameTime);  // Send game time.
		NETauto(&pc);
	return NETend();
}
Example #3
0
static void NETauto(PACKAGED_CHECK *v)
{
	NETauto(&v->player);
	NETauto(&v->droidID);
	NETauto(&v->order);
	NETauto(&v->secondaryOrder);
	NETauto(&v->body);
	NETauto(&v->experience);
	NETauto(&v->pos);
	NETauto(&v->rot);
	if (v->order == DORDER_ATTACK)
	{
		NETauto(&v->targetID);
	}
	else if (v->order == DORDER_MOVE)
	{
		NETauto(&v->orderX);
		NETauto(&v->orderY);
	}
}
Example #4
0
// ////////////////////////////////////////////////////////////////////////////
// receive a check and update the local world state accordingly
bool recvDroidCheck(NETQUEUE queue)
{
	uint8_t		count;
	int		i;
	uint32_t        synchTime;

	NETbeginDecode(queue, GAME_CHECK_DROID);

		// Get the number of droids to expect
		NETuint8_t(&count);
		NETuint32_t(&synchTime);  // Get game time.

		for (i = 0; i < count; i++)
		{
			DROID *         pD;
			PACKAGED_CHECK  pc;

			NETauto(&pc);

			// Find the droid in question
			pD = IdToDroid(pc.droidID, pc.player);
			if (!pD)
			{
				NETlogEntry("Recvd Unknown droid info. val=player", SYNC_FLAG, pc.player);
				debug(LOG_SYNC, "Received checking info for an unknown (as yet) droid. player:%d ref:%d", pc.player, pc.droidID);
				continue;
			}

			syncDebugDroid(pD, '<');

			if (pD->gameCheckDroid == NULL)
			{
				debug(LOG_SYNC, "We got a droid %u synch, but we couldn't find the droid!", pc.droidID);
				continue;  // Can't synch, since we didn't save data to be able to calculate a delta.
			}

			PACKAGED_CHECK const pc2 = *pD->gameCheckDroid;

			if (pc2.gameTime != synchTime + MIN_DELAY_BETWEEN_DROID_SYNCHS)
			{
				debug(LOG_SYNC, "We got a droid %u synch, but we didn't choose the same droid to synch.", pc.droidID);
				pD->gameCheckDroid->gameTime = synchTime + MIN_DELAY_BETWEEN_DROID_SYNCHS;  // Get droid synch time back in synch.
				continue;  // Can't synch, since we didn't save data to be able to calculate a delta.
			}

#define MERGECOPYSYNC(x, y, z)  if (pc.y != pc2.y) { debug(LOG_SYNC, "Droid %u out of synch, changing "#x" from %"z" to %"z".", pc.droidID, x, pc.y);             x = pc.y; }
#define MERGEDELTA(x, y, z) if (pc.y != pc2.y) { debug(LOG_SYNC, "Droid %u out of synch, changing "#x" from %"z" to %"z".", pc.droidID, x, x + pc.y - pc2.y); x += pc.y - pc2.y; }
			// player not synched here...
			MERGEDELTA(pD->pos.x, pos.x, "d");
			MERGEDELTA(pD->pos.y, pos.y, "d");
			MERGEDELTA(pD->pos.z, pos.z, "d");
			MERGEDELTA(pD->rot.direction, rot.direction, "d");
			MERGEDELTA(pD->rot.pitch, rot.pitch, "d");
			MERGEDELTA(pD->rot.roll, rot.roll, "d");
			MERGEDELTA(pD->body, body, "u");
			if (pD->body > pD->originalBody)
			{
				pD->body = pD->originalBody;
				debug(LOG_SYNC, "Droid %u body was too high after synch, reducing to %u.", pc.droidID, pD->body);
			}
			MERGEDELTA(pD->experience, experience, "u");

			if (pc.pos.x != pc2.pos.x || pc.pos.y != pc2.pos.y)
			{
				// snap droid(if on ground) to terrain level at x,y.
				if ((asPropulsionStats + pD->asBits[COMP_PROPULSION].nStat)->propulsionType != PROPULSION_TYPE_LIFT)  // if not airborne.
				{
					pD->pos.z = map_Height(pD->pos.x, pD->pos.y);
				}
			}

			// Doesn't cover all cases, but at least doesn't actively break stuff randomly.
			switch (pc.order)
			{
				case DORDER_MOVE:
					if (pc.order != pc2.order || pc.orderX != pc2.orderX || pc.orderY != pc2.orderY)
					{
						debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s(%d, %d).", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order), pc.orderX, pc.orderY);
						// reroute the droid.
						orderDroidLoc(pD, (DROID_ORDER)pc.order, pc.orderX, pc.orderY, ModeImmediate);
					}
					break;
				case DORDER_ATTACK:
					if (pc.order != pc2.order || pc.targetID != pc2.targetID)
					{
						BASE_OBJECT *obj = IdToPointer(pc.targetID, ANYPLAYER);
						if (obj != NULL)
						{
							debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s(%u).", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order), pc.targetID);
							// remote droid is attacking, not here tho!
							orderDroidObj(pD, (DROID_ORDER)pc.order, IdToPointer(pc.targetID, ANYPLAYER), ModeImmediate);
						}
						else
						{
							debug(LOG_SYNC, "Droid %u out of synch, would change order from %s to %s(%u), but can't find target.", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order), pc.targetID);
						}
					}
					break;
				case DORDER_NONE:
				case DORDER_GUARD:
					if (pc.order != pc2.order)
					{
						DROID_ORDER_DATA sOrder;
						memset(&sOrder, 0, sizeof(DROID_ORDER_DATA));
						sOrder.order = (DROID_ORDER)pc.order;

						debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s.", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order));
						turnOffMultiMsg(true);
						moveStopDroid(pD);
						orderDroidBase(pD, &sOrder);
						turnOffMultiMsg(false);
					}
					break;
				default:
					break;  // Don't know what to do, but at least won't be actively breaking anything.
			}

			MERGECOPYSYNC(pD->secondaryOrder, secondaryOrder, "u");  // The old code set this after changing orders, so doing that in case.
#undef MERGECOPYSYNC
#undef MERGEDELTA

			syncDebugDroid(pD, '>');

			// ...and repeat!
		}

	NETend();

	return true;
}
Example #5
0
// ///////////////////////////////////////////////////////////////////////////
// send a droid info packet.
static bool sendDroidCheck(void)
{
	DROID			*pD, **ppD;
	uint8_t			i, count;
	static UDWORD	lastSent = 0;		// Last time a struct was sent.
	UDWORD			toSend = 12;

	if (lastSent > gameTime)
	{
		lastSent= 0;
	}

	// Only send a struct send if not done recently
	if (gameTime - lastSent < DROID_PERIOD)
	{
		return true;
	}

	lastSent = gameTime;


	if (!isInSync())  // Don't really send anything, unless out of synch.
	{
		NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_DROID);
	}

		// Allocate space for the list of droids to send
		ppD = (DROID **)alloca(sizeof(DROID *) * toSend);

		// Get the list of droids to sent
		for (i = 0, count = 0; i < toSend; i++)
		{
			pD = pickADroid();

			if (pD == NULL || (pD->gameCheckDroid != NULL && pD->gameCheckDroid->gameTime > gameTime))
			{
				continue;  // Didn't find a droid, or droid was synched recently.
			}

			// If the droid is ours add it to the list
			if (myResponsibility(pD->player))
			{
				ppD[count++] = pD;
			}
			delete pD->gameCheckDroid;
			pD->gameCheckDroid = new PACKAGED_CHECK(packageCheck(pD));
		}

		if (!isInSync())  // Don't really send anything, unless out of synch.
		{
			// Send the number of droids to expect
			NETuint8_t(&count);
			NETuint32_t(&gameTime);  // Send game time.

			// Add the droids to the packet
			for (i = 0; i < count; i++)
			{
				NETauto(ppD[i]->gameCheckDroid);
			}
		}

	if (!isInSync())  // Don't really send anything, unless out of synch.
	{
		return NETend();
	}

	return true;
}