Zamanında Lean Roleplay projesi için AFK tespiti üzerine çalışmıştık ama o dönem tecrübesizliğimizden dolayı pek başarılı olamamıştık. Sonrasında UniqueRPG paketinden bulduğum AFK.inc dosyasını denedim. Fakat içinde kullanılan foreach include'u ciddi hatalara sebep oldu.
Ben de bu problemi aşmak için sadece a_samp.inc ile uyumlu, foreach kullanmayan temiz ve stabil çalışan bir versiyon hazırladım. Elimdeki include'u baştan düzenleyerek sade ve stabil bir hale getirdim. Eski halini "v1", düzenlediğim halini ise "v2" olarak düşünebilirsiniz.
Sunucularınızda kullanmak isterseniz, doğrudan entegre edebilirsiniz. Eğer debug çıktılarından (konsolda gözüken printf satırları) rahatsız oluyorsanız, include içerisindeki printf komutlarını silerek debug olmadan bir şekilde de çalıştırabilirsiniz.
Umarım işinize yarar.
Eğer direkt indirmek isterseniz aşağıda bıraktığım linke tıklayıp indirebilirsiniz.
https://www.upload.ee/files/18407737/afk.inc.html
V1 Eski Kaynak:
https://github.com/Mihaitza/samp/blob/master/afk.inc
// Otomatik AFK Tespit v2.0.0
// McAllen tarafından düzenlendi.
new bool:PlayerAFK[MAX_PLAYERS]; // Oyuncunun AFK olup olmadığını belirler [0-NOT-AFK | 1-AFK]
new AFKDetect[MAX_PLAYERS]; // Oyuncunun AFK durumu tespit zamanı
new bool: FunctionCall[2][MAX_PLAYERS]; // OnPlayerPause ve/veya OnPlayerUnpause fonksiyonlarının tekrar çağrılmasını engeller
new playerAName[50]; // Oyuncu adı
new AFKTime[MAX_PLAYERS]; // Oyuncunun AFK olduğu sürenin başlama zamanı
#include <a_samp>
forward OnPlayerPause(playerid);
forward OnPlayerUnpause(playerid);
forward AFKChecker();
forward IsPlayerPause(playerid);
forward TimeSincePaused(playerid);
public OnPlayerUpdate(playerid)
{
AFKDetect[playerid] = gettime();
#if defined VFUNC_OnPlayerUpdate
return VFUNC_OnPlayerUpdate(playerid);
#else
return 1;
#endif
}
#if defined VFUNC_OnPlayerUpdate
forward VFUNC_OnPlayerUpdate(playerid);
#endif
#if defined _ALS_OnPlayerUpdate
#undef OnPlayerUpdate
#else
#define _ALS_OnPlayerUpdate
#endif
#define OnPlayerUpdate VFUNC_OnPlayerUpdate
public OnPlayerDisconnect(playerid, reason)
{
if (PlayerAFK[playerid] == true && FunctionCall[1][playerid] == false)
{
GetPlayerName(playerid, playerAName, sizeof(playerAName));
PlayerAFK[playerid] = false;
printf("[AFK-DEBUG] %s artık AFK değil, sunucudan ayrıldı. (%d saniye)", playerAName, gettime() - AFKTime[playerid]);
FunctionCall[1][playerid] = true;
FunctionCall[0][playerid] = false;
AFKTime[playerid] = 0;
CallLocalFunction("OnPlayerUnpause", "i", playerid);
}
#if defined VFUNC_OnPlayerDisconnect
return VFUNC_OnPlayerDisconnect(playerid, reason);
#else
return 1;
#endif
}
#if defined VFUNC_OnPlayerDisconnect
forward VFUNC_OnPlayerDisconnect(playerid, reason);
#endif
#if defined _ALS_OnPlayerDisconnect
#undef OnPlayerDisconnect
#else
#define _ALS_OnPlayerDisconnect
#endif
#define OnPlayerDisconnect VFUNC_OnPlayerDisconnect
public OnGameModeInit()
{
SetTimer("AFKChecker", 500, true);
#if defined VFUNC_OnGameModeInit
return VFUNC_OnGameModeInit();
#else
return 1;
#endif
}
#if defined VFUNC_OnGameModeInit
forward VFUNC_OnGameModeInit();
#endif
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit VFUNC_OnGameModeInit
public AFKChecker()
{
for (new i = 0; i < MAX_PLAYERS; i++)
{
if (IsPlayerConnected(i))
{
if (gettime() - AFKDetect[i] > 5)
{
if (PlayerAFK[i] == false && FunctionCall[0][i] == false)
{
GetPlayerName(i, playerAName, sizeof(playerAName));
PlayerAFK[i] = true;
CallLocalFunction("OnPlayerPause", "i", i);
printf("[AFK-DEBUG] %s artık AFK.", playerAName);
FunctionCall[0][i] = true;
FunctionCall[1][i] = false;
AFKTime[i] = gettime();
}
}
else
{
if (PlayerAFK[i] == true && FunctionCall[1][i] == false)
{
GetPlayerName(i, playerAName, sizeof(playerAName));
PlayerAFK[i] = false;
CallLocalFunction("OnPlayerUnpause", "i", i);
printf("[AFK-DEBUG] %s artık AFK değil. (%d saniye)", playerAName, gettime() - AFKTime[i]);
FunctionCall[1][i] = true;
FunctionCall[0][i] = false;
AFKTime[i] = gettime() - AFKTime[i];
}
}
}
}
return 1;
}
public IsPlayerPause(playerid)
{
if (PlayerAFK[playerid] == true) return 1;
else return 0;
}
public TimeSincePaused(playerid)
{
if (PlayerAFK[playerid] == true) return gettime() - AFKTime[playerid];
else return AFKTime[playerid];
}
Örnek Kullanım:
if (IsPlayerPause(userid)) SendWarningMessage(playerid, "PM attığınız kişi AFK, mesajınızı göremeyebilir.");
aslan yiğenim
Başarılı, Ellerine Sağlık!
Afk sistemlerindeki genel mantık OnPlayerUpdate methodunun tetiklenmesini kontrol etmekten geçer. Sizin yaptığınız yöntem ise time değerini değişkene atayıp güncel zamandan fark almak olmuş. Geçerli bir yöntem, elinize sağlık.
new g_PlayerLastUpdate[MAX_PLAYERS];
public OnPlayerUpdate(playerid)
{
g_PlayerLastUpdate[playerid] = GetTickCount(); // Oyuncudan gelen güncellemeyi kaydet
return 1;
}
public OnPlayerConnect(playerid)
{
g_PlayerLastUpdate[playerid] = GetTickCount();
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
g_PlayerLastUpdate[playerid] = 0;
return 1;
}
forward CheckAFK();
public CheckAFK()
{
new currentTime = GetTickCount();
for(new i = 0; i < MAX_PLAYERS; i++)
{
if(IsPlayerConnected(i))
{
if(currentTime - g_PlayerLastUpdate[i] > 5000) // 5 saniye
{
printf("Oyuncu %d AFK", i);
}
}
}
return 1;
}