void LoginHandler::processLoginData(Net::MessageIn &msg) { // Skip the length word msg.skip(2); // size clearWorlds(); const int worldCount = (msg.getLength() - 47) / 32; mToken.session_ID1 = msg.readInt32(); mToken.account_ID = msg.readInt32(); mToken.session_ID2 = msg.readInt32(); msg.skip(4); // old ip loginData.lastLogin = msg.readString(24); msg.skip(2); // 0 unused bytes // msg.skip(30); // unknown // reserve bits for future usage mToken.sex = Being::intToGender(static_cast<uint8_t>( msg.readUInt8() & 3U)); for (int i = 0; i < worldCount; i++) { WorldInfo *const world = new WorldInfo; world->address = msg.readInt32(); world->port = msg.readInt16(); world->name = msg.readString(20); world->online_users = msg.readInt16(); config.setValue("updatehost", mUpdateHost); world->updateHost = mUpdateHost; msg.skip(2); // maintenance msg.skip(2); // new logger->log("Network: Server: %s (%s:%d)", world->name.c_str(), ipToString(world->address), world->port); mWorlds.push_back(world); } client->setState(STATE_WORLD_SELECT); }
void WorldlinkMgr::reloadWorldsFromDB(database::connection db) { clearWorlds(); loadWorldsFromDB(db); preparePacket(); //regenerate packet for later use }
void LoginHandler::handleMessage(Net::MessageIn &msg) { int code, worldCount; switch (msg.getId()) { case SMSG_CHAR_PASSWORD_RESPONSE: { // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short int errMsg = msg.readInt8(); // Successful pass change if (errMsg == 1) { Client::setState(STATE_CHANGEPASSWORD_SUCCESS); } // pass change failed else { switch (errMsg) { case 0: errorMessage = _("Account was not found. Please re-login."); break; case 2: errorMessage = _("Old password incorrect."); break; case 3: errorMessage = _("New password too short."); break; default: errorMessage = _("Unknown error."); break; } Client::setState(STATE_ACCOUNTCHANGE_ERROR); } } break; case SMSG_UPDATE_HOST: int len; len = msg.readInt16() - 4; mUpdateHost = msg.readString(len); loginData.updateHost = mUpdateHost; logger->log("Received update host \"%s\" from login server.", mUpdateHost.c_str()); break; case SMSG_LOGIN_DATA: // Skip the length word msg.skip(2); clearWorlds(); worldCount = (msg.getLength() - 47) / 32; mToken.session_ID1 = msg.readInt32(); mToken.account_ID = msg.readInt32(); mToken.session_ID2 = msg.readInt32(); msg.skip(30); // unknown mToken.sex = msg.readInt8() ? GENDER_MALE : GENDER_FEMALE; for (int i = 0; i < worldCount; i++) { WorldInfo *world = new WorldInfo; world->address = msg.readInt32(); world->port = msg.readInt16(); world->name = msg.readString(20); world->online_users = msg.readInt32(); world->updateHost = mUpdateHost; msg.skip(2); // unknown logger->log("Network: Server: %s (%s:%d)", world->name.c_str(), ipToString(world->address), world->port); mWorlds.push_back(world); } Client::setState(STATE_WORLD_SELECT); break; case SMSG_LOGIN_ERROR: code = msg.readInt8(); logger->log("Login::error code: %i", code); switch (code) { case 0: errorMessage = _("Unregistered ID."); break; case 1: errorMessage = _("Wrong password."); break; case 2: errorMessage = _("Account expired."); break; case 3: errorMessage = _("Rejected from server."); break; case 4: errorMessage = _("You have been permanently banned from " "the game. Please contact the GM team."); break; case 5: errorMessage = _("Client too old."); break; case 6: errorMessage = strprintf(_("You have been temporarily " "banned from the game until " "%s.\nPlease contact the GM " "team via the forums."), msg.readString(20).c_str()); break; case 7: errorMessage = _("Server overpopulated."); break; case 9: errorMessage = _("This user name is already taken."); break; case 99: errorMessage = _("Username permanently erased."); break; default: errorMessage = _("Unknown error."); break; } Client::setState(STATE_ERROR); break; case SMSG_SERVER_VERSION_RESPONSE: { // TODO: verify these! msg.readInt8(); // -1 msg.readInt8(); // T msg.readInt8(); // M msg.readInt8(); // W unsigned int options = msg.readInt32(); mRegistrationEnabled = (options & 1); // Leave this last mVersionResponse = true; } break; } }
WorldlinkMgr::~WorldlinkMgr() { clearWorlds(); }
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int) { // константы // максимальное число сфер - для выделения буффера памяти long MAX_NUM_SPHERES = 100000000; // реальное число - определяется при считывании из файла или используется в рандомной генерации. long REAL_NUM_SPHERES = 10000000; // количество миров сфер, когда мы убираем сферы лежащие в других сферах - нужно разделять все сферы по разным мирам - там добавления новых сфер происходит быстрее. int SPHERE_WORLD_NUMBER = 128; // количество сфер которое мы обрабатываем полностью, то есть убираем все сферы содержащиеся в других сферах. Так мы бъем все сферы на такие группы и обрабатываем полностью. // после этого мы просто склеиваем все такие группы. Это сделано для того что, обрабатывать все 100M долго по времени (>1h), из за этого нам придется отрисовывать на 30% // cфер больше. long SPHERES_PROCESSING_STEP = 10000000; // имена файлов std::string inputFileName = "input2.txt"; std::string outputTxtFileName = "balabok2.txt"; std::string outputBmpFileName = "balabok2.bmp"; std::string fullOutputTxtFileName = "tmp_balabok/spheres_fullOutput.txt"; CreateDirectory (L"tmp_balabok", NULL); LoggerCreate("tmp_balabok/spheres.log"); // установим зерно генератора случайных чисел srand((unsigned int)time(NULL)); /// create window, start main loop, etc. int windowWidht = 1024; int windowHeight = 1024; if (!GLWindowCreate(L"Spheres", windowWidht, windowHeight)) return 1; /// SphereKoords *allSpheres = new SphereKoords[MAX_NUM_SPHERES]; /// считывание сфер из файла REAL_NUM_SPHERES = readSpheresDataFromFile(inputFileName, allSpheres, MAX_NUM_SPHERES); //generateRandomSpheres(allSpheres, REAL_NUM_SPHERES); SphereWorld * sphereWorlds = new SphereWorld[SPHERE_WORLD_NUMBER]; SphereWorld finalWorld; LOG_DEBUG ("Please, be patient. There is a quite long data preprocessing before rendering.\n"); LOG_DEBUG ("It can take up to 20 minutes for 100M spheres.\n"); LOG_DEBUG ("Take into account, that time for preprocessing wasn't limited.\n"); LOG_DEBUG ("By the way, you can see the progress in this file\n"); auto beginTime = GetTickCount(); /// вычисление сфер внутри других сфер в несколько потоков по блокам (мирам) for (int spheresInitialNumber = 0; spheresInitialNumber < REAL_NUM_SPHERES; spheresInitialNumber += SPHERES_PROCESSING_STEP) { long spheresToProcess = spheresInitialNumber + SPHERES_PROCESSING_STEP >= REAL_NUM_SPHERES ? REAL_NUM_SPHERES - spheresInitialNumber : SPHERES_PROCESSING_STEP; LOG_DEBUG ("processing spheres from %i to %i, time: %i\n", spheresInitialNumber, spheresInitialNumber + spheresToProcess , GetTickCount() - beginTime); int worldsPerThread = SPHERE_WORLD_NUMBER/THREADS_COUNT; SphereWorldWorkerData workersData[THREADS_COUNT]; HANDLE hHandles[THREADS_COUNT]; for (int threadNumber = 0; threadNumber < THREADS_COUNT; ++threadNumber) { long spheresPerThread = spheresToProcess/THREADS_COUNT; workersData[threadNumber] = SphereWorldWorkerData(worldsPerThread, sphereWorlds + threadNumber * worldsPerThread, threadNumber == THREADS_COUNT - 1 ? spheresToProcess - spheresPerThread * (THREADS_COUNT - 1) : spheresPerThread, allSpheres + spheresInitialNumber + spheresPerThread * threadNumber); DWORD ThreadId; hHandles[threadNumber] = CreateThread(NULL, 0, SphereWorldWorker, workersData + threadNumber, 0, &ThreadId); } for (int i = 0; i < THREADS_COUNT; i++) { WaitForSingleObject(hHandles[i],INFINITE); } /// склейка миров из разных потоков for (int degree = (int)(log((double)worldsPerThread) / log(2.0)); degree < log((double)SPHERE_WORLD_NUMBER) / log(2.0); ++degree) { int step = (int) pow(2.0f, (int)degree); for (int worldNumber = 0; worldNumber < SPHERE_WORLD_NUMBER; worldNumber += step * 2) { sphereWorlds[worldNumber].AddSphereWorldInSeveralThreads(sphereWorlds[worldNumber + step], THREADS_COUNT); } } /// простое (без вычислений) добавление сфер из разных миров к финальному миру - сделано для увеличение скорости предобработки. finalWorld.SimpleAddSphereWorld(sphereWorlds[0]); clearWorlds(sphereWorlds, SPHERE_WORLD_NUMBER); } LOG_DEBUG("sphere amount after removing the spheres located insides others: %i, time %i\n", finalWorld.GetCurrentSize(), GetTickCount() - beginTime); LOG_DEBUG("started checking how spheres cover cube (0,0,0 - 1,1,1)\n"); /// проверка насколько сферы покрывают все стороны каждой ячейки finalWorld.GenerateCover(coverBuilder); LOG_DEBUG("covering finished, time %i\n", GetTickCount() - beginTime); LOG_DEBUG("creating the main window, etc, and started rendering\n"); /// generate matrix in cells; REDUCED_NUM_SPHERES = finalWorld.GetCurrentSize(); spheres = new mat4[REDUCED_NUM_SPHERES]; finalWorld.GenerateMatrixInCells(matrixInCells, spheres); /// вектор со временами отрисовки фремов std::vector<double> msecsPerFrameList; int nSize = windowWidht * windowHeight * 3; GLubyte *pixels = new GLubyte [nSize]; /// старт петли сообщений int result = GLWindowMainLoop(msecsPerFrameList, pixels); /// сохранение всех данных в файлы if (pixels) { SaveBMP(pixels, windowWidht, windowHeight, nSize, outputBmpFileName.c_str()); } double performance = 0; double medianeMsecsPerFrame = 0; std::ofstream fullResultStream(fullOutputTxtFileName); std::ofstream resultStream(outputTxtFileName); fullResultStream << "msecs per frame: "; for (auto msecsValue = msecsPerFrameList.begin(); msecsValue != msecsPerFrameList.end(); ++msecsValue) { medianeMsecsPerFrame += *msecsValue; fullResultStream << *msecsValue << " "; } medianeMsecsPerFrame /= 10.0f; fullResultStream << std::endl << "average msecs per frame: " << medianeMsecsPerFrame ; performance = REAL_NUM_SPHERES / (1000 * medianeMsecsPerFrame); fullResultStream << std::endl << "Mspheres per second: " << performance; resultStream << performance << std::endl; GLWindowDestroy(); LoggerDestroy(); /// TODO: kill all windows handlers and free all the memory. return result; }