Добавлен , опубликован
Способ реализации:
Версия Warcraft:
Hashtable 8000 | Cool Hashtable

Введение

При сохранении данных в хеш-таблице используется следующая формула:
Объект -> уникальный идентификатор(UID) -> номер ячейки массива
Для получения UID большинства объектов в вакрафте используется функция GetHandleId().
Хеш-таблица очень удобна при построении многих алгоритмов и систем. Но создание встроенных hashtable ограничено 256-ю. Эта наработка призвана обойти сей недостаток.

Описание

Область применения
Постоянное хранилище. Временное хранилище. Передача больших объемов данных в функцию.
Характеристики
  • Количество элементов внутри одной таблицы до 18747.
  • Количество таблиц до 8190.
Наработка добавляет несколько новых vjass типов. Каждый тип является оберткой для удобного обращения к нативной хеш-таблице. Теперь их можно создавать, удалять, хранить и передавать в качестве параметра. Во время конечной оптимизации карты неиспользуемые типы можно отключить, закоментировав вызов макроса так, как это показано на скриншоте.
спойлер
Все названия типов выглядят как h8k_type, где type - название нативного типа для которого создается таблица. Ключем всегда является тип integer.
  • Пример таблицы для типа real
h8k_real var = h8k_real.create() // создать
var[-81] = 15 // сохранить
var[R2I(var[-81])] = 7
var[15] -> 7 // получить
var.remove(15) // освободить
var.destroy() // удалить таблицу
О хранении элементов
Так как эти хеш-таблицы основаны на встроенной, то имеют такие же особенности хранения данных. А именно: если удалить объект ссылочного типа (например, вызвать RemoveUnit() или юнит просто разложится) то его значение автоматически станет null, хотя ячейка не освободится. Если обратиться к несуществующему элементу, то в ответ получите то же, как если бы обратились к стандартной jass hashtable.
Список поддерживаемых типов данных
(string)
(destructable)
(effect)
(integer)
(item)
(lightning)
(multiboard)
(multiboarditem)
(player)
(real)
(rect)
(region)
(timer)
(trigger)
(unit)

Пример

Допустим, у нас есть разные типы юнитов, которые по разному взаимодействуют со способностями персонажа. В моем примере заводятся две глобальные таблицы для хранения существ типа огонь и вода:
globals
  h8k_boolean bdWater
  h8k_boolean bdFire
endglobals
В триггере инициализации прописываем типы существ, которые заранее имеют свой тип. У меня это элеменаль огня и воды соответственно.
  set bdWater = h8k_boolean.create()
  set bdFire = h8k_boolean.create()
  
  set bdWater['hwat'] = true
  // ...
  set bdFire['nlv1'] = true
Далее будет способность "Облить", которая добавляет элемент любому существу:
  if GetSpellAbilityId() == 'A001' then
    set bdWater[GetHandleId(GetSpellTargetUnit())] = true
    // ...
  endif
Теперь мы можем сделать проверку на нахождение юнита или его типа в соответствующей таблице. И, в зависимости от проверки, наносить дополнительный урон при применении нашего особого заклинания. В данном случае заклинание детектится по наличию определенного бафа в событии получения урона:
  local unit tu = GetTriggerUnit()
  local integer hid = GetHandleId(tu)
  local integer typ = GetUnitTypeId(tu)
  // ...
  if GetUnitAbilityLevel(tu, 'BNbf') > 0 and (bdWater[typ] or bdWater[hid]) then
    call UnitRemoveAbility(tu, 'BNbf')
    call UnitDamageTarget(GetEventDamageSource(), tu, 100, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
  endif
Старый пример
Описание
  1. В области применения случайно появляются N предупреждающих знаков.
  2. Через некоторое время в этих местах поочередно происходят электовзрывы.
Реализация
Будем использовать хеш-таблицу как локальный массив.
  1. Создаем хеш-таблицы для хранения координат и эффектов. Сохраняем количество точек и хеш-таблицы на таймер.
  2. Поочередно создаем взрывы в нужных местах.

Установка

Скопировать папку HT8k
В архиве находятся две карты HT8k_vjass_cjass и HT8k_vjass. Для первой требуется поддержка vjass и cjass, для второй только vjass.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
15
Что насчёт возможности стора кастомных типов (vjass types или struct)?
vJass не типобезопасен. Все типы vJass это псевдонимы для integer, поэтому для сохранения данных этого типа используется integer.
18
Обновление
Изменен синтаксис обращения к таблицам, теперь можно писать так:
//! runtextmacro HT8k("myInt","integer")
//! runtextmacro HT8k("myStr","string")
myInt i = myInt.create()
myStr s = myStr.create()
i[3] = 8
i[-50] = i[3]
s[i[3]] = "hello"
s.destroy()
38
Там вроде вся фича была в том, что можно хранить разные типы в одной хешмапе?
21
256 хэштаблиц шооо?) мне больше одной пока что не приходилось юзать
18
Ну если кто то чем то не пользовался, разве это значит, что это не нужно) В lua, например, все построено на таблицах, и код получается гибким и легким.
ScorpioT1000:
Там вроде вся фича была в том, что можно хранить разные типы в одной хешмапе?
Когда в статических языках можно было класть в переменную значения разных типов.
СмысОл в том, чтобы не указывать тип переменной при каждом обращении:
call SaveUnitHandle(hashtable, _, key, unit)
call SaveEffectHandle(hashtable, _, key, effect)

set target[key] = unit
set baff[key] = effect
21
Ну если кто то чем то не пользовался, разве это значит, что это не нужно)
я так и не говорил, просто удивлён )
18
Обновление
  • Отобрана возможность задавать собственные названия типов для таблиц. Теперь все типы имеют строго определенный синтаксис.
  • Теперь все типы доступны сначала, а пользователь может лишь отключать ненужные для оптимизации.
  • Добавлен новый показательный пример.
  • Наработка разделена на 2 версии: cjass+vjass и vjass only. Обе имею одинаковую установку и синтаксис обращения, а отличаются лишь внутренней реализацией.
38
Зачем тогда cjass?
18
Обнаружено, что если использовать эти хештаблицы в library, то все обращения автоматически заменяются на вызов TriggerEvaluate(), потому что код библиотек помещается выше.

Обновление
  • Оптимизирован код, уменьшено его количество.
  • Все собрано в одну библиотеку. Теперь для использования наработки в других библиотеках достаточно указать H8k в requires.

Для обнаружения таких ситуаций вы можете добавить [forcemethodevaluate] в jasshelper.conf (спасибо PT153)
18
Обновление
  • Исправлена утечка.
  • Для версии vjass_cjass использованы define вместо textmacro, больше нет дополнительного окна консоли во время сохранения карты.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.