/* * 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-2017, 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 #include #include "Lobby2Client_Steam.h" // If Lobby2Client_Steam.h is included before SocketLayer.h, then it will use the steam send functions #include "Lobby2Message_Steam.h" #include "slikenet/time.h" #include "slikenet/sleep.h" #include "slikenet/types.h" #include "slikenet/peerinterface.h" #include "slikenet/GetTime.h" #include "slikenet/MessageIdentifiers.h" #include #include #include "slikenet/Gets.h" #include "slikenet/FullyConnectedMesh2.h" #pragma warning( push ) #pragma warning(disable:4127) // conditional expression is constant (with Steamworks 1.23a) #include "steam_api.h" #pragma warning( pop ) using namespace SLNet; Lobby2MessageFactory_Steam *messageFactory; Lobby2Client_Steam *lobby2Client; SLNet::RakPeerInterface *rakPeer; SLNet::FullyConnectedMesh2 *fcm2; uint64_t lastRoom; void PrintCommands(void) { printf("a. GetRoomList\n"); printf("b. LeaveRoom\n"); printf("c. CreateRoom\n"); printf("d. JoinRoom\n"); printf("e. RefreshRoom\n"); printf("f. SendRoomChatMessage\n"); printf("g. ListRoomMembers\n"); printf("?. Help\n"); printf("(Escape). Quit\n"); } struct SteamResults : public SLNet::Lobby2Callbacks { virtual void MessageResult(SLNet::Notification_Console_MemberJoinedRoom *message) { SLNet::Notification_Console_MemberJoinedRoom_Steam *msgSteam = (SLNet::Notification_Console_MemberJoinedRoom_Steam *) message; SLNet::RakString msg; msgSteam->DebugMsg(msg); printf("%s\n", msg.C_String()); // Guy with the lower ID connects to the guy with the higher ID uint64_t mySteamId=SteamUser()->GetSteamID().ConvertToUint64(); if (mySteamId < msgSteam->srcMemberId) { // Steam's NAT punch is implicit, so it takes a long time to connect. Give it extra time unsigned int sendConnectionAttemptCount=24; unsigned int timeBetweenSendConnectionAttemptsMS=500; ConnectionAttemptResult car = rakPeer->Connect(msgSteam->remoteSystem.ToString(false), msgSteam->remoteSystem.GetPort(), 0, 0, 0, 0, sendConnectionAttemptCount, timeBetweenSendConnectionAttemptsMS); RakAssert(car==CONNECTION_ATTEMPT_STARTED); } } virtual void MessageResult(SLNet::Console_SearchRooms *message) { SLNet::Console_SearchRooms_Steam *msgSteam = (SLNet::Console_SearchRooms_Steam *) message; SLNet::RakString msg; msgSteam->DebugMsg(msg); printf("%s\n", msg.C_String()); if (msgSteam->roomIds.GetSize()>0) { lastRoom=msgSteam->roomIds[0]; } } virtual void ExecuteDefaultResult(SLNet::Lobby2Message *message) { SLNet::RakString out; message->DebugMsg(out); printf("%s\n", out.C_String()); } }; 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 = SLNet::RakPeerInterface::GetInstance(); fcm2 = SLNet::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, ""); SLNet::Lobby2Message* msg = messageFactory->Alloc(SLNet::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) { SLNet::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== SLNet::UNASSIGNED_SYSTEM_ADDRESS) printf("Got new host (ourselves)"); else printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString()); SLNet::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': { SLNet::Lobby2Message* logoffMsg = messageFactory->Alloc(SLNet::L2MID_Console_SearchRooms); lobby2Client->SendMsg(logoffMsg); messageFactory->Dealloc(logoffMsg); } break; case 'b': { if (lobby2Client->GetRoomID()==0) { printf("Not in a room\n"); break; } SLNet::Console_LeaveRoom_Steam* leaveroomMsg = (SLNet::Console_LeaveRoom_Steam*) messageFactory->Alloc(SLNet::L2MID_Console_LeaveRoom); leaveroomMsg->roomId=lobby2Client->GetRoomID(); lobby2Client->SendMsg(leaveroomMsg); messageFactory->Dealloc(leaveroomMsg); } break; case 'c': { if (lobby2Client->GetRoomID()!=0) { printf("Already in a room\n"); break; } SLNet::Console_CreateRoom_Steam* createroomMsg = (SLNet::Console_CreateRoom_Steam*) messageFactory->Alloc(SLNet::L2MID_Console_CreateRoom); // set the name of the lobby if it's ours char rgchLobbyName[256]; createroomMsg->roomIsPublic=true; _snprintf( rgchLobbyName, sizeof( rgchLobbyName ), "%s's lobby", SteamFriends()->GetPersonaName() ); createroomMsg->roomName=rgchLobbyName; createroomMsg->publicSlots=8; lobby2Client->SendMsg(createroomMsg); messageFactory->Dealloc(createroomMsg); } break; case 'd': { if (lobby2Client->GetRoomID()!=0) { printf("Already in a room\n"); break; } SLNet::Console_JoinRoom_Steam* joinroomMsg = (SLNet::Console_JoinRoom_Steam*) messageFactory->Alloc(SLNet::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) { joinroomMsg->roomId=lastRoom; } else { joinroomMsg->roomId=_atoi64(str); } lobby2Client->SendMsg(joinroomMsg); messageFactory->Dealloc(joinroomMsg); } break; case 'e': { if (lobby2Client->GetRoomID()==0) { printf("Not in a room\n"); break; } SLNet::Console_GetRoomDetails_Steam* roomdetailsMsg = (SLNet::Console_GetRoomDetails_Steam*) messageFactory->Alloc(SLNet::L2MID_Console_GetRoomDetails); roomdetailsMsg->roomId=lobby2Client->GetRoomID(); lobby2Client->SendMsg(roomdetailsMsg); messageFactory->Dealloc(roomdetailsMsg); } break; case 'f': { if (lobby2Client->GetRoomID()==0) { printf("Not in a room\n"); break; } SLNet::Console_SendRoomChatMessage_Steam* roomchatMsg = (SLNet::Console_SendRoomChatMessage_Steam*) messageFactory->Alloc(SLNet::L2MID_Console_SendRoomChatMessage); roomchatMsg->message="Test chat message."; roomchatMsg->roomId=lobby2Client->GetRoomID(); lobby2Client->SendMsg(roomchatMsg); messageFactory->Dealloc(roomchatMsg); } break; case 'g': { DataStructures::OrderedList 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); } SLNet::Lobby2Message* logoffMsg = messageFactory->Alloc(SLNet::L2MID_Client_Logoff); lobby2Client->SendMsg(logoffMsg); messageFactory->Dealloc(logoffMsg); rakPeer->DetachPlugin(lobby2Client); rakPeer->DetachPlugin(fcm2); SLNet::RakPeerInterface::DestroyInstance(rakPeer); Lobby2Client_Steam::DestroyInstance(lobby2Client); SLNet::FullyConnectedMesh2::DestroyInstance(fcm2); return 1; }