19

» WarCraft 3 / Сценарий на любом языке

Библиотека с твоим скриптом загружается и исполняется паралельно у всех игроков.
Просто пиши код также, как ты делал это на JASS'е. Правила те же: все действия должны быть одинаковы на компьютерах всех игроков. Локально можно делать лишь некоторые, такие как смена цвета/размера юнита.
19

» WarCraft 3 / Сценарий на любом языке

Vampir_kolik, создание юнита для локального игрока вызовет десинк на любом языке.
На игровом клиенте красного игрока создается юнит, принадлежащий игроку красному, а на клиенте синего - синему. В итоге состояние мира отличается и они играют в разные игры.
В моём примере главный работник создается для красного игрока, а прочие для игроков 1-10.
Вижу, ты цитируешь старую версию исходников библиотеки со скриптом, советую скачать последнюю.
19

» WarCraft 3 / Работа с нативными функциями

Как играть по сети со своими нативными функциями?
Я как-то делал интереса ради одну систему, которая позволяла достичь этой цели.
Принцип работы: сначала временный скрипт распаковывает и загружает библиотеки, а затем он компилирует и запускает оригинальный скрипт карты, после чего самоуничтожается. Таким образом, к моменту запуска основного сценария, нативки уже зарегистрированы и компилятор не ругается.
Вот только, на сайте сейчас нерабочая версия висит. Я скрывал ресурс ибо лень исправлять, но модератор зачем-то его опубликовал.
Впрочем, думаю есть способ получше: можно модифицировать байт-код во время исполнения таким образом, чтобы вызов обычной функции превратился в вызов нативки.
Будет выглядеть как-то так
function MyNativeFunction takes nothing returns nothing
endfunction

function main takes nothing returns nothing
	call RedirectToNative(function MyNativeFunction)
	// На самом деле вызовется не пустая функция объявленная выше, а нативка с таким же именем.
	call MyNativeFunction()
endfunction
19

» WarCraft 3 / Намертво зависает вкладка Сценарий/свойство игрока.

Кажется, я уже встречал подобное и проблема была в огромном количестве улучшений/способностей либо их уровней.
Нашёл ссылку на тот вопрос.
19

» WarCraft 3 / Laddik не может открыть архив

ну там действительно есть дллки, которые появляются во время запуска карты.
Не думаю, что карта стоит упоминания, если только в ней не находится код, извлекающий файлы из архива, в чем я сомневаюсь, ведь он имеет расширение mix, а значит должен быть библиотекой, которая и сама себя сможет распаковать.
Могу предположить, что автор защиты не стал особо мудрить и поместил архив в ресурсы библиотеки, может даже не зашифровав его. Если всё так, то тебе лишь нужно открыть файл в программе, умеющей показывать вшитые в исполняемые файлы ресурсы, и извлечь их. Возможно, среди них найдется искомый архив.
Еще, как вариант, при помощи специальных программ, можно посмотреть какие файлы открывает игра и, если повезет, среди них может обнаружиться распакованый архив.
Если же нет, то придется восстанавливать исходный код библиотеки, после чего можно будет выяснить, каким же образом она добавляет новые файлы в игру.
Можешь заняться этим сам, воспользовавшись программами для обратной разработки (например, IDA), либо нанять специалистов, которые выполнят работу за тебя.
19

» WarCraft 3 / Laddik не может открыть архив

Файл mix, в первую очередь, является библиотекой (DLL). К ней можно прикрепить MPQ-архив, получив тем самым mix-архив, но вовсе необязательно, что твой файл относится к этому типу.
Возможно, эта библиотека извлекает из себя архив во временную папку и загружает оттуда в игру. А может, она перехватывает запросы игры на ресурсы (модели, текстуры) и загружает их из памяти. Сделано так могло быть из нежелания автора делиться своими трудами.
А еще, автор может, при желании, засунуть туда вирусов и майнить на твоей видеокарте или удалить тебе все файлы с диска, если ты ему в игре не понравишься.
19

» WarCraft 3 / Просмотр состояния виртуальной машины JASS

Последние новости!
Добавил библиотеку для снятия защиты с процесса игры.
19

» WarCraft 3 / Получение строки в Prealod файле

Принятый ответ
Из-за того, что нативки возвращают строки в виде индексов из таблицы строк главного потока карты, все прочие потоки, не являющиеся дочерними ему, например те, что исполняют прелоад скрипты или ИИ, не могут получить результат от нативок с таким типом. Индекс не будет подходить для их таблицы строк.
Будет получена случайная строка или произойдет выход за границы таблицы с печальным концом.
Получение строк в результате вызова нативок работает лишь в главном потоке.
19

» WarCraft 3 / Переодические вылеты в карте, может кто по коду ошибки скажет.

Принятый ответ
Инструкция по адресу 0x6F430C91 попыталась прочесть память по адресу 0x00000020, но так как там ничего не было — она крашнулась.
Этот код расположен в пределах game.dll (0x6F000000 - 0x6FBB5000 F:\Warcraft III 1.26S\Game.dll), что видно в разделе Loaded Modules. Учтите, что пусть эта библиотека и предпочитает распологаться по адресу 0x6F000000, но операционная система может загрузить её куда либо еще и тогда, с теми же смещениями, абсолютные адреса будут отличаться. К примеру, если библиотека будет по адресу 0x24F00000, то вместо 0x6F430C91 вы увидите 0x25330C91 (0x24F00000 + 0x430C91).
По смещению 0x430C91 находится код функции CGameState::GetAgentHandle, которая принимает указатель на агент и возвращает его хэндл.
В дампе памяти стека видны значения трёх сохраненных регистров (0x00000010 0x0019DFE8 0xFFFFFFFF), а также адрес возврата 0x6F3BBB58 и полученные аргументы: agent=0x00000010, auto_free=0x00000000. Кто-то передал кривой указатель 0x10, который ссылается на нечитаемую память.
Адрес возврата ведет к нативке Player. В стеке можно увидеть сохраненное ею значение регистра (0x6F9473BE), адрес возврата к коду виртуальной машины (0x6F45D1B8) и полученный ею аргумент (number=0xFFFFFFFF), который в виде знакового целого равняется числу -1.
Вывод: кто-то вызвал нативку Player с параметром -1, что и привело к крашу.
Найти конкретного виновника поможет программа, ссылку на которую я скинул выше.
Начало дампа стека
Обратите внимание, что дамп стека выровнен по границе 16 байт, так что, на самом деле вершина стека находится не по адресу 0x0019DF10, а как написано ниже — 0x0019DF18, так что, в данном случае, первые 8 байт можно пропустить (зачеркнуты).
Синим выделены сохраненные значения регистров, зеленым — адреса возврата, а красным — кривые параметры, приведшие к крашу.
Stack: 1024 bytes starting at (ESP = 0019DF18)
= addr ** *
0019DF10: E8 DF 19 00 75 91 45 6F 10 00 00 00 E8 DF 19 00 ....u.Eo........
0019DF20: FF FF FF FF 58 BB 3B 6F 10 00 00 00 00 00 00 00 ....X.;o........
0019DF30: BE 73 94 6F B8 D1 45 6F FF FF FF FF A4 D1 45 6F .s.o..Eo......Eo
начало метода CGameState::GetAgentHandle
.text:6F430C80 ; int __thiscall CGameState::GetAgentHandle(CGameState *this, CAgent *agent, BOOL AutoFree)
.text:6F430C80 CGameState__GetAgentHandle proc near    ; CODE XREF: CUnit__PostEvent+8F↑p
.text:6F430C80                                         ; CUnit__NotifyAboutInstantOrder+195↑p ...
.text:6F430C80
.text:6F430C80 agent           = dword ptr  4
.text:6F430C80 AutoFree        = dword ptr  8
.text:6F430C80
.text:6F430C80                 push    ebx
.text:6F430C81                 push    ebp
.text:6F430C82                 mov     ebp, [esp+8+agent]
.text:6F430C86                 test    ebp, ebp
.text:6F430C88                 push    esi
.text:6F430C89                 mov     ebx, ecx
.text:6F430C8B                 jz      loc_6F430D9B
.text:6F430C91                 mov     esi, [ebp+10h]
нативка Player
.text:6F3BBB30 ; DWORD __cdecl Jass::Common::Player(int number)
.text:6F3BBB30 Jass__Common__Player proc near          ; DATA XREF: InitJass+3007↓o
.text:6F3BBB30
.text:6F3BBB30 number          = dword ptr  4
.text:6F3BBB30
.text:6F3BBB30                 mov     eax, [esp+number]
.text:6F3BBB34                 mov     ecx, CGameWar3__Instance
.text:6F3BBB3A                 push    esi
.text:6F3BBB3B                 push    eax
.text:6F3BBB3C                 call    CGameWar3__GetPlayer
.text:6F3BBB41                 mov     ecx, CGameWar3__Instance
.text:6F3BBB47                 mov     esi, eax
.text:6F3BBB49                 call    CGameWar3__GetGameState
.text:6F3BBB4E                 push    0
.text:6F3BBB50                 push    esi
.text:6F3BBB51                 mov     ecx, eax
.text:6F3BBB53                 call    CGameState__GetAgentHandle
.text:6F3BBB58                 pop     esi
.text:6F3BBB59                 retn
.text:6F3BBB59 Jass__Common__Player endp
19

» WarCraft 3 / Переодические вылеты в карте, может кто по коду ошибки скажет.

Если мне интересно, почему карта крашнулась, то я обычно запускаю эту программу, пускай она и не всегда работает (но в таком случае я могу покопаться в памяти игры отладчиком, так что лень исправлять).
По твоему краш-репорту видно, что произошел вызов нативки Player с параметром -1, который и привел к ожидаемому крашу.
19

» WarCraft 3 / Синхронизация данных

Я не изучил всё вдоль и поперек, но подозреваю, что при более низких задержках пропускная способность должна увеличиться.
Чтобы узнать наверняка, стоит провести тесты на хост-боте: запустить скрипт, который будет синхронизировать большое количество данных и замерить потраченное на это время при разных задержках.
Чтобы узнать время, можешь использовать нативку GetTickCount добавляемую этим модом.
19

» WarCraft 3 / MapHack для реплея

Главное назначение этого мода — вернуть панель приказов, которую зачем-то удалили разработчики. А для быстрой перемотки используют ReplaySeeker, но, чтобы отмотать время назад, прийдется перезагрузить реплей и проигрывать его с самого начала до нужного момента.
В теории, если добавить в реплей ключевые точки через равные промежутки времени, то можно будет загружать реплей с ближайшей позиции и начинать промотку уже с неё.
Осталось только найти желающих реализовать это улучшение.
19

» WarCraft 3 / Своя нативка на С++

Использование неправильной конвенции вызова приведет к повреждению памяти стэка.
Хранящиеся в нём локальные переменные и адреса возврата могут быть перезаписаны случайными значениями, что приведет к непредсказуемым последствиям.
Хотя, стоит отметить, что виртуальная машина JASS'а (по крайней мере на 1.26а версии) способна правильно вызывать нативки использующие как cdecl так и stdcall, что используется мемхаком.
Но, если такую неправильную нативку вызовет кто другой, то весьма вероятны баги и краши.
19

» WarCraft 3 / Своя нативка на С++

Даже в твоём коде файла moduleutils.pas используется stdcall:
Библиотека "JassApi.dll" экспортирует функции, используя соглашение о вызове stdcall, а нативки варкрафта, возвращаемые функцией GetJassNative, используют соглашение cdecl.
И приведеный тобою код на самом деле находится в модуле "jassapi.pas".
19

» WarCraft 3 / Своя нативка на С++

int __stdcall test()
Нативки используют конвенцию вызова cdecl.
Можно увидеть пример наивной функции, использующей JREAL?
Я не специалист по C++, но если хочешь создать нативку принимающую/возвращающую вещественные числа, то это будет выглядеть примерно так:
uint32_t __cdecl jIncrementReal(float *value) {
	return reinterpret_cast<uint32_t>(*value + 1.0f);
}

RegisterJassNative("IncrementReal", "(R)R", &jIncrementReal);
В JASS скрипте объявляется следующим образом:
native IncrementReal takes real value returns real
Также можешь взглянуть на этот ресурс.
В примере оттуда есть сгенерированные обертки для всех нативок из "common.j", но на pascal'е.
19

» WarCraft 3 / Работа с нативными функциями

Вышла новая версия!
Прокрутить к ресурсу
  • Изменения в RedirectCalls
    • Теперь может быть безопасно загружен во время игры.
    • Может быть одновременно установлен в папку с игрой и встроен в карту: активен будет лишь первый загруженый экземпляр.
19

» WarCraft 3 / Сценарий на любом языке

Вышла новая версия!
Прокрутить к ресурсу
  • Адаптировал к новым версиям JassAPI и RedirectCalls.
  • Больше деталей о работе системы.
  • Выложил исходники cJASS-скрипта и встроенной в него программы.
  • Упростил процесс установки.
  • Приложил генератор кода для нативок.
19

» WarCraft 3 / Сценарий на любом языке

Интересно, но это будет работать с мультиплеерными картами?
Разумеется, в этом и есть вся суть. Нет нужды просить всех игроков качать специальные лаунчеры, которые добавят новые возможности, карта сама распакует и загрузит DLL'ки.
Учтите, что данный ресурс использует старые версии JassAPI и RedirectCalls, так что, примеры из него не получится использовать с последними версиями.
19

» WarCraft 3 / Установка варика в 2023 году

Ты имеешь в виду редактор? Как это делается?
В настройках операционной системы.
19

» WarCraft 3 / Установка варика в 2023 году

Язык программ, не поддерживающих юникод, должен быть установлен на русский.
19

» WarCraft 3 / Сценарий на любом языке

Этот файл автоматически сгенерирован на основе "common.j".
Отрывок из common.j
constant itemtype ITEM_TYPE_PERMANENT                   = ConvertItemType(0)
constant itemtype ITEM_TYPE_CHARGED                     = ConvertItemType(1)
constant itemtype ITEM_TYPE_POWERUP                     = ConvertItemType(2)
constant itemtype ITEM_TYPE_ARTIFACT                    = ConvertItemType(3)
constant itemtype ITEM_TYPE_PURCHASABLE                 = ConvertItemType(4)
constant itemtype ITEM_TYPE_CAMPAIGN                    = ConvertItemType(5)
constant itemtype ITEM_TYPE_MISCELLANEOUS               = ConvertItemType(6)
constant itemtype ITEM_TYPE_UNKNOWN                     = ConvertItemType(7)
constant itemtype ITEM_TYPE_ANY                         = ConvertItemType(8)
// Deprecated, should use ITEM_TYPE_POWERUP
constant itemtype ITEM_TYPE_TOME                        = ConvertItemType(2)
19

» WarCraft 3 / Синхронизация данных

Перезалил архив с модом. Добавил недостающую библиотеку "MinHook_x86.dll".
Надо будет разобраться, как её статически скомпоновать с библиотекой на FreePascal.
19

» WarCraft 3 / Синхронизация данных

Последние новости!
Обновил статью:
  • Уточнил лимит буфера команд.
  • Убрал связанные с выдуманной потерей данных части.
  • Добавил информацию о командах выделения и синхронизации кэша.
  • Сделал мод для логирования команд.
Сколько байт буфера занимает каждое выделение юнита за один момент времени?
Теперь ты можешь проверить это и сам, но всё же отвечу:
При добавлении одного юнита в выделение, шлется NET_COMMAND_UNIT_SELECTION_MODIFY (12 байт).
Каждый вызов SelectUnit всегда создает событие (если есть подписчики) и следовательно шлется NET_COMMAND_UNIT_SELECTION_EVENT (10 байт).
Также, могут слаться NET_COMMAND_UNIT_REFRESH_SUB_GROUP (1 байт) и NET_COMMAND_UNIT_SELECT_SUB_GROUP (13 байт).
Следовательно, пошлется до 36 байт.