19

» WarCraft 3 / Что предпочтительней и почему Lua или Jass?

Первая карта (benchmark.w3m) содержит исходники скрипта.
Вторая карта (benchmark-packed.w3m) уже укомплектована DLL с нативками и готова к запуску.
Загруженные файлы
19

» WarCraft 3 / Что предпочтительней и почему Lua или Jass?

Unryze
Длина переменной не влияет на скорость никак - это очередной тупой миф
Написал для теста код, что упорядочивает массив используя сортировку пузырьком.
функция сортировки
function s__NormalArray_sort takes nothing returns nothing
local boolean swapped
local integer temp
local integer i

	loop
		set swapped = false
		set i = 0

		loop
			exitwhen not (i < JASS_MAX_ARRAY_SIZE-1)

			if items[i] > items[i+1] then
				set temp = items[i]
				set items[i] = items[i+1]
				set items[i+1] = temp
				set swapped = true
			endif

			set i = i + 1
		endloop

		exitwhen not swapped
	endloop
	
endfunction

Результаты теста

Имена переменных Затраченное время
Без изменений 90704 мс (1 минута 30 секунд)
Длина 1 символ 84484 мс (1 минута 24 секунд)
Длина 85 символов 387219 мс (6 минут 27 секунд)
Длина 340 символов 1235703 мс (20 минут 35 секунд)

Исходники JASS скрипта

Caller
library Caller initializer init {

     #include "cj_types_priv.j"

    private force dummy_force

    void CallFunction(code f) {
        ForForce(dummy_force, f)
    }

    private void init() {
        dummy_force = CreateForce()
        ForceAddPlayer(dummy_force, Player(0))
    }

}
Benchmark
native GetTickCount takes nothing returns integer
native SetOperationLimitEnabled takes boolean state returns nothing
native IsOperationLimitEnabled takes nothing returns boolean

library benchmark initializer init uses Caller {

    #include "cj_types_priv.j"

    define ITEMS_COUNT = JASS_MAX_ARRAY_SIZE
    
    define MAKE_SORTABLE_ARRAY(TYPE_NAME, items, swapped, temp, i) = {
        integer items[]
    
        struct TYPE_NAME {
        
            static void fill() {
                for (int i = 0; i < ITEMS_COUNT; i++) {
                    items[i] = ITEMS_COUNT - 1 - i
                }
            }
            
            static void sort() {
                bool swapped
                int temp
                int i;
                
                loop {
                    swapped = false
                    
                    for (i = 0; i < ITEMS_COUNT-1; i++) {
                        if items[i] > items[i+1] {
                            temp = items[i]
                            items[i] = items[i+1]
                            items[i+1] = temp
                            swapped = true
                        }
                    }
                    
                    exitwhen not swapped
                }
                
                BJDebugMsg("Sorting finished.")
            }
            
            static bool check() {
                for (int i = 0; i < ITEMS_COUNT-1; i++) {
                    if items[i] > items[i+1] {
                        return false
                    }
                }
                
                for (int i = 0; i < ITEMS_COUNT; i++) {
                    if items[i] != i {
                        return false
                    }
                }
                
                return true
            }
            
            static void benchmark() {
                fill()
                
                int start_time = GetTickCount()
                
                CallFunction(function thistype.sort)
                
                int end_time = GetTickCount()
                int difference = end_time - start_time
                
                if !check() {
                    BJDebugMsg("Sorting failed.")
                }
                else {
                    BJDebugMsg("Time elapsed: " + I2S(difference) + " ms.")
                }
            }
        }
    }
    
    MAKE_SORTABLE_ARRAY(FastArray, a, b, c, d)
    MAKE_SORTABLE_ARRAY(NormalArray, items, swapped, temp, i)
    MAKE_SORTABLE_ARRAY(SlowArray,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc,ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd)
    MAKE_SORTABLE_ARRAY(VerySlowArray,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc,dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd)
    
    void start() {
        bool old_state = IsOperationLimitEnabled()
        SetOperationLimitEnabled(false)
        
        CallFunction(function FastArray.benchmark)
        CallFunction(function NormalArray.benchmark)
        CallFunction(function SlowArray.benchmark)
        CallFunction(function VerySlowArray.benchmark)
        
        SetOperationLimitEnabled(old_state)
    }
    
    void init() {
        trigger t = CreateTrigger()
        TriggerAddAction(t, function start)
        TriggerRegisterPlayerChatEvent(t, Player(0), "-start", true)
    }

}

Другие языки

На Pascal'е сортировка заняла 85 мс, что почти в тысячу раз быстрее.
А при использовании статических массивов время снизилось до 72 мс.
Тот же результат выдала и моя asm реализация независимо от типа массива.
pascal
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
	Windows,
	Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

	{ TForm1 }

	TForm1 = class(TForm)
		StartButton: TButton;
		Log: TMemo;
		procedure StartButtonClick(Sender: TObject);
	private

	public

	end;

    //{$define STATIC_ARRAY}

const
	TEST_ARRAY_SIZE = 8192;

type
	TIntegerArray = array {$ifdef STATIC_ARRAY}[0..TEST_ARRAY_SIZE-1]{$endif} of Integer;
	TSortFunction = procedure (var Items: TIntegerArray);

var
	Form1: TForm1;

implementation

{$R *.lfm}

procedure FillArray({$ifdef STATIC_ARRAY}out{$endif} Items: TIntegerArray);
var
	i: Integer;
begin
	for i:= 0 to High(Items) do begin
		Items[i]:= High(Items) - i;
	end;
end;

procedure BubbleSort({$ifdef STATIC_ARRAY}var{$endif} Items: TIntegerArray);
var
	i: Integer;
	Temp: Integer;
	Swapped: Boolean;
begin
	repeat
		Swapped:= False;

		for i:= 0 to High(Items) - 1 do begin
			if Items[i] > Items[i+1] then begin
				Temp:= Items[i];
				Items[i]:= Items[i+1];
				Items[i+1]:= Temp;

				Swapped:= True;
			end;
		end;

	until not Swapped;
end;

procedure BubbleSortASM(Items: PInteger; Count: Integer); cdecl;
begin
	asm
		pushad

		mov edx, Items
		mov ebx, Count
		dec ebx

		@repeat:
			mov eax, False

			xor ecx, ecx
			@loop:
				lea ebp, [edx+ecx*4]
				mov esi, [ebp]
				mov edi, [ebp+4]

				cmp esi, edi
				jle @skip
					mov [ebp], edi
					mov [ebp+4], esi
					mov eax, True

				@skip:

				inc ecx
				cmp ecx, ebx
				jl @loop

			test eax, eax
			jnz @repeat

		popad
	end;
end;

function IsArraySorted({$ifdef STATIC_ARRAY}const{$endif} Items: TIntegerArray): Boolean;
var
	i: Integer;
begin
	Result:= True;

	for i:= 0 to High(Items) - 1 do begin
		if Items[i] > Items[i+1] then
			Result:= False;
	end;

	for i:= 0 to High(Items) do begin
		if Items[i] <> i then
			Result:= False;
	end;
end;

procedure StartTest(TestFunction: TSortFunction);
var
	Items: TIntegerArray = nil;
	Frequency: Qword;
	StartTime, EndTime, ElapsedTime: Qword;
begin
	QueryPerformanceFrequency(@Frequency);

	{$ifndef STATIC_ARRAY}SetLength(Items, TEST_ARRAY_SIZE);{$endif}
	FillArray(Items);

	QueryPerformanceCounter(@StartTime);
	TestFunction(Items);
	QueryPerformanceCounter(@EndTime);

	ElapsedTime:= EndTime - StartTime;

	if IsArraySorted(Items) then
		Form1.Log.Lines.Add('Time elapsed: %d ms.', [ElapsedTime div (Frequency div 1000)])
	else
		Form1.Log.Lines.Add('Sorting failed.');
end;

procedure BubbleSortBenchmark(var Items: TIntegerArray);
begin
	BubbleSort(Items);
end;

procedure BubbleSortASMBenchmark(var Items: TIntegerArray);
begin
	BubbleSortASM(@Items[0], Length(Items));
end;

{ TForm1 }

procedure TForm1.StartButtonClick(Sender: TObject);
begin
	StartTest(@BubbleSortBenchmark);
	StartTest(@BubbleSortASMBenchmark);
end;

end.
19

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

Ты собираешься встроить в карту mix-архив?
Разве в этом есть какой-либо толк?
Как бы то ни было, у моей системы не должно быть проблем с их загрузкой.
19

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

Всё возможно уже сейчас, в своей библиотеке, пользователь может и виртуальную машину python'а загрузить, и игру на Unity запустить.
19

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

не работает кнопка ESC
Теперь хоткей "Ctrl Escape", исправил описание.
отключить Окно Смерти Курьеров
добавить CreateLeaderboard
Локальное (не)создание агента может привести к десинку, лучше заблокировать нативку, отвечающую за показ таблицы.
19

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

SJ Cyber Droeed, да, такая возможность не помешает, если появятся время и желание - сделаю, а пока советую поискать обычные мапхаки, которые умеют показывать кд предметов и не крашатся в реплее.
19

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

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

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

Не могли бы вы объяснить?
В архиве, прикрепленном к этому ресурсу, изначально находится набор библиотек, которые необходимы для работы системы, так что не стоит их удалять.
Из предоставленных же мною исходников сценария, компилируется файл "Example.dll", который и был использован в карте-примере.
19

» WarCraft 3 / Telemetry.txt

В этом файле хранятся хэши строковых команд, используемых для активации читов.
19

» WarCraft 3 / Выделение памяти в хеш-таблице

Для доступа к ячейке хэштаблицы jass'а нужно пройти через 3 словаря.
Ключ для первого - номер хэштаблицы, для остальных двух - parentKey и childKey.
Игра использует собственные коллекции.
Вот как выглядит поиск в их словаре:
code
type
	generic TSHashTable<TKey, TValue, TKeyManager> = object
	public type
		PValue = ^TValue;
		TItems = specialize TSLinkedList<TValue>;
		PItems = ^TItems;
		TPages = specialize TSGrowableArray<TItems>;
	public
		vtable: Pointer;
		Items: TItems;
		Counter: Dword;
		Pages: TPages;
		HashMask: Dword;
	end;

function TSHashTable.Find(const AKey: TKey): PValue;
var
	Hash: Dword;
	Index: Integer;
	Page: PItems;
	Item: PValue;
begin
	Result:= nil;

	if HashMask = Dword(-1) then exit;
	
	Hash:= TKeyManager.GetKeyHash(AKey);
	Index:= Hash and HashMask;
	Page:= Pages.ItemPointers[Index];

	for Item in Page do begin
		if (Item^.HashKeyData.Hash = Hash) and
			TKeyManager.IsKeysEqual(Item^.HashKeyData.Key, AKey)
		then begin
			Result:= Item;
			break;
		end;
	end;
end;
19

» WarCraft 3 / Опять утечка, может ли утекать переменная типа строка?

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

» WarCraft 3 / Манипуляции с кругом выделения и не только

Steal nerves, сомневаюсь, что такое может происходить из-за скрипта.
Другие карты не глючат?
Локальные файлы включены?
Попробуй запустить напрямую через игру. Может быть, твой редактор при сохранении ломает что-то.
19

» WarCraft 3 / Передача аргументов в функции callback'ов

данный код каждый раз выдает разные цифры
Boolexpr'ы кэшируются, а вот результат функции SetCodeOneArg — нет.
Каждый её вызов создает абсолютно новую функцию.
19

» WarCraft 3 / Утечка или не утечка.

получишь нового юнита со старым хендлом
При создании юнита и первом получении его хендла, количество ссылок равно единице.
Каждая ссылающаяся на handle переменная, добавляет к счетчику единицу.
Уничтожение юнита уменьшает счетчик на единицу.
По достижению нуля ссылок, handle освобождается и может быть переиспользован.
А значит, пока есть переменная, которая держит ссылку на юнита, его handle не будет использован для других объектов, даже после его уничтожения.
19

» WarCraft 3 / Синхронизация строк

Разработчики игры не доделали синхронизацию строк. Тебе придется искать обходные пути.
19

» WarCraft 3 / JASS: Курс молодого бойца

Хорошо бы внести эти пояснения в статью.
Там об этом написано.
При объявлении скаляра ему не присваивается начальное значение его типа. Инициализировать его нужно отдельно, при этом, если его не инициализировать, выполнение программы остановится при чтении неинициализированного скаляра.
Массивная переменная - несколько скаляров, расположенных в памяти друг за другом. Эти скаляры называются элементами массива, а их количество называется размером массива.
Каждому элементу массива присваивается начальное значение его типа, то есть элементы массива в отличие от скаляров инициализируются при объявлении массива.
19

» WarCraft 3 / JASS: Курс молодого бойца

то есть он приобретет false по умолчанию только в случае, если это элемент массива, а не самостоятельная переменная?
Да.
Что касается обычной переменной, думаю, в памяти игры у неё значение 0 (false), но это не важно, так как игра не даст его прочитать.
Поэтому, необходимо явно задавать их значение перед использованием.
19

» WarCraft 3 / JASS: Курс молодого бойца

avuremybe, при обращении к неинициализированной переменной, поток выполнения обрывается.
Исключение — массивы, элементы которых имеют значения по-умолчанию.
19

» WarCraft 3 / Манипуляции с кругом выделения и не только

Скачай карту и скопируй все триггеры, кроме тех, что находятся в папке demo.
Из ресурса тоже можно взять код, но он здесь для тех, кому лень качать или у кого нет редактора.
19

» WarCraft 3 / Манипуляции с кругом выделения и не только

для чего нужна скрытая тень?
Был вопрос, в котором хотели спрятать тень предмета. Не знаю зачем, но раз спросили, значит нужно. Ответ на тот вопрос, собственно, и сподвиг меня проверить: как это работает и на что оно еще способно.
19

» WarCraft 3 / убрать круг выбора

Существует костыль, позволяющий редактировать круг выбора.
screenshot
Загруженные файлы
19

» WarCraft 3 / Memory Hack: Загрузчик native функций

JaBeN_Симфер, очевидно, что нет. Она лишь позволяет добавлять нативки перед компиляцией скрипта.
С такими потребностями, тебе следует зайти в тему мемхака. Возможно, там есть сетевые функции.