23.02.2012, 21:22
(
Последний раз редактировалось JernejL; 23.02.2012 в 22:29.
)
pawn Код:
#define foreach(%1,%2) for (new %2 = 0; %2 < sizeof(%1); %2++ )
// Store last X ips, 37 seems to be a perfectly decent and efficiently well rounded number for this purpose.
#define max_joins_log 37
// Current index @ ipjoinlog in sequence
new autoinc_join_sequence = 0;
enum core_ipjoin { // struct
ip_add,
timestamp
}
new ipjoinlog[max_joins_log][core_ipjoin]; // last X times and ips of people joining.
stock intabs(innumber) {
if (innumber < 0)
return -innumber;
return innumber;
}
stock Distance1Dint(fPos1, fPos2) {
if (fPos1 > fPos2)
return intabs(fPos1 - fPos2);
else
return intabs(fPos2 - fPos1);
}
// This function manages to properly calculate time even if the timers wrap around and underflow.
stock GetTimeDistance(a, b) {
// a pawn cell is signed 32-bit integer.
// -2147483648 to 2147483647
if ((a < 0) && (b > 0)) {
new dist;
dist = Distance1Dint(a, b);
if (dist > 2147483647)
return Distance1Dint(a - 2147483647, b - 2147483647);
else
return dist;
} else {
return Distance1Dint(a, b);
}
}
// please note that this is NOT a perfect inet_aton function, but you will not be able to output the number as a unsigned integer as pawn uses signed int32 only.
// (by specification the returned type of inet_aton should be UNSIGNED int 32)
// example conversion failures:
// 127.0.0.1 -> 2130706433
// 128.68.103.132 -> -2143000700
stock inet_aton(ip[]) {
new ipv = strval(ip) << 24, pos = 0;
while (pos < 15 && ip[pos++] != '.') {}
ipv += strval(ip[pos]) << 16;
while (pos < 15 && ip[pos++] != '.') {}
ipv += strval(ip[pos]) << 8;
while (pos < 15 && ip[pos++] != '.') {}
ipv += strval(ip[pos]);
return ipv;
}
stock log_new_join(PlayerID) {
new ip[18];
GetPlayerIp(PlayerID, ip, sizeof(ip));
new ipv = inet_aton(ip);
ipjoinlog[autoinc_join_sequence][ip_add] = ipv;
ipjoinlog[autoinc_join_sequence][timestamp] = TickCount();
autoinc_join_sequence++;
if (autoinc_join_sequence >= max_joins_log)
autoinc_join_sequence = 0;
}
stock number_joins_time_range(PlayerID, max_time) {
new ip[18];
GetPlayerIp(PlayerID, ip, sizeof(ip));
new ipv = inet_aton(ip);
new counted = 0;
foreach(ipjoinlog, I) {
if (ipjoinlog[I][ip_add] != ipv) // different IP.
continue;
if (GetTimeDistance(TickCount(), ipjoinlog[I][timestamp]) <= max_time)
counted++;
}
return counted;
}
public OnPlayerConnect(playerid) {
log_new_join(playerid);
new intjoins = number_joins_time_range(playerid, 5000);
printf("received player %d with nickname %s and number of joins from same ip in last 5 seconds is %d", playerid, pNickname[playerid], intjoins);
// Now you know how many times the IP has joined in past 5 seconds, now you can do as you please.
// I suggest a RCON ban as it will block all the join spam and all further attempts to mess with your server further
}