یوشا

وبگاه دست نوشته ها و تجربیات شخصی

یوشا

وبگاه دست نوشته ها و تجربیات شخصی

یوشا

دکتر مصطفی چمران: می گویند تقوا از تخصص لازمتر است، آنرا می پذیرم، اما می گویم: آنکس که تخصص ندارد و کاری را می پذیرد، بی تقواست!

بایگانی
تبلیغات
Blog.ir بلاگ، رسانه متخصصین و اهل قلم، استفاده آسان از امکانات وبلاگ نویسی حرفه‌ای، در محیطی نوین، امن و پایدار bayanbox.ir صندوق بیان - تجربه‌ای متفاوت در نشر و نگهداری فایل‌ها، ۳ گیگا بایت فضای پیشرفته رایگان Bayan.ir - بیان، پیشرو در فناوری‌های فضای مجازی ایران

1- همیشه از تابع mysql_tquery() بجای mysql_query() استفاده کنید. تابع mysql_tquery از نوع multi-thread هستش و میزان وقفه/lag در سرور رو بسیار کاهش میده. (عملیات رو بین Thread ها تقسیم میکنه)

 

2- درصورتی که از سیستم های ضد hack/cheat استفاده می کنید، همیشه EnableStuntBonusForAll رو 0 قرار بدید.

در غیراینصورت سرور کاربر رو هکر قلمداد میکنه.

 

3- توسط پلاگین crashdetect میتونید crash های سرور رو ردیابی کنید.

https://github.com/Zeex/samp-plugin-crashdetect

نکته: برای استفاده از این پلاگین در ویندوز، مطعمن بشید که VC++ runtime 2010 - VC10 نگارش x86 و x64 رو نصب دارید.

 

4- همیشه دستورات AddPlayerClass() رو در مختصات مناسب و قابل دسترس تنظیم کنید تا در صورت بروز باگ یا مشکلات شبکه ای(packet lost) کاربر به موقعیت مناسبی teleport بشه.

5- با include کردن کتابخانه MapFix باگهای mapping world همگی رفع خواهند شد.

http://forum.sa-mp.com/showthread.php?t=591476

 

6- توسط فیلتر اسکریپت PAOE براحتی attachment های کاربر رو اضافه، حذف و ویرایش کنید!

http://forum.sa-mp.com/showthread.php?t=416138

 

7- حتاالمکان بجای استفاده از Timer های متعدد و کاهش performance سرور، از دستور GetTickCount() استفاده کنید.

 

8- هنگام تعریف اولیه resource هایی مثل Text3D, PlayerText, Text, Actor, Vehicle, Player, GangZone همیشه مقدار پیشفرض رو INVALID قرار بدید تا موقع بررسی وجود resource با مشکل مواجه نشید.

INVALID_3DTEXT_ID, INVALID_PLAYER_ID, INVALID_ACTOR_ID, INVALID_VEHICLE_ID...

 

9- بجای تکرار مختصات 0.0, 0.0, 0.0 در همه قسمتهای برنامه، میتونید اینهارو به ثابت define تبدیل و در همه جا فراخونی کنید:

#DEFINE COORDINATE_DEFAULT 0.0, 0.0, 0.0

 

10- یادتون نره که در کالبک OnGameModeExit داده های همه کاربران رو save کنید، درغیراین صورت هنگام stop شدن سرور(دستی یا crash) داده های کاربر از بین خواهند رفت!

 

11- برای بهبود کارایی سیستم ban تعبیه شده در SA-MP، بهتره پارامتر reloadbans رو توسط دستور SendRconCommand() در کالبک OnIncomingConnection قرار بدید:

public OnIncomingConnection(playerid, ip_address[], port)
{
   SendRconCommand("reloadbans");
}

 

12- از انجایی که برای پروژه های Pawn/SA-MP ساختار استاندارد و اصولی وجود نداره، پیشنهاد می کنم از این ساختار استفاده کنید:

commands.inc برای دستورات

utils.inc برای توابع و رویه ها

textdraws.inc برای ساخت و نگهداری textdraw ها

variables.inc برای تعریف متغیر های سراسری

objects.inc برای ساخت و نگهداری game object و mapping ها

enumerates.inc برای enum ها

tasks.inc برای timer ها(درصورتی که از کتابخانه y_less استفاده می کنید)

configuration.inc برای پیکربندی اولیه و ثابت های define

و همگی باید در پوشه include باشن.

 

13- بجای تعریف متغیر برای رشته های static(مثل help/) میتونید از یک متغیر سراسری استفاده کنید. یا حتی اونهارو بصورت ثابت define تعریف کنید.

 

14- نکته جزیی: جهت افزایش پرفومنس هنگام پرس و جو با SQL بهتره با Id کار کنید و نه نام، عنوان و...

 

15- جای استفاده از دستور mysql_escape_string() بهمراه format()، میتونید از دستور mysql_format() با e% استفاده کنید. با اینکار MySQL بصورت خودکار رشته رو در مقابل حملات SQL Injection ایمن میکنه.

 

16- درصورتی که از NPC(نه Actor) استفاده می کنید، برای جلوگیری از ایجاد باگ و تداخل بین کاربر و NPC عبارت if (IsPlayerNPC(playerid)) return 1; رو در همه کالبک های OnPlayer* قرار بدید. مثال:

public OnPlayerStateChange(playerid, newstate, oldstate)
{
   if (IsPlayerNPC(playerid))
   {
      return 1;
   }

// ...
 

17- برای بررسی valid بودن vehicle از کد زیر استفاده کنید:

bool:IsVehicleInGame(const vehicleid)
{
   new Float:x, Float:y, Float:z;
   GetVehiclePos(vehicleid, x, y, z);

   if (((x == 0.0) && (y == 0.0) && (z == 0.0)) || (vehicleid == INVALID_VEHICLE_ID) || (vehicleid == INVALID_VALUE))
   {
      return false;
   }

   return true;
}

 

18- نکته جزیی: با استفاده از دستور SetPlayerWorldBounds() میتونید برای کاربران محدودیت مکانی ایجاد کنید.

 

19- توجه کنید که دستور TextDrawCreate() با دستور CreatePlayerTextDraw() متفاوته! و هرکدوم باید درجای خودش استفاده بشه. PlayerTextDraws میتونه با خروج کاربر از سرور نابود بشه، اما TextDrawCreate استاتیک هستش و فقط با TextDrawDestroy() نابود میشه.

 

20- برای گرفتن نام کاربر و جلوگیری از تکرار کد میتونید تابع زیر رو بکار ببندید:

ReturnPlayerName(const playerid)
{
   new name[MAX_PLAYER_NAME];
   GetPlayerName(playerid, name, sizeof(name));
   return name;
}

 

21- بجای استفاده از ثابت MAX_PLAYERS در حلقه for برای عملیات روی کاربران باید از روش زیر استفاده کنید:

for (new i = 0, j = GetPlayerPoolSize(); i <= j; i ++)
{
   SetPlayerHealth(i, 100.0);
}

چون ثابت MAX_PLAYERS حاوی ظرفیت کل سرور هستش(50-500-1000...) اما دستور GetPlayerPoolSize() حاوی آخرین ID کاربری هستش که وارد سرور شده. پس بسیار بهینه و بصرفه هست.

 

22- کاملترین روش برای بررسی وجود کاربر موردنظر در سرور استفاده از تابع زیر هست:

bool:IsPlayerInGame(const playerid)
{
   if (!IsPlayerConnected(playerid) || (playerid == INVALID_PLAYER_ID) || IsPlayerNPC(playerid))
   {
      return false;
   }

   return true;
}

 

23- برای ثابت نگه داشتن Health کارمندان سرور میتونید از روش زیر استفاده کنید:

public OnPlayerUpdate(playerid)
{
   if (playerData[playerid][pd_IsOnDutyAdmin]) // !
   {
      SetPlayerHealth(playerid, 65535.0);
   }

   return 1;
}

 

24- نکاتی راجب کالبک های OnPlayerRequestClass, OnPlayerRequestSpawn و OnPlayerSpawn:

کالبک OnPlayerRequestClass: هنگام ورود کاربر به صفحه Class Selection و چپ و راست کردن بین Class ها صدا زده میشه.

کالبک OnPlayerRequestSpawn: هنگامی که کاربر دکمه Spawn رو فشار میده صدا زده میشه.

کالبک OnPlayerSpawn: هر زمان که کاربر Spawn میشه یا دستور Spawn() صراحتاً اجرا میشه، صدا زده میشه.

نکته: در بعضی از قسمت های سرور با Spawn شدن کاربر، $100 از CASH کاربر برداشت میشه.

نکته 2: این کالبک OnPlayerSpawn در Filterscript ها همیشه اول از همه کالبکهای کاربر صدا زده میشه.

 

25- مقدار 0 / 1 بازگشتی return در کالبک های اصلی SA-MP تعیین میکنن که آیا کالبک در پایان عملیات به Filterscript ها هم منتقل بشه یا خیر.

 

26- هرگز float و integer رو با یکدیگر mix نکنید، اینکار باعث ایجاد خطا(tag mismatch) یا اشتباه در برنامه نویسی خواهد شد:

غلط:

new Float:result = 2.0 + 1;

صحیح:

new Float:result = 2.0 + 1.0;

 

27- نکته جزیی: بهترین محل برای reset کردن داده های کاربر داخل کالبک OnPlayerConnect هستش.

 

28- نکته جزیی: یادتون باشه که حداکثر طول رشته ای SA-MP میتونه نمایش بده 128 کاراکتر هستش، پس برای ارسال پیام به کاربر بیش از این مقدار رو اختصاص ندید!

 

29- درصورتی که از سیستم های ضد hack/cheat استفاده می کنید، به هیچ وجه از pickupmodel های 1212, 1240, 1242, 1274 و weapon در دستور CreatePickup() استفاده نکنید.

در غیراینصورت سیستم کاربر رو هکر قلمداد میکنه.

 

30- عدد پارامتر iconid در تابع SetPlayerMapIcon() تعیین کننده slot استفاده شده mapicon هستش. در صورت استفاده از slot تکراری، mapicon جدید جایگزین mapicon قبلی خواهد شد.

 

31- برای امنیت بیشتر سرور بهتره مقدار rcon در server.cfg رو 0 قرار بدید.

 

32- نکته جزیی: برای غیرفعال کردن Chat پیشفرض SA-MP کافیه مقدار بازگشتی return در کالبک OnPlayerText رو 0 قرار بدید.

 

31- برای تمیز نگه داشتن console سرور بهتره مقدار chatlogging در server.cfg رو 0 قرار بدید تا از ثبت Chat کاربران در console جلوگیری بشه.

 

32- همیشه مقدار lagcompmode در server.cfg رو 1 قرار بدید تا lag بین کاربران و فعالیتشون از بین بره.

 

33- برای جلوگیری از disconnect/timeout شدن کاربران مقدار ackslimit در server.cfg رو 4000 قرار بدید.

 

34- نکته جزیی: مقدار stream_distance در server.cfg تعیین کننده برد stream شدن world/game object ها در صفحه نمایش کاربر هستش.

 

35- برای حل مشکل Knife کافیه عبارت زیر رو در کالبک OnPlayerTakeDamage قرار بدید:

if ((weaponid == WEAPON_KNIFE) && (bodypart == 9))
{
   SetPlayerHealth(playerid, 0.0);
}

 

36- برای teleport از طریق کلیک روی Map میتونید از کد زیر استفاده کنید:

public OnPlayerClickMap(playerid, Float:fX, Float:fY, Float:fZ)
{
   if (IsPlayerAdmin(playerid))
   {
      SetPlayerPosFindZ(playerid, fX, fY, fZ + 3.0);
      // Stop all player's sounds.
   }

   return 1;
}

 

37- برای جلوگیری از crash کاربران توسط اکسپلویت های bullet میتونید از کد زیر استفاده کنید:

public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
   if ((fX > 2140000000) || (fY > 2140000000) || (fZ > 2140000000))
   {
      Kick(playerid);
      return 0; // Desync the shot.
   }

   return 1;
}

 

38- برای جلوگیری از crash سرور توسط کاراکتر % در کالبک OnDialogResponse کافیه از کد زیر استفاده کنید:

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
   if (strfind(inputtext, "%", true) != INVALID_VALUE) // Fixes crash.
   {
      return 0;
   }

   return 1;
}

 

39- بعد از اینکه Dialog ای در کالبک OnDialogResponse هندل می کنید، قطعاً باید مقدار return 1 رو بازگشت بدید!

 

40- همیشه بجای نوشتن مختصات های طولانی و بی نام و نشان از ثابت define استفاده کنید:

#define COORDINATE_AREA51 213.0, 1902.0, 17.9

 

41- برای خوانایی و دسته بندی بهتر ثابت های define اونها رو بر اساس نوع resource دسته بندی کنید:

#define MAPICON_SKULL 23
#define WEATHER_SUNNY 1
#define WEAPON_NIGHTVISIONGOGGLES 44
#define SKIN_TRUTH 1
#define VEHICLE_HYDRA 520
#define SOUND_PUNCH 1130
#define PICKUPICON_BRIEFCASE 1210
#define COLOR_BLACK 0x000000FF
#define INTERIOR_OUTSIDE 0
// ...

 

42- بهتره زمانی از enum استفاده بشه که مقادیر پشت هم یا وضعیتی هستن... مثل انواع آب و هوا. درجات کاربر. جنسیت و... در غیر اینصورت بهتره که define استفاده بشه.

// Dialog
enum
{
   DIALOG_GLOBAL, // 0
   DIALOG_REGISTER_ISSUE,
   DIALOG_REGISTER,
   DIALOG_LOGIN,
   DIALOG_SHOP,
   DIALOG_COMMANDS, // 5
   DIALOG_CLASSSELECTION
};

 

43- نکته جزیی: برای خوانایی بهتر همیشه متغیرهایی که فقط دو وضعیت(0 / 1) دارن رو از نوع bool تعریف کنید.

 

44- تفاوت تابع نوع stock و public:

تابع stock: این نوع تابع در صورت قید شدن ولی استفاده نشدن هشدارهای کامپایلر رو خفه میکنه. میتونه مقدار return داشته/نداشته باشه. مناسب برای کتابخانه ها و Include ها هستش.

تابع public: این نوع تابع حتماً باید مقدار return داشته باشه. مقادیر string رو نمیتونه return کنه. مناسب برای استفاده در کالبک توابع CallLocalFunction, CallRemoteFunction, SetTimer, و SetTimerEx.

 

44- نکته جزیی: همیشه آرایه هایی که مقدار ثابتی دارند رو از نوع const تعریف کنید.

 

45- هنگام طراحی Filterscript ها همه game object های ساخته شده رو در کالبک OnFilterScriptExit نابود/destroy کنید.

 

46- کتابخانه i-zcmd، یک command processor ساده، سبک و پرسرعت!

https://github.com/YashasSamaga/I-ZCMD/blob/master/izcmd.inc

 

47- بکمک تابع زیر میتونید nitro/non-nitro بودن vehicle رو بررسی کنید:

bool:IsNonNitroVehicle(const vehiclemodelid)
{
   static const nonNitroVehicles[29] = {581, 523, 462, 521, 463, 522, 461, 448, 468, 586, 509, 481, 510, 472, 473, 493, 595, 484, 430, 453, 452, 446, 454, 590, 569, 537, 538, 570, 449};

   for (new i = 0, j = sizeof(nonNitroVehicles); i != j; ++ i)
   {
      if (vehiclemodelid == nonNitroVehicles[i])
      {
         return true;
      }
   }

   return false;
}

 

48- در صورت خالی گذاشتن پارامتر title در دستور ShowPlayerDialog، دیالوگ مورد نظر نمایش داده نخواهد شد!

 

49- درصورتی که از پلاگین streamer استفاده می کنید، دیگر نیازی به include کردن فایل a_samp در ابتدای فایل ندارید.

 

50- بهتره همیشه زمان world رو با زمان server در کالبک OnGameModeInit یکی کنید:

new hour, minute, second;
gettime(hour, minute, second);
SetWorldTime(hour);
 

51- توسط پلاگین nativechecker میتونید خطاهای runtime سرور رو ردیابی کنید.

http://forum.sa-mp.com/showthread.php?t=249226

 

52- هنگام استفاده از پلاگین MySQL در لینوکس، اگر کتابخانه به libmysqlclient دسترسی ندارید یا با خطا مواجه هستید از فایل mysql_static.so این پلاگین استفاده کنید.

 

53- برای استفاده از پلاگین MySQL در ویندوز، باید VC++ runtime 2015 - VC14 نگارش x86 و x64 رو نصب داشته باشید.

نکته: فایل libmysql.dll نگارش 32 بیتی رو هم در کنار فایلهای سرور باید داشته باشید.

 

54- یادتون نره که پلاگین crashdetect باید همیشه دومین include سرور شما باشه:

#include <a_samp>
#include <streamer>
#include <crashdetect>

 

55- توسط فیلتر اسکریپت Zamaroht's TextDraw Editor براحتی TextDraw های سرور رو اضافه، حذف و ویرایش کنید.

http://forum.sa-mp.com/index.php?topic=143025.0

 

56- پلاگین FCNPC قدرتمند ترین و سریعترین پلاگین کار با NPC!

https://github.com/ziggi/FCNPC

نکته: برای استفاده از این پلاگین در ویندوز باید VC++ runtime 2015 - VC14 نگارش x86 و x64 رو نصب داشته باشید.

 

57- برای تبدیل integer به boolean میتونید مثل زیر عمل کنید:

new intVariable = 33;

new bool:boolVariable = !!intVariable;

 

58- هرگز source فایلها با پسوند pwn و inc رو در سرور آپلود نکنید، فقط فایلهای با پسوند amx رو آپلود کنید!

 

59- نکته جزیی: هرگز دایرکتوری sa-mp رو در لینوکس به 777 chmod نکنید.

 

60- همیشه متغیر های local رو در محل استفاده تعریف کنید، و نه در ابتدای کار.

غلط:

// WRONG!
CMD:getip(playerid, params[])
{
 new targetName[MAX_PLAYER_NAME], message[128], ip[40];
 new targetId;

 if (sscanf(params, "u", targetId))
 {
    return SendClientMessage(playerid, -1, "/getip <player>");
 }

 // ...

 

61- نکته جزیی: از پسوردهای ایمن و طولانی برای RCon استفاده کنید.

 

62- نکته جزیی: همیشه پسوردها رو بصورت hash شده در دیتابیس/فایل ذخیره کنید.

 

63- بجای استفاده های مکرر و طولانی format() و SendClientMessage() از تابع بهینه شده زیر استفاده کنید:

stock SendClientMessageEx(playerid, color, form[], {Float, _}: ...)
{
   #pragma unused form

   static tmp[145];
   new t1 = playerid, t2 = color ;
   const n4 = -4, n16 = -16, size = sizeof tmp;
   #emit stack 28
   #emit push.c size
   #emit push.c tmp
   #emit stack n4
   #emit sysreq.c format
   #emit stack n16
   return SendClientMessage(t1, t2, tmp);
}

 

64- همیشه بصورت روزانه یا هفتگی از داده های سرور backup بگیرید!

 

65- نکته جزیی: یادتون باشه که سرعت پردازش متغیر آرایه از متغیر عادی کندتر هست.

 

66- توسط دستور memcpy میتونید همه داده های کاربر جدید رو در OnPlayerConnect یکجا ریست کنید:

public OnPlayerConnect(playerid)
{
   memcpy(playerData[playerid], playerData[MAX_PLAYERS], 0, sizeof(playerData[]) * 4, sizeof(playerData[]));
}

 

67- قطعاً سرعت توابع Native خود SA-MP/Pawn از توابع دست نویس شما سریعتر هستن!

 

68- نکته جزیی: برای غیرفعال کردن Chat پیشفرض SA-MP کافیه مقدار بازگشتی return در کالبک OnPlayerText رو 0 قرار بدید.

 

69- توسط SA-MP GDK - SAMP Gamemode Development Kit میتونید موتور بازی رو با زبان Cpp طراحی کنید:

http://zeex.github.io/sampgdk/

http://forum.sa-mp.com/showthread.php?t=421090

 

70-  دلیل خطای Format specifier does not match parameter count در پلاگین sscanf این هست که یک پارامتر قید شده اما برای گرفتن متغیر تعریف نشده.

sscanf(params, "fsi", coordinate, playerName)

 

71- اگر هنگام استفاده از پلاگین socket با خطای Error: Function not registered: 'socket_create' مواجه شدید، مطمعن بشید که پلاگین به درستی در server.cfg نوشته شده و کتابخانه OpenSSL هم نصب باشه.

 

72- بهتره همیشه هنگام #include کردن فایلهای سورس، پسوند فایل inc رو هم بنویسید تا با فایلهای pwn همنام مغایرت نداشته باشن.

#include <a_samp.inc>
#include <streamer.inc>
#include <crashdetect.inc>

 

73- زمانی میتونید 2 رشته رو برابر هم قرار بدید که رشته مقصد بزرگتر از رشته مبدا باشه. (بجای استفاده از format)

new stringDestination[20], stringSource[10];

stringSource = "12345";
stringDestination = stringSource;
printf("stringDestination: %s", stringDestination);

 

74- برای کشتن بازیکن بهتره از مقدار 1- بجای 0.0 استفاده کنید تا سریعاً پروسه مرگ انجام بشه.

SetPlayerHealth(%0, -1);

 

75- اگر هنگام اجرای gamemode با خطای Run time error 18: "File is for a newer version of the AMX" مواجه شدید، مطعمن بشید که پارامتر -O2 در دستور کامپایل وجود نداشته باشد.

 

76- نکته جزیی: سرعت پردازش دستور format نسبت به دستور mysql_format (درصورتی که اتصال واقعی برقرار باشه) بسیار بسیار بیشتر هست.

 

۹۷/۰۵/۲۲

نظرات (۰)

هیچ نظری هنوز ثبت نشده است
کاربران بیان میتوانند بدون نیاز به تأیید، نظرات خود را ارسال کنند.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">