> > > >

Склад полезного кода [Source]

Сообщения
68
Рейтинг
157
#1
Тема для готовых функций на SourcePawn, которые можно просто вставить в свой код и использовать.

  1. Передача прав на указатель (Handle)
    Трюк основан на функциях CloneHandle() и CloseHandle(). Сначала клонируется нужный указатель, потом удаляется старый.
    C++:
    stock void ChangeHandleOwner(Handle &hPointer, Handle hNewOwner = null) {
      Handle hDummy = CloneHandle(hPointer, hNewOwner);
      CloseHandle(hPointer);
      hPointer = hDummy;
    }
  2. Вызов форвардов с клоном указателя
    Ещё один полезный, по-моему мнению, сток. Позволяет вызвать некий "форвард". Но в отличие от обычного форварда, передаётся на каждый плагин не оригинальный указатель, а его клон.
    C++:
    stock void CallEventWithClonedHandle(const char[] szFunctionName, Handle hPointer) {
      Handle    hClone;
      Function  ptrFunc;
      Handle    hPlugin;
      Handle    hPlugIter = GetPluginIterator();
      Handle    hCoreHandle = GetMyHandle();
    
      while (MorePlugins(hPlugIter)) {
        hPlugin = ReadPlugin(hPlugIter);
        if (hPlugin == hCoreHandle || GetPluginStatus(hPlugin) != Plugin_Running)
          continue;
    
        ptrFunc = GetFunctionByName(hPlugin, szFunctionName);
        if (ptrFunc == INVALID_FUNCTION)
          continue;
    
        hClone = CloneHandle(hPointer, hPlugin);
    
        Call_StartFunction(hPlugin, ptrFunc);
        Call_PushCell(hClone);
        Call_Finish();
      }
    
      CloseHandle(hPlugIter);
    }
  3. Перевод IP-адреса из строкового представления в бинарное (двоичное)
    Перегоняет айпишник из строкового представления - в двоичное. Позволяет сэкономить память, если он где-то впоследствии хранится, т.к. IP-адрес в бинарном представлении занимает фиксированно 4 байта.
    C++:
    stock int IP2Bin(const char[] szAddress) {
      char szAddr[16];
      strcopy(szAddr, sizeof(szAddr), szAddress);
    
      int iPos = 0;
      int iResult;
    
      for (int iDotId = 0; iDotId < 4; ++iDotId) {
        iPos = FindCharInString(szAddr, '.', true);
        iResult |= StringToInt(szAddr[iPos+1]) << (iDotId * 8);
    
        if (iPos != -1)
          szAddr[iPos] = 0;
      }
    
      return iResult;
    }

Делитесь своими стоками. Будем собирать.
 
6  
Сообщения
124
Рейтинг
98
#2
Функция с исходников амхмодх. Делит строку на левую и правую часть с помощью разделителя.
Переписал потому что не нашел аналогов.
Код:
bool strtok( char[ ] sText, char[ ] sLeft, char[ ] sRight, int iToken = ' ' )
{
    bool bDoneFlag;

    int iLeftPos, iRightPos;
    int iLen = strlen( sText );

    for( int i = 0; i < iLen; i++ )
    {
        if( !bDoneFlag && sText[ i ] == iToken )
        {
            bDoneFlag = true;
            i++;
        }

        if( bDoneFlag )
            sRight[ iRightPos++ ] = sText[ i ];
        else
            sLeft[ iLeftPos++ ] = sText[ i ];
    }

    sRight[ iRightPos ] = 0;
    sLeft[ iLeftPos ] = 0;

    return true;
}
 
Последнее редактирование:
4  
Сообщения
124
Рейтинг
98
#3
C++:
stock void SetEntityRender( int iEntity, RenderFx iFx = RENDERFX_NONE, RenderMode iMode = RENDER_NORMAL, int iRed = 255, int iGreen = 255, int iBlue = 255, int iAlpha = 255 )
{
    SetEntityRenderFx( iEntity, iFx );
    SetEntityRenderMode( iEntity, iMode );
    SetEntityRenderColor( iEntity, iRed, iGreen, iBlue, iAlpha );
}
10 Июн 2018
Хз почему таких элементарных вещей нет в этом вашем сурсе.
Код:
#define MIN(%0,%1)                ( ( ( %0 ) < ( %1 ) ) ? ( %0 ) : ( %1 ) )
#define MAX(%0,%1)                ( ( ( %0 ) > ( %1 ) ) ? ( %0 ) : ( %1 ) )
Код:
enum
{
    WEAPON_DEAGLE = 1, WEAPON_ELITE, WEAPON_FIVESEVEN, WEAPON_GLOCK, WEAPON_AK47 = 7, WEAPON_AUG, WEAPON_AWP,
    WEAPON_FAMAS, WEAPON_G3SG1, WEAPON_GALILAR = 13, WEAPON_M249, WEAPON_M4A1 = 16, WEAPON_MAC10, WEAPON_P90 = 19,
    WEAPON_UMP45 = 24, WEAPON_XM1014, WEAPON_BIZON, WEAPON_MAG7, WEAPON_NEGEV, WEAPON_SAWEDOFF,
    WEAPON_TEC9, WEAPON_TASER, WEAPON_HKP2000, WEAPON_MP7, WEAPON_MP9, WEAPON_NOVA, WEAPON_P250,
    WEAPON_SCAR20 = 38, WEAPON_SG556, WEAPON_SSG08, WEAPON_KNIFE = 42, WEAPON_FLASHBANG, WEAPON_HEGRENADE,
    WEAPON_SMOKEGRENADE, WEAPON_MOLOTOV, WEAPON_DECOY, WEAPON_INCGRENADE, WEAPON_C4,
    WEAPON_KNIFE_T = 59, WEAPON_M4A1_SILENCER, WEAPON_USP_SILENCER, WEAPON_CZ75A = 63, WEAPON_REVOLVER
};

char WEAPON_NAMES[ MAX_WEAPONS + 1 ][ ] =
{
    "", "weapon_deagle", "weapon_elite", "weapon_fiveseven", "weapon_glock", "", "", "weapon_ak47", "weapon_aug", "weapon_awp",
    "weapon_famas", "weapon_g3sg1", "", "weapon_galilar", "weapon_m249", "", "weapon_m4a1", "weapon_mac10", "", "weapon_p90",
    "", "", "", "", "weapon_ump45", "weapon_xm1014", "weapon_bizon", "weapon_mag7", "weapon_negev", "weapon_sawedoff",
    "weapon_tec9", "weapon_taser", "weapon_hkp2000", "weapon_mp7", "weapon_mp9", "weapon_nova", "weapon_p250",
    "", "weapon_scar20", "weapon_sg556", "weapon_ssg08", "", "weapon_knife", "weapon_flashbang", "weapon_hegrenade",
    "weapon_smokegrenade", "weapon_molotov", "weapon_decoy", "weapon_incgrenade", "weapon_c4", "", "", "", "", "",
    "", "", "", "", "weapon_knife_t", "weapon_m4a1_silencer", "weapon_usp_silencer", "", "weapon_cz75a", "weapon_revolver"
};
 
1  
Сообщения
68
Рейтинг
157
#4
Простейший define для обработки всех игроков на сервере.
C++:
#define LoopPlayers(%0) for (int %0 = MaxClients; %0 != 0; --%0) if (IsClientInGame(%0))
Пример использования из реального плагина (кое-что убрал):
C++:
public void OnGroupsInfoLoaded(Database hDB, DBResultSet hResults, const char[] szError, any data) {
  if (szError[0]) {
    LogError("[XF] Database failure when fetching groups information: %s", szError);
    return;
  }

  // ...

  if (g_bLate)
    LoopPlayers(iClient)
      if (!IsFakeClient(iClient) && IsClientAuthorized(iClient))
        LookupUserPermissions(iClient);
}
 
2  
Сообщения
185
Рейтинг
193
#5
CrazyHackGUT, я правильно понял, что там только однострочечная конструкция может использоваться?
 
 
Сообщения
68
Рейтинг
157
#6
BoecSpecOPs, нет. Можно и несколько строк. Тогда в конце каждой строки (кроме последней) надо дописывать \. Экранизировать перевод каретки короче.
16 Июн 2018
На основе кода fantom отсюда сделал аналогичный конвертер строкового простейшего представления времени (1y3m, 1y2m4d5i6 и т.д.) - в секундное.
C++:
stock int UTIL_ParseTime(const char[] szStr) {
  static int  iTime[]   = {60,  3600, 86400, 2592000, 31104000};
  static char szTime[]  = "ihdmy";

  int iDummy, iResult;
  int iPos, iTPos;
  char cData;

  while (szStr[iPos] != EOS) {
    cData = szStr[iPos++];

    if (cData >= '0' && cData <= '9') {
      iDummy = (iDummy * 10) + (cData - '0');
      continue;
    }

    for (iTPos = 0; iTPos < sizeof(iTime); ++iTPos) {
      if (cData == szTime[iTPos]) {
        iResult += iDummy * iTime[iTPos];
        iDummy = 0;
        break;
      }
    }
  }

  iResult += iDummy;
  return iResult;
}
1529176815141.png
 
4  
Сообщения
68
Рейтинг
157
#7
Псевдо-генератор UUID v4
C++:
stock void GenerateUUID(char[] szBuffer, int iBufferLength) {
  FormatEx(szBuffer, iBufferLength, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
    // 32 bits for "time_low"
    GetRandomInt(0, 0xffff), GetRandomInt(0, 0xffff),

    // 16 bits for "time_mid"
    GetRandomInt(0, 0xffff),

    // 16 bits for "time_hi_and_version"
    // four most significant bits holds version number 4
    (GetRandomInt(0, 0x0fff) | 0x4000),

    // 16 bits, 8 bits for "clk_seq_hi_res",
    // 8 bits for "clk_seq_low",
    // two most significant bits holds zero and one for variant DCE1.1
    (GetRandomInt(0, 0x3fff) | 0x8000),

    // 48 bits for node
    GetRandomInt(0, 0xffff), GetRandomInt(0, 0xffff), GetRandomInt(0, 0xffff)
  );
}
 
1  
Сообщения
68
Рейтинг
157
#8
Чистка ника от мультибайтовых символов размером 4 байта
Полезно, когда база в кодировке utf8, и перегонять в utf8mb4 нет возможности или просто отсутствие желания.
Оригинал написан Фениксом.
C++:
int GetFixedClientName(int iClient, char[] szBuffer, int iMaxLength) {
  char sName[MAX_NAME_LENGTH * 2 + 1];
  GetClientName(iClient, sName, sizeof(sName));

  for (int i = 0, len = strlen(sName), CharBytes; i < len;) {
    if ((CharBytes = GetCharBytes(sName[i])) == 4){
      len -= 4;
      for (int u = i; u <= len; u++) {
        sName[u] = sName[u+4];
      }
    } else {
      i += CharBytes;
    }
  }

  return strcopy(szBuffer, iMaxLength, sName);
}
 
 

Похожие темы

Ответы
1
Просмотры
1.018
Ответы
62
Просмотры
10.310
Ответы
6
Просмотры
657
> > > >