/* * Original work: Copyright (c) 2014, Oculus VR, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * RakNet License.txt file in the licenses directory of this source tree. An additional grant * of patent rights can be found in the RakNet Patents.txt file in the same directory. * * * Modified work: Copyright (c) 2016-2021, SLikeSoft UG (haftungsbeschränkt) * * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style * license found in the license.txt file in the root directory of this source tree. */ #include "RoomsPlugin.h" #include "slikenet/BitStream.h" #include "RoomsErrorCodes.h" #include "slikenet/TableSerializer.h" #include "slikenet/assert.h" #include "slikenet/MessageIdentifiers.h" #include "slikenet/peerinterface.h" #include "ProfanityFilter.h" #include "slikenet/GetTime.h" using namespace SLNet; int RoomsPlugin::RoomsPluginParticipantCompByRakString( const SLNet::RakString &key, RoomsPluginParticipant* const &data ) { return strcmp(key.C_String(), data->GetName().C_String()); } void RoomsPluginFunc::PrintResult(void) { printf("Result for user %s: %s\n", userName.C_String(), RoomsErrorCodeDescription::ToEnglish(resultCode)); } void CreateRoom_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_CREATE_ROOM; bitStream->Serialize(writeToBitstream, messageId); networkedRoomCreationParameters.Serialize(writeToBitstream, bitStream); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, gameIdentifier); if (writeToBitstream) TableSerializer::SerializeTable(&initialRoomProperties, bitStream); else TableSerializer::DeserializeTable(bitStream, &initialRoomProperties); } void CreateRoom_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); bitStream->Serialize( writeToBitstream, roomId ); roomDescriptor.Serialize(writeToBitstream,bitStream); } void EnterRoom_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_ENTER_ROOM; bitStream->Serialize(writeToBitstream, messageId); networkedRoomCreationParameters.Serialize(writeToBitstream, bitStream); bitStream->Serialize(writeToBitstream, roomMemberMode); query.Serialize(writeToBitstream, bitStream); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, gameIdentifier); } void EnterRoom_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); bitStream->Serialize( writeToBitstream, createdRoom ); joinedRoomResult.Serialize(writeToBitstream, bitStream); bitStream->Serialize( writeToBitstream, roomId ); } void JoinByFilter_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_JOIN_BY_FILTER; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, gameIdentifier); bitStream->Serialize(writeToBitstream, roomMemberMode); bitStream->Serialize(writeToBitstream, userName); query.Serialize(writeToBitstream, bitStream); } void JoinByFilter_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); joinedRoomResult.Serialize(writeToBitstream, bitStream); } void LeaveRoom_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_LEAVE_ROOM; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream,userName); } void LeaveRoom_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); removeUserResult.Serialize(writeToBitstream, bitStream); } void GetInvitesToParticipant_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_GET_INVITES_TO_PARTICIPANT; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); } void GetInvitesToParticipant_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); unsigned int i; unsigned int listSize; listSize=invitedUsers.Size(); bitStream->Serialize(writeToBitstream, listSize); for (i=0; i < listSize; i++) { if (writeToBitstream) invitedUsers[i].Serialize(true,bitStream); else { InvitedUser invitedUser; invitedUser.Serialize(false,bitStream); invitedUsers.Insert(invitedUser, _FILE_AND_LINE_ ); } } } void SendInvite_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_SEND_INVITE; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, inviteeName); bitStream->Serialize(writeToBitstream, inviteToSpectatorSlot); bitStream->Serialize(writeToBitstream, subject); bitStream->Serialize(writeToBitstream, body); } void SendInvite_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void AcceptInvite_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_ACCEPT_INVITE; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, inviteSender); bitStream->Serialize(writeToBitstream, roomId); } void AcceptInvite_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void StartSpectating_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_START_SPECTATING; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); } void StartSpectating_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void StopSpectating_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_STOP_SPECTATING; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); } void StopSpectating_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void GrantModerator_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_GRANT_MODERATOR; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, newModerator); } void GrantModerator_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void ChangeSlotCounts_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_CHANGE_SLOT_COUNTS; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); slots.Serialize(writeToBitstream, bitStream); } void ChangeSlotCounts_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void SetCustomRoomProperties_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_SET_CUSTOM_ROOM_PROPERTIES; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); if (writeToBitstream) TableSerializer::SerializeTable(&table, bitStream); else TableSerializer::DeserializeTable(bitStream, &table); } void SetCustomRoomProperties_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void GetRoomProperties_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_GET_ROOM_PROPERTIES; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, roomName); } void GetRoomProperties_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); roomDescriptor.Serialize(writeToBitstream,bitStream); } void ChangeRoomName_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_CHANGE_ROOM_NAME; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, newRoomName); } void ChangeRoomName_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void SetHiddenFromSearches_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_SET_HIDDEN_FROM_SEARCHES; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, hiddenFromSearches); } void SetHiddenFromSearches_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void SetDestroyOnModeratorLeave_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_SET_DESTROY_ON_MODERATOR_LEAVE; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, destroyOnModeratorLeave); } void SetDestroyOnModeratorLeave_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void SetReadyStatus_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_SET_READY_STATUS; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, isReady); } void SetReadyStatus_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); unsigned int listSize; unsigned int i; SLNet::RakString name; listSize=readyUsers.Size(); bitStream->Serialize(writeToBitstream, listSize); if (writeToBitstream) { for (i=0; i < listSize; i++) bitStream->Serialize(writeToBitstream, readyUsers[i]); } else { for (i=0; i < listSize; i++) { bitStream->Serialize(writeToBitstream, name); readyUsers.Insert(name, _FILE_AND_LINE_ ); } } listSize=unreadyUsers.Size(); bitStream->Serialize(writeToBitstream, listSize); if (writeToBitstream) { for (i=0; i < listSize; i++) bitStream->Serialize(writeToBitstream, unreadyUsers[i]); } else { for (i=0; i < listSize; i++) { bitStream->Serialize(writeToBitstream, name); unreadyUsers.Insert(name, _FILE_AND_LINE_ ); } } } void GetReadyStatus_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_GET_READY_STATUS; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); unsigned int listSize; SLNet::RakString name; unsigned int i; listSize=readyUsers.Size(); bitStream->Serialize(writeToBitstream, listSize); if (writeToBitstream) { for (i=0; i < listSize; i++) bitStream->Serialize(writeToBitstream, readyUsers[i]); } else { for (i=0; i < listSize; i++) { bitStream->Serialize(writeToBitstream, name); readyUsers.Insert(name, _FILE_AND_LINE_ ); } } listSize=unreadyUsers.Size(); bitStream->Serialize(writeToBitstream, listSize); if (writeToBitstream) { for (i=0; i < listSize; i++) bitStream->Serialize(writeToBitstream, unreadyUsers[i]); } else { for (i=0; i < listSize; i++) { bitStream->Serialize(writeToBitstream, name); unreadyUsers.Insert(name, _FILE_AND_LINE_ ); } } } void GetReadyStatus_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void SetRoomLockState_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_SET_ROOM_LOCK_STATE; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, roomLockState); } void SetRoomLockState_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void GetRoomLockState_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_GET_ROOM_LOCK_STATE; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); } void GetRoomLockState_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); bitStream->Serialize(writeToBitstream, roomLockState); } void AreAllMembersReady_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_ARE_ALL_MEMBERS_READY; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, allReady); } void AreAllMembersReady_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void KickMember_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_KICK_MEMBER; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, kickedMember); bitStream->Serialize(writeToBitstream, reason); } void KickMember_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void UnbanMember_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_UNBAN_MEMBER; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, bannedMemberName); } void UnbanMember_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void GetBanReason_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_GET_BAN_REASON; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, roomId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, reason); } void GetBanReason_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void AddUserToQuickJoin_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_ADD_USER_TO_QUICK_JOIN; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, gameIdentifier); networkedQuickJoinUser.Serialize(writeToBitstream, bitStream); } void AddUserToQuickJoin_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void RemoveUserFromQuickJoin_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_REMOVE_USER_FROM_QUICK_JOIN; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); } void RemoveUserFromQuickJoin_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void IsInQuickJoin_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_IS_IN_QUICK_JOIN; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, isInQuickJoin); } void IsInQuickJoin_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } SearchByFilter_Func::~SearchByFilter_Func() { for (unsigned int i=0; i < roomsOutput.Size(); i++) SLNet::OP_DELETE(roomsOutput[i], _FILE_AND_LINE_); } void SearchByFilter_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_SEARCH_BY_FILTER; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, gameIdentifier); bitStream->Serialize(writeToBitstream, onlyJoinable); roomQuery.Serialize(writeToBitstream, bitStream); } void SearchByFilter_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); unsigned int i; unsigned int listSize; listSize=roomsOutput.Size(); bitStream->Serialize(writeToBitstream, listSize); for (i=0; i < listSize; i++) { if (writeToBitstream) roomsOutput[i]->Serialize(true,bitStream); else { RoomDescriptor *desc = SLNet::OP_NEW( _FILE_AND_LINE_ ); desc->Serialize(false,bitStream); roomsOutput.Insert(desc, _FILE_AND_LINE_ ); } } } void ChangeHandle_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_CHANGE_HANDLE; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, newHandle); } void ChangeHandle_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void Chat_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_CHAT; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, chatMessage); bitStream->Serialize(writeToBitstream, privateMessageRecipient); bitStream->Serialize(writeToBitstream, chatDirectedToRoom); } void Chat_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void Bitstream_Func::SerializeIn(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPO_BITSTREAM; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, userName); BitSize_t numBits = bsToSend.GetNumberOfBitsUsed(); bitStream->Serialize(writeToBitstream, numBits); if (!writeToBitstream) bsToSend.AddBitsAndReallocate(numBits); bitStream->SerializeBits(writeToBitstream, bsToSend.GetData(), numBits, true); bsToSend.SetWriteOffset(numBits); bitStream->Serialize(writeToBitstream, privateMessageRecipient); bitStream->Serialize(writeToBitstream, directedToRoom); } void Bitstream_Func::SerializeOut(bool writeToBitstream, SLNet::BitStream *bitStream) { SerializeIn( writeToBitstream, bitStream ); bitStream->Serialize( writeToBitstream, resultCode ); } void QuickJoinExpired_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_QUICK_JOIN_EXPIRED; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); networkedQuickJoinUser.Serialize(writeToBitstream, bitStream); } void QuickJoinEnteredRoom_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_QUICK_JOIN_ENTERED_ROOM; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); joinedRoomResult.Serialize(writeToBitstream, bitStream); } void RoomMemberStartedSpectating_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_MEMBER_STARTED_SPECTATING; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, roomId); } void RoomMemberStoppedSpectating_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_MEMBER_STARTED_SPECTATING; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, userName); bitStream->Serialize(writeToBitstream, roomId); } void ModeratorChanged_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_MODERATOR_CHANGED; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, newModerator); bitStream->Serialize(writeToBitstream, oldModerator); bitStream->Serialize(writeToBitstream, roomId); } void SlotCountsSet_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_SLOT_COUNTS_SET; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); slots.Serialize(writeToBitstream, bitStream); bitStream->Serialize(writeToBitstream, roomId); } void CustomRoomPropertiesSet_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_CUSTOM_ROOM_PROPERTIES_SET; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomId); if (writeToBitstream) { if (tablePtr==0) tablePtr=&table; TableSerializer::SerializeTable(tablePtr, bitStream); } else { TableSerializer::DeserializeTable(bitStream, &table); tablePtr=&table; } } void RoomNameSet_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_NAME_SET; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, oldName); bitStream->Serialize(writeToBitstream, newName); bitStream->Serialize(writeToBitstream, roomId); } void HiddenFromSearchesSet_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_HIDDEN_FROM_SEARCHES_SET; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomId); bitStream->Serialize(writeToBitstream, hiddenFromSearches); } void RoomMemberReadyStatusSet_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_MEMBER_READY_STATUS_SET; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomId); bitStream->Serialize(writeToBitstream, isReady); bitStream->Serialize(writeToBitstream, roomMember); unsigned int listSize; unsigned int i; SLNet::RakString name; listSize=readyUsers.Size(); bitStream->Serialize(writeToBitstream, listSize); if (writeToBitstream) { for (i=0; i < listSize; i++) bitStream->Serialize(writeToBitstream, readyUsers[i]); } else { for (i=0; i < listSize; i++) { bitStream->Serialize(writeToBitstream, name); readyUsers.Insert(name, _FILE_AND_LINE_ ); } } listSize=unreadyUsers.Size(); bitStream->Serialize(writeToBitstream, listSize); if (writeToBitstream) { for (i=0; i < listSize; i++) bitStream->Serialize(writeToBitstream, unreadyUsers[i]); } else { for (i=0; i < listSize; i++) { bitStream->Serialize(writeToBitstream, name); unreadyUsers.Insert(name, _FILE_AND_LINE_ ); } } } void RoomLockStateSet_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_LOCK_STATE_SET; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomId); bitStream->Serialize(writeToBitstream, roomLockState); } void RoomMemberKicked_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_MEMBER_KICKED; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomId); bitStream->Serialize(writeToBitstream, kickedMember); bitStream->Serialize(writeToBitstream, moderator); bitStream->Serialize(writeToBitstream, reason); } void RoomMemberHandleSet_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_MEMBER_HANDLE_SET; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, oldName); bitStream->Serialize(writeToBitstream, newName); bitStream->Serialize(writeToBitstream, roomId); } void RoomMemberLeftRoom_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_MEMBER_LEFT_ROOM; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomMember); bitStream->Serialize(writeToBitstream, roomId); } void RoomMemberJoinedRoom_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_MEMBER_JOINED_ROOM; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomId); if (joinedRoomResult==0 && !writeToBitstream) joinedRoomResult = SLNet::OP_NEW( _FILE_AND_LINE_ ); joinedRoomResult->Serialize(writeToBitstream, bitStream); } void RoomInvitationSent_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_INVITATION_SENT; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, invitorName); bitStream->Serialize(writeToBitstream, inviteeName); bitStream->Serialize(writeToBitstream, inviteToSpectatorSlot); bitStream->Serialize(writeToBitstream, subject); bitStream->Serialize(writeToBitstream, body); bitStream->Serialize(writeToBitstream, roomId); } void RoomInvitationWithdrawn_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_INVITATION_WITHDRAWN; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); invitedUser.Serialize(writeToBitstream, bitStream); } void RoomDestroyedOnModeratorLeft_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_ROOM_DESTROYED_ON_MODERATOR_LEFT; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, roomId); bitStream->Serialize(writeToBitstream, oldModerator); roomDescriptor.Serialize(writeToBitstream, bitStream); } void Chat_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_CHAT_NOTIFICATION; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, sender); bitStream->Serialize(writeToBitstream, privateMessageRecipient); bitStream->Serialize(writeToBitstream, chatMessage); bitStream->Serialize(writeToBitstream, filteredChatMessage); } void Bitstream_Notification::Serialize(bool writeToBitstream, SLNet::BitStream *bitStream) { MessageID messageId = RPN_BITSTREAM_NOTIFICATION; bitStream->Serialize(writeToBitstream, messageId); bitStream->Serialize(writeToBitstream, recipient); bitStream->Serialize(writeToBitstream, sender); bitStream->Serialize(writeToBitstream, privateMessageRecipient); BitSize_t numBits = bitStreamReceived.GetNumberOfBitsUsed(); bitStream->Serialize(writeToBitstream, numBits); if (!writeToBitstream) bitStreamReceived.AddBitsAndReallocate(numBits); bitStream->SerializeBits(writeToBitstream, bitStreamReceived.GetData(), numBits, true); bitStreamReceived.SetWriteOffset(numBits); } RoomsPlugin::RoomsPlugin() { lastUpdateTime=0; orderingChannel=0; profanityFilter=0; packetPriority=HIGH_PRIORITY; serverAddress= SLNet::UNASSIGNED_SYSTEM_ADDRESS; SetRoomsCallback(this); } RoomsPlugin::~RoomsPlugin() { Clear(); } void RoomsPlugin::SetOrderingChannel(char oc) { orderingChannel=oc; } void RoomsPlugin::SetSendPriority(PacketPriority pp) { packetPriority=pp; } void RoomsPlugin::SetRoomsCallback(RoomsCallback *_roomsCallback) { roomsCallback.Clear(true,_FILE_AND_LINE_); roomsCallback.Push(_roomsCallback,_FILE_AND_LINE_); } void RoomsPlugin::AddRoomsCallback(RoomsCallback *_roomsCallback) { if (roomsCallback.GetIndexOf(_roomsCallback)==(unsigned int) -1) roomsCallback.Push(_roomsCallback,_FILE_AND_LINE_); } void RoomsPlugin::RemoveRoomsCallback(RoomsCallback *_roomsCallback) { unsigned int idx = roomsCallback.GetIndexOf(_roomsCallback); if (idx!=(unsigned int) -1) roomsCallback.RemoveAtIndex(idx); } void RoomsPlugin::ExecuteFunc(RoomsPluginFunc *func) { ExecuteFunc(func,serverAddress); } void RoomsPlugin::ExecuteFunc(RoomsPluginFunc *func, SystemAddress remoteAddress) { SLNet::BitStream bs; bs.Write((MessageID)ID_ROOMS_EXECUTE_FUNC); if (IsServer()) func->SerializeOut(true, &bs); else func->SerializeIn(true, &bs); SendUnified(&bs, packetPriority, RELIABLE_ORDERED, orderingChannel, remoteAddress, false); } void RoomsPlugin::ExecuteNotification(RoomsPluginNotification *func, RoomsPluginParticipant *recipient) { SLNet::BitStream bs; bs.Write((MessageID)ID_ROOMS_EXECUTE_FUNC); func->recipient=recipient->GetName(); func->Serialize(true, &bs); SendUnified(&bs, packetPriority, RELIABLE_ORDERED, orderingChannel, recipient->GetSystemAddress(), false); } void RoomsPlugin::SetServerAddress( SystemAddress systemAddress ) { serverAddress=systemAddress; if (serverAddress!= SLNet::UNASSIGNED_SYSTEM_ADDRESS) { RemoveRoomsCallback(this); } } bool RoomsPlugin::LoginRoomsParticipant(SLNet::RakString userName, SystemAddress roomsParticipantAddress, RakNetGUID guid, SystemAddress loginServerAddress) { if (loginServerAddress!= SLNet::UNASSIGNED_SYSTEM_ADDRESS && loginServers.GetIndexOf(loginServerAddress)==(unsigned int) -1) return false; bool objectExists; unsigned int index; index=roomsParticipants.GetIndexFromKey(userName, &objectExists); if (!objectExists) { RoomsPluginParticipant *rpp = SLNet::OP_NEW( _FILE_AND_LINE_ ); rpp->SetSystemAddress(roomsParticipantAddress); rpp->SetGUID(guid); rpp->SetName(userName); roomsParticipants.InsertAtIndex(rpp, index, _FILE_AND_LINE_ ); return true; } return false; } bool RoomsPlugin::LogoffRoomsParticipant(SLNet::RakString userName, SystemAddress loginServerAddress) { if (loginServerAddress!= SLNet::UNASSIGNED_SYSTEM_ADDRESS && loginServers.GetIndexOf(loginServerAddress)==(unsigned int) -1) return false; bool objectExists; unsigned int index; index=roomsParticipants.GetIndexFromKey(userName, &objectExists); if (objectExists) { RemoveUserResult removeUserResult; roomsContainer.RemoveUser(roomsParticipants[index], &removeUserResult); ProcessRemoveUserResult(&removeUserResult); SLNet::OP_DELETE(roomsParticipants[index], _FILE_AND_LINE_); roomsParticipants.RemoveAtIndex(index); return true; } return false; } void RoomsPlugin::ClearRoomMembers(void) { unsigned int i; for (i=0; i < roomsParticipants.Size(); i++) SLNet::OP_DELETE(roomsParticipants[i], _FILE_AND_LINE_); roomsParticipants.Clear(false, _FILE_AND_LINE_); } void RoomsPlugin::SerializeLogin(SLNet::RakString userName, SystemAddress userAddress, RakNetGUID guid, SLNet::BitStream *bs) { bs->Write((MessageID)ID_ROOMS_LOGON_STATUS); bs->Write(userName); bs->Write(true); bs->Write(userAddress); bs->Write(guid); } void RoomsPlugin::SerializeLogoff(SLNet::RakString userName, SLNet::BitStream *bs) { bs->Write((MessageID)ID_ROOMS_LOGON_STATUS); bs->Write(userName); bs->Write(false); } void RoomsPlugin::SerializeChangeHandle(SLNet::RakString oldHandle, SLNet::RakString newHandle, SLNet::BitStream *bs) { bs->Write((MessageID)ID_ROOMS_HANDLE_CHANGE); bs->Write(oldHandle); bs->Write(newHandle); } void RoomsPlugin::ChangeHandle(SLNet::RakString oldHandle, SLNet::RakString newHandle) { RoomMemberHandleSet_Notification notification; notification.oldName=oldHandle; notification.newName=newHandle; roomsContainer.ChangeHandle( oldHandle, newHandle ); RoomsPluginParticipant* roomsPluginParticipant = GetParticipantByHandle( newHandle, SLNet::UNASSIGNED_SYSTEM_ADDRESS); if (roomsPluginParticipant && roomsPluginParticipant->GetRoom()) { notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } } void RoomsPlugin::AddLoginServerAddress(SystemAddress systemAddress) { unsigned int index = loginServers.GetIndexOf(systemAddress); if (index==(unsigned int) -1) loginServers.Push(systemAddress, _FILE_AND_LINE_ ); } void RoomsPlugin::RemoveLoginServerAddress(SystemAddress systemAddress) { unsigned int index = loginServers.GetIndexOf(systemAddress); if (index!=(unsigned int) -1) loginServers.RemoveAtIndexFast(index); } void RoomsPlugin::ClearLoginServerAdddresses(void) { loginServers.Clear(false, _FILE_AND_LINE_); } void RoomsPlugin::SetProfanityFilter(ProfanityFilter *pf) { profanityFilter=pf; } void RoomsPlugin::OnDetach(void) { Clear(); } void RoomsPlugin::OnShutdown(void) { Clear(); } void RoomsPlugin::Update(void) { if (!IsServer()) return; DataStructures::List timeoutExpired; DataStructures::List dereferencedPointers; DataStructures::List joinedRoomMembers; SLNet::TimeMS curTime = SLNet::GetTimeMS(); if (lastUpdateTime!=0) { SLNet::TimeMS elapsedTime = curTime-lastUpdateTime; roomsContainer.ProcessQuickJoins( timeoutExpired, joinedRoomMembers, dereferencedPointers, elapsedTime ); unsigned int i; for (i=0; i < timeoutExpired.Size(); i++) { QuickJoinExpired_Notification notification; notification.networkedQuickJoinUser=timeoutExpired[i]->networkedQuickJoinUser; ExecuteNotification(¬ification, ((RoomsPluginParticipant*)timeoutExpired[i]->roomsParticipant)); } for (i=0; i < joinedRoomMembers.Size(); i++) { ((RoomsPluginParticipant*)joinedRoomMembers[i].joiningMember)->lastRoomJoined=joinedRoomMembers[i].roomOutput->GetID(); QuickJoinEnteredRoom_Notification notificationToTarget; notificationToTarget.joinedRoomResult=joinedRoomMembers[i]; notificationToTarget.joinedRoomResult.agrc=&roomsContainer; ExecuteNotification(¬ificationToTarget, ((RoomsPluginParticipant*)joinedRoomMembers[i].joiningMember)); } for (i=0; i < joinedRoomMembers.Size(); i++) { RoomMemberJoinedRoom_Notification notificationToRoom; notificationToRoom.joinedRoomResult=&joinedRoomMembers[i]; notificationToRoom.joinedRoomResult->agrc=&roomsContainer; notificationToRoom.roomId=notificationToRoom.joinedRoomResult->roomDescriptor.lobbyRoomId; ExecuteNotificationToOtherRoomMembers(joinedRoomMembers[i].joiningMember->GetRoom(), (RoomsPluginParticipant*)joinedRoomMembers[i].joiningMember, ¬ificationToRoom); notificationToRoom.joinedRoomResult=0; } for (i=0; i < dereferencedPointers.Size(); i++) SLNet::OP_DELETE(dereferencedPointers[i], _FILE_AND_LINE_); } lastUpdateTime=curTime; } PluginReceiveResult RoomsPlugin::OnReceive(Packet *packet) { switch (packet->data[0]) { case ID_ROOMS_EXECUTE_FUNC: OnRoomsExecuteFunc(packet); break; case ID_ROOMS_LOGON_STATUS: OnLoginStatus(packet); break; case ID_ROOMS_HANDLE_CHANGE: OnHandleChange(packet); break; } return RR_CONTINUE_PROCESSING; } void RoomsPlugin::OnLoginStatus(Packet *packet) { unsigned int i; for (i=0; i < loginServers.Size(); i++) { if (loginServers[i]==packet->systemAddress) { SLNet::BitStream bs(packet->data, packet->length, false); bs.IgnoreBytes(1); SLNet::RakString name; bs.Read(name); bool loggedOn; bs.Read(loggedOn); SystemAddress userAddress; RakNetGUID guid; if (loggedOn) { bs.Read(userAddress); bs.Read(guid); LoginRoomsParticipant(name, userAddress, guid, packet->systemAddress); } else { LogoffRoomsParticipant(name, packet->systemAddress); } break; } } } void RoomsPlugin::OnHandleChange(Packet *packet) { unsigned int i; for (i=0; i < loginServers.Size(); i++) { if (loginServers[i]==packet->systemAddress) { SLNet::BitStream bs(packet->data, packet->length, false); bs.IgnoreBytes(1); SLNet::RakString oldHandle, newHandle; bs.Read(oldHandle); bs.Read(newHandle); ChangeHandle(oldHandle, newHandle); break; } } } void RoomsPlugin::OnRoomsExecuteFunc(Packet *packet) { SLNet::BitStream bs(packet->data, packet->length, false); bs.IgnoreBytes(1); if (packet->length<2) return; if (roomsCallback.Size()==0) return; switch (packet->data[1]) { case RPO_CREATE_ROOM: { CreateRoom_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->CreateRoom_Callback(packet->systemAddress,&func); } break; case RPO_ENTER_ROOM: { EnterRoom_Func func; func.joinedRoomResult.agrc=&roomsContainer; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->EnterRoom_Callback(packet->systemAddress,&func); } break; case RPO_JOIN_BY_FILTER: { JoinByFilter_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->JoinByFilter_Callback(packet->systemAddress,&func); } break; case RPO_LEAVE_ROOM: { LeaveRoom_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->LeaveRoom_Callback(packet->systemAddress,&func); } break; case RPO_GET_INVITES_TO_PARTICIPANT: { GetInvitesToParticipant_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->GetInvitesToParticipant_Callback(packet->systemAddress,&func); } break; case RPO_SEND_INVITE: { SendInvite_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SendInvite_Callback(packet->systemAddress,&func); } break; case RPO_ACCEPT_INVITE: { AcceptInvite_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->AcceptInvite_Callback(packet->systemAddress,&func); } break; case RPO_START_SPECTATING: { StartSpectating_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->StartSpectating_Callback(packet->systemAddress,&func); } break; case RPO_STOP_SPECTATING: { StopSpectating_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->StopSpectating_Callback(packet->systemAddress,&func); } break; case RPO_GRANT_MODERATOR: { GrantModerator_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->GrantModerator_Callback(packet->systemAddress,&func); } break; case RPO_CHANGE_SLOT_COUNTS: { ChangeSlotCounts_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->ChangeSlotCounts_Callback(packet->systemAddress,&func); } break; case RPO_SET_CUSTOM_ROOM_PROPERTIES: { SetCustomRoomProperties_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SetCustomRoomProperties_Callback(packet->systemAddress,&func); } break; case RPO_GET_ROOM_PROPERTIES: { GetRoomProperties_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->GetRoomProperties_Callback(packet->systemAddress,&func); } break; case RPO_CHANGE_ROOM_NAME: { ChangeRoomName_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->ChangeRoomName_Callback(packet->systemAddress,&func); } break; case RPO_SET_HIDDEN_FROM_SEARCHES: { SetHiddenFromSearches_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SetHiddenFromSearches_Callback(packet->systemAddress,&func); } break; case RPO_SET_DESTROY_ON_MODERATOR_LEAVE: { SetDestroyOnModeratorLeave_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SetDestroyOnModeratorLeave_Callback(packet->systemAddress,&func); } break; case RPO_SET_READY_STATUS: { SetReadyStatus_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SetReadyStatus_Callback(packet->systemAddress,&func); } break; case RPO_GET_READY_STATUS: { GetReadyStatus_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->GetReadyStatus_Callback(packet->systemAddress,&func); } break; case RPO_SET_ROOM_LOCK_STATE: { SetRoomLockState_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SetRoomLockState_Callback(packet->systemAddress,&func); } break; case RPO_GET_ROOM_LOCK_STATE: { GetRoomLockState_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->GetRoomLockState_Callback(packet->systemAddress,&func); } break; case RPO_ARE_ALL_MEMBERS_READY: { AreAllMembersReady_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->AreAllMembersReady_Callback(packet->systemAddress,&func); } break; case RPO_KICK_MEMBER: { KickMember_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->KickMember_Callback(packet->systemAddress,&func); } break; case RPO_UNBAN_MEMBER: { UnbanMember_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->UnbanMember_Callback(packet->systemAddress,&func); } break; case RPO_GET_BAN_REASON: { GetBanReason_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->GetBanReason_Callback(packet->systemAddress,&func); } break; case RPO_ADD_USER_TO_QUICK_JOIN: { AddUserToQuickJoin_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->AddUserToQuickJoin_Callback(packet->systemAddress,&func); } break; case RPO_REMOVE_USER_FROM_QUICK_JOIN: { RemoveUserFromQuickJoin_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RemoveUserFromQuickJoin_Callback(packet->systemAddress,&func); } break; case RPO_IS_IN_QUICK_JOIN: { IsInQuickJoin_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->IsInQuickJoin_Callback(packet->systemAddress,&func); } break; case RPO_SEARCH_BY_FILTER: { SearchByFilter_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SearchByFilter_Callback(packet->systemAddress,&func); } break; case RPO_CHANGE_HANDLE: { ChangeHandle_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->ChangeHandle_Callback(packet->systemAddress,&func); } break; case RPO_CHAT: { Chat_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->Chat_Callback(packet->systemAddress,&func); } break; case RPO_BITSTREAM: { Bitstream_Func func; if (!IsServer()) func.SerializeOut(false,&bs); else func.SerializeIn(false,&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->Bitstream_Callback(packet->systemAddress,&func); } break; case RPN_QUICK_JOIN_EXPIRED: { QuickJoinExpired_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->QuickJoinExpired_Callback(packet->systemAddress,&func); } break; case RPN_QUICK_JOIN_ENTERED_ROOM: { QuickJoinEnteredRoom_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->QuickJoinEnteredRoom_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_MEMBER_STARTED_SPECTATING: { RoomMemberStartedSpectating_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomMemberStartedSpectating_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_MEMBER_STOPPED_SPECTATING: { RoomMemberStoppedSpectating_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomMemberStoppedSpectating_Callback(packet->systemAddress,&func); } break; case RPN_MODERATOR_CHANGED: { ModeratorChanged_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->ModeratorChanged_Callback(packet->systemAddress,&func); } break; case RPN_SLOT_COUNTS_SET: { SlotCountsSet_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->SlotCountsSet_Callback(packet->systemAddress,&func); } break; case RPN_CUSTOM_ROOM_PROPERTIES_SET: { CustomRoomPropertiesSet_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->CustomRoomPropertiesSet_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_NAME_SET: { RoomNameSet_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomNameSet_Callback(packet->systemAddress,&func); } break; case RPN_HIDDEN_FROM_SEARCHES_SET: { HiddenFromSearchesSet_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->HiddenFromSearchesSet_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_MEMBER_READY_STATUS_SET: { RoomMemberReadyStatusSet_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomMemberReadyStatusSet_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_LOCK_STATE_SET: { RoomLockStateSet_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomLockStateSet_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_MEMBER_KICKED: { RoomMemberKicked_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomMemberKicked_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_MEMBER_HANDLE_SET: { RoomMemberHandleSet_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomMemberHandleSet_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_MEMBER_LEFT_ROOM: { RoomMemberLeftRoom_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomMemberLeftRoom_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_MEMBER_JOINED_ROOM: { RoomMemberJoinedRoom_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomMemberJoinedRoom_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_INVITATION_SENT: { RoomInvitationSent_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomInvitationSent_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_INVITATION_WITHDRAWN: { RoomInvitationWithdrawn_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomInvitationWithdrawn_Callback(packet->systemAddress,&func); } break; case RPN_ROOM_DESTROYED_ON_MODERATOR_LEFT: { RoomDestroyedOnModeratorLeft_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->RoomDestroyedOnModeratorLeft_Callback(packet->systemAddress,&func); } break; case RPN_CHAT_NOTIFICATION: { Chat_Notification func; func.Serialize(IsServer(),&bs); // When the filtered chat message is empty, that means the original chat message didn't have profanity anyway. if (func.filteredChatMessage.IsEmpty()) func.filteredChatMessage=func.chatMessage; for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->Chat_Callback(packet->systemAddress,&func); } break; case RPN_BITSTREAM_NOTIFICATION: { Bitstream_Notification func; func.Serialize(IsServer(),&bs); for (unsigned int rci=0; rci < roomsCallback.Size(); rci++) roomsCallback[rci]->Bitstream_Callback(packet->systemAddress,&func); } break; } } void RoomsPlugin::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ) { (void) lostConnectionReason; (void) rakNetGUID; RemoveUserResult removeUserResult; unsigned i; i=0; while (i < roomsParticipants.Size()) { if (roomsParticipants[i]->GetSystemAddress()==systemAddress) { roomsContainer.RemoveUser(roomsParticipants[i], &removeUserResult); ProcessRemoveUserResult(&removeUserResult); SLNet::OP_DELETE(roomsParticipants[i], _FILE_AND_LINE_); roomsParticipants.RemoveAtIndex(i); } else { i++; } } } void RoomsPlugin::Clear(void) { ClearRoomMembers(); ClearLoginServerAdddresses(); } bool RoomsPlugin::IsServer(void) const { RoomsCallback *rc=(RoomsCallback *) this; return roomsCallback.GetIndexOf(rc)!=(unsigned int) -1; } RoomsPlugin::RoomsPluginParticipant* RoomsPlugin::GetParticipantByHandle(SLNet::RakString handle, const SystemAddress &senderAddress) { (void) senderAddress; if (roomsParticipants.HasData(handle)) { RoomsPluginParticipant *rp = roomsParticipants.GetElementFromKey(handle); RakAssert(IsServer()); // 08/21/2012 - Uncommented: This was a bug with SendInvite_Func checking the sender's address against the invitees address // 10/27/2010 - what was this for? Caused the bug http://www.jenkinssoftware.com/forum/index.php?topic=3720.0;topicseen // This apparently validates the systemAddress to match the one in the function call if (senderAddress== SLNet::UNASSIGNED_SYSTEM_ADDRESS || senderAddress==serverAddress) return rp; if (rp->GetSystemAddress()!=senderAddress) return 0; return rp; } return 0; } RoomsPlugin::RoomsPluginParticipant* RoomsPlugin::ValidateUserHandle(RoomsPluginFunc* func, const SystemAddress &systemAddress) { if (func->userName.IsEmpty()) { func->resultCode=REC_USERNAME_IS_EMPTY; ExecuteFunc(func, systemAddress); return 0; } RoomsPluginParticipant* roomsPluginParticipant = GetParticipantByHandle(func->userName, systemAddress); if (roomsPluginParticipant==0) { func->resultCode=REC_NOT_LOGGED_IN; ExecuteFunc(func, systemAddress); } return roomsPluginParticipant; } void RoomsPlugin::CreateRoom_Callback( const SystemAddress &senderAddress, CreateRoom_Func *callResult) { RoomCreationParameters rcp; rcp.networkedRoomCreationParameters=callResult->networkedRoomCreationParameters; rcp.gameIdentifier=callResult->gameIdentifier; RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; rcp.firstUser=roomsPluginParticipant; callResult->resultCode=roomsContainer.CreateRoom(&rcp, profanityFilter); if (callResult->resultCode==REC_SUCCESS) { roomsPluginParticipant->lastRoomJoined=roomsPluginParticipant->GetRoom()->GetID(); callResult->roomId=roomsPluginParticipant->lastRoomJoined; if (callResult->initialRoomProperties.GetRowCount()>0) callResult->resultCode=roomsContainer.SetCustomRoomProperties( roomsPluginParticipant, &callResult->initialRoomProperties ); callResult->roomDescriptor.FromRoom(roomsPluginParticipant->GetRoom(), &roomsContainer); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::EnterRoom_Callback( const SystemAddress &senderAddress, EnterRoom_Func *callResult) { RoomCreationParameters rcp; rcp.networkedRoomCreationParameters=callResult->networkedRoomCreationParameters; rcp.gameIdentifier=callResult->gameIdentifier; RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; rcp.firstUser=roomsPluginParticipant; callResult->resultCode=roomsContainer.EnterRoom(&rcp, callResult->roomMemberMode, profanityFilter, &callResult->query, &callResult->joinedRoomResult); callResult->createdRoom=rcp.createdRoom; if (callResult->resultCode==REC_SUCCESS) { roomsPluginParticipant->lastRoomJoined=roomsPluginParticipant->GetRoom()->GetID(); callResult->roomId=roomsPluginParticipant->lastRoomJoined; if (callResult->joinedRoomResult.roomOutput) { RoomMemberJoinedRoom_Notification notificationToRoom; notificationToRoom.joinedRoomResult=&callResult->joinedRoomResult; notificationToRoom.roomId=notificationToRoom.joinedRoomResult->roomDescriptor.lobbyRoomId; ExecuteNotificationToOtherRoomMembers(callResult->joinedRoomResult.roomOutput, roomsPluginParticipant, ¬ificationToRoom); notificationToRoom.joinedRoomResult=0; } } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::JoinByFilter_Callback( const SystemAddress &senderAddress, JoinByFilter_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.JoinByFilter(callResult->gameIdentifier, callResult->roomMemberMode, roomsPluginParticipant, roomsPluginParticipant->lastRoomJoined, &callResult->query, &callResult->joinedRoomResult ); if (callResult->resultCode==REC_SUCCESS) { RakAssert(callResult->joinedRoomResult.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_SLOTS)==callResult->joinedRoomResult.roomOutput->roomMemberList.Size()-1); roomsPluginParticipant->lastRoomJoined=roomsPluginParticipant->GetRoom()->GetID(); RoomMemberJoinedRoom_Notification notificationToRoom; notificationToRoom.joinedRoomResult=&callResult->joinedRoomResult; notificationToRoom.roomId=notificationToRoom.joinedRoomResult->roomDescriptor.lobbyRoomId; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ificationToRoom); notificationToRoom.joinedRoomResult=0; } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::LeaveRoom_Callback( const SystemAddress &senderAddress, LeaveRoom_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.LeaveRoom( roomsPluginParticipant, &callResult->removeUserResult ); ProcessRemoveUserResult(&callResult->removeUserResult); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::GetInvitesToParticipant_Callback( const SystemAddress &senderAddress, GetInvitesToParticipant_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; DataStructures::List invitedUsers; callResult->resultCode=roomsContainer.GetInvitesToParticipant( roomsPluginParticipant, invitedUsers ); unsigned int i; for (i=0; i < invitedUsers.Size(); i++) callResult->invitedUsers.Insert(* (invitedUsers[i]), _FILE_AND_LINE_ ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::SendInvite_Callback( const SystemAddress &senderAddress, SendInvite_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; RoomsPluginParticipant* inviteeId = GetParticipantByHandle( callResult->inviteeName, UNASSIGNED_SYSTEM_ADDRESS ); if (inviteeId==0) { callResult->resultCode=REC_SEND_INVITE_RECIPIENT_NOT_ONLINE; ExecuteFunc(callResult, senderAddress); return; } callResult->resultCode=roomsContainer.SendInvite( roomsPluginParticipant, inviteeId, callResult->inviteToSpectatorSlot, callResult->subject, callResult->body ); if (callResult->resultCode==REC_SUCCESS) { RoomInvitationSent_Notification notification; notification.invitorName=roomsPluginParticipant->GetName(); notification.inviteeName=inviteeId->GetName(); notification.inviteToSpectatorSlot=callResult->inviteToSpectatorSlot; notification.subject=callResult->subject; notification.body=callResult->body; notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); ExecuteNotification(¬ification, inviteeId); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::AcceptInvite_Callback( const SystemAddress &senderAddress, AcceptInvite_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; Room *room; callResult->resultCode=roomsContainer.AcceptInvite( callResult->roomId, &room, roomsPluginParticipant, callResult->inviteSender ); if (callResult->resultCode==REC_SUCCESS) { RoomMemberJoinedRoom_Notification notificationToRoom; notificationToRoom.joinedRoomResult= SLNet::OP_NEW( _FILE_AND_LINE_ ); notificationToRoom.joinedRoomResult->acceptedInvitor=0; notificationToRoom.joinedRoomResult->acceptedInvitorName=callResult->inviteSender; notificationToRoom.joinedRoomResult->joiningMember=roomsPluginParticipant; notificationToRoom.joinedRoomResult->joiningMemberName=roomsPluginParticipant->GetName(); notificationToRoom.joinedRoomResult->roomDescriptor.FromRoom(roomsPluginParticipant->GetRoom(), &roomsContainer); notificationToRoom.joinedRoomResult->roomOutput=roomsPluginParticipant->GetRoom(); notificationToRoom.joinedRoomResult->agrc=&roomsContainer; notificationToRoom.roomId=notificationToRoom.joinedRoomResult->roomDescriptor.lobbyRoomId; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ificationToRoom); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::StartSpectating_Callback( const SystemAddress &senderAddress, StartSpectating_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.StartSpectating( roomsPluginParticipant ); if (callResult->resultCode==REC_SUCCESS) { RoomMemberStartedSpectating_Notification notification; //notification.userName=roomsPluginParticipant->GetName(); notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::StopSpectating_Callback( const SystemAddress &senderAddress, StopSpectating_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.StopSpectating( roomsPluginParticipant ); if (callResult->resultCode==REC_SUCCESS) { RoomMemberStoppedSpectating_Notification notification; //notification.userName=roomsPluginParticipant->GetName(); notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::GrantModerator_Callback( const SystemAddress &senderAddress, GrantModerator_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; RoomsPluginParticipant* newModerator = GetParticipantByHandle( callResult->newModerator, UNASSIGNED_SYSTEM_ADDRESS ); if (newModerator==0) { callResult->resultCode=REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_ONLINE; ExecuteFunc(callResult, senderAddress); return; } DataStructures::List clearedInvites; callResult->resultCode=roomsContainer.GrantModerator( roomsPluginParticipant, newModerator, clearedInvites ); if (callResult->resultCode==REC_SUCCESS) { ModeratorChanged_Notification notification; notification.oldModerator=roomsPluginParticipant->GetName(); notification.newModerator=newModerator->GetName(); notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); for (unsigned int i=0; i < clearedInvites.Size(); i++) { // Room *room = newModerator->GetRoom(); RoomInvitationWithdrawn_Notification roomnotification; roomnotification.invitedUser=clearedInvites[i]; ExecuteNotification(&roomnotification, GetParticipantByHandle(clearedInvites[i].target, SLNet::UNASSIGNED_SYSTEM_ADDRESS)); } } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::ChangeSlotCounts_Callback( const SystemAddress &senderAddress, ChangeSlotCounts_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.ChangeSlotCounts( roomsPluginParticipant, callResult->slots ); if (callResult->resultCode==REC_SUCCESS) { SlotCountsSet_Notification notification; notification.slots=callResult->slots; notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::SetCustomRoomProperties_Callback( const SystemAddress &senderAddress, SetCustomRoomProperties_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.SetCustomRoomProperties( roomsPluginParticipant, &callResult->table ); if (callResult->resultCode==REC_SUCCESS) { CustomRoomPropertiesSet_Notification notification; notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); notification.tablePtr=&callResult->table; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::GetRoomProperties_Callback( const SystemAddress &senderAddress, GetRoomProperties_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; Room *room; if (callResult->roomName.IsEmpty()) { room=roomsPluginParticipant->GetRoom(); if (room==0) { callResult->resultCode=REC_GET_ROOM_PROPERTIES_EMPTY_ROOM_NAME_AND_NOT_IN_A_ROOM; ExecuteFunc(callResult, senderAddress); return; } callResult->roomName=roomsPluginParticipant->GetRoom()->GetStringProperty(DefaultRoomColumns::TC_ROOM_NAME); } else { room = roomsContainer.GetRoomByName(callResult->roomName); if (room==0) { callResult->resultCode=REC_GET_ROOM_PROPERTIES_UNKNOWN_ROOM_NAME; ExecuteFunc(callResult, senderAddress); return; } } callResult->roomDescriptor.FromRoom(room, &roomsContainer); callResult->resultCode=REC_SUCCESS; ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::ChangeRoomName_Callback( const SystemAddress &senderAddress, ChangeRoomName_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; RoomNameSet_Notification notification; if (roomsPluginParticipant->GetRoom()) notification.oldName=roomsPluginParticipant->GetRoom()->GetStringProperty(DefaultRoomColumns::TC_ROOM_NAME); callResult->resultCode=roomsContainer.ChangeRoomName( roomsPluginParticipant, callResult->newRoomName, profanityFilter ); if (callResult->resultCode==REC_SUCCESS) { notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); notification.newName=callResult->newRoomName; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::SetHiddenFromSearches_Callback( const SystemAddress &senderAddress, SetHiddenFromSearches_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.SetHiddenFromSearches( roomsPluginParticipant, callResult->hiddenFromSearches ); if (callResult->resultCode==REC_SUCCESS) { HiddenFromSearchesSet_Notification notification; notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); notification.hiddenFromSearches=callResult->hiddenFromSearches; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::SetDestroyOnModeratorLeave_Callback( const SystemAddress &senderAddress, SetDestroyOnModeratorLeave_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.SetDestroyOnModeratorLeave( roomsPluginParticipant, callResult->destroyOnModeratorLeave ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::SetReadyStatus_Callback( const SystemAddress &senderAddress, SetReadyStatus_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.SetReadyStatus( roomsPluginParticipant, callResult->isReady ); DataStructures::List readyUsers; DataStructures::List unreadyUsers; unsigned int i; roomsPluginParticipant->GetRoom()->GetReadyStatus(readyUsers, unreadyUsers); if (callResult->resultCode==REC_SUCCESS) { RoomMemberReadyStatusSet_Notification notification; notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); notification.isReady=callResult->isReady; notification.roomMember=roomsPluginParticipant->GetName(); for (i=0; i < readyUsers.Size(); i++) notification.readyUsers.Insert(readyUsers[i]->GetName(), _FILE_AND_LINE_ ); for (i=0; i < unreadyUsers.Size(); i++) notification.unreadyUsers.Insert(unreadyUsers[i]->GetName(), _FILE_AND_LINE_ ); ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } for (i=0; i < readyUsers.Size(); i++) callResult->readyUsers.Insert(readyUsers[i]->GetName(), _FILE_AND_LINE_ ); for (i=0; i < unreadyUsers.Size(); i++) callResult->unreadyUsers.Insert(unreadyUsers[i]->GetName(), _FILE_AND_LINE_ ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::GetReadyStatus_Callback( const SystemAddress &senderAddress, GetReadyStatus_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; if (roomsPluginParticipant->GetRoom()==0) { callResult->resultCode=REC_GET_READY_STATUS_NOT_IN_ROOM; ExecuteFunc(callResult, senderAddress); return; } Room *room; DataStructures::List readyUsers; DataStructures::List unreadyUsers; callResult->resultCode=roomsContainer.GetReadyStatus( roomsPluginParticipant->GetRoom()->GetID(), &room, readyUsers, unreadyUsers ); unsigned int i; for (i=0; i < readyUsers.Size(); i++) callResult->readyUsers.Insert(readyUsers[i]->GetName(), _FILE_AND_LINE_ ); for (i=0; i < unreadyUsers.Size(); i++) callResult->unreadyUsers.Insert(unreadyUsers[i]->GetName(), _FILE_AND_LINE_ ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::SetRoomLockState_Callback( const SystemAddress &senderAddress, SetRoomLockState_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.SetRoomLockState( roomsPluginParticipant, callResult->roomLockState ); if (callResult->resultCode==REC_SUCCESS) { RoomLockStateSet_Notification notification; notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); notification.roomLockState=callResult->roomLockState; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::GetRoomLockState_Callback( const SystemAddress &senderAddress, GetRoomLockState_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; if (roomsPluginParticipant->GetRoom()==0) { callResult->resultCode=REC_GET_ROOM_LOCK_STATE_NOT_IN_ROOM; ExecuteFunc(callResult, senderAddress); return; } Room *room; callResult->resultCode=roomsContainer.GetRoomLockState( roomsPluginParticipant->GetRoom()->GetID(), &room, &callResult->roomLockState ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::AreAllMembersReady_Callback( const SystemAddress &senderAddress, AreAllMembersReady_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; if (roomsPluginParticipant->GetRoom()==0) { callResult->resultCode=REC_ARE_ALL_MEMBERS_READY_NOT_IN_ROOM; ExecuteFunc(callResult, senderAddress); return; } Room *room; callResult->resultCode=roomsContainer.AreAllMembersReady( roomsPluginParticipant->GetRoom()->GetID(), &room, &callResult->allReady ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::KickMember_Callback( const SystemAddress &senderAddress, KickMember_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; RoomsPluginParticipant* kickedMember = GetParticipantByHandle(callResult->kickedMember, SLNet::UNASSIGNED_SYSTEM_ADDRESS); if (kickedMember==0) { callResult->resultCode=REC_KICK_MEMBER_TARGET_NOT_ONLINE; ExecuteFunc(callResult, senderAddress); return; } callResult->resultCode=roomsContainer.KickMember( roomsPluginParticipant, kickedMember, callResult->reason ); if (callResult->resultCode==REC_SUCCESS) { RoomMemberKicked_Notification notification; notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); notification.moderator=roomsPluginParticipant->GetName(); notification.kickedMember=callResult->kickedMember; notification.reason=callResult->reason; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); // Also send notification to the guy kicked ExecuteNotification(¬ification, kickedMember); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::UnbanMember_Callback( const SystemAddress &senderAddress, UnbanMember_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=roomsContainer.UnbanMember( roomsPluginParticipant, callResult->bannedMemberName ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::GetBanReason_Callback( const SystemAddress &senderAddress, GetBanReason_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; Room *room; callResult->resultCode=roomsContainer.GetBanReason( callResult->roomId, &room, callResult->userName, &callResult->reason ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::AddUserToQuickJoin_Callback( const SystemAddress &senderAddress, AddUserToQuickJoin_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; QuickJoinUser *qju = SLNet::OP_NEW( _FILE_AND_LINE_ ); qju->networkedQuickJoinUser=callResult->networkedQuickJoinUser; qju->roomsParticipant=roomsPluginParticipant; callResult->resultCode=roomsContainer.AddUserToQuickJoin( callResult->gameIdentifier, qju ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::RemoveUserFromQuickJoin_Callback( const SystemAddress &senderAddress, RemoveUserFromQuickJoin_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; QuickJoinUser *qju; callResult->resultCode=roomsContainer.RemoveUserFromQuickJoin( roomsPluginParticipant, &qju ); if (qju) SLNet::OP_DELETE(qju, _FILE_AND_LINE_); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::IsInQuickJoin_Callback( const SystemAddress &senderAddress, IsInQuickJoin_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; callResult->resultCode=REC_SUCCESS; callResult->isInQuickJoin=roomsContainer.IsInQuickJoin( roomsPluginParticipant ); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::SearchByFilter_Callback( const SystemAddress &senderAddress, SearchByFilter_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; DataStructures::OrderedList roomsOutput; callResult->resultCode=roomsContainer.SearchByFilter( callResult->gameIdentifier, roomsPluginParticipant, &callResult->roomQuery, roomsOutput, callResult->onlyJoinable); unsigned i; RoomDescriptor *desc; for (i=0; i < roomsOutput.Size(); i++) { desc = SLNet::OP_NEW( _FILE_AND_LINE_ ); desc->FromRoom(roomsOutput[i], &roomsContainer); callResult->roomsOutput.Insert(desc, _FILE_AND_LINE_ ); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::ChangeHandle_Callback( const SystemAddress &senderAddress, ChangeHandle_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; if (profanityFilter->HasProfanity(callResult->newHandle.C_String())) { callResult->resultCode=REC_CHANGE_HANDLE_CONTAINS_PROFANITY; ExecuteFunc(callResult, senderAddress); return; } RoomMemberHandleSet_Notification notification; if (roomsPluginParticipant) notification.oldName=roomsPluginParticipant->GetName(); if (GetParticipantByHandle(callResult->newHandle, SLNet::UNASSIGNED_SYSTEM_ADDRESS)) { callResult->resultCode=REC_CHANGE_HANDLE_NEW_HANDLE_IN_USE; ExecuteFunc(callResult, senderAddress); return; } callResult->resultCode=REC_SUCCESS; roomsContainer.ChangeHandle( roomsPluginParticipant->GetName(), callResult->newHandle ); if (roomsPluginParticipant->GetRoom()) { notification.roomId=roomsPluginParticipant->GetRoom()->GetID(); notification.newName=callResult->newHandle; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); } ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::Chat_Callback( const SystemAddress &senderAddress, Chat_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; if (roomsPluginParticipant->GetRoom()==0 && callResult->chatDirectedToRoom) { callResult->resultCode=REC_CHAT_USER_NOT_IN_ROOM; ExecuteFunc(callResult, senderAddress); return; } Chat_Notification notification; notification.sender=roomsPluginParticipant->GetName(); notification.privateMessageRecipient=callResult->privateMessageRecipient; notification.chatMessage=callResult->chatMessage; notification.filteredChatMessage=callResult->chatMessage; if (profanityFilter) { char* buffer = notification.filteredChatMessage.C_StringUnsafe(); profanityFilter->FilterProfanity(notification.filteredChatMessage.C_String(), buffer, notification.filteredChatMessage.sharedString->bytesUsed, true); } if (notification.filteredChatMessage==notification.chatMessage) notification.filteredChatMessage.Clear(); // Save bandwidth if (!callResult->privateMessageRecipient.IsEmpty()) { RoomsPluginParticipant* recipient = GetParticipantByHandle(callResult->privateMessageRecipient, SLNet::UNASSIGNED_SYSTEM_ADDRESS); if (recipient==0) { callResult->resultCode=REC_CHAT_RECIPIENT_NOT_ONLINE; ExecuteFunc(callResult, senderAddress); return; } if (callResult->chatDirectedToRoom) { if (recipient->GetRoom()==0) { callResult->resultCode=REC_CHAT_RECIPIENT_NOT_IN_ANY_ROOM; ExecuteFunc(callResult, senderAddress); return; } if (recipient->GetRoom()!=roomsPluginParticipant->GetRoom()) { callResult->resultCode=REC_CHAT_RECIPIENT_NOT_IN_YOUR_ROOM; ExecuteFunc(callResult, senderAddress); return; } } callResult->resultCode=REC_SUCCESS; ExecuteNotification(¬ification, recipient); ExecuteFunc(callResult, senderAddress); return; } else { if (!callResult->chatDirectedToRoom) { // Chat not directed to room, and no recipients. callResult->resultCode=REC_CHAT_RECIPIENT_NOT_ONLINE; ExecuteFunc(callResult, senderAddress); return; } } callResult->resultCode=REC_SUCCESS; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::Bitstream_Callback( const SystemAddress &senderAddress, Bitstream_Func *callResult) { RoomsPluginParticipant* roomsPluginParticipant = ValidateUserHandle(callResult, senderAddress); if (roomsPluginParticipant==0) return; if (roomsPluginParticipant->GetRoom()==0 && callResult->directedToRoom) { callResult->resultCode=REC_BITSTREAM_USER_NOT_IN_ROOM; ExecuteFunc(callResult, senderAddress); return; } Bitstream_Notification notification; notification.sender=roomsPluginParticipant->GetName(); notification.privateMessageRecipient=callResult->privateMessageRecipient; notification.bitStreamReceived.Write(callResult->bsToSend); if (!callResult->privateMessageRecipient.IsEmpty()) { RoomsPluginParticipant* recipient = GetParticipantByHandle(callResult->privateMessageRecipient, SLNet::UNASSIGNED_SYSTEM_ADDRESS); if (recipient==0) { callResult->resultCode=REC_BITSTREAM_RECIPIENT_NOT_ONLINE; ExecuteFunc(callResult, senderAddress); return; } if (callResult->directedToRoom) { if (recipient->GetRoom()==0) { callResult->resultCode=REC_BITSTREAM_RECIPIENT_NOT_IN_ANY_ROOM; ExecuteFunc(callResult, senderAddress); return; } if (recipient->GetRoom()!=roomsPluginParticipant->GetRoom()) { callResult->resultCode=REC_BITSTREAM_RECIPIENT_NOT_IN_YOUR_ROOM; ExecuteFunc(callResult, senderAddress); return; } } callResult->resultCode=REC_SUCCESS; ExecuteNotification(¬ification, recipient); ExecuteFunc(callResult, senderAddress); return; } else { if (!callResult->directedToRoom) { // Chat not directed to room, and no recipients. callResult->resultCode=REC_BITSTREAM_RECIPIENT_NOT_ONLINE; ExecuteFunc(callResult, senderAddress); return; } } callResult->resultCode=REC_SUCCESS; ExecuteNotificationToOtherRoomMembers(roomsPluginParticipant->GetRoom(), roomsPluginParticipant, ¬ification); ExecuteFunc(callResult, senderAddress); } void RoomsPlugin::ProcessRemoveUserResult(RemoveUserResult *removeUserResult) { unsigned int j; for (j=0; j < removeUserResult->clearedInvitations.Size(); j++) { RoomsPluginParticipant* invitationRecipient = GetParticipantByHandle(removeUserResult->clearedInvitations[j].target, SLNet::UNASSIGNED_SYSTEM_ADDRESS); if (invitationRecipient) { RoomInvitationWithdrawn_Notification notification; notification.invitedUser=removeUserResult->clearedInvitations[j]; ExecuteNotification(¬ification, invitationRecipient); } } if (removeUserResult->removedFromRoom) { if (removeUserResult->room) { if (!removeUserResult->roomDestroyed) { if (removeUserResult->gotNewModerator) { ModeratorChanged_Notification notification; notification.oldModerator=removeUserResult->removedUserName; notification.newModerator=removeUserResult->room->GetModerator()->GetName(); ExecuteNotificationToOtherRoomMembers(removeUserResult->room, 0, ¬ification); } RoomMemberLeftRoom_Notification notification; notification.roomId=removeUserResult->room->GetID(); notification.roomMember=removeUserResult->removedUserName; ExecuteNotificationToOtherRoomMembers(removeUserResult->room, 0, ¬ification); } else { RoomDestroyedOnModeratorLeft_Notification notification; notification.oldModerator=removeUserResult->removedUserName; notification.roomId=removeUserResult->room->GetID(); notification.roomDescriptor.FromRoom(removeUserResult->room, &roomsContainer); ExecuteNotificationToOtherRoomMembers(removeUserResult->room, 0, ¬ification); } } } if (removeUserResult->removedFromQuickJoin) { if (removeUserResult->qju) SLNet::OP_DELETE(removeUserResult->qju, _FILE_AND_LINE_); } roomsContainer.DestroyRoomIfDead(removeUserResult->room); } void RoomsPlugin::ExecuteNotificationToOtherRoomMembers(Room *room, RoomsPluginParticipant* roomsPluginParticipant, RoomsPluginNotification *notification) { unsigned roomMemberIndex; for (roomMemberIndex=0; roomMemberIndex < room->roomMemberList.Size(); roomMemberIndex++) { if (room->roomMemberList[roomMemberIndex]->roomsParticipant!=roomsPluginParticipant ) ExecuteNotification(notification, ((RoomsPluginParticipant*)room->roomMemberList[roomMemberIndex]->roomsParticipant)); } }