SourcePawn [SourcePawn] Урок 5 - DataPack

Pushistik↯❤

Команда форума
Регистрация
6 Июл 2017
Сообщения
393
Реакции
97
Баллы
28
[SourcePawn] Урок 5 - DataPack
<= К содержанию
DataPack - производный тип от Handle, который позволяет хранить данные различных типов.
Часто нужно передать в функцию несколько значений или же массив (строку), а функция может получать только 1 параметр. Такое встречается при работе с таймерами, запросами в базу, другими запросами, которым в обратный вызов необходимо передать нужные значения.
Поэтому DataPack используется чтобы записать в него данные, передать его в нужные функции, затем извлечь из него данные и уничтожить его.
У DataPack есть особенность - данные из него нужно извлекать в той же последовательности, в которой они были записаны.

Методы для работы с DataPack можно найти здесь DataPack · datapack · SourceMod Scripting API Reference

Рассмотрим их подробнее:
  • Методы для работы с DataPack
    • DataPack - Создает объект типа DataPack
      PHP:
      DataPack hPack = new DataPack();
    • Reset - Сбрасывает позицию считывания с DataPack, чтобы начать считывание/запись сначала
      PHP:
      hPack.Reset();    // Сбросит позицию считывания
      hPack.Reset(true);    // Сбросит позицию считывания и очистит DataPack
    • IsReadable - Возвращает логическое значение возможно ли считать данные из DataPack
      PHP:
      int iValue = 0;
      if(hPack.IsReadable()) // В DataPack еще есть значение для считывания
      {
          iValue = hPack.ReadCell();
      }
    • Position - Свойство, которое позволяет указывать/получать позицию для считывания.
      При этом позиция определяется количеством байт записанных данных:
      PHP:
      // Напишем простой плагин:
      public void OnPluginStart()
      {
          DataPack hPack = new DataPack();
          LogMessage("Position: %i", hPack.Position);
          // Сейчас позиция = 0
          hPack.WriteCell(5);    // Запишет число 5.
          LogMessage("Position: %i", hPack.Position);
          // Каждый метод записи сперва записывает количество байт для записи, а затем данные
          // Значит чтобы записать число 5 (int) ему нужно 8 байт (2 раза по 4)
          // Сейчас позиция = 9 т.к. мы записали 8 байт и следующая запись будет начинаться с 9-го байта
          hPack.WriteFloat(7.5);
          LogMessage("Position: %i", hPack.Position);
          // Сейчас позиция = 18
          hPack.WriteString("string");
          LogMessage("Position: %i", hPack.Position);    // 6 символов по 1 байт и еще 1 нулевой, обозначающий конец строки, и того 7 символов по 1 байту = 7 байт
          // Сейчас позиция = 30
          hPack.WriteCell(1);
          LogMessage("Position: %i", hPack.Position);
          // Сейчас позиция = 39
      
          hPack.Reset(); // Возвращаем позицию на 0
          LogMessage("Position: %i", hPack.Position);
          int iValue = hPack.ReadCell();
          LogMessage("Position: %i -> %i", hPack.Position, iValue);
          float fValue = hPack.ReadFloat();
          LogMessage("Position: %i -> %.2f", hPack.Position, fValue);
          char szBuffer[256];
          hPack.ReadString(szBuffer, sizeof(szBuffer));
          LogMessage("Position: %i -> %s", hPack.Position, szBuffer);
          iValue = hPack.ReadCell();
          LogMessage("Position: %i -> %i", hPack.Position, iValue);
          
          delete hPack;
      }
      Результат:
      Position: 0
      Position: 9
      Position: 18
      Position: 30
      Position: 39
      // Тут сбросили позицию на 0 и начали считывать
      Position: 0
      Position: 9 -> 5
      Position: 18 -> 7.50
      Position: 30 -> string
      Position: 39 -> 1
      Визуально выглядит так:
      Код:
      00 - Позиция 1
      01 --\
      02 ---\        Значение = 4 (указывает что хранить будем значение размером 4 байта)
      03 ---/        Размер = 4 байта (размер int)
      04 --/
      05 --\
      06 ---\        Значение = 5
      07 ---/        Размер = 4 байта (размер int)
      08 --/
      09 - Позиция 2
      10 --\
      11 ---\        Значение = 4 (указывает что хранить будем значение размером 4 байта)
      12 ---/        Размер = 4 байта (размер int)
      13 --/
      14 --\
      15 ---\        Значение = 7.5
      16 ---/        Размер = 4 байта (размер float)
      17 --/
      18 - Позиция 3
      19 --\
      20 ---\        Значение = 7 (указывает что хранить будем 7 символов по 1 байт каждый)
      21 ---/        Размер = 4 байта (размер int)
      22 --/
      23 - Символ 's'
      24 - Символ 't'
      25 - Символ 'r'
      26 - Символ 'i'
      27 - Символ 'n'
      28 - Символ 'g'
      29 - Символ '\0'
      30 - Позиция 4
      31  --\
      32  ---\        Значение = 4 (указывает что хранить будем значение размером 4 байта)
      33  ---/        Размер = 4 байта (размер int)
      34  --/
      35  --\
      36  ---\        Значение = 1
      37  ---/        Размер = 4 байта (размер float)
      38  --/
      39 - Позиция 5
      Числа - это количество байт
  • Методы для записи в DataPack
    • WriteCell - Записывает в DataPack ячейку (int, Handle и любое другое 4-х байтовое значение)
      PHP:
      hPack.WriteCell(5);
    • WriteFloat - Записывает в DataPack число с плавающей точкой (дробное)
      PHP:
      hPack.WriteFloat(7.3);
    • WriteString - Записывает в DataPack строку
      PHP:
      hPack.WriteString("моя строка");
    • WriteFunction - Записывает в DataPack указатель на функцию
      PHP:
      function MyFunc = GetFunctionByName(null, "MyFunction");
      if(MyFunc != INVALID_FUNCTION)
      {
          hPack.WriteFunction(MyFunc);
      }
  • Методы для чтения из DataPack
    • ReadCell - Получает из DataPack ячейку
      PHP:
      int iValue = hPack.ReadCell();
    • ReadFloat - Получает из DataPack число с плавающей точкой (дробное)
      PHP:
      float fValue = hPack.ReadFloat();
    • ReadString - Получает из DataPack строку
      PHP:
      char szBuffer[256];
      hPack.ReadString(szBuffer, sizeof(szBuffer));
    • ReadFunction - Полуачет из DataPack указатель на функцию
      PHP:
      function MyFunc = hPack.ReadFunction(MyFunc);
Когда DataPack больше не нужен его обязательно нужно удалить:
PHP:
delete hPack;
Пример использования DataPack:

Передача DataPack в таймере:
PHP:
public void OnPluginStart()
{
    DataPack hPack = new DataPack();
    hPack.WriteCell(5);
    hPack.WriteFloat(7.5);
    hPack.WriteString("string");
    CreateTimer(5.0, Timer_ReadDataPack, hPack);
}

public Action Timer_ReadDataPack(Handle hTimer, Handle hDataPack)
{
    DataPack hPack = view_as<DataPack>(hDataPack);    // Методы работают только с типом DataPack, а не Handle
    hPack.Reset(); // Возвращаем позицию на 0
    int iValue = hPack.ReadCell();
    LogMessage("Position: %i -> %i", hPack.Position, iValue);
    float fValue = hPack.ReadFloat();
    LogMessage("Position: %i -> %.2f", hPack.Position, fValue);
    char szBuffer[256];
    hPack.ReadString(szBuffer, sizeof(szBuffer));
    LogMessage("Position: %i -> %s", hPack.Position, szBuffer);
    delete hPack;
}
Результат:
Position: 9 -> 5
Position: 18 -> 7.50
Position: 30 -> string
<= К содержанию
 
Последнее редактирование:
Сверху Снизу