samosi, научись пользоватся знаками препинания. чесное слово, о чем последнее сообщение вообще не понял.
Врятли сервер тебя выпустит с игры. Ексит сделаешь, а в игре останешься. И сдохнешь. :lol: На счет gm команд - они просто открывают gm консоль. Надо будет сейчас декомпильнуть клиент и проверить консоль. Видимо там какой то конфликт, так как для ГМа любая команда которая начинается на gm открывает gm консоль. Кстати, большинство из этих команд я нашел как протоколы для gdelivery.
Спасибо, капитан. Но этот вариант я рассматриваю только если не найду другой. Когда закончу разбор GRoleDetail посмотрим найду или не найду эти количества. Кстати дам подсказку, что количество ПК находится в одной из октетных переменных в GRoleStatus.
Это и есть XML, правда полученный через мое приложение. Я кстати нашел где же находится количество ПК убийств персонажа. А количество смертей и ПВП пока не нашел :lol:
А разве MSSQL поддерживает двойной left join?
А, ты про количество времени ПК. А я про именно количество ПК. А не часов. ХМЛ это не юзерфрендли данные, самые юзерфрендли это данные потока. Ты вот это имеешь ввиду? Object GetRoleStatus: (a548ebc380d055fb1674e1e8a3f80217.class) Opcode: Arg=3015, Res=3015 Size: 1080 Xid: 87442 Arg: >Object RoleId: (3354c9e579b7d61f66e8ff297be4feae.class) > roleid: 34 Res: >Object RoleStatusRes: (8763e50cbe6b27946a7573db185a977d.class) > retcode: 0 > value: >Object GRoleStatus: (7f0b40a81bc26d1d596e284744b6ac83.class) > version: 1 > level: 1 > level2: 8 > exp: 0 > sp: 0 > pp: 0 > hp: 50 > mp: 70 > posx: 1263.2598877 > posy: 223.293426514 > posz: 1029.36865234 > worldtag: 1 >>>>>>> invader_state: 0 >>>>>>> invader_time: 0 >>>>>>> pariah_time: 0 > reputation: 200000 > custom_status: > [S] > [H] > filter_data: > [S] �� > [H] 0000000000000000 > charactermode: > [S] > [H] > instancekeylist: > [S] [Click to display] > [H] [Click to display] > dbltime_expire: 0 > dbltime_mode: 0 > dbltime_begin: 1279486800 > dbltime_used: 0 > dbltime_max: 50400 > time_used: 5409 > dbltime_data: > [S] ���䱉 > [H] 010000000000000000000000000000005000f40049004c00 > storesize: 0 > petcorral: > [S] � > [H] 0000000000000a000000 > property: > [S] ����2�F����䀀馚䂙�䁀�䂠������䀠����������������������������������� Ə� > [H] [Click to display] > var_data: > [S] �������ﻬꑺ����P���㬌ቖ줰ຑ㬌ቖˆ� > [H] [Click to display] > skills: > [S] �q����}����§���� > [H] [Click to display] > storehousepasswd: > [S] > [H] > waypointlist: > [S] ᑑ > [H] 51001400 > coolingtime: > [S] �� > [H] ff00ff00ff00ff000000000000000000 > reserved1: 0 > reserved2: 0 > reserved3: 0 > reserved4: 0
Кстати, список протоколов gamedbd: GNET::GetTaskDataRpc::GetTaskDataRpc(a1, (int)GNET::__stub_GetTaskDataRpc, 115, (int)v294, (int)v292); GNET::PutTaskDataRpc::PutTaskDataRpc(a1, (int)GNET::__stub_PutTaskDataRpc, 135, (int)v298, (int)v296); GNET::PutFriendList::PutFriendList(a1, (int)GNET::__stub_PutFriendList, 200, (int)v282, (int)v280); GNET::GetFriendList::GetFriendList(a1, (int)GNET::__stub_GetFriendList, 201, (int)v278, (int)v276); GNET::PutMessage::PutMessage(a1, (int)GNET::__stub_PutMessage, 215, (int)v286, (int)v284); GNET::GetMessage::GetMessage(a1, (int)GNET::__stub_GetMessage, 216, (int)v290, (int)v288); GNET::DBStockBalance::DBStockBalance(a1, (int)GNET::__stub_DBStockBalance, 413, (int)v491, (int)v489); GNET::DBStockTransaction::DBStockTransaction(a1, (int)GNET::__stub_DBStockTransaction, 414, (int)v487, (int)v485); GNET::DBStockLoad::DBStockLoad(a1, (int)GNET::__stub_DBStockLoad, 415, (int)v483, (int)v481); GNET::DBStockCommission::DBStockCommission(a1, (int)GNET::__stub_DBStockCommission, 416, (int)v495, (int)v493); GNET::DBStockCancel::DBStockCancel(a1, (int)GNET::__stub_DBStockCancel, 417, (int)v499, (int)v497); AnnounceZoneid 505 GNET::GetAddCashSN::GetAddCashSN(a1, (int)GNET::__stub_GetAddCashSN, 514, (int)v479, (int)v477); AddCash 515 AddCash_Re 516 SyncSellInfo 609 GNET::DBSellPoint::DBSellPoint(a1, (int)GNET::__stub_DBSellPoint, 611, (int)v132, (int)v130); GNET::DBSyncSellInfo::DBSyncSellInfo(a1, (int)GNET::__stub_DBSyncSellInfo, 612, (int)v463, (int)v461); GNET::DBSellTimeout::DBSellTimeout(a1, (int)GNET::__stub_DBSellTimeout, 613, (int)v467, (int)v465); GNET::DBSellCancel::DBSellCancel(a1, (int)GNET::__stub_DBSellCancel, 614, (int)v471, (int)v469); GNET::DBBuyPoint::DBBuyPoint(a1, (int)GNET::__stub_DBBuyPoint, 615, (int)v459, (int)v457); TransBuyPoint 616 TransBuyPoint_Re 617 GNET::DBTransPointDeal::DBTransPointDeal(a1, (int)GNET::__stub_DBTransPointDeal, 618, (int)v475, (int)v473); GNET::DBAuctionOpen::DBAuctionOpen(a1, (int)GNET::__stub_DBAuctionOpen, 810, (int)v433, (int)v431); GNET::DBAuctionBid::DBAuctionBid(a1, (int)GNET::__stub_DBAuctionBid, 811, (int)v437, (int)v435); GNET::DBAuctionList::DBAuctionList(a1, (int)GNET::__stub_DBAuctionList, 812, (int)v451, (int)v449); GNET::DBAuctionGet::DBAuctionGet(a1, (int)GNET::__stub_DBAuctionGet, 813, (int)v443, (int)v440); GNET::DBAuctionTimeout::DBAuctionTimeout(a1, (int)GNET::__stub_DBAuctionTimeout, 814, (int)v455, (int)v453); GNET::DBAuctionClose::DBAuctionClose(a1, (int)GNET::__stub_DBAuctionClose, 815, (int)v447, (int)v445); GNET::DBBattleLoad::DBBattleLoad(a1, (int)GNET::__stub_DBBattleLoad, 863, (int)v364, (int)v362); GNET::DBBattleSet::DBBattleSet(a1, (int)GNET::__stub_DBBattleSet, 864, (int)v368, (int)v366); GNET::DBBattleChallenge::DBBattleChallenge(a1, (int)GNET::__stub_DBBattleChallenge, 865, (int)v356, (int)v348); GNET::DBBattleEnd::DBBattleEnd(a1, (int)GNET::__stub_DBBattleEnd, 868, (int)v373, (int)v370); GNET::DBBattleMail::DBBattleMail(a1, (int)GNET::__stub_DBBattleMail, 871, (int)v377, (int)v375); GNET::DBBattleBonus::DBBattleBonus(a1, (int)GNET::__stub_DBBattleBonus, 872, (int)v384, (int)v382); GNET::PutUser::PutUser(a1, (int)GNET::__stub_PutUser, 3001, (int)v154, (int)v152); GNET::GetUser::GetUser(a1, (int)GNET::__stub_GetUser, 3002, (int)v158, (int)v156); GNET::DelUser::DelUser(a1, (int)GNET::__stub_DelUser, 3003, (int)v162, (int)v160); GNET::GetRole::GetRole(a1, (int)GNET::__stub_GetRole, 3005, (int)v166, (int)v164); GNET::DelRole::DelRole(a1, (int)GNET::__stub_DelRole, 3006, (int)v174, (int)v172); GNET::DBCreateRole::DBCreateRole(a1, (int)GNET::__stub_DBCreateRole, 3007, (int)v136, (int)v134); GNET::DBDeleteRole::DBDeleteRole(a1, (int)GNET::__stub_DBDeleteRole, 3008, (int)v146, (int)v144); GNET::DBUndoDeleteRole::DBUndoDeleteRole(a1, (int)GNET::__stub_DBUndoDeleteRole, 3009, (int)v150, (int)v148); GNET::PutRoleBase::PutRoleBase(a1, (int)GNET::__stub_PutRoleBase, 3012, (int)v178, (int)v176); GNET::GetRoleBase::GetRoleBase(a1, (int)GNET::__stub_GetRoleBase, 3013, (int)v182, (int)v180); GNET::PutRoleStatus::PutRoleStatus(a1, (int)GNET::__stub_PutRoleStatus, 3014, (int)v186, (int)v184); GNET::GetRoleStatus::GetRoleStatus(a1, (int)GNET::__stub_GetRoleStatus, 3015, (int)v198, (int)v196); GNET::PutRoleEquipment::PutRoleEquipment(a1, (int)GNET::__stub_PutRoleEquipment, 3016, (int)v202, (int)v200); GNET::GetRoleEquipment::GetRoleEquipment(a1, (int)GNET::__stub_GetRoleEquipment, 3017, (int)v206, (int)v204); GNET::PutRoleTask::PutRoleTask(a1, (int)GNET::__stub_PutRoleTask, 3018, (int)v210, (int)v208); GNET::GetRoleTask::GetRoleTask(a1, (int)GNET::__stub_GetRoleTask, 3019, (int)v214, (int)v212); GNET::TradeInventory::TradeInventory(a1, (int)GNET::__stub_TradeInventory, 3020, (int)v218, (int)v216); GNET::TradeSave::TradeSave(a1, (int)GNET::__stub_TradeSave, 3021, (int)v222, (int)v220); GNET::GetMoneyInventory::GetMoneyInventory(a1, (int)GNET::__stub_GetMoneyInventory, 3022, (int)v230, (int)v228); GNET::PutMoneyInventory::PutMoneyInventory(a1, (int)GNET::__stub_PutMoneyInventory, 3023, (int)v234, (int)v232); GNET::PutRole::PutRole(a1, (int)GNET::__stub_PutRole, 3024, (int)v226, (int)v224); GNET::GetRoleBaseStatus::GetRoleBaseStatus(a1, (int)GNET::__stub_GetRoleBaseStatus, 3025, (int)v238, (int)v236); GNET::PutRoleStorehouse::PutRoleStorehouse(a1, (int)GNET::__stub_PutRoleStorehouse, 3026, (int)v242, (int)v240); GNET::GetRoleStorehouse::GetRoleStorehouse(a1, (int)GNET::__stub_GetRoleStorehouse, 3027, (int)v246, (int)v244); DelRoleAnnounce 3029 GNET::PutRoleForbid::PutRoleForbid(a1, (int)GNET::__stub_PutRoleForbid, 3030, (int)v250, (int)v248); GNET::GetRoleForbid::GetRoleForbid(a1, (int)GNET::__stub_GetRoleForbid, 3031, (int)v254, (int)v252); GNET::GetUserRoles::GetUserRoles(a1, (int)GNET::__stub_GetUserRoles, 3032, (int)v258, (int)v256); GNET::GetRoleId::GetRoleId(a1, (int)GNET::__stub_GetRoleId, 3033, (int)v262, (int)v260); GNET::TransactionAcquire::TransactionAcquire(a1, (int)GNET::__stub_TransactionAcquire, 3034, (int)v388, (int)v386); GNET::TransactionAbort::TransactionAbort(a1, (int)GNET::__stub_TransactionAbort, 3035, (int)v392, (int)v390); GNET::TransactionCommit::TransactionCommit(a1, (int)GNET::__stub_TransactionCommit, 3036, (int)v396, (int)v394); GNET::ClearStorehousePasswd::ClearStorehousePasswd(a1, (int)GNET::__stub_ClearStorehousePasswd, 3043, (int)v270, (int)v268); GNET::RenameRole::RenameRole(a1, (int)GNET::__stub_RenameRole, 3044, (int)v274, (int)v272); GNET::CanChangeRolename::CanChangeRolename(a1, (int)GNET::__stub_CanChangeRolename, 3047, (int)v266, (int)v264); GNET::GetRoleInfo::GetRoleInfo(a1, (int)GNET::__stub_GetRoleInfo, 3049, (int)v170, (int)v168); GNET::PutRolePocket::PutRolePocket(a1, (int)GNET::__stub_PutRolePocket, 3050, (int)v194, (int)v192); GNET::GetRolePocket::GetRolePocket(a1, (int)GNET::__stub_GetRolePocket, 3051, (int)v190, (int)v188); GNET::DBSetCashPassword::DBSetCashPassword(a1, (int)GNET::__stub_DBSetCashPassword, 3100, (int)v503, (int)v501); GNET::PutSpouse::PutSpouse(a1, (int)GNET::__stub_PutSpouse, 4047, (int)v507, (int)v505); GNET::DBGetMailList::DBGetMailList(a1, (int)GNET::__stub_DBGetMailList, 4251, (int)v400, (int)v398); GNET::DBGetMail::DBGetMail(a1, (int)GNET::__stub_DBGetMail, 4252, (int)v404, (int)v402); GNET::DBGetMailAttach::DBGetMailAttach(a1, (int)GNET::__stub_DBGetMailAttach, 4253, (int)v410, (int)v406); GNET::DBSetMailAttr::DBSetMailAttr(a1, (int)GNET::__stub_DBSetMailAttr, 4254, (int)v415, (int)v413); GNET::DBSendMail::DBSendMail(a1, (int)GNET::__stub_DBSendMail, 4255, (int)v419, (int)v417); GNET::DBDeleteMail::DBDeleteMail(a1, (int)GNET::__stub_DBDeleteMail, 4256, (int)v429, (int)v427); GNET::AddFaction::AddFaction(a1, (int)GNET::__stub_AddFaction, 4600, (int)v302, (int)v300); GNET::DelFaction::DelFaction(a1, (int)GNET::__stub_DelFaction, 4601, (int)v306, (int)v304); GNET::AddMember::AddMember(a1, (int)GNET::__stub_AddMember, 4602, (int)v310, (int)v308); GNET::DelMember::DelMember(a1, (int)GNET::__stub_DelMember, 4603, (int)v314, (int)v312); GNET::UpdateUserFaction::UpdateUserFaction(a1, (int)GNET::__stub_UpdateUserFaction, 4604, (int)v318, (int)v316); GNET::UpdateFaction::UpdateFaction(a1, (int)GNET::__stub_UpdateFaction, 4605, (int)v322, (int)v320); GNET::GetFactionInfo::GetFactionInfo(a1, (int)GNET::__stub_GetFactionInfo, 4606, (int)v334, (int)v332); GNET::GetUserFaction::GetUserFaction(a1, (int)GNET::__stub_GetUserFaction, 4607, (int)v338, (int)v336); GNET::GetFactionDetail::GetFactionDetail(a1, (int)GNET::__stub_GetFactionDetail, 4608, (int)v342, (int)v340); GNET::DBVerifyMaster::DBVerifyMaster(a1, (int)GNET::__stub_DBVerifyMaster, 4609, (int)v346, (int)v344); GNET::DBFactionUpgrade::DBFactionUpgrade(a1, (int)GNET::__stub_DBFactionUpgrade, 4610, (int)v326, (int)v324); GNET::DBFactionPromote::DBFactionPromote(a1, (int)GNET::__stub_DBFactionPromote, 4611, (int)v330, (int)v328); Уверен, что gdelivery будет намного интереснее :lol:
А разве у нас в gamedbd ведется учет количества ПК? *Черт*, это же возможно та неизвесная переменная, которую я недавно в протоколе GRoleDetail нашел... *Ушел ковырять GetRole обратно*
Если в php, то в mssql пароль будет md5($login.$password,true), а в mysql base64_encode(md5($login.$password,true)) $hash = base64_encode(md5($login.$password,true)); mysql_query("call changePasswd($login,$hash)"); для топа ПК И как ты данные об количестве ПК вытащишь?
updateUserInfo меняет данные пользователя в базе данных. эти данные нам интереса особого не представляют, так как использовались китаезами для их ЛК. я например в них храню ссылку на PWSAI пользователя в другой базе данных и айпи адрес регистрации. если перевести, то данные такие: PROCEDURE `updateUserInfo`( in name1 VARCHAR(32), - логин, данные которого будем менять in prompt1 VARCHAR(32), - секретный вопрос in answer1 VARCHAR(32), - секретный ответ in truename1 VARCHAR(32), - настоящее имя in idnumber1 VARCHAR(32), - идентификатор (у каждого чела в китае есть свой идент) in email1 VARCHAR(32), - электронная почта in mobilenumber1 VARCHAR(32), - мобильный телефон in province1 VARCHAR(32), - провинция in city1 VARCHAR(32), - город in phonenumber1 VARCHAR(32), - домашний телефон in address1 VARCHAR(32), - адрес in postalcode1 VARCHAR(32), - почтовый код in gender1 INTEGER, - пол in birthday1 VARCHAR(32), - день рождения in qq1 VARCHAR(32) - ??? ) На счет changePasswd - я имею ввиду что очень просто. Я лично меняю пароль через прямой запрос update в базу данных. На счет adduser - формат пароля зависит от реализации auth. Например, в оригинальном auth для mssql пароль хранится в бинарном md5 от конкетанации логина и пароля. В mauthd, он еще берется в base64 и хранится в тексте. На счет addforbid, не помню точно то ли там UTF16le то ли там UTF16be, когда вернусь и проверю напишу точно.
Ну тогда нужно в блок данных добавлять random число. Как это делается в VK Secure API. А в качестве проверочного например md5(secret . $params . $rand)
Эх, когда то ручками все это делали... а теперь наделали программ всяких... конечно проще намного... :lol: Помнится как эти самые октеты с Максимианом и разбирали. На правах оффа: Скоро буду создавать php скрипт, разбирвающий elements.data на 115 xml-файлов. :lol: Кстати если использовать GDelivery::SysSendMail то можно без релогина отсылать вещи себе на почту. При этом при получении вещи нет никакого риска, что сервер упадет. Даже если октеты неправильные. Если найду, то выложу свой модуль для 1.01 айвеба, позволяющий отсылать вещи на почту.
Проанализируем mySql процедуры. PROCEDURE `acquireuserpasswd`(in name1 VARCHAR(64), out uid1 INTEGER, out passwd1 VARCHAR(64)) BEGIN SELECT id, passwd INTO uid1, passwd1 FROM users WHERE name = name1; END На вход идет логин игрока, на выходе дает id и хеш пароля. Для чего нужна и так понятно. Ищет строку у которой логин (name) совпадает со входным параметром (name1). Если такая находится, то возвращает ее айди (uid) и пароль (passwd) в выходные параметры (uid1 и passwd1 соответственно). PROCEDURE `addForbid`(in userid1 INTEGER, in type1 INTEGER, in forbid_time1 INTEGER, in reason1 BINARY(255), in gmroleid1 INTEGER) BEGIN DECLARE rowcount INTEGER; START TRANSACTION; UPDATE forbid SET ctime = now(), forbid_time = forbid_time1, reason = reason1, gmroleid = gmroleid1 WHERE userid = userid1 AND type = type1; SET rowcount = ROW_COUNT(); IF rowcount = 0 THEN INSERT INTO forbid VALUES(userid1, type1, now(), forbid_time1, reason1, gmroleid); END IF; COMMIT; END Добавляет бан на аккаунт. userid1 - айди пользователя, type1 - тип бана (вроде 100 на вход, 101 на чат, остальные вроде не играют роли), forbid_time1 - длинна бана в секундах, reason1 - причина бана (бинарный код текста в UTF16), gmroleid1 - айди персонажа ГМа, который дал бан. Если бан такого типа для такого же игрока существует, то лишь обновляется время в таблице, причина и гмайди. Иначе же создается новая строка для этого бана. PROCEDURE `addGM`(in userid INTEGER, in zoneid INTEGER) BEGIN DECLARE x INTEGER; START TRANSACTION; SET x = 0; WHILE x < 12 DO INSERT INTO auth VALUES (userid, zoneid, x); SET x = x + 1; END WHILE; SET x = 100; WHILE x < 106 DO INSERT INTO auth VALUES (userid, zoneid, x); SET x = x + 1; END WHILE; SET x = 200; WHILE x < 215 DO INSERT INTO auth VALUES (userid, zoneid, x); SET x = x + 1; END WHILE; SET x = 500; WHILE x < 519 DO INSERT INTO auth VALUES (userid, zoneid, x); SET x = x + 1; END WHILE; COMMIT; END Фактически, делает пользователя с айди userid ГМом в зоне zoneid. Если разжевать выполнение, то дает ему все привилегии которые нужны ГМу (да впрочем и те, что не нужны). К ним относятся: 0-11, 100-105, 200-214, 500-518. PROCEDURE `adduser`( in name1 VARCHAR(64), in passwd1 VARCHAR(64), in prompt1 VARCHAR(32), in answer1 VARCHAR(32), in truename1 VARCHAR(32), in idnumber1 VARCHAR(32), in email1 VARCHAR(32), in mobilenumber1 VARCHAR(32), in province1 VARCHAR(32), in city1 VARCHAR(32), in phonenumber1 VARCHAR(32), in address1 VARCHAR(64), in postalcode1 VARCHAR(8), in gender1 INTEGER, in birthday1 VARCHAR(32), in qq1 VARCHAR(32), in passwd21 VARCHAR(64) ) BEGIN DECLARE idtemp INTEGER; SELECT IFNULL(MAX(id), 16) + 16 INTO idtemp FROM users; INSERT INTO users (id,name,passwd,prompt,answer,truename,idnumber,email,mobilenumber,province,city,phonenumber,address,postalcode,gender,birthday,creatime,qq,passwd2) VALUES( idtemp, name1, passwd1, prompt1, answer1, truename1, idnumber1, email1, mobilenumber1, province1, city1, phonenumber1, address1, postalcode1, gender1, birthday1, now(), qq1, passwd21 ); END Создает пользователя со всема укзаными данными, с айди, который вычисляется следующим образом: Если не сущестует пользователей, то IFNULL(..., 16) вернет 16, а айди будет 32. Если пользователи существуют, то IFNULL(MAX(id), ...) вернет MAX(id), и соответственно айди пользователя будет (макс айди в базе) + 16. PROCEDURE `adduserpoint`(in uid1 INTEGER, in aid1 INTEGER, in time1 INTEGER) BEGIN DECLARE rowcount INTEGER; START TRANSACTION; UPDATE point SET time = IFNULL(time,0) + time1 WHERE uid1 = uid AND aid1 = aid; SET rowcount = ROW_COUNT(); IF rowcount = 0 THEN INSERT INTO point (uid,aid,time) VALUES (uid1,aid1,time1); END IF; COMMIT; END Обновляет проведенное время игроком в игре, используется вроде на серверах world1, где игровое время платное. К тому же относится и параметр freecreatetime в gdelivery. PROCEDURE `addUserPriv`(in userid INTEGER, in zoneid INTEGER, in rid INTEGER) BEGIN START TRANSACTION; INSERT INTO auth VALUES(userid, zoneid, rid); COMMIT; END Выдает пользователю конкретную ГМ привилегию (В отличие от addGM который выдает все возможные). PROCEDURE `changePasswd`(in name1 VARCHAR(64), in passwd1 VARCHAR(64)) BEGIN START TRANSACTION; UPDATE users SET passwd = passwd1 WHERE name = name1; COMMIT; END Меняет пароль пользователя. Интереса не представляет. Функция changePasswd2 делает аналогично для второго пароля который нашими mauthd и authd не используется. PROCEDURE `clearonlinerecords`(in zoneid1 INTEGER, in aid1 INTEGER) BEGIN START TRANSACTION; UPDATE point SET zoneid = NULL, zonelocalid = NULL WHERE aid = aid1 AND zoneid = zoneid1; COMMIT; END Вызывается при запуске mauthd. Как видим очищает записи онлайн в таблице point для зоны zoneid1 и (хзчего) aid1. PROCEDURE `deleteTimeoutForbid`(in userid1 INTEGER) BEGIN START TRANSACTION; DELETE FROM forbid WHERE userid = userid1 AND timestampdiff(second, ctime, now()) > forbid_time; COMMIT; END Насколько я помню вызывается каждый раз перед логином. Очищает баны которые уже истекли. PROCEDURE `delUserPriv`(in userid1 INTEGER, in zoneid1 INTEGER, in rid1 INTEGER, in deltype1 INTEGER) BEGIN START TRANSACTION; IF deltype1 = 0 THEN DELETE FROM auth WHERE userid = userid1 AND zoneid = zoneid1 AND rid = rid1; ELSE IF deltype1 = 1 THEN DELETE FROM auth WHERE userid = userid1 AND zoneid = zoneid1; ELSE IF deltype1 = 2 THEN DELETE FROM auth WHERE userid = userid1; END IF; END IF; END IF; COMMIT; END Достаточно интересная функция. Убирает некоторые ГМ привилегии у пользователя userid. Если deltype1 равен нулю, то убирает конретную привилегию rid1 в конкретной зоне zoneid1. Если deltype1 равен единице, то убирает ВСЕ привилегии в конкретной зоне zoneid1. Если deltype1 равен двум, то убирает ВСЕ привилегии во ВСЕХ зонах. PROCEDURE `enableiplimit`(in uid1 INTEGER, in enable1 CHAR(1)) BEGIN DECLARE rowcount INTEGER; START TRANSACTION; UPDATE iplimit SET enable=enable1 WHERE uid=uid1; SET rowcount = ROW_COUNT(); IF rowcount = 0 THEN INSERT INTO iplimit (uid,enable) VALUES (uid1,enable1); END IF; COMMIT; END Включает iplimit (для включения enable1 должен быть t, иначе работать не будет). Проанализировав код mauth сделал вывод что iplimit в чистом виде нигде не используется. Решил так, потому что функция checkIpLimit нигде не вызывается. Но айпилимит можно использовать и для других целей (см ниже). PROCEDURE `lockuser`(in uid1 INTEGER, in lockstatus1 CHAR(1)) BEGIN DECLARE rowcount INTEGER; START TRANSACTION; UPDATE iplimit SET lockstatus=lockstatus1 WHERE uid=uid1; SET rowcount = ROW_COUNT(); IF rowcount = 0 THEN INSERT INTO iplimit (uid,lockstatus,enable) VALUES (uid1,lockstatus1,'t'); END IF; COMMIT; END Если lockstatus1 равен t, то перманентно банит пользователя uid1. У него всегда будет выдаватся в причине бана какие то китайские буквы, а бан постоянно будет на где-то 576 тыс минут (и это число уменьшатся не будет). Проверено. Для разбана нужно ставить lockstatus1 что угодно, но только не t. PROCEDURE `recordoffline`(in uid1 INTEGER, in aid1 INTEGER, inout zoneid1 INTEGER, inout zonelocalid1 INTEGER, inout overwrite1 INTEGER) BEGIN DECLARE rowcount INTEGER; START TRANSACTION; UPDATE point SET zoneid = NULL, zonelocalid = NULL WHERE uid = uid1 AND aid = aid1 AND zoneid = zoneid1; SET rowcount = ROW_COUNT(); IF overwrite1 = rowcount THEN SELECT zoneid, zonelocalid INTO zoneid1, zonelocalid1 FROM point WHERE uid = uid1 AND aid = aid1; END IF; COMMIT; END Вызывается когда игрок уходит в офф. Аналогично clearOnlineRecords, но очищает данные лишь для конкретного пользователя uid1. PROCEDURE `recordonline`(in uid1 INTEGER, in aid1 INTEGER, inout zoneid1 INTEGER, inout zonelocalid1 INTEGER, inout overwrite INTEGER) BEGIN DECLARE tmp_zoneid INTEGER; DECLARE tmp_zonelocalid INTEGER; DECLARE rowcount INTEGER; START TRANSACTION; SELECT SQL_CALC_FOUND_ROWS zoneid, zonelocalid INTO tmp_zoneid, tmp_zonelocalid FROM point WHERE uid = uid1 and aid = aid1; SET rowcount = FOUND_ROWS(); IF rowcount = 0 THEN INSERT INTO point (uid, aid, time, zoneid, zonelocalid, lastlogin) VALUES (uid1, aid1, 0, zoneid1, zonelocalid1, now()); ELSE IF tmp_zoneid IS NULL OR overwrite = 1 THEN UPDATE point SET zoneid = zoneid1, zonelocalid = zonelocalid1, lastlogin = now() WHERE uid = uid1 AND aid = aid1; END IF; END IF; IF tmp_zoneid IS NULL THEN SET overwrite = 1; ELSE SET zoneid1 = tmp_zoneid; SET zonelocalid1 = tmp_zonelocalid; END IF; COMMIT; END Вызывается при входе пользователя в игру. Устанавливает в пойнте текущую зону, локалайди, и дату последнего входа. По неподтвержденным данным позволяет изменить зону, на которую входит игрок. !!! PROCEDURE `remaintime`(in uid1 INTEGER, in aid1 INTEGER, out remain INTEGER, out freetimeleft INTEGER) BEGIN DECLARE enddate1 DATETIME; DECLARE now1 DATETIME; DECLARE rowcount INTEGER; START TRANSACTION; SET now1 = now(); IF aid1 = 0 THEN SET remain = 86313600; SET enddate1 = date_add(now1, INTERVAL '30' DAY); ELSE SELECT time, IFNULL(enddate, now1) INTO remain, enddate1 FROM point WHERE uid = uid1 AND aid = aid1; SET rowcount = ROW_COUNT(); IF rowcount = 0 THEN SET remain = 0; INSERT INTO point (uid,aid,time) VALUES (uid1, aid1, remain); END IF; END IF; SET freetimeleft = 0; IF enddate1 > now1 THEN SET freetimeleft = timestampdiff(second, now1, enddate1); END IF; COMMIT; END Вычисляет количество оставшегося бесплатного игрового времени. Используется на world1 серверах. PROCEDURE `setiplimit`(in uid1 INTEGER, in ipaddr11 INTEGER, in ipmask11 VARCHAR(2), in ipaddr21 INTEGER, in ipmask21 VARCHAR(2), in ipaddr31 INTEGER, in ipmask31 VARCHAR(2), in enable1 CHAR(1)) BEGIN DECLARE rowcount INTEGER; START TRANSACTION; UPDATE iplimit SET ipaddr1 = ipaddr11, ipmask1 = ipmask11, ipaddr2 = ipaddr21, ipmask2 = ipmask21, ipaddr3 = ipaddr31, ipmask3 = ipmask31 WHERE uid = uid1; SET rowcount = ROW_COUNT(); IF rowcount = 0 THEN INSERT INTO iplimit (uid, ipaddr1, ipmask1, ipaddr2, ipmask2, ipaddr3, ipmask3, enable1) VALUES (uid1, ipaddr11, ipmask11, ipaddr21, ipmask21, ipaddr31, ipmask31,'t'); END IF; COMMIT; END Устанавливает айпилимит, который к сожалению с нашими mauthd не работает. Если найду время перекомпилирую mauthd. PROCEDURE `updateUserInfo`( in name1 VARCHAR(32), in prompt1 VARCHAR(32), in answer1 VARCHAR(32), in truename1 VARCHAR(32), in idnumber1 VARCHAR(32), in email1 VARCHAR(32), in mobilenumber1 VARCHAR(32), in province1 VARCHAR(32), in city1 VARCHAR(32), in phonenumber1 VARCHAR(32), in address1 VARCHAR(32), in postalcode1 VARCHAR(32), in gender1 INTEGER, in birthday1 VARCHAR(32), in qq1 VARCHAR(32) ) BEGIN START TRANSACTION; UPDATE users SET prompt = prompt1, answer = answer1, truename = truename1, idnumber = idnumber1, email = email1, mobilenumber = mobilenumber1, province = province1, city = city1, phonenumber = phonenumber1, address = address1, postalcode = postalcode1, gender = gender1, birthday = birthda1, qq = qq1 WHERE name = name1; COMMIT; END Изменяет информацию об пользователе. При этом логин и пароли не меняет. PROCEDURE `usecash`( in userid1 INTEGER, in zoneid1 INTEGER, in sn1 INTEGER, in aid1 INTEGER, in point1 INTEGER, in cash1 INTEGER, in status1 INTEGER, out error INTEGER ) BEGIN DECLARE sn_old INTEGER; DECLARE aid_old INTEGER; DECLARE point_old INTEGER; DECLARE cash_old INTEGER; DECLARE status_old INTEGER; DECLARE createtime_old DATETIME; DECLARE time_old INTEGER; DECLARE need_restore INTEGER; DECLARE exists1 INTEGER; DECLARE rowcount INTEGER; START TRANSACTION; SET error = 0; SET need_restore = 0; SELECT SQL_CALC_FOUND_ROWS sn, aid, point, cash, status, creatime INTO sn_old, aid_old, point_old, cash_old, status_old, createtime_old FROM usecashnow WHERE userid = userid1 AND zoneid = zoneid1 AND sn >= 0; SET rowcount = FOUND_ROWS(); IF rowcount = 1 THEN SET exists1 = 1; ELSE SET exists1 = 0; END IF; IF status1 = 0 THEN IF exists1 = 0 THEN SELECT aid, point INTO aid1, point1 FROM usecashnow WHERE userid = userid1 AND zoneid = zoneid1 AND sn = sn1; SET point1 = IFNULL(point1,0); UPDATE point SET time = time-point1 WHERE uid = userid1 AND aid = aid1 AND time >= point1; SET rowcount = ROW_COUNT(); IF rowcount = 1 THEN UPDATE usecashnow SET sn = 0, status = 1 WHERE userid = userid1 AND zoneid = zoneid1 AND sn = sn1; ELSE SET error = -8; END IF; END IF; ELSE IF status1 = 1 THEN IF exists1 = 0 THEN UPDATE point SET time = time-point1 WHERE uid = userid1 AND aid = aid1 AND time >= point1; SET rowcount = ROW_COUNT(); IF rowcount = 1 THEN INSERT INTO usecashnow (userid, zoneid, sn, aid, point, cash, status, creatime) VALUES (userid1, zoneid1, sn1, aid1, point1, cash1, status1, now()); ELSE INSERT INTO usecashnow SELECT userid1, zoneid1, IFNULL(min(sn),0)-1, aid1, point1, cash1, 0, now() FROM usecashnow WHERE userid = userid1 AND zoneid = zoneid1 AND 0 >= sn; SET error = -8; END IF; ELSE INSERT INTO usecashnow SELECT userid1, zoneid1, IFNULL(min(sn),0)-1, aid1, point1, cash1, 0, now() FROM usecashnow WHERE userid = userid1 AND zoneid = zoneid1 AND 0 >= sn; SET error = -7; END IF; ELSE IF status1 = 2 THEN IF exists1 = 1 AND status_old = 1 AND sn_old = 0 THEN UPDATE usecashnow SET sn = sn1, status = status1 WHERE userid = userid1 AND zoneid = zoneid1 AND sn = sn_old; ELSE SET error = -9; END IF; ELSE IF status1 = 3 THEN IF exists1 = 1 AND status_old = 2 THEN UPDATE usecashnow SET status = status1 WHERE userid = userid1 AND zoneid = zoneid1 AND sn = sn_old; ELSE SET error = -10; END IF; ELSE IF status1 = 4 THEN IF exists1 = 1 THEN DELETE FROM usecashnow WHERE userid = userid1 AND zoneid = zoneid1 AND sn = sn_old; INSERT INTO usecashlog (userid, zoneid, sn, aid, point, cash, status, creatime, fintime) VALUES (userid1, zoneid1, sn_old, aid_old, point_old, cash_old, status1, createtime_old, now()); END IF; IF NOT (exists1 = 1 AND status_old = 3) THEN SET error = -11; END IF; ELSE SET error = -12; END IF; END IF; END IF; END IF; END IF; IF need_restore = 1 THEN UPDATE point SET time = time+point_old WHERE uid = userid1 AND aid = aid_old; DELETE FROM usecashnow WHERE userid = userid1 AND zoneid = zoneid1 AND sn = sn_old; INSERT INTO usecashlog (userid, zoneid, sn, aid, point, cash, status, creatime, fintime) VALUES (userid1, zoneid1, sn_old, aid_old, point_old, cash_old, status1, createtime_old, now()); END IF; COMMIT; END Нами функция используется для выдачи голда игроку. На серверах с ограниченым игровым временем может использоватся для продления доступного игрового времени за голды. Если чесно, сам лично этого не проверял. Также чинит незавершенные транзакции с голдом.
В смысле "разжевывания"? Там и так все очевидно. Единственое, что вызывает трудности, так это usecash - сложная процедура. Я помню когда то прописал логгинг всех вызовов процедур в таблицу. Интересная картина вышла. На счет юзкеша - учитывая ее линейную структуру можно ее проанализировать. *На правах оффа: сейчас я анализирую выполнение гораздо более сложных процедур в gamedbd и gdeliveryd*
Например как у меня( с недавних пор у нас=)) ) - есть сайт на хостинге и сервер, там и там бд только на локале, какбы сам знаешь) при включённом сервере http://pw.j-games.org/ игрок заполнив поля регистрации игрового аккаунта заставляет скрипт проверить поля и если поля удовлетворяют условиям то и идёт file_get_contents(http://........./.../.../index.php?admin_key=......&login=логин&pass=пасс); где admin_key это уникальный ключ, по login и пасс создаётся новая учётная запись в бд функция возвращает результат от скрипта на сервере. Учитывая то что длинна admin_key может быть сколь угодно длинной а сам скрипт лежать в хз какой директории (например в http://IP:80808080/5...8fh6/index.php) а в корне и в 5ddf5hh6dfhdfh5 лежит .htaccess с deny from all Машина Франкенштейна прямо... А у тебя хотя бы проверяется дошли данные или нет? ----------------------------------------------------------------------------- Уже кстати разобрал 85% протоколов gamedbd. :lol: На счет кода gouranga: ... <!--#########--> <!-- gamedbd --> <class name="RoleId"> <var name="roleid" type="int"/> </class> ... <!-- 3013 GetRoleBase --> <class name="RoleBaseRes"> <var name="retcode" type="int"/> <var name="value" type="GRoleBase"/> </class> <class name="GetRoleBase" arg="RoleId" res="RoleBaseRes" type="3013"/> ...
На счет наивного - нужно 6 запросов на то чтобы полностью сформировать xml роли в старом формате (айвеба). А если вытаскивать всю инфу (список друзей, факцию, итд) то и того больше.
Если при старте gamedbd у вас пишет err : Initialize storage environment failed и база не запускается то возможных причин две: 1. Неверно указаны пути к базе 2. Ваша база испортилась (самое вероятное) Первое решается путем указания правильных путей в gamesys.conf. Для решения второго нужно починить базу. Для этого создаем файл rebuild.sh, со следующим содержанием: #!/bin/sh mkdir dbhomewdb/dbrepair ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/auction -d /home/gamedbd/dbhomewdb/dbrepair/auction ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/auctionindex -d /home/gamedbd/dbhomewdb/dbrepair/auctionindex ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/base -d /home/gamedbd/dbhomewdb/dbrepair/base ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/city -d /home/gamedbd/dbhomewdb/dbrepair/city ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/clsconfig -d /home/gamedbd/dbhomewdb/dbrepair/clsconfig ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/config -d /home/gamedbd/dbhomewdb/dbrepair/config ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/equipment -d /home/gamedbd/dbhomewdb/dbrepair/equipment ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/factioninfo -d /home/gamedbd/dbhomewdb/dbrepair/factioninfo ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/factionname -d /home/gamedbd/dbhomewdb/dbrepair/factionname ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/friends -d /home/gamedbd/dbhomewdb/dbrepair/friends ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/gtask -d /home/gamedbd/dbhomewdb/dbrepair/gtask ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/inventory -d /home/gamedbd/dbhomewdb/dbrepair/inventory ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/mailbox -d /home/gamedbd/dbhomewdb/dbrepair/mailbox ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/messages -d /home/gamedbd/dbhomewdb/dbrepair/messages ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/order -d /home/gamedbd/dbhomewdb/dbrepair/order ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/rolename -d /home/gamedbd/dbhomewdb/dbrepair/rolename ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/sellpoint -d /home/gamedbd/dbhomewdb/dbrepair/sellpoint ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/shoplog -d /home/gamedbd/dbhomewdb/dbrepair/shoplog ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/status -d /home/gamedbd/dbhomewdb/dbrepair/status ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/storehouse -d /home/gamedbd/dbhomewdb/dbrepair/storehouse ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/task -d /home/gamedbd/dbhomewdb/dbrepair/task ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/translog -d /home/gamedbd/dbhomewdb/dbrepair/translog ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/user -d /home/gamedbd/dbhomewdb/dbrepair/user ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/userfaction -d /home/gamedbd/dbhomewdb/dbrepair/userfaction ./dbtool -r -s /home/gamedbd/dbhomewdb/dbdata/waitdel -d /home/gamedbd/dbhomewdb/dbrepair/waitdel cd dbhomewdb mv dbdata dbold mv dbrepair dbdata chmod 777 dbdata/* и кладем его в папку /home/gamedbd/ Далее переходим в папку /home/gamedbd/ если еще не там: cd /home/gamedbd/ Затем выполняем команду chmod 777 rebuild.sh и после этого выполняем наш скрипт: ./rebuild.sh Запускаем сервер :lol:
Наивный. Как будто при помощи одной операции можно XML вытащить. Чесно скажу, что API будет сложнее. :lol: А file_get_contents - это вообще неправильно. Вытащищь код файла api.php и что с ним делать будешь? А учитывая твои знаки вопроса и проч, то вообще ничего не вытащишь. И вообще, API планировал делать совсем по другому. Но до API еще как до луны, будем о нем думать когда закончу все протоколы. ПЫСЫ: Сделал маленькую Factory, для производства классов протоколов по строке. Например (дописал вектор и класс для демонстрации): FactoryGMarObj('gdelivery','PublicChat',79,'Byte channel, Byte emotion, Int roleid, Int localsid, Octets msg, ~GFactionMemberVector members, ~GRoleBase base'); создаст следующий файл /protocol/gdelivery/PublicChat.php: <?php /* Marshal Object Class Definition DO NOT MODIFY THIS COMMENT BLOCK CN:{|GPublicChat|} UN:{|PublicChat|} OC:{|79|} PK:{|gdelivery|} PR:{|byte channel, byte emotion, int roleid, int localsid, octets msg, ~GFactionMemberVector members, ~GRoleBase base|} DP:{|GMarObj,GFactionMemberVector,GRoleBase|} */ class GPublicChat extends GMarObj { public $channel; public $emotion; public $roleid; public $localsid; public $msg; public $members; public $base; public function getoc() { return 79; } public function mar(GConnection &$p) { $p->mByte($this->channel); $p->mByte($this->emotion); $p->mInt($this->roleid); $p->mInt($this->localsid); $p->mOctets($this->msg); $p->marshal($this->members); $p->marshal($this->base); } public function unmar(GConnection &$p) { $this->channel=$p->uByte(); $this->emotion=$p->uByte(); $this->roleid=$p->uInt(); $this->localsid=$p->uInt(); $this->msg=$p->uOctets(); $this->members = new GFactionMemberVector; $p->unmarshal($this->members); $this->base = new GRoleBase; $p->unmarshal($this->base); } }; (когда с gamedbd закончим начнём изучать другие подсервера) Я уже начал изучать gdelivery, guniquenamed и gfactiond. Затем пойдут glinkd и gamed. Кстати программа даже не для распространения в ЗР.
Подойдет для добавления элементарных протоколов, которые были и в оригинальном айвебе. Кстати, исеккей и осеккей в конфигах в базе64 или просто как есть?
Основную масу этого антимата составляют несколько слов написаных всевозможными вариантами капитализации. Чесное слово, лучше бы регексп сделали для этого всего. А все китайские слова что там есть тоже маты? :lol: Кстати слов 3415
Имена участников (разделяйте запятой).