void RunAsClient(void) { rakClient = RakNetworkFactory::GetRakPeerInterface(); // Apple is defined in "Common.h", and it's our class derived from NetworkIDObject Apple *serverApple = 0; #if DOLOG clientLogger.SetPrefix("CLIENT> "); clientLogger.SetSuffix("\n"); rakClient->AttachPlugin(&clientLogger); #endif char serverip[256]; printf("Enter ip of the server (ENTER defaults to 127.0.0.1): "); gets(serverip); if (serverip[0]==0) strcpy(serverip, "127.0.0.1"); char serverport[256]; printf("Enter port of the server (ENTER defaults to 60000): "); gets(serverport); if (serverport[0]==0) strcpy(serverport, "60000"); rakClient->Startup(1, 30, &SocketDescriptor(), 1); rakClient->Connect(serverip, atoi(serverport), 0,0); // In a client/server architecture, only the server can create NetworkIDs clientNetworkIDManager.SetIsNetworkIDAuthority(false); rakClient->SetNetworkIDManager(&clientNetworkIDManager); // Clear keyboard buffer before entering loop while(kbhit()) getch(); do{ Packet *p = rakClient->Receive(); while(p){ unsigned char msgID = p->data[0]; // Check if the server has sent us the NetworkID of his Apple object if (msgID==ID_USER_SERVERAPPLE_CREATED) { RakNet::BitStream bs(p->data, p->length, false); // Ignore the message ID bs.IgnoreBits(8); NetworkID appleNetworkID; bs.Read(appleNetworkID); // Create the object on the client side serverApple = new GrannySmith; serverApple->SetNetworkIDManager(&clientNetworkIDManager); serverApple->SetNetworkID(appleNetworkID); // Now that we have the object created, we can use RPC on it. const char *hello="Hello World!!!!!"; rakClient->RPC(CLASS_MEMBER_ID(Apple,func1), hello, (unsigned int) (strlen(hello)+1)*8, HIGH_PRIORITY, RELIABLE_ORDERED,0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, serverApple->GetNetworkID(),0); rakClient->RPC(CLASS_MEMBER_ID(Apple,func2), hello, (unsigned int) (strlen(hello)+1)*8, HIGH_PRIORITY, RELIABLE_ORDERED,0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, serverApple->GetNetworkID(),0); rakClient->RPC(CLASS_MEMBER_ID(Apple,func3), hello, (unsigned int) (strlen(hello)+1)*8, HIGH_PRIORITY, RELIABLE_ORDERED,0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, serverApple->GetNetworkID(),0); } rakClient->DeallocatePacket(p); p = rakClient->Receive(); } // Sleep for a while, so we don't eat all the CPU time with such a simple program. // In a real game, you probably won't need this, as you want your game to run at full speed. RakSleep(30); } while(!kbhit()); // Shutdown if (serverApple) delete serverApple; rakClient->Shutdown(300); RakNetworkFactory::DestroyRakPeerInterface(rakClient); }
void WorldLoop(CONNECT_INFO* cfg, Ref< UsersPool > OnlineUsers, Ref< CharactersPool> OnlineCharacters, Ref< CrossThreadQueue< string > > OutputQueue) { // Initialize the RakPeerInterface used throughout the entire server rakServer = RakNetworkFactory::GetRakPeerInterface(); // Initialize the PacketFileLogger plugin (for the logs) PacketFileLogger* msgFileHandler = NULL; if (cfg->logFile) { msgFileHandler = new PacketFileLogger(); rakServer->AttachPlugin(msgFileHandler); } // Initialize security IF user has enabled it in config.ini InitSecurity(rakServer, cfg->useEncryption); // Initialize the SocketDescriptor SocketDescriptor socketDescriptor(cfg->listenPort, 0); // If the startup of the server is successful, print it to the console // Otherwise, quit the server (as the char server is REQUIRED for the // server to function properly) if (rakServer->Startup(8, 30, &socketDescriptor, 1)) { stringstream s; s << "world started! Listening on: " << cfg->listenPort << "\n"; OutputQueue->Insert(s.str()); } else exit(2); rakServer->SetNetworkIDManager(&networkIdManager); rakServer->AttachPlugin(&replicaManager); networkIdManager.SetIsNetworkIDAuthority(true); // Attach the ReplicaManager2 replicaManager.SetAutoSerializeInScope(true); replicaManager.SetAutoParticipateNewConnections(true); replicaManager.SetAutoConstructToNewParticipants(true); // Set max incoming connections to 8 rakServer->SetMaximumIncomingConnections(8); // If msgFileHandler is not NULL, save logs of char server if (msgFileHandler != NULL) msgFileHandler->StartLog(".\\logs\\world"); // Initialize the Packet class for the packets Packet* packet; // This will be used in the saving of packets below int i = 0; ZoneId zone = NIMBUS_ISLE; // This will be used in the saving of packets below... while (!LUNIterminate) { RakSleep(30); // This sleep keeps RakNet responsive packet = rakServer->Receive(); // Recieve the packets from the server if (packet == NULL) continue; // If packet is NULL, just continue without processing anything // This will save all packets recieved from the client if running from DEBUG #ifdef DEBUG stringstream packetName; packetName << ".//Saves//World_Packet" << i << ".bin"; if (packet->data[3] != 22) { SavePacket(packetName.str(), (char*)packet->data, packet->length); i++; } #endif // Create and send packets back here according to the one we got switch (packet->data[0]) { case ID_USER_PACKET_ENUM: switch (packet->data[1]) { case GENERAL: if (packet->data[3] == 0) { // thats just a formality so far since no other numbers occured for this case auto v = OpenPacket(".\\worldTest\\init_aw2.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); } break; case WORLD: switch (packet->data[3]) { case CLIENT_VALIDATION: { auto usr = OnlineUsers->Find(packet->systemAddress); //this packets contains ZoneId and something else... but what? // it starts whit: 53 05 00 02 00 00 00 00 -- -- (<-ZoneId) ?? ?? ?? vector< uchar > v; /*if (usr != NULL && usr->nextcid == 2444680020) { //monkeybrown v = OpenPacket(".\\world\\monkeybrown\\char_aw2.bin"); } else if (usr != NULL && usr->nextcid == 1534792735) { //gruntmonkey v = OpenPacket(".\\world\\gruntmonkey\\char_aw2.bin"); } else if (usr != NULL && usr->nextcid == 1457240027) { //shafantastic v = OpenPacket(".\\world\\shastafantastic\\char_aw22.bin"); } else { //cheekymonkey v = OpenPacket(".\\world\\char_aw2.bin"); }*/ if (zone == NIMBUS_ISLE) v = OpenPacket(".\\world\\char_aw2.bin"); else if (zone == NIMBUS_STATION) { v = OpenPacket(".\\worldTest\\NS\\char_aw2.bin"); } else if (zone == LEGO_CLUB) { v = OpenPacket(".\\worldTest\\LC\\char_aw2.bin"); } //ReadCompressedLDFData(); #ifdef DEBUG if (v.size() > 0) { RakNet::BitStream bs(CleanPacket(v.data(), v.size()), v.size() - 8, false); ZoneId zid; bs.Read(zid); stringstream s; s << "\nLoading world: " << zid << endl; OutputQueue->Insert(s.str()); } else OutputQueue->Insert("\nWorld Error: can't load char_aw2.bin\n"); #endif ServerSendPacket(rakServer, v, packet->systemAddress); if (zone == NIMBUS_ISLE) { //auto character = Character::InitializeCharacter(12241); //character->WriteInitPacket(rakServer, packet->systemAddress); v = OpenPacket(".\\worldTest\\game_msg1.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); v = OpenPacket(".\\worldTest\\game_msg2.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); } else if (zone == NIMBUS_STATION) { v = OpenPacket(".\\worldTest\\NS\\msg1.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); } else if (zone == LEGO_CLUB) { v = OpenPacket(".\\worldTest\\LC\\msg1.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); v = OpenPacket(".\\worldTest\\LC\\msg2.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); } } break; case CLIENT_GAME_MSG: { #ifdef DEBUG vector< uchar > t; for (int i = 8; i <= 11; i++) t.push_back(packet->data[i]); ulong cid = *(ulong*)t.data(); cout << "Character wants to do something using packet: " << RawDataToString(packet->data, packet->length) << endl; //cout << "\nCharacter id is doing something?: " << cid; #endif if (packet->length >= 18) { ushort gameMsg; memcpy(&gameMsg, (uchar*)packet->data + 0x10, 2); cout << "Game Message ID is: " << gameMsg << endl; auto user = OnlineUsers->Find(packet->systemAddress); HandleGameMessage(rakServer, packet->systemAddress, gameMsg, (uchar*)packet->data, packet->length, user); break; } } case CLIENT_GENERAL_CHAT_MESSAGE: { auto usr = OnlineUsers->Find(packet->systemAddress); vector<uchar> chatMsg; /*for (uchar i = 0; i <= packet->length; i++) { chatMsg.push_back(packet->data[0x0f + i++]); if (packet->data[0x0f + i + 1] == 0) { i++; break; } } chatMsg.push_back(0); string msg(chatMsg.begin(), chatMsg.end());*/ for (uchar i = 15; i < packet->length; i++) { chatMsg.push_back(packet->data[i]); } string wMsg(chatMsg.begin(), chatMsg.end()); cout << "User entered: " << wMsg.c_str() << endl; RakNet::BitStream bitStream; CreatePacketHeader(ID_USER_PACKET_ENUM, 2, 1, &bitStream); ulonglong l1 = 0; uchar l2 = 0; ushort l3 = 0; ulonglong senderID = 63515; bitStream.Write(l1); bitStream.Write(l2); bitStream.Write((uchar)(wMsg.length() * 2 + 2)); bitStream.Write(l2); bitStream.Write(l3); string x1 = ""; wstring emptyUser = StringToWString(x1, 66); bitStream.Write((char*)emptyUser.data(), sizeof(wchar_t)* emptyUser.size() / 2); bitStream.Write(senderID); bitStream.Write(l3); bitStream.Write((uchar)1); bitStream.Write((char*)wMsg.data(), sizeof(char)* wMsg.length()); rakServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false); SavePacket("msg_response.bin", (char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed()); /*RakNet::BitStream bitStream2; CreatePacketHeader(ID_USER_PACKET_ENUM, 5, 12, &bitStream2); ushort u2 = 858; ulong u3 = 0; ushort u4 = 0; bitStream2.Write(u1); bitStream2.Write(u2); bitStream2.Write(u3); bitStream2.Write(u4); bitStream2.Write(wMsg.length()); bitStream2.Write(wMsg); rakServer->Send(&bitStream2, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false); SavePacket("hi_msg.bin", (char*)bitStream2.GetData(), bitStream2.GetNumberOfBytesUsed());*/ } break; case CLIENT_LEVEL_LOAD_COMPLETE: { // Response: 05, 04 // The answer to this is compressed data detailing character data // also since the answer seems to consist of a split packet, does RakNet automatically split the packets if the data is too big? or do we have to do something, if yes what? // byte 08 (2 or 4 bytes long? I guess 4...) seems to define the size of the data we send, no idea what the data itself is though... auto usr = OnlineUsers->Find(packet->systemAddress); // If the user is not equal to null and next character id = below number, // Open the packets of monkeybrown and load him into a world /*if (usr != NULL && usr->nextcid == 2444680020) { cout << "\n Replying to monkeybrown\n"; auto v = OpenPacket(".\\world\\monkeybrown\\rocket_1a.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); v = OpenPacket(".\\world\\monkeybrown\\rocket_1b.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); v = OpenPacket(".\\world\\monkeybrown\\rocket_1c.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); v = OpenPacket(".\\world\\monkeybrown\\world_2a.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); // test, is this the right thing to do? there's no difference in the process when they are (not) sent so far v = OpenPacket(".\\world\\monkeybrown\\world_2b.bin"); // I assume these two are sent together? ServerSendPacket(rakServer, v, packet->systemAddress); for (int i = 0; i < 42; i++) { // herpaderp stringstream fl; fl << ".\\world\\monkeybrown\\test\\world_2_" << (i + 1) << ".bin"; auto v = OpenPacket(fl.str()); ServerSendPacket(rakServer, v, packet->systemAddress); } v = OpenPacket(".\\world\\monkeybrown\\test\\world_2_1.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); for (int i = 42; i < 210; i++) { // herpaderp stringstream fl; fl << ".\\world\\monkeybrown\\test\\world_2_" << (i + 1) << ".bin"; auto v = OpenPacket(fl.str()); ServerSendPacket(rakServer, v, packet->systemAddress); } } else { // Otherwise, reply to Cheekymonkey and open his packets*/ cout << "\n Replying to Character\n"; //auto v = OpenPacket("LEGO Software.bin"); cout << "Attempting to create new char..." << endl; //if (character == 0) { //cout << "Creating new char..." << endl; //character = new Character(63450); //replicaManager.Construct(character, false, UNASSIGNED_SYSTEM_ADDRESS, true); //replicaManager.SignalSerializeNeeded(character, UNASSIGNED_SYSTEM_ADDRESS, true); //} auto v = OpenPacket(".\\world\\world_2a.bin"); if (v.size() <= 0) { cout << "World 2A contains no data!!!!" << endl; } ServerSendPacket(rakServer, v, packet->systemAddress); // test, is this the right thing to do? there's no difference in the process when they are (not) sent so far v = OpenPacket(".\\world\\world_2b.bin"); // I assume these two are sent together? ServerSendPacket(rakServer, v, packet->systemAddress); auto currentChar = OnlineCharacters->Find(packet->systemAddress); replicaManager.Construct(currentChar.Get(), false, UNASSIGNED_SYSTEM_ADDRESS, true); //replicaManager.Construct(character, false, UNASSIGNED_SYSTEM_ADDRESS, true); if (zone == NIMBUS_ISLE) { for (int i = 1; i < 5; i++) { // herpaderp stringstream fl; fl << ".\\world\\test\\world_2_" << (i + 1) << ".bin"; auto v = OpenPacket(fl.str()); ServerSendPacket(rakServer, v, packet->systemAddress); } //auto character = Character::InitializeCharacter(12241); //character->WriteInitPacket(rakServer, packet->systemAddress); } else if (zone == NIMBUS_STATION) { auto v = OpenPacket(".\\worldTest\\NS\\msg1.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); for (int i = 1; i < 10; i++) { stringstream fl; fl << ".\\worldTest\\NS\\replica\\ns_replica" << i << ".bin"; v = OpenPacket(fl.str()); ServerSendPacket(rakServer, v, packet->systemAddress); } for (int j = 1; j < 10; j++) { stringstream fl2; fl2 << ".\\worldTest\\NS\\messages\\ns_message" << j << endl; v = OpenPacket(fl2.str()); ServerSendPacket(rakServer, v, packet->systemAddress); } } else if (zone == LEGO_CLUB) { cout << "Loading LEGO CLUB" << endl; for (int i = 47; i < 300; i) { stringstream packetName; packetName << ".\\..\\..\\..\\..\\Downloaded Packets\\GruntMonkey\\Lego Club - 42\\output_data\\" << i << "s.bin"; auto v = OpenPacket(packetName.str()); if (v.size() > 0) { ServerSendPacket(rakServer, v, packet->systemAddress); } for (int j = 0; j < 20; j) { stringstream packetName2; packetName2 << ".\\..\\..\\..\\..\\Downloaded Packets\\GruntMonkey\\Lego Club - 42\\output_data\\" << i << "s_" << j << ".bin"; v = OpenPacket(packetName2.str()); if (v.size() > 0) { ServerSendPacket(rakServer, v, packet->systemAddress); } j++; } i++; } cout << "DONE Loading LEGO CLUB" << endl; } //} /*cout << "Loading Venture Explorer for character..." << endl; auto v = OpenPacket(".\\worldTest\\char\\char_load.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); v = OpenPacket(".\\worldTest\\char\\server_status.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); for (int i = 1; i <= 50; i++) { stringstream fileName; fileName << ".\\worldTest\\replica\\replica" << i << ".bin"; v = OpenPacket(fileName.str()); ServerSendPacket(rakServer, v, packet->systemAddress); }*/ /*for (int i = 35; i <= 789; i++) { stringstream fileName; fileName << ".\\worldTest\\replicaTest\\" << i << "s.bin"; auto v = OpenPacket(fileName.str()); if (v.data() > 0) { cout << "Sending file: " << fileName.str() << endl; ServerSendPacket(rakServer, v, packet->systemAddress); } for (int j = 2; j < 12; j++) { stringstream fileNameStr; fileNameStr << ".\\worldTest\\replicaTest\\" << i << "s_" << j << ".bin"; v = OpenPacket(fileNameStr.str()); if (v.data() > 0) { cout << "Sending file: " << fileNameStr.str() << endl; ServerSendPacket(rakServer, v, packet->systemAddress); } } }*/ } break; case CLIENT_MAIL: { auto usr = OnlineUsers->Find(packet->systemAddress); uint mailID; memcpy(&mailID, packet->data + 0x08, 4); if (mailID == 3) { FetchMailData(rakServer, packet->systemAddress, usr); } } break; case CLIENT_ROUTE_PACKET: { uchar remoteConnection; uchar packetID; memcpy(&remoteConnection, packet->data + 0x0C, 1); memcpy(&packetID, packet->data + 0x0E, 1); /*if (remoteConnection == 2 && packetID == 10) { auto character = OnlineUsers->FindChar(packet->systemAddress); character->CreateFriendsList(rakServer, packet->systemAddress, character->charObjectID); }*/ } break; case CLIENT_STRING_CHECK: { uchar requestID = packet->data[9]; cout << "Getting char moderation request with id: " << requestID << endl; RakNet::BitStream bitStream; CreatePacketHeader(ID_USER_PACKET_ENUM, 5, 59, &bitStream); bitStream.Write((uchar)1); bitStream.Write((ushort)0); bitStream.Write(requestID); rakServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false); } break; case 22: //user moving / update request? { auto usr = OnlineUsers->Find(packet->systemAddress); #ifdef DEBUG //OutputQueue->Insert("Received packet 22: " + RawDataToString(packet->data, packet->length) + "\n"); #endif } break; /*case LUNI_WORLD_CHAT: //user wrote a chat message { if (packet->length >= 10 && RawDataToString(packet->data + packet->length - 10, 10, true) == "730064006f0077006e00") {//virus used to be here } // dummy try vector< uchar > v(packet->length); for (uint i = 0; i < packet->length; i++) v.push_back(packet->data[i]); ServerSendPacket(rakServer, v, packet->systemAddress); }*/ break; /*case 5: { #ifdef DEBUG vector< uchar > t; for (int i = 8; i <= 11; i++) t.push_back(packet->data[i]); ulong cid = *(ulong*)t.data(); cout << "Character wants to do something using packet: " << RawDataToString(packet->data, packet->length) << endl; //cout << "\nCharacter id is doing something?: " << cid; #endif if (packet->data[0x1A] == 123 && packet->data[0x1B] == 33 & packet->data[0x1C] == 22) { cout << "Sending char to new world..." << endl; zone = NIMBUS_STATION; auto v = OpenPacket(".\\worldTest\\init_aw2.bin"); ServerSendPacket(rakServer, v, packet->systemAddress); } } break;*/ default: stringstream s; s << "\nworld received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl; OutputQueue->Insert(s.str()); } break; default: stringstream s; s << "\nworld received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl; OutputQueue->Insert(s.str()); } break; case ID_NEW_INCOMING_CONNECTION: { #ifdef DEBUG OutputQueue->Insert("\n World is receiving a new connection...\n"); #endif //replicaManager.AddNewConnection(packet->systemAddress); /*Player *newPlayer = new Player; newPlayer->SetReplicaManager(&replicaManager); newPlayer->systemAddress = packet->systemAddress; newPlayer->LOT = 1; newPlayer->AddAutoSerializeTimer(100); newPlayer->BroadcastConstruction();*/ } break; case ID_DISCONNECTION_NOTIFICATION: { auto usr = OnlineUsers->Find(packet->systemAddress); if (OnlineUsers->Remove(packet->systemAddress)) OutputQueue->Insert("Disconnected " + usr->GetUsername() + "\n"); } //Player::DeletePlayerByAddress(packet->systemAddress); delete character; break; default: stringstream s; s << "\nworld received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl; OutputQueue->Insert(s.str()); } rakServer->DeallocatePacket(packet); } stringstream s; s << "Quitting world\n"; OutputQueue->Insert(s.str()); rakServer->Shutdown(0); RakNetworkFactory::DestroyRakPeerInterface(rakServer); }