GTAOnline.net

San Andreas Multiplayer (sa:mp) => Scripting SA-MP [Pawn center] => Discussion démarrée par: Winklevows le 10 Juin 2011, 03:50:44

Titre: Problème avec mon anticheat cheat SERVER SIDE
Posté par: Winklevows le 10 Juin 2011, 03:50:44
Bonjour,
J'ai créé un anticheat serveur (money, hp et armure) en m'inspirant d'un aticheat cheat money SERVER SIDE.

Bon, je m'adresse aux personnes qui ont un minimum de connaissances et de logique  :happy

Voila mon problème, quelque fois, mon anticheat détecte un cheat alors qu'il ne devrait pas.
Par exemple, quand je donne de l'armure à un joueur avec ma commande, l'anticheat reset l'armure et me dit que le joueur a essayé de cheat. Là est le problème.

Pour faire simple, je vais vous montrer simplement l'anticheat armure:

Le timer qui check si je joueur cheat:
<?php
public AntiCheatPlayer(playerid// TimerEx exécuté toute les 1 seconde (lancé quand un joueur se connecte et killed quand il se déconnecte)
{
if(IsSpawned[playerid] == && AdminLevel[playerid] == 0
{
new Float:Armor;
GetPlayerArmour(playeridArmor);
if(Armor != SSArmor[playerid]) // Armor = l'armure coté client et SSArmor[playerid] coté serveur
{
if(Armor SSArmor[playerid])
{
SSArmor[playerid] = Armor;
}
else if(Armor SSArmor[playerid])
{
new username[MAX_PLAYER_NAME], string[150];
GetPlayerName(playerid,username,sizeof(username));
format(string,sizeof(string),"[ANTI-CHEAT]"ECOLOR_WHITE" %s(%d) a tenté de regénérer son armure."username,playerid);
SendClientAlertToAllAdmins(string);
SetPlayerArmour(playerid,SSArmor[playerid]); // là on remet l'armure du joueur (valeur contenue dans la variable coté serveur)
}
}
}
}
La fonction SetPlayerArmourSS:
<?php
stock SetPlayerArmourSS
(playeridFloat:Armor)
{
SSArmor[playerid] = Armor;
return SetPlayerArmour(playerid,SSArmor[playerid]);
}

Maintenant la commande pour donner de l'armure à un joueur:

<?php
COMMAND
:adarmour(playerid,params[])
{
new string[128], nom[MAX_PLAYER_NAME], IDFloat:armure;
if(AdminLevel[playerid] <=2) return 0// si le joueur n'est pas admin on stop la commande ici
if(!sscanf(params"uf"ID,armure))
{
if(IsPlayerConnected(ID))
{
GetPlayerName(ID,nom,sizeof(nom));
format(string,65,"Vous avez fixé l'armure de %s(%d) à %f.",nom,ID,armure);
SendClientMessage(playerid,COLOR_ADMIN,string);
format(string,85,"7[ARMURE] Un Administrateur a fixé l'armure de %s(%d) à %f.",nom,ID,armure);
IRC_GroupSay(gGroupID,IRC_CHANNEL,string);
SetPlayerArmourSS(ID,armure); // on défini l'armure grâce à ma fonction SetPlayerArmourSS
}
else SendClientMessage(playerid,COLOR_ERROR,"Ce joueur n'est pas connecté.");
}
else SendClientMessage(playerid,COLOR_ERROR,"Utilisation: /adarmour (ID/Nom Joueur) (Armure [DOIT ÊTRE INFÉRIEUR OU ÉGAL À 100 !])."); 
return 1;
}

Même problème quand un joueur achète de l'armure, malgré que je lui donne l'armure avec ma fonctione SetPlayerArmourSS, quelque fois son armure est reset...

Merci de votre aide !  :)

Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 10 Juin 2011, 11:21:49
Tu peut nous montrer comment tu déclare la variable SSArmor, s'il te plait ^^
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Winklevows le 10 Juin 2011, 13:20:31
Voila:
new Float:SSArmor[MAX_PLAYERS];
Et la variable est définie à 0 quand le joueur spawn:
public OnPlayerSpawn(playerid)
{
SSArmor[playerid] = 0.00;
...
}
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 10 Juin 2011, 13:39:32
j'ai trouvé ^^

GetPlayerArmour(playerid, Armor);
Armor = GetPlayerArmour( playerid );
Titre: Re : Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Winklevows le 10 Juin 2011, 14:40:34
j'ai trouvé ^^

GetPlayerArmour(playerid, Armor);
Armor = GetPlayerArmour( playerid );

Citer
FCRPG.pwn(24289) : warning 202: number of arguments does not match definition

 :'(

Je précise que mon anticheat fonctionne sauf quelque fois, donc s'est encore plus bizarre...
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 10 Juin 2011, 15:51:51
ah oui désolé, c'est moi qui c'est trompé :s

Je ne connais plus du tout les prototypes des fonctions que proposent sa-mp :s
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Syg le 11 Juin 2011, 23:37:09
Je pense qu'on a là un bel exemple d'accès concurrent à une variable.

Pour éviter ça, on peut faire un double contrôle pour gérer le cas où l'armure à été modifiée alors qu'on vient juste de la lire dans la fonction du timer.
Dans ton cas, il n'y a qu'une seul ligne de code à ajouter :
public AntiCheatPlayer(playerid) // TimerEx exécuté toute les 1 seconde (lancé quand un joueur se connecte et killed quand il se déconnecte)
{
if(IsSpawned[playerid] == 1 && AdminLevel[playerid] == 0)
{
new Float:Armor;
GetPlayerArmour(playerid, Armor);
/* Premier contrôle */
if(Armor != SSArmor[playerid]) // Armor = l'armure coté client et SSArmor[playerid] coté serveur
{
/* LIGNE DE CODE A AJOUTER */
/* On récupère l'armure pour un double controle */
GetPlayerArmour(playerid, Armor);

/* Deuxième contrôle */
if(Armor < SSArmor[playerid])
{
SSArmor[playerid] = Armor;
}
else if(Armor > SSArmor[playerid])
{
new username[MAX_PLAYER_NAME], string[150];
GetPlayerName(playerid,username,sizeof(username));
format(string,sizeof(string),"[ANTI-CHEAT]"ECOLOR_WHITE" %s(%d) a tenté de regénérer son armure.", username,playerid);
SendClientAlertToAllAdmins(string);
SetPlayerArmour(playerid,SSArmor[playerid]); // là on remet l'armure du joueur (valeur contenue dans la variable coté serveur)
}
}
}
}
Ceci permet de gérer le cas où les deux fonctions (SetPlayerArmourSS et AntiCheatPlayer) s’exécutent en même temps.

L'autre technique fiable à 100 % consiste à protéger l'accès à la variable SSArmor par un mutex. Malheureusement, ceux-ci n'existe pas sous SAMP et il faut coder soi-même leur gestion.
Mais bon, la technique du double contrôle fonctionne très bien aussi.

++
Syg
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: S!m le 12 Juin 2011, 00:32:38
Salut,

j'ai toujours cru que le PAWN ne gérait pas le multi-thread, serais-je dans l'erreur?

Pour moi une chose s'exécute puis une autre etc... dans ce cas on ne peut pas faire deux chose en même temps.. non?

++Sim++
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 12 Juin 2011, 02:47:56
ouais sim, mais sont code s'exécute dans un timer, et je pense que c'est cela qui fais que ce n'est pas dans le même thread, je vérifierai ça demain ^^ ( plutôt ce matin :p )
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Syg le 12 Juin 2011, 13:21:54
Tous les timers sont dans des threads séparés (du moins c'est ce que j'ai cru comprendre, Ssk confirmera ou pas). D'ailleurs, si ce n'était pas le cas, on aurait beaucoup de mal à scripter correctement. A moins que la team SAMP ait fait elle même sa gestion du multitâche.
Pour le reste, effectivement, SAMP n'a qu'un seul thread.

++
Syg
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 12 Juin 2011, 13:56:02
Dans ce que je lit du code du serveur je vois que les timers sont géré dans le même thread que celui du serveur :s
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Syg le 12 Juin 2011, 22:04:55
Il y a forcément un gestion du multitâche, sinon l'exécution des timers serait aléatoire et on ne pourrait pas s'en servir convenablement.
Je ne sais pas comment ça marche sous Linux mais sous Windows, le thread est créé automatiquement quand on démarre un timer et c'est Windows qui le gère.

Reste que le problème est là et comme il est aléatoire, la seule raison logique est l'exécution simultanée de ses deux bouts de script car s'ils étaient exécutés en séquence (dans un ordre ou dans l'autre) le problème ne serait pas présent.

++
Syg
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 12 Juin 2011, 23:16:24
Je t'assure que non Syg.

Quand tu créer un timer ça te le stock dans une liste qui elle même est dans une classe, puis dans la boucle principale du serveur on appel la méthode Process de cette classe là, et c'est ici que sa-mp gère tout ça.
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Syg le 13 Juin 2011, 01:33:21
D'une manière ou d'une autre, les deux bouts de code s'exécutent en parallèle. Comme je le dit, il n'est pas possible d'avoir le problème si ce n'est pas la cas.
Et ce n'est pas parce qu'on a qu'un seul thread qu'on ne peut pas faire de multitâche. C'est dur à programmer mais pas impossible.

NB : Le processus SAMP-server.exe a 3 threads sous windows. En admettant qu'il y en ait un qui gère la routine principale du serveur (le gamemode), un qui gère la connexion avec les clients, à quoi sert le troisième ?

++
Syg
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 13 Juin 2011, 02:21:15
Tu as tout à fait raison, il y a bien 3 threads, un pour le serveur, un pour raknet ( le réseau ), et un qui est seulement sous Windows pour pouvoir capturer des entrées de textes sur la console.


Et je peut t'assurer à 100% que les timers sont gérés dans le même thread que le serveur, sont bug est très bizarre mais ne peut provenir du fais qu'on accède en même temps à la même variable :s
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Syg le 13 Juin 2011, 13:18:35
Reste maintenant à savoir si ma proposition corrige le problème.
D'ailleurs, je me rappelle qu'à l'époque, j'avais aidé Guigui a corrigé un problème similaire sur le SFTDM concernant l'argent. C'était il y a 2 ou 3 ans et je me rappelle plus ce qu'on avait fait mais surement quelque chose d'équivalent.

++
Syg
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 13 Juin 2011, 13:33:37
ça m'étais aussi arrivé mais je me souviens plus comment j'ai réglé le problème lol
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Winklevows le 16 Juin 2011, 22:27:56
Bonjour,
Je pensais que mon topic avait été abandonné mais je suis retombé dessus par hasard et je vois que non finalement  :)

Étant en plein bac actuellement je vais pas pouvoir vérifié ton code maintenant Syg...

Avant sa, je me rappel (si je me souvient bien) que lorsque je donnais de l'armure avec ma fonction, la variable SSArmor[playerid] était égal à 100 mais lorsque le timer "checkais", l'armure était reset car la variable SSArmor[playerid] était égal à 0 (quelque fois elle était bien était égal à 100 donc l'armure n'était pas reset, par conséquence l'armure était bien donné).
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Winklevows le 04 Juillet 2011, 22:37:59
Bonjour,

Alors j'ai une mauvaise nouvelle, ton code ne fonctionne pas plus Syg.

Mais j'ai trouvé la solution: Utilisé un booléen qui indique à l'anticheat si le joueur peut ou non utiliser l'armure.

stock SetPlayerArmourEx(playerid, Float:varArmor)
{
CanUseArmour[playerid] = 1; // Indique que le joueur peut utiliser l'armure qu'il a acheté / trouvé
SSArmor[playerid] = varArmor;
return SetPlayerArmour(playerid,varArmor);
}

Ensuite, au lieu d'utiliser un Timer, j'ai préféré utilise OnPlayerUpdate qui est, selon moi, plus adapté pour un anti-cheat bien que mon propos peut être discutable.

public OnPlayerUpdate(playerid)
{
if(IsSpawned[playerid] == 1 && AdminLevel[playerid] == 1337)
{
new Float:tArmor;
GetPlayerArmour(playerid, tArmor);
if(tArmor != SSArmor[playerid]) /* Premier contrôle */
{
/* On récupère l'armure pour un double controle */
GetPlayerArmour(playerid, tArmor);
if(tArmor < SSArmor[playerid]) /* Deuxième contrôle */
{
SSArmor[playerid] = tArmor;
}
else if(tArmor > SSArmor[playerid])
{
if(CanUseArmour[playerid] == 1) // Si le joueur peut utiliser l'armure qu'il a acheté/trouvé
{
CanUseArmour[playerid] = 0;
SSArmor[playerid] = tArmor; // alors on met à jour la variable qui n'avait pas été mise à jour pour une raison inconnue ??
}
else // Sinon cela signifie qu'il a cheaté donc:
{
new username[MAX_PLAYER_NAME], string[150];
GetPlayerName(playerid,username,sizeof(username));
format(string,sizeof(string),"[ANTI-CHEAT]"ECOLOR_WHITE" %s(%d) a tenté de regénérer son armure.", username,playerid);
SendClientMessageToAllAdmins(string);
SetPlayerArmour(playerid,SSArmor[playerid]);
}
}
}
}
return 1;
}

Et sa fonctionne d'après mes tests !

Je pense qu'en réalité la variable SSArmor n'avait pas le temps de se mettre à jour car elle était reset aussitôt, j'ai remarqué sa car le bug était plus flagrant en utilisant OnPlayerUpdate qu'avec un timer (qui est exécuté moins souvent);

Que pensez vous de ma solution ?

Merci
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Ssk le 04 Juillet 2011, 23:33:34
Dans la première condition tu test si le joueur est admin au level 1337, cela veut donc dire que les autres joueurs qui ne sont pas admins pourront cheater sans problème.
Titre: Re : Problème avec mon anticheat cheat SERVER SIDE
Posté par: Winklevows le 06 Juillet 2011, 03:08:40
S'était pour utiliser mon compte administrateur et mes commandes admins pour me donner de l'armure lors de mes tests, j'ai juste oublié de remplacé 1337 par 0 quand je vous ai collé mon code  :happy