void ConnectionGraph::SerializeIgnoreListAndBroadcast(RakNet::BitStream *outBitstream, DataStructures::OrderedList<SystemAddress,SystemAddress> &ignoreList, RakPeerInterface *peer) { DataStructures::List<SystemAddress> sendList; unsigned i; for (i=0; i < participantList.Size(); i++) { if (ignoreList.HasData(participantList[i])==false) sendList.Insert(participantList[i], __FILE__, __LINE__); } if (sendList.Size()==0) return; SystemAddress self = peer->GetExternalID(sendList[0]); ignoreList.Insert(self,self, false, __FILE__, __LINE__); outBitstream->Write((unsigned short) (ignoreList.Size()+sendList.Size())); for (i=0; i < ignoreList.Size(); i++) outBitstream->Write(ignoreList[i]); for (i=0; i < sendList.Size(); i++) outBitstream->Write(sendList[i]); for (i=0; i < sendList.Size(); i++) { peer->Send(outBitstream, LOW_PRIORITY, RELIABLE_ORDERED, connectionGraphChannel, sendList[i], false); } }
void GridSectorizer::GetEntries(DataStructures::List<void*>& intersectionList, const float minX, const float minY, const float maxX, const float maxY) { #ifdef _USE_ORDERED_LIST DataStructures::OrderedList<void*, void*>* cell; #else DataStructures::List<void*>* cell; #endif int xStart, yStart, xEnd, yEnd, xCur, yCur; unsigned index; xStart=WorldToCellXOffsetAndClamped(minX); yStart=WorldToCellYOffsetAndClamped(minY); xEnd=WorldToCellXOffsetAndClamped(maxX); yEnd=WorldToCellYOffsetAndClamped(maxY); intersectionList.Clear(true, _FILE_AND_LINE_); for (xCur=xStart; xCur <= xEnd; ++xCur) { for (yCur=yStart; yCur <= yEnd; ++yCur) { cell = grid+yCur*gridCellWidthCount+xCur; for (index=0; index < cell->Size(); ++index) intersectionList.Insert(cell->operator [](index), _FILE_AND_LINE_); } } }
void UDPProxyCoordinator::ForwardingRequest::OrderRemainingServersToTry(void) { //DataStructures::Multilist<ML_ORDERED_LIST,UDPProxyCoordinator::ServerWithPing,unsigned short> swpList; DataStructures::OrderedList<unsigned short, UDPProxyCoordinator::ServerWithPing, ServerWithPingComp> swpList; // swpList.SetSortOrder(true); if (sourceServerPings.Size()==0 && targetServerPings.Size()==0) return; unsigned int idx; UDPProxyCoordinator::ServerWithPing swp; for (idx=0; idx < remainingServersToTry.Size(); idx++) { swp.serverAddress=remainingServersToTry[idx]; swp.ping=0; if (sourceServerPings.Size()) swp.ping+=(unsigned short) (sourceServerPings[idx].ping); else swp.ping+=(unsigned short) (DEFAULT_CLIENT_UNRESPONSIVE_PING_TIME); if (targetServerPings.Size()) swp.ping+=(unsigned short) (targetServerPings[idx].ping); else swp.ping+=(unsigned short) (DEFAULT_CLIENT_UNRESPONSIVE_PING_TIME); swpList.Insert(swp.ping, swp, false, _FILE_AND_LINE_); } remainingServersToTry.Clear(_FILE_AND_LINE_ ); for (idx=0; idx < swpList.Size(); idx++) { remainingServersToTry.Push(swpList[idx].serverAddress, _FILE_AND_LINE_ ); } }
bool StatisticsHistory::GetHistorySorted(uint64_t objectId, SHSortOperation sortType, DataStructures::List<StatisticsHistory::TimeAndValueQueue *> &values) const { unsigned int idx = GetObjectIndex(objectId); if (idx == (unsigned int) -1) return false; TrackedObject *to = objects[idx]; DataStructures::List<TimeAndValueQueue*> itemList; DataStructures::List<RakString> keyList; to->dataQueues.GetAsList(itemList,keyList,_FILE_AND_LINE_); Time curTime = GetTime(); DataStructures::OrderedList<TimeAndValueQueue*, TimeAndValueQueue*,TimeAndValueQueueCompAsc> sortedQueues; for (unsigned int i=0; i < itemList.Size(); i++) { TimeAndValueQueue *tavq = itemList[i]; tavq->CullExpiredValues(curTime); if (sortType == SH_SORT_BY_RECENT_SUM_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_DESCENDING) tavq->sortValue = tavq->GetRecentSum(); else if (sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_SUM_DESCENDING) tavq->sortValue = tavq->GetLongTermSum(); else if (sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_DESCENDING) tavq->sortValue = tavq->GetRecentSumOfSquares(); else if (sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING || sortType == SH_SORT_BY_RECENT_AVERAGE_DESCENDING) tavq->sortValue = tavq->GetRecentAverage(); else if (sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_AVERAGE_DESCENDING) tavq->sortValue = tavq->GetLongTermAverage(); else if (sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING || sortType == SH_SORT_BY_RECENT_HIGHEST_DESCENDING) tavq->sortValue = tavq->GetRecentHighest(); else if (sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING || sortType == SH_SORT_BY_RECENT_LOWEST_DESCENDING) tavq->sortValue = tavq->GetRecentLowest(); else if (sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_HIGHEST_DESCENDING) tavq->sortValue = tavq->GetLongTermHighest(); else tavq->sortValue = tavq->GetLongTermLowest(); if ( sortType == SH_SORT_BY_RECENT_SUM_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING || sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING || sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING || sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_LOWEST_ASCENDING) sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompAsc); else sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompDesc); } for (unsigned int i=0; i < sortedQueues.Size(); i++) values.Push(sortedQueues[i], _FILE_AND_LINE_); return true; }
void Table::SortTable(Table::SortQuery *sortQueries, unsigned numSortQueries, Table::Row** out) { unsigned i; unsigned outLength; DataStructures::List<unsigned> columnIndices; _sortQueries=sortQueries; _numSortQueries=numSortQueries; _columnIndices=&columnIndices; _columns=&columns; bool anyValid=false; for (i=0; i < numSortQueries; i++) { if (sortQueries[i].columnIndex<columns.Size() && columns[sortQueries[i].columnIndex].columnType!=BINARY) { columnIndices.Insert(sortQueries[i].columnIndex, _FILE_AND_LINE_); anyValid=true; } else columnIndices.Insert((unsigned)-1, _FILE_AND_LINE_); // Means don't check this column } DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur; cur = rows.GetListHead(); if (anyValid==false) { outLength=0; while (cur) { for (i=0; i < (unsigned)cur->size; i++) { out[(outLength)++]=cur->data[i]; } cur=cur->next; } return; } // Start adding to ordered list. DataStructures::OrderedList<Row*, Row*, RowSort> orderedList; while (cur) { for (i=0; i < (unsigned)cur->size; i++) { RakAssert(cur->data[i]); orderedList.Insert(cur->data[i],cur->data[i], true, _FILE_AND_LINE_); } cur=cur->next; } outLength=0; for (i=0; i < orderedList.Size(); i++) out[(outLength)++]=orderedList[i]; }
void AutoRPC::OnCloseConnection(RakPeerInterface *peer, SystemAddress systemAddress) { (void) peer; if (remoteFunctions.Has(systemAddress)) { DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions.Get(systemAddress); unsigned i; for (i=0; i < theList->Size(); i++) { if (theList->operator [](i).identifier.uniqueIdentifier) rakFree(theList->operator [](i).identifier.uniqueIdentifier); } RakNet::OP_DELETE(theList); remoteFunctions.Delete(systemAddress); } }
void AutoRPC::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ) { (void) rakNetGUID; (void) lostConnectionReason; if (remoteFunctions.Has(systemAddress)) { DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions.Get(systemAddress); unsigned i; for (i=0; i < theList->Size(); i++) { if (theList->operator [](i).identifier.uniqueIdentifier) rakFree_Ex(theList->operator [](i).identifier.uniqueIdentifier, __FILE__, __LINE__ ); } RakNet::OP_DELETE(theList, __FILE__, __LINE__); remoteFunctions.Delete(systemAddress); } }
void AutoRPC::Clear(void) { unsigned i,j; for (j=0; j < remoteFunctions.Size(); j++) { DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions[j]; for (i=0; i < theList->Size(); i++) { if (theList->operator [](i).identifier.uniqueIdentifier) rakFree_Ex(theList->operator [](i).identifier.uniqueIdentifier, __FILE__, __LINE__ ); } RakNet::OP_DELETE(theList, __FILE__, __LINE__); } for (i=0; i < localFunctions.Size(); i++) { if (localFunctions[i].identifier.uniqueIdentifier) rakFree_Ex(localFunctions[i].identifier.uniqueIdentifier, __FILE__, __LINE__ ); } localFunctions.Clear(false, __FILE__, __LINE__); remoteFunctions.Clear(); outgoingExtraData.Reset(); incomingExtraData.Reset(); }
void FullyConnectedMesh2::GetHostOrder(DataStructures::List<RakNetGUID> &hostList) { hostList.Clear(true, _FILE_AND_LINE_); if (ourFCMGuid==0 || fcm2ParticipantList.Size()==0) { hostList.Push(rakPeerInterface->GetMyGUID(), _FILE_AND_LINE_); return; } FCM2Participant fcm2; fcm2.fcm2Guid=ourFCMGuid; fcm2.rakNetGuid=rakPeerInterface->GetMyGUID(); DataStructures::OrderedList<FCM2Participant, FCM2Participant, FCM2ParticipantComp> olist; olist.Insert(fcm2, fcm2, true, _FILE_AND_LINE_); for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++) olist.Insert(fcm2ParticipantList[i], fcm2ParticipantList[i], true, _FILE_AND_LINE_); for (unsigned int i=0; i < olist.Size(); i++) { hostList.Push(olist[i].rakNetGuid, _FILE_AND_LINE_); } }
void Lobby2Client_Steam_Impl::CallRoomCallbacks() { DataStructures::OrderedList<uint64_t,uint64_t> currentMembers; GetRoomMembers(currentMembers); DataStructures::OrderedList<uint64_t, RoomMember, SteamIDAndRoomMemberComp> updatedRoomMembers; bool anyChanges=false; unsigned int currentMemberIndex=0, oldMemberIndex=0; while (currentMemberIndex < currentMembers.Size() && oldMemberIndex < roomMembersById.Size()) { if (currentMembers[currentMemberIndex]<roomMembersById[oldMemberIndex].steamIDRemote) { RoomMember roomMember; roomMember.steamIDRemote=currentMembers[currentMemberIndex]; roomMember.systemAddress.address.addr4.sin_addr.s_addr=nextFreeSystemAddress++; roomMember.systemAddress.SetPortHostOrder(STEAM_UNUSED_PORT); updatedRoomMembers.Insert(roomMember.steamIDRemote,roomMember,true,_FILE_AND_LINE_); anyChanges=true; // new member NotifyNewMember(currentMembers[currentMemberIndex], roomMember.systemAddress); currentMemberIndex++; } else if (currentMembers[currentMemberIndex]>roomMembersById[oldMemberIndex].steamIDRemote) { anyChanges=true; // dropped member NotifyDroppedMember(roomMembersById[oldMemberIndex].steamIDRemote, roomMembersById[oldMemberIndex].systemAddress); oldMemberIndex++; } else { updatedRoomMembers.Insert(roomMembersById[oldMemberIndex].steamIDRemote,roomMembersById[oldMemberIndex],true,_FILE_AND_LINE_); currentMemberIndex++; oldMemberIndex++; } } while (oldMemberIndex < roomMembersById.Size()) { anyChanges=true; // dropped member NotifyDroppedMember(roomMembersById[oldMemberIndex].steamIDRemote, roomMembersById[oldMemberIndex].systemAddress); oldMemberIndex++; } while (currentMemberIndex < currentMembers.Size()) { RoomMember roomMember; roomMember.steamIDRemote=currentMembers[currentMemberIndex]; roomMember.systemAddress.address.addr4.sin_addr.s_addr=nextFreeSystemAddress++; roomMember.systemAddress.SetPortHostOrder(STEAM_UNUSED_PORT); updatedRoomMembers.Insert(roomMember.steamIDRemote,roomMember,true,_FILE_AND_LINE_); anyChanges=true; // new member NotifyNewMember(currentMembers[currentMemberIndex], roomMember.systemAddress); currentMemberIndex++; } if (anyChanges) { roomMembersById=updatedRoomMembers; roomMembersByAddr.Clear(true, _FILE_AND_LINE_); for (currentMemberIndex=0; currentMemberIndex < roomMembersById.Size(); currentMemberIndex++) { roomMembersByAddr.Insert(roomMembersById[currentMemberIndex].systemAddress, roomMembersById[currentMemberIndex], true, _FILE_AND_LINE_); } } }
int main(int argc, char **argv) { if (argc>1) { printf("Command arguments:\n"); for (int i=1; i < argc; i++) { printf("%i. %s\n", i, argv[i]); } } SteamResults steamResults; rakPeer = RakNet::RakPeerInterface::GetInstance(); fcm2 = RakNet::FullyConnectedMesh2::GetInstance(); messageFactory = new Lobby2MessageFactory_Steam; lobby2Client = Lobby2Client_Steam::GetInstance(); lobby2Client->AddCallbackInterface(&steamResults); lobby2Client->SetMessageFactory(messageFactory); SocketDescriptor sd(1234,0); rakPeer->Startup(32,&sd,1); rakPeer->SetMaximumIncomingConnections(32); rakPeer->AttachPlugin(fcm2); rakPeer->AttachPlugin(lobby2Client); // Connect manually in Notification_Console_MemberJoinedRoom fcm2->SetConnectOnNewRemoteConnection(false, ""); RakNet::Lobby2Message* msg = messageFactory->Alloc(RakNet::L2MID_Client_Login); lobby2Client->SendMsg(msg); if (msg->resultCode!=L2RC_PROCESSING && msg->resultCode!=L2RC_SUCCESS) { printf("Steam must be running to play this game (SteamAPI_Init() failed).\n"); printf("If this fails, steam_appid.txt was probably not in the working directory.\n"); messageFactory->Dealloc(msg); return -1; } messageFactory->Dealloc(msg); PrintCommands(); bool quit=false; char ch; while(!quit) { RakNet::Packet *packet; for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive()) { switch (packet->data[0]) { case ID_DISCONNECTION_NOTIFICATION: // Connection lost normally printf("ID_DISCONNECTION_NOTIFICATION\n"); break; case ID_ALREADY_CONNECTED: // Connection lost normally printf("ID_ALREADY_CONNECTED\n"); break; case ID_REMOTE_DISCONNECTION_NOTIFICATION: // Server telling the clients of another client disconnecting gracefully. You can manually broadcast this in a peer to peer enviroment if you want. printf("ID_REMOTE_DISCONNECTION_NOTIFICATION\n"); break; case ID_REMOTE_CONNECTION_LOST: // Server telling the clients of another client disconnecting forcefully. You can manually broadcast this in a peer to peer enviroment if you want. printf("ID_REMOTE_CONNECTION_LOST\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: // Server telling the clients of another client connecting. You can manually broadcast this in a peer to peer enviroment if you want. printf("ID_REMOTE_NEW_INCOMING_CONNECTION\n"); break; case ID_CONNECTION_BANNED: // Banned from this server printf("We are banned from this server.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: printf("Connection attempt failed\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: // Sorry, the server is full. I don't do anything here but // A real app should tell the user printf("ID_NO_FREE_INCOMING_CONNECTIONS\n"); break; case ID_INVALID_PASSWORD: printf("ID_INVALID_PASSWORD\n"); break; case ID_CONNECTION_LOST: // Couldn't deliver a reliable packet - i.e. the other system was abnormally // terminated printf("ID_CONNECTION_LOST\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: // This tells the client they have connected printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", packet->systemAddress.ToString(), packet->guid.ToString()); break; case ID_NEW_INCOMING_CONNECTION: printf("ID_NEW_INCOMING_CONNECTION\n"); break; case ID_FCM2_NEW_HOST: { if (packet->systemAddress==RakNet::UNASSIGNED_SYSTEM_ADDRESS) printf("Got new host (ourselves)"); else printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString()); RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(1); RakNetGUID oldHost; bs.Read(oldHost); // If the old host is different, then this message was due to losing connection to the host. if (oldHost!=packet->guid) printf(". Oldhost Guid=%s\n", oldHost.ToString()); else printf("\n"); } break; default: // It's a client, so just show the message printf("Unknown Message ID %i\n", packet->data[0]); break; } } if (kbhit()) { ch=(char)getch(); switch (ch) { case 'a': { RakNet::Lobby2Message* logoffMsg = messageFactory->Alloc(RakNet::L2MID_Console_SearchRooms); lobby2Client->SendMsg(logoffMsg); messageFactory->Dealloc(logoffMsg); } break; case 'b': { if (lobby2Client->GetRoomID()==0) { printf("Not in a room\n"); break; } RakNet::Console_LeaveRoom_Steam* msg = (RakNet::Console_LeaveRoom_Steam*) messageFactory->Alloc(RakNet::L2MID_Console_LeaveRoom); msg->roomId=lobby2Client->GetRoomID(); lobby2Client->SendMsg(msg); messageFactory->Dealloc(msg); } break; case 'c': { if (lobby2Client->GetRoomID()!=0) { printf("Already in a room\n"); break; } RakNet::Console_CreateRoom_Steam* msg = (RakNet::Console_CreateRoom_Steam*) messageFactory->Alloc(RakNet::L2MID_Console_CreateRoom); // set the name of the lobby if it's ours char rgchLobbyName[256]; msg->roomIsPublic=true; _snprintf( rgchLobbyName, sizeof( rgchLobbyName ), "%s's lobby", SteamFriends()->GetPersonaName() ); msg->roomName=rgchLobbyName; msg->publicSlots=8; lobby2Client->SendMsg(msg); messageFactory->Dealloc(msg); } break; case 'd': { if (lobby2Client->GetRoomID()!=0) { printf("Already in a room\n"); break; } RakNet::Console_JoinRoom_Steam* msg = (RakNet::Console_JoinRoom_Steam*) messageFactory->Alloc(RakNet::L2MID_Console_JoinRoom); printf("Enter room id, or enter for %" PRINTF_64_BIT_MODIFIER "u: ", lastRoom); char str[256]; Gets(str, sizeof(str)); if (str[0]==0) { msg->roomId=lastRoom; } else { msg->roomId=_atoi64(str); } lobby2Client->SendMsg(msg); messageFactory->Dealloc(msg); } break; case 'e': { if (lobby2Client->GetRoomID()==0) { printf("Not in a room\n"); break; } RakNet::Console_GetRoomDetails_Steam* msg = (RakNet::Console_GetRoomDetails_Steam*) messageFactory->Alloc(RakNet::L2MID_Console_GetRoomDetails); msg->roomId=lobby2Client->GetRoomID(); lobby2Client->SendMsg(msg); messageFactory->Dealloc(msg); } break; case 'f': { if (lobby2Client->GetRoomID()==0) { printf("Not in a room\n"); break; } RakNet::Console_SendRoomChatMessage_Steam* msg = (RakNet::Console_SendRoomChatMessage_Steam*) messageFactory->Alloc(RakNet::L2MID_Console_SendRoomChatMessage); msg->message="Test chat message."; msg->roomId=lobby2Client->GetRoomID(); lobby2Client->SendMsg(msg); messageFactory->Dealloc(msg); } break; case 'g': { DataStructures::OrderedList<uint64_t, uint64_t> roomMembers; lobby2Client->GetRoomMembers(roomMembers); for (unsigned int i=0; i < roomMembers.Size(); i++) { printf("%i. %s ID=%" PRINTF_64_BIT_MODIFIER "u\n", i+1, lobby2Client->GetRoomMemberName(roomMembers[i]), roomMembers[i]); } } break; case '?': { PrintCommands(); } break; case 27: { quit=true; } break; } } RakSleep(30); } RakNet::Lobby2Message* logoffMsg = messageFactory->Alloc(RakNet::L2MID_Client_Logoff); lobby2Client->SendMsg(logoffMsg); messageFactory->Dealloc(logoffMsg); rakPeer->DetachPlugin(lobby2Client); rakPeer->DetachPlugin(fcm2); RakNet::RakPeerInterface::DestroyInstance(rakPeer); Lobby2Client_Steam::DestroyInstance(lobby2Client); RakNet::FullyConnectedMesh2::DestroyInstance(fcm2); return 1; }
void AutoRPC::OnRPCUnknownRemoteIndex(SystemAddress systemAddress, unsigned char *data, unsigned int lengthInBytes, RakNetTime timestamp) { char inputStack[ARPC_MAX_STACK_SIZE]; NetworkID networkId; bool hasNetworkId=false; unsigned int functionIndex; unsigned int bytesOnStack; int numberOfBitsUsed; char parameterCount; bool hasParameterCount=false; RakNet::BitStream extraData; RakNet::BitStream bs(data,lengthInBytes,false); bs.Read(hasParameterCount); if (hasParameterCount) bs.Read(parameterCount); bs.ReadCompressed(functionIndex); bs.ReadCompressed(numberOfBitsUsed); extraData.AddBitsAndReallocate(numberOfBitsUsed); bs.ReadBits(extraData.GetData(), numberOfBitsUsed, false); extraData.SetWriteOffset(numberOfBitsUsed); bs.Read(hasNetworkId); if (hasNetworkId) bs.Read(networkId); bs.ReadCompressed(bytesOnStack); bs.ReadAlignedBytes((unsigned char*) inputStack, bytesOnStack); unsigned outerIndex; if (remoteFunctions.Has(systemAddress)) { outerIndex = remoteFunctions.GetIndexAtKey(systemAddress); DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions[outerIndex]; unsigned i; for (i=0; i < theList->Size(); i++) { if (theList->operator [](i).functionIndex==functionIndex) { RakNet::BitStream out; // Recover by resending the RPC with the function identifier string this time if (timestamp!=0) { out.Write((MessageID)ID_TIMESTAMP); out.Write(timestamp); } out.Write((MessageID)ID_AUTO_RPC_CALL); if (parameterCount>=0) { out.Write(true); out.Write(parameterCount); } else { out.Write(false); } out.WriteCompressed(numberOfBitsUsed); out.Write(&extraData); out.Write(hasNetworkId); if (hasNetworkId) out.Write(networkId); out.AlignWriteToByteBoundary(); out.Write(false); stringCompressor->EncodeString(theList->operator [](i).identifier.uniqueIdentifier, 512, &out, 0); out.WriteCompressed(bytesOnStack); out.WriteAlignedBytes((const unsigned char*) inputStack, bytesOnStack); SendUnified(&out, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddress, false); return; } } } // Failed to recover, inform the user Packet *p = rakPeerInterface->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char)); RakNet::BitStream bs2(p->data, sizeof(MessageID)+sizeof(unsigned char), false); bs2.SetWriteOffset(0); bs2.Write((MessageID)ID_RPC_REMOTE_ERROR); bs2.Write((unsigned char)RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED); stringCompressor->EncodeString("",256,&bs,0); p->systemAddress=systemAddress; rakPeerInterface->PushBackPacket(p, false); }