Помощь - Поиск - Пользователи - Календарь
Полная версия: Идентификация
Город Мастеров > РЕДАКТОРЫ > Шарды рунета
_kaa_
Любой скриптер когда-нибудь сталкивается с такой задачей - однозначно идентифицировать персонажа.
Обычные варианты логин+СДКЕЙ+имя персонажа - не являются 100% надежными, ведь можно создать второго персонажа с таким же именем.

Вот скрипт, "считающих" всех персонажей и выдающий им номер. Для простоты\быстроты номер хранится в Deity, но проверяется в любом случае.

Версия скрипта еще не последняя и возможны ошибки, но в целом - скрипт проверенный и работоспособный.
Код

//возвращает UNIQ_ID, -1 - если ошибка
int ID_GetID(object oPC);

//возвращает объект-игрока с номером ID или OBJECT_INVALID - если такого игрока нет онлайн
object ID_FindPC(int ID);

///////////////////////////////////////////////////////////////////////

object ID_FindPC(int ID)
{
   object oPC = GetFirstPC();
   while (GetIsObjectValid(oPC))
   {
       if ( GetLocalInt(oPC,"UNIQ_ID") == ID)
           return oPC;
       oPC = GetNextPC();
   }
   return OBJECT_INVALID;
}


int ID_GetID(object oPC)
{
   while (GetIsObjectValid(GetMaster(oPC)))
   {
       oPC=GetMaster(oPC);
   }

   if (!GetIsPC(oPC))
   {
       return -1;
   }

   //кэширование результата, чтобы не лазить в БД каждый раз
   int id = GetLocalInt(oPC,"UNIQ_ID");
   if (id > 0)
   {
       return id;
   }

   //длЯ ДМ-ов упрощенна проверка
   if (GetIsDM(oPC))
   {
       id = GetCampaignInt("ident_dm",GetPCPublicCDKey(oPC)+"_"+GetPCPlayerName(oPC));
       if (id > 0)
       {
           SetLocalInt(oPC,"UNIQ_ID",id);
           return id;
       }
       //maybe first time? assign new ID
       int id = GetCampaignInt("ident_dm","LAST_UNIQ_ID");
       if (id == 0)
       {
           //ДМ-ы получают номера начинаЯ с 101
           id = 100;
       }
       id++;
       SetCampaignInt("ident_dm","LAST_UNIQ_ID",id);
       SetLocalInt(oPC,"UNIQ_ID",id);
       SetCampaignInt("ident_dm",GetPCPublicCDKey(oPC)+"_"+GetPCPlayerName(oPC),id);
       return id;
   }

   //проверочнаЯ строка, котораЯ записываетсЯ в БД
   string sID_STRING = "mg_ident"+"_"+GetPCPublicCDKey(oPC)+"_"+GetPCPlayerName(oPC)+"_"+GetName(oPC);
   int iDeity = StringToInt(GetDeity(oPC));

   //Если игрок в первый раз пришел - обнулим ему поле Deity.
   //!!! Не забудьте выдать игроку хотЯ-бы 1 XP, чтобы он не считалсЯ впервые зашедшим на щард
   if (GetXP(oPC) == 0)
   {
       iDeity =0;
       SetDeity(oPC,"");
   }

   //Если в Deity есть число - проверЯем по базе с ID_STRING
   //Сама база устроена в виде записей номер:ID_строка
   if (iDeity > 0)
   {
       string sDB = GetCampaignString("ident",IntToString(iDeity));

       if (sDB == sID_STRING)
       {
           //check ok! cache & return
           SetLocalInt(oPC,"UNIQ_ID",iDeity);
           return iDeity;
       }
       else if (sDB != "") //may be corrupted DB?
       //Вариант, если испортилась БД (например удалили всех персонажей, но не почистили каталог с БД.
       {
           BootPC(oPC);
           return -1;
       }
   }

   //Если дошли до сюда - видимо новый персонаж,  провери его имЯ и логин по всей базе и если найдем такого-же - значит кто-то пытаетсЯ создать "дублЯ"
   int iLastPC = GetCampaignInt("ident","LAST_UNIQ_ID");
   if (iLastPC == 0)
   {
       iLastPC = 1000; //Игроки нумеруютсЯ с 1001
   }
   int k;
   string sTest;
   for (k = 1000;k <= iLastPC; k++)
   {
       sTest =GetCampaignString("ident",IntToString(k));
       if (sTest == sID_STRING)
       {
           //Ага, это читер. Выбрасываем его.
           BootPC(oPC)
           return -1;
       }
   }
   //Все нормально, просто новый игрок - запишем его в БД и выставим ему Deity- длЯ более быстрого поиска в следующий раз
   iLastPC++;
   SetCampaignInt("ident","LAST_UNIQ_ID",iLastPC);
   SetLocalInt(oPC,"UNIQ_ID",iLastPC);
   SetCampaignString("ident",IntToString(iLastPC),sID_STRING);
   SetDeity(oPC,IntToString(iLastPC));
   //На всЯкий запишем персонажа
   DelayCommand(4.0,ExportSingleCharacter(oPC));
   //и вернем номер.
   return iLastPC;
}



После такой нумерации мы получаем уникальный номер для каждого персонажа, что открывает нам новые возможности - мы можем сохранять инфромацию в базе данных для персонажа даже когда сам игрок не на шарде (оффлайн)

Если на шарде используется БД - очень удобно хранить всю информацию, относящиюся к данному игроку, в отдельной БД (лучше несколько маленьких БД, чем одна большая - скорость куда выше).

Как это сделанно у нас - есть библиотека для работы с БД, очень похожая на обычные SetLocal*, GetLocal*, только пишет инфу кроме памяти в БД (если флаг стоит). Она хранится в памяти, использую в виде префикса номер игрока, поэтому переменные с одним именем не пересекаются для разных игроков. Кроме того, позволяет писать в БД информацию по оффлайн-игрокам (к примеру нужно для обработки события onClientLeve)
baskan
А как бороться с проблемой создания чара с таким же именем?
Vanes
QUOTE
А как бороться с проблемой создания чара с таким же именем?

помоему ответ на этот вопрос был где-то на этом форуме...
если в кратце, то это будет выглядеть так...
при входе проверяем наличие в базе данных записи со значением "имя+акк"...
если такой записи нет - добавляем и пропускаем чара.. + даем чару 1 экспу...
если запись есть - то проверяем кол-во экспы на чаре...
если экспы больше 0, то то легальный чар - пропускаем...
если экспа равна 0, значит чар только что создан - бутим...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.
Invision Power Board © 2001-2024 Invision Power Services, Inc.