PDA

Просмотр полной версии : [Вопрос] Вопрос при INVALID_PLAYER_ID



DmitriyVasilev
20.04.2019, 15:58
Здравствуйте, вижу во многих местах данную проверка на валидность.
Для чего она нужна , и еще смотрел разные мода в некоторых одних и тех же командах стоит эта проверка а в другом моде нет например
else if(strcmp(x_job,"repair",true) == 0)
{
if(RepairOffer[playerid] != INVALID_PLAYER_ID)
{
if(PlayerInfo[playerid][pCash] > RepairPrice[playerid])
{
if(IsPlayerInAnyVehicle(playerid))
{
if(IsPlayerConnected(RepairOffer[playerid]))
{
RepairCar[playerid] = GetPlayerVehicleID(playerid);
SetVehicleHealth(RepairCar[playerid], 1000.0);
AnRepairVehicle(GetPlayerVehicleID(playerid));
format(stringer, sizeof(stringer), "Механик %s починил вашу машину за %d вирт",PlayerInfo[RepairOffer[playerid]][pNames], RepairPrice[playerid]);
SendClientMessage(playerid, 0x6ab1ffaa, stringer);
format(stringer, sizeof(stringer), "Вы починили атомобиль %s за %d вирт",PlayerInfo[playerid][pNames],RepairPrice[playerid]);
SendClientMessage(RepairOffer[playerid], 0x6ab1ffaa, stringer);
PlayerInfo[playerid][pCash] -=RepairPrice[playerid];
PlayerInfo[RepairOffer[playerid]][pCash] +=RepairPrice[playerid];
RepairOffer[playerid] = INVALID_PLAYER_ID;
RepairPrice[playerid] = 0;
return true;
}
return true;
}
return true;
}
else { SendClientMessage(playerid, COLOR_GREY, "У вас не хватает денег!"); return true; }
}
else { SendClientMessage(playerid, COLOR_GREY, "Вам не предлагали чинить машину!"); return true; }
}
а вот тут нема этой проверки
else if(strcmp(x_job, "repair",true) == 0)
{
if(RepairOffer[playerid] < 999)
{
if(User[playerid][pCash] > RepairPrice[playerid])
{
if(IsPlayerInAnyVehicle(playerid))
{
if(IsPlayerConnected(RepairOffer[playerid]))
{
GetPlayerName(RepairOffer[playerid], giveplayer, sizeof(giveplayer));
GetPlayerName(playerid, sendername, sizeof(sendername));
RepairCar[playerid] = GetPlayerVehicleID(playerid);
SetVehicleHealth(RepairCar[playerid], 1000.0);
AnRepairVehicle(GetPlayerVehicleID(playerid));
format(string, 128, "Âàøó ìàøèíó îòðåìîíòèðîâàë(à) çà %i âèðò, Ìåõàíèê %s", RepairPrice[playerid], giveplayer);
SendClientMessage(playerid, 0x6495EDFF, string);
format(string, 128, "Âû ïî÷èíèëè àòîìîáèëü %s çà %i âèðò",sendername,RepairPrice[playerid]);
SendClientMessage(RepairOffer[playerid], 0x6495EDFF, string);
SendClientMessage(RepairOffer[playerid], 0x6495EDFF, !"Äåíüãè ïîñòóïÿò ê âàì íà áàíêîâñêèé ñ÷åò âî âðåìÿ çàðïëàòû");
User[playerid][pCash] -= RepairPrice[playerid];
User[RepairOffer[playerid]][pPayCheck] += RepairPrice[playerid];
RepairOffer[playerid] = 999;
RepairPrice[playerid] = 0;
return 1;
}
return 1;
}
return 1;
}
else return SCM(playerid, COLOR_GREY, !"Ó âàñ íå õâàòàåò äåíåã!");
}
else return SCM(playerid, COLOR_GREY, !"Âàì íå ïðåäëàãàëè ÷èíèòü ìàøèíó!");
}
все таки когда ее надо ставить и зачем?

Paradox
20.04.2019, 22:01
В RepairOffer записывает ид игрока, которому в данной команде будут ремонтировать авто, то есть и проверка естественно на это, если ли ид игрока. (если же он ровняется INVALID_PLAYER_ID, значит игрока нет, команда не будет выполнена).
И во второй команде которую ты дал, там баг, 999 ид может быть в игре, что есть не хорошо, тогда уж либо ставить 1000, но а лучше нечего не придумывать и писать INVALID_PLAYER_ID, для этого оно и есть собственно.
Да и вообще, эти команды все по хорошему переписать стоило бы, код там конечно..

DeimoS
20.04.2019, 22:58
Немного дополню.

INVALID_PLAYER_ID - это просто макрос, который преобразуется в число 65535. Это не какая-то особая штука, которую нужно использовать только в определённых случаях. Это просто стандартный макрос, который используется в некоторых стандартных функциях, обозначающий невалидный (несуществующий) ID игрока.

Соответственно, использовать этот макрос нужно либо со стандартными функциями, которые возвращают данное значение (65535 aka INVALID_PLAYER_ID), либо когда определённая функция/переменная должна хранить ID игрока, тем самым помечая, что в конкретный момент времени эта самая функция/переменная никакой ID не хранит.
И, опять же, использовать такой макрос нужно не потому что он какой-то особенный и использование чего-то ещё приведёт к багам (хотя если указать значение в районе "0-999", то баг, как выше заметили, всё же появится),. Нет, ты можешь хоть 143242 записывать, сверять с этим значением, и всё будет работать. Но так не делают, ибо использование стандартного макроса более стандартизирует код (ну когда ты увидишь, что, например, переменная сравнивается с INVALID_PLAYER_ID, ты сразу поймёшь, что переменная должна хранить ID игрока), что упростит его понимание при последующем чтении этого же кода тобой.

Собственно, как выше заметили, во втором случае лучше 999 заменить на INVALID_PLAYER_ID.

Daniel_Cortez
21.04.2019, 18:44
хотя если указать значение в районе "0-999", то баг, как выше заметили, всё же появится
Пожалуй, тоже подключусь к дополнению.
Даже если указать значение "1000" (или любое другое больше 999), это всё равно может привести к багам - не сейчас, так в будущем, если выйдет сервер с количеством игроков больше 1000. А с появлением open.mp и отговорки в стиле "больше 1000 игроков никогда не будет, SA-MP мёртв" теряют актуальность.

DmitriyVasilev
25.04.2019, 20:30
а что будет например если я с этой команды уберу этот макрос?
CMD:cput(playerid, params[])
{
if(User[playerid][pRank] >= 1 && (User[playerid][pMember] == 1 || User[playerid][pMember] == 2 || User[playerid][pMember] == 10 ||User[playerid][pMember] == 21))
{
if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 596 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 490 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 597 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 598) return SCM(playerid, COLOR_GRAD1, "[Ошибка] Вы не в патрульной машине");
if(sscanf(params, "u",params[0])) return SCM(playerid, -1, !"Введите: /cput [playerid]");
if(!IsPlayerConnected(params[0])) return 1;
if(params[0] == INVALID_PLAYER_ID) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек небыл найден");
if (!ProxDetectorS(5.0, playerid, params[0])) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек далеко от вас");
if(params[0] == playerid) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Вы не можете затащить в машину самого себя");
if(!User[params[0]][pWantedLevel]) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек не является преступником");
if(GetPlayerState(params[0]) != PLAYER_STATE_ONFOOT) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек в автомобиле");
new mesto2,vehicle=GetPlayerVehicleID(playerid);
foreach(new i : Player)
{
if(IsPlayerInVehicle(i,vehicle))
{
mesto2 = GetPlayerVehicleSeat(i);
if(mesto2==2) return SendClientMessage(playerid, COLOR_GRAD1, !"[Ошибка] Место в машине уже занято");
}
}
PutPlayerInVehicleEx(params[0],vehicle,1);
SetPlayerArmedWeapon(params[0],0);
format(YCMDstr,sizeof(YCMDstr), "Вы были затащены в машину %s",Name(playerid));
SendClientMessage(params[0],0x64E96EDFF,YCMDstr);
format(YCMDstr,sizeof(YCMDstr), "Вы затащили в машину %s",Name(params[0]));
SendClientMessage(playerid,0x64E96EDFF,YCMDstr);
}
return 1;
}

Paradox
25.04.2019, 21:05
а что будет например если я с этой команды уберу этот макрос?
CMD:cput(playerid, params[])
{
if(User[playerid][pRank] >= 1 && (User[playerid][pMember] == 1 || User[playerid][pMember] == 2 || User[playerid][pMember] == 10 ||User[playerid][pMember] == 21))
{
if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 596 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 490 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 597 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 598) return SCM(playerid, COLOR_GRAD1, "[Ошибка] Вы не в патрульной машине");
if(sscanf(params, "u",params[0])) return SCM(playerid, -1, !"Введите: /cput [playerid]");
if(!IsPlayerConnected(params[0])) return 1;
if(params[0] == INVALID_PLAYER_ID) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек небыл найден");
if (!ProxDetectorS(5.0, playerid, params[0])) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек далеко от вас");
if(params[0] == playerid) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Вы не можете затащить в машину самого себя");
if(!User[params[0]][pWantedLevel]) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек не является преступником");
if(GetPlayerState(params[0]) != PLAYER_STATE_ONFOOT) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек в автомобиле");
new mesto2,vehicle=GetPlayerVehicleID(playerid);
foreach(new i : Player)
{
if(IsPlayerInVehicle(i,vehicle))
{
mesto2 = GetPlayerVehicleSeat(i);
if(mesto2==2) return SendClientMessage(playerid, COLOR_GRAD1, !"[Ошибка] Место в машине уже занято");
}
}
PutPlayerInVehicleEx(params[0],vehicle,1);
SetPlayerArmedWeapon(params[0],0);
format(YCMDstr,sizeof(YCMDstr), "Вы были затащены в машину %s",Name(playerid));
SendClientMessage(params[0],0x64E96EDFF,YCMDstr);
format(YCMDstr,sizeof(YCMDstr), "Вы затащили в машину %s",Name(params[0]));
SendClientMessage(playerid,0x64E96EDFF,YCMDstr);
}
return 1;
}

Убери и глянь :D
P.S а вообще команда будет выполняться на ид игрока которого ты ввел.
Потом это значение может подгрузить левый игрок, который зайдет на этот ид.

DeimoS
26.04.2019, 10:33
В данной команде не нужна проверка
if(!IsPlayerConnected(params[0])) return 1;
Ибо в sscanf указан спецификатор "u", который сам проверяет, онлайн ли игрок и если не онлайн, то присваивает переменной значение INVALID_PLAYER_ID.

В общем, достаточно будет лишь:
if(sscanf(params, "u",params[0])) return SCM(playerid, -1, !"Введите: /cput [playerid]");
if(params[0] == INVALID_PLAYER_ID) return SCM(playerid, COLOR_GRAD1, !"[Ошибка] Человек небыл найден");

DmitriyVasilev
26.04.2019, 14:38
Убрал, но все работает так же как обычно

DeimoS
26.04.2019, 14:40
Так ничего и не должно измениться. Эта проверка просто была бессмысленна и лишь время на её обработку затрачивалось лишнее.

DmitriyVasilev
26.04.2019, 14:41
если автоматически присвается инволид плеер ид то зачем проверку делать?

Paradox
26.04.2019, 14:55
Может просто команды были реализованы через strtok, sscanf подключился позже, естественно когда переписывали, переписывали основное, и не обращали внимание на то или иное. а может просто не знали, и оставили.

DeimoS
26.04.2019, 18:13
если автоматически присвается инволид плеер ид то зачем проверку делать?

Ну так sscanf проверяет, подключён ли игрок, и если нет, то переменной, в которую нужно записать ID, записывает значение INVALID_PLAYER_ID. Соответственно, теперь чтоб узнать, онлайн ли игрок, достаточно проверить значение переменной на равенство с INVALID_PLAYER_ID.
Я же написал в позапрошлом сообщении об этом.