cJass2Lua(v1.12) - Преобразователь кода cJass и JASS в Lua

Published
» Предназначение: Работа с кодом
Warcraft III Reforged привнес в игру скрипты Lua, но многие разработчики карт для WC3 до сих пор используют JASS, а многие и cJass (просто потому, что правила синтаксиса в стиле C тупо рулят) К сожалению, расширение cJass не поддерживается для Reforged, и кто знает, как это будет, вероятнее всего вряд ли c-подобный синтаксис появится в Reforged. А JASS устаревает, крайне дырявый и имеет громоздкий и неудобный синтаксис.
Lua более эффективен, полезен и прост в разработке игр, он фактически стал стандартом в игровом скриптинге благодаря своему удобству, простоте и быстроте. Но многие проекты все еще находятся на cJass/JASS, и нет возможности конвертировать их в Lua. Редактор без расширения cJass не воспринимает этот код и в результате ваш проект может просто пропасть. А многие у кого проект написан на JASS предпочли бы переписать его на более удобный Lua, который легче и приятнее поддерживать. Переписывание кода вручную для Lua может занять много времени, само собой никто не хочет тратить на это время, чтоб делать свой проект фактически второй раз.
Этот инструмент создан, чтобы решить эту проблему. cJass2Lua может легко конвертировать cJass и JASS в читаемый Lua код, он поможет вам менее болезненно перенести код своей карты с JASS и cJass который находится в тупиковом положении на код в Lua. В большинстве случаев при переносе кода его даже не нужно редактировать, чтобы заставить работать, допустимо даже подавать мешанину из cJass и JASS кода на вход.
Скриншот:
Возможности:
  • Полная поддержка cJass и JASS
  • Возможность комбинировать синтаксис этих двух языков в одном файле
  • Поддержка парсинга структур(классов) в Lua'шные объекты мета-таблиц совместимые с оригинальным кодом, зачастую не требующие даже внесения правок чтобы они работали
  • Примитивный синтаксический анализ (на правильность кода) в процессе парсинга и вывод ошибок в лог
  • Генерация Lua кода на основе вашего cJass/JASS кода
  • Генерация спец-комментариев emmyDoc для Lua, которые помогают IDE ориентироваться в коде
  • Способен конвертировать common.j, blizzard.j и JASS код любой сложности
  • Удобный выбор файла/папки с файлами
  • Конвертация одиночных файлов
  • Массовая конвертация файлов из папки в папку
  • Подробное логгирование всех действий программы в лог файл для анализа проблем
  • Распознавание пост-инкрементов и пре-инкрементов
  • 100% читабельный код на выходе
  • Сохраняет комментарии, их позиции и переносы строк в любых местах
  • Сохраняет совместимость кода и его изначальную планировку (порой достаточно просто конвертировать текст каждого триггера по отдельности и ваша карта уже работает на Lua)
  • Расставляет табуляцию
  • Конфигурационный файл с настройками
  • Минималистичный встроенный графический интерфейс где удобно и подробно можно отслеживать прогресс
  • Интерфейс командной строки
Ограничения:
  • Отсутствует и вряд ли планируется семантический анализатор. За семантику выражений отвечает автор скриптов.
  • Структуры не поддерживают наследование и не понимают разницу между public и private (поддерживаются статические методы, статические переменные переводятся в глобальные)
  • Отсутствие поддержки расширенных фич vJASS как module, library, scope (Они по сути в Lua и не нужны, и просто игнорируются при парсе)
  • Не поддерживаются пре-процессорные директивы (Лишено смысла при переводе в Lua)
  • Макросы ограничены. блоки define распознаются, но только как константы. Избегайте функциональных макросов.
  • В некоторых случаях массивы в Lua индексируются с единицы, в большинстве случаев вам это ничем не грозит, но имейте в виду.
  • Инкременты в выражениях выгдядят так a = (var++) --> a = (var + 1). Но сам var в этом случае не увеличится на 1, нужно фиксить руками.
  • Циклы for из cJass не поддерживаются и вряд ли будут, перед тем как транслировать файл на Lua - сохраните его на диск.
  • Всё на английском языке
Внимание:
Перед преобразованием кода, убедитесь что...
  • Ваш код на 100% правильный и не содержит ошибок
  • Ваши структуры не используют наследование
  • Если в вашей структуре предусмотрен конструктор (статический "создавальщик") то он обязан называться new или create
  • Если у вас в коде используются структуры не объявленные в этом файле, объявите их в начале файла при помощи type StructName, так парсер поймет с чем имеет дело
  • Не используются ключевые слова в качестве идентификаторов. Такие как do, else, while, then и тд.
  • Имейте в виду, что хоть и присутствует умная замена оператора конкатенации строк, строчные идентификаторы и функции объявленные в других файлах не будут распознаны как строки и если + не поменялся на .. - это придется делать вручную.
Приложение оставляет после своей работы рядом с собой лог файл, читайте его если вдруг что-то не так. Когда нормально отрабатывает приложение - там не должно быть ни одного сообщения типа Warning, Critical или Fatal.
Пример преобразования:
//Входящий JASS/cJass код
type Projectile

bool KatonItachiConditions()
{
	if (GetSpellAbilityId() == 'A07Z')
	{
		return true;
	}

	return false;
}

define
	KATON_DUMMY           =  1
	KATON_RADIUS		  =  2
	KATON_DAMAGE		  =  3
	KATON_FINAL_POINT_X   =  4
	KATON_FINAL_POINT_Y   =  5
	KATON_EFFECT          =  6
	KATON_DIRECTION       =  7
	KATON_TRAVELED        =  8
	KATON_DMG_FACTOR      =  9
	
	
	KATON_DISTANCE        =  1100
	KATON_VELOCITY        =  5.35
enddefine

globals 
	unit g_KatonDummy;
	float g_KatonDMG;
	trigger g_TrgKatonPreCast;
endglobals

void KatonItachiActions()
{
	unit u = GetTriggerUnit();
	player p = GetOwningPlayer(u);
	location loc = GetSpellTargetLoc();
	location myLoc = GetUnitLoc(u);
	float facing = GetUnitFacing(u);
	location spawnPoint = PolarProjectionBJ(myLoc, 115.00, facing);
	location finalPoint = PolarProjectionBJ(spawnPoint, KATON_DISTANCE, facing);
	int lvl = GetUnitAbilityLevel(u, GetSpellAbilityId());
	float r = 200 + (25 * (lvl - 1));
	float dmg = 10;//10 + (4 * (lvl - 1)); 
	float travelFactor = 0.006 + (0.002 * (lvl - 1));
	float dummyScale = 2.00 + (0.30 * (lvl - 1));
	
	timer t = CreateTimer();
	InitPeriodicTimer(t, 0.01, 3.5);
	unit dummy =  CreateDummy(p, u, spawnPoint);
	SetUnitPathing(dummy, false);
	effect e = AddSpecialEffectTarget("fireball.mdx", dummy, "origin");
	SetUnitScale(dummy, dummyScale, dummyScale, dummyScale);
	SaveUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY, dummy);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_RADIUS, r);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR, travelFactor);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION, facing);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, 0);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X, GetLocationX(finalPoint));
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y, GetLocationY(finalPoint));
	SaveEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT, e);
	
	RemoveLocation(spawnPoint);
	RemoveLocation(loc);
	RemoveLocation(myLoc);
	RemoveLocation(finalPoint);
	
	TimerStart(t, 0.01, true, lambda void ()
	{
		timer t = GetExpiredTimer();
		float dur = GetTimerDuration(t);
		unit dummy = LoadUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY);
		location dummyLoc = GetUnitLoc(dummy);
		float r = LoadReal(g_Hashtable, GetHandleId(t), KATON_RADIUS);
		float traveled = LoadReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED);
		float dir = LoadReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION);
		float finalPointX = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X);
		float finalPointY = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y);
		location newLoc = PolarProjectionBJ(dummyLoc, KATON_VELOCITY, dir);
		SetUnitPositionLoc(dummy, newLoc);
		RemoveLocation(newLoc);
		RemoveLocation(dummyLoc);
		traveled += KATON_VELOCITY;
		SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, traveled);
		
		if (ModuloInteger(R2I(dur * 100), 10) == 0)
		{
			group g = CreateGroup();
			float travelFactor = LoadReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR);
			float dmg = LoadReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE) + (traveled * travelFactor);
			g_KatonDummy = dummy;
			g_KatonDMG = dmg;
			boolexpr bexp = Condition(lambda bool ()
			{
				unit u = GetFilterUnit();
				if (!IsPlayerAlly(GetOwningPlayer(u), GetOwningPlayer(g_KatonDummy)) && !IsUnitType(u, UNIT_TYPE_STRUCTURE) && IsUnitAlive(u) && !IsUnitDummy(u))
				{
					return true;
				}
				return false;
			});
			GroupEnumUnitsInRange(g, GetUnitX(dummy), GetUnitY(dummy), r, bexp);
			ForGroup(g, lambda void ()
			{
				 DummyDealDamage(g_KatonDummy, GetEnumUnit(), g_KatonDMG, SCHOOL_MAGIC);
			});
			SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg);
			DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralB​uildingExplosion.mdl", GetUnitX(dummy), GetUnitY(dummy)));
			DestroyBoolExpr(bexp);
			DestroyGroup(g);
		}
		
		
		
		if (!TimerTick(t) || dummy == null || traveled > KATON_DISTANCE)
		{
			DestroyEffect(LoadEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT));
			RemoveUnit_s(dummy, "KatonItachiActions", "KatonItachi");
			DestroyTimer_s(t);
		}
	});
}

void KatonSoundActions()
{
	unit u = GetTriggerUnit();
	AddSoundUnit("katon.mp3", u);
	u = null;
}

void KatonItachiActionsNew()
{
	unit u = GetTriggerUnit();
	location loc = GetSpellTargetLoc();
	int lvl = GetUnitAbilityLevel(u, GetSpellAbilityId());
	float r = 200 + (25 * (lvl - 1));
	float dmg = 100;//100 + (4 * (lvl - 1)); 
	float travelFactor = 0.04 + (0.02 * (lvl - 1));
	float dummyScale = 2.00 + (0.30 * (lvl - 1));
	
	FinishDuel();
	Projectile katonProj = Projectile.create(DEFAULT_DUMMY, "fireball.mdx", dummyScale, u, 110);
	katonProj.SetVelocity(535, 1.0);
	katonProj.DamageOnce(false);
	katonProj.SetDamageData(0.1, dmg, r, 0, 0, travelFactor, SCHOOL_MAGIC);
	katonProj.SetDestLoc(loc);
	katonProj.SetDistance(1100, true);
	katonProj.InstantRemove(true);
	katonProj.SetDamageEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildi​ngExplosion.mdl");
	katonProj.Launch();
	
	RemoveLocation(loc);
	u = null;
	loc = null;
}

void InitTrig_KatonItachi()
{
    gg_trg_KatonItachi = CreateTrigger();
	g_TrgKatonPreCast = CreateTrigger();
    TriggerRegisterAnyUnitEventBJ(gg_trg_KatonItachi, EVENT_PLAYER_UNIT_SPELL_EFFECT);
	TriggerRegisterAnyUnitEventBJ(g_TrgKatonPreCast, EVENT_PLAYER_UNIT_SPELL_CHANNEL);
    TriggerAddCondition(gg_trg_KatonItachi, Condition(function KatonItachiConditions));
    TriggerAddAction(gg_trg_KatonItachi, function KatonItachiActionsNew);
	TriggerAddCondition(g_TrgKatonPreCast, Condition(function KatonItachiConditions));
    TriggerAddAction(g_TrgKatonPreCast, function KatonSoundActions);
}
-- Lua код на выходе

---@class  Projectile
---@return bool
function KatonItachiConditions()
	if (GetSpellAbilityId() == FourCC('A07Z')) then
		return true
	end
	
	return false
end

KATON_DUMMY = 1	---@type integer	
KATON_RADIUS = 2	---@type integer	
KATON_DAMAGE = 3	---@type integer	
KATON_FINAL_POINT_X = 4	---@type integer	
KATON_FINAL_POINT_Y = 5	---@type integer	
KATON_EFFECT = 6	---@type integer	
KATON_DIRECTION = 7	---@type integer	
KATON_TRAVELED = 8	---@type integer	
KATON_DMG_FACTOR = 9	---@type integer	
KATON_DISTANCE = 1100	---@type integer	
KATON_VELOCITY = 5.35	---@type real	

-- g_KatonDummy	---@type unit	
-- g_KatonDMG	---@type float	
-- g_TrgKatonPreCast	---@type trigger	

---@return void
function KatonItachiActions()
	local u = GetTriggerUnit()
	local p = GetOwningPlayer(u)
	local loc = GetSpellTargetLoc()
	local myLoc = GetUnitLoc(u)
	local facing = GetUnitFacing(u)
	local spawnPoint = PolarProjectionBJ(myLoc, 115.00, facing)
	local finalPoint = PolarProjectionBJ(spawnPoint, KATON_DISTANCE, facing)
	local lvl = GetUnitAbilityLevel(u, GetSpellAbilityId())
	local r = 200 + (25 * (lvl - 1))
	local dmg = 10	-- 10 + (4 * (lvl - 1)); 
	local travelFactor = 0.006 + (0.002 * (lvl - 1))
	local dummyScale = 2.00 + (0.30 * (lvl - 1))
	
	local t = CreateTimer()
	InitPeriodicTimer(t, 0.01, 3.5)
	local dummy = CreateDummy(p, u, spawnPoint)
	SetUnitPathing(dummy, false)
	local e = AddSpecialEffectTarget("fireball.mdx", dummy, "origin")
	SetUnitScale(dummy, dummyScale, dummyScale, dummyScale)
	SaveUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY, dummy)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_RADIUS, r)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR, travelFactor)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION, facing)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, 0)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X, GetLocationX(finalPoint))
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y, GetLocationY(finalPoint))
	SaveEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT, e)
	
	RemoveLocation(spawnPoint)
	RemoveLocation(loc)
	RemoveLocation(myLoc)
	RemoveLocation(finalPoint)
	
	TimerStart(t, 0.01, true, function ()
		local t = GetExpiredTimer()
		local dur = GetTimerDuration(t)
		local dummy = LoadUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY)
		local dummyLoc = GetUnitLoc(dummy)
		local r = LoadReal(g_Hashtable, GetHandleId(t), KATON_RADIUS)
		local traveled = LoadReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED)
		local dir = LoadReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION)
		local finalPointX = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X)
		local finalPointY = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y)
		local newLoc = PolarProjectionBJ(dummyLoc, KATON_VELOCITY, dir)
		SetUnitPositionLoc(dummy, newLoc)
		RemoveLocation(newLoc)
		RemoveLocation(dummyLoc)
		traveled = traveled + KATON_VELOCITY
		SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, traveled)
		
		if (ModuloInteger(R2I(dur * 100), 10) == 0) then
			local g = CreateGroup()
			local travelFactor = LoadReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR)
			local dmg = LoadReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE) + (traveled * travelFactor)
			g_KatonDummy = dummy
			g_KatonDMG = dmg
			local bexp = Condition(function ()
				local u = GetFilterUnit()
				if ( not IsPlayerAlly(GetOwningPlayer(u), GetOwningPlayer(g_KatonDummy)) and  not IsUnitType(u, UNIT_TYPE_STRUCTURE) and IsUnitAlive(u) and  not IsUnitDummy(u)) then
					return true
				end
				return false
			end)
			GroupEnumUnitsInRange(g, GetUnitX(dummy), GetUnitY(dummy), r, bexp)
			ForGroup(g, function ()
				DummyDealDamage(g_KatonDummy, GetEnumUnit(), g_KatonDMG, SCHOOL_MAGIC)
			end)
			SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg)
			DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralB​uildingExplosion.mdl", GetUnitX(dummy), GetUnitY(dummy)))
			DestroyBoolExpr(bexp)
			DestroyGroup(g)
		end
		
		
		if ( not TimerTick(t) or dummy == nil or traveled > KATON_DISTANCE) then
			DestroyEffect(LoadEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT))
			RemoveUnit_s(dummy, "KatonItachiActions", "KatonItachi")
			DestroyTimer_s(t)
		end
	end)
end

---@return void
function KatonSoundActions()
	local u = GetTriggerUnit()
	AddSoundUnit("katon.mp3", u)
	u = nil
end

---@return void
function KatonItachiActionsNew()
	local u = GetTriggerUnit()
	local loc = GetSpellTargetLoc()
	local lvl = GetUnitAbilityLevel(u, GetSpellAbilityId())
	local r = 200 + (25 * (lvl - 1))
	local dmg = 100	-- 100 + (4 * (lvl - 1)); 
	local travelFactor = 0.04 + (0.02 * (lvl - 1))
	local dummyScale = 2.00 + (0.30 * (lvl - 1))
	
	FinishDuel()
	local katonProj = Projectile:create(DEFAULT_DUMMY, "fireball.mdx", dummyScale, u, 110)
	katonProj.SetVelocity(535, 1.0)
	katonProj.DamageOnce(false)
	katonProj.SetDamageData(0.1, dmg, r, 0, 0, travelFactor, SCHOOL_MAGIC)
	katonProj.SetDestLoc(loc)
	katonProj.SetDistance(1100, true)
	katonProj.InstantRemove(true)
	katonProj.SetDamageEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildi​ngExplosion.mdl")
	katonProj.Launch()
	
	RemoveLocation(loc)
	u = nil
	loc = nil
end

---@return void
function InitTrig_KatonItachi()
	gg_trg_KatonItachi = CreateTrigger()
	g_TrgKatonPreCast = CreateTrigger()
	TriggerRegisterAnyUnitEventBJ(gg_trg_KatonItachi, EVENT_PLAYER_UNIT_SPELL_EFFECT)
	TriggerRegisterAnyUnitEventBJ(g_TrgKatonPreCast, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
	TriggerAddCondition(gg_trg_KatonItachi, Condition(KatonItachiConditions))
	TriggerAddAction(gg_trg_KatonItachi, KatonItachiActionsNew)
	TriggerAddCondition(g_TrgKatonPreCast, Condition(KatonItachiConditions))
	TriggerAddAction(g_TrgKatonPreCast, KatonSoundActions)
end

Инструкция:
Чтобы пользоваться просто укажите во входящий путь в окне приложения путь к файлу или папке с cjass/jass файлами при помощи кнопки Browse. Чтобы выбрать папку, а не файл - нажмите Browse с зажатым шифтом. Внизу укажите путь к папке в которую запишется готовый Lua файл (или прямой путь к выходному луа файлу), выбор файла или папки через Browse аналогичен. Также имеется и консольный интерфейс (первый аргумент входящий путь, второй - исходящий). Если исходящий путь не указан, то .lua файлик сохранится туда же, где и входящий .j файлик.
СКАЧАТЬ: (версия v1.12 07.12.2019)
x86 сборка: Скачать
x64 сборка: Скачать
Исходный код (и подробности использования):
GitHub: github.com/fullmetal-a/cjass2lua
Изменения v1.12:
  • Исправлены все случаи, когда this. не добавлялся периодически перед членами и методами
  • Исправлен баг, когда иногда оператор ! заменялся на - вместо not
  • Теперь все названия методов корректны и полностью работоспособны, они больше не пишутся через :
  • Добавлена поддержка .deallocate
  • Теперь переменная объекта текущего класса, созданная в методе .create при помощи .allocate удаляется при трансляции кода, а все обращения к ней меняются на this.
  • Исправлено множество багов
Изменения v1.11/1.10:
  • Улучшен парсинг
  • Улучшен консольный интерфейс
  • Исправлены редкие критические баги
  • Исправлен критический баг с трансляцией идентификаторов
  • Теперь поля входящих и выходящих путей в интерфейсе больше не read-only
Изменения v1.09:
  • Добавлена поддержка перевода структур/классов в мета-табличные объекты
  • Добавлена поддержка коротких void лямбда-выражений через оператор ()->
  • Парс теперь прерывается с ошибкой если мы переобъявляем глобальную функцию\переменную
  • Небольшие улучшения и оптимизация
  • Исправления багов


Views: 5 023

» Лучшие комментарии


Drulia_san #53 - 2 years ago (изм. ) 0
Голосов: +0 / -0
ScorpioT1000:
Отсутствие поддержки расширенных фич vJASS как module, library, scope
И зачем это тогда?) код без этих фич таких размеров, что его и руками можно перенести
Абсолютно ненужные при переносе фичи, на луа можно конечно сделать подобие неймспейсов, но в этом нет сущей необходимости. Зачем это?
Для конвертации синтаксиса, попробуй 100к строчек кода мешанины из JASS/cJass перенеси на луа руками, это занятие не на один месяц (если не сидеть часами каждый день за этим), чтобы еще всё правильно было, и просто регулярки тут не прокатят. А так во множестве случаев код даже редактирования не требует, работает сходу после конвертации. Перенести код руками? Ты много желающих видел которые горят желанием добровольно переписывать всё на луа? Причем не рефакторить, а именно сидеть переписывать, пытаться просто заставить код заработать.
Для 99% тех кто пишет на джассе, такие вещи как module, library, scope это просто красивое обрамление кода и костыль для его финальной композиции, потому что без этого функции могут быть ниже зоны видимости скриптов, которые дергают функции из библиотеки,когда в луа изначально всё видит всё и то что выше, и то что ниже. Имхо, всякие library, module, scope - ненужный мусор на луа, можно реализовать, но это уже вкусовщина, оборачивать кучу функций в огромную function UtilsLibrary() или типа того.. Ради чего? Ради того чтоб постоянно писать UtilsLibrary:Func()? Это маразм. Реализовать подобное дело получаса, я намеренно это не добавил, чтобы не уродовать код.
Как пользователю мне в первую очередь было бы важно, чтобы сохранялась читаемость кода, переводились сложные выражения и за меня бы сделалась вся рутина переноса, где в конце можно чуток дополировать. Желательно еще чтоб структурки конвертились. У меня куча кода в этих модулях, либрарях и скоупах, и мне вообще без разницы что и как с ними будет после, главное чтоб код был красивым и работал.
ScorpioT1000 #54 - 2 years ago (изм. ) 0
Голосов: +0 / -0
Для 99% тех кто пишет на джассе, такие вещи как module, library, scope это просто красивое обрамление кода и костыль для его финальной композиции
yasno
Drulia_san #55 - 2 years ago 2
Голосов: +2 / -0
yasno
Это нужно и имеет практический смысл на c/vJASS, но не на луа точно, не нужно пихать уродства из джасса в простой и компактный луа.
ScorpioT1000 #56 - 2 years ago 0
Голосов: +0 / -0
не нужно пихать уродства из джасса в простой и компактный луа.
Эта тулза занимается именно этим. А то, что нужно - запаковать набор из N легаси-библиотек - как раз не делает.
Drulia_san #57 - 2 years ago (изм. ) 2
Голосов: +2 / -0
ScorpioT1000:
не нужно пихать уродства из джасса в простой и компактный луа.
Эта тулза занимается именно этим. А то, что нужно - запаковать набор из N легаси-библиотек - как раз не делает.
Если нужно что-то запаковать это можно сделать и руками, дело 1-2 минут. Это - вкусовщина для разработчика, а не необходимость, лично мне достаточно по файлам рассортировать нужный функционал.
Да может это и удобно для тебя или кого-нибудь еще, никто не мешает это делать, но не преувеличивай значимость, будто это самое важное, это просто обёртка.
Doc #58 - 2 years ago 0
Голосов: +0 / -0
Ну если семантика сохраняется. У модулей/библиотек есть например инициализаторы, без них код поломается. Опять же совпадение имен в разных скоупах. Если эти проблемы решаются, то ок.
Drulia_san #59 - 2 years ago (изм. ) 0
Голосов: +0 / -0
Doc:
Ну если семантика сохраняется. У модулей/библиотек есть например инициализаторы, без них код поломается. Опять же совпадение имен в разных скоупах. Если эти проблемы решаются, то ок.
Код преобразуется по-файлово, сеанс трансляции для одного файла не помнит что было в другом, потому о таких вещах должен позаботиться автор кода. Однако в следующей версии уже реализована фича, когда при парсе глобалка\функция переобъявляется, то парс обрывается с предупреждением внести изменения.
ScorpioT1000 #60 - 2 years ago 0
Голосов: +0 / -0
Более того, разные библиотеки объявляют разные общеизвестные функции и переменные приватными (типа GetUnitZ), которые встречаются во многих местах
потому о таких вещах должен позаботиться автор кода
» Больно долго заботиться)
#include "MainEngine_PRELOADING.j"
#include "GameCounter.j"

#include "MainENGINE.j"
#include "MainEngine_Local.j"

#include "IfDebug.j"
#include "MainEngine_JcMath.j"
#include "MainEngine_String.j"
#include "MainEngine_Cache.j"
#include "MainEngine_MinionControl.j"
#include "Cinema.j"
#include "Dialog.j"
#include "INDOOR.j"
#include "MainEngine_FightMode.j"
#include "MainEngine_ActionMode.j"
#include "MainEngine_TimeOfDay_Control.j"
#include "MainEngine_SlashCmd.j"
#include "DGUI.j"
#include "SpellSystem.j"
#include "MainEngine_SS_SkillBase.j"
#include "MainEngine_SS_Interface.j"
#include "MainEngine_Settings.j"
#include "MainEngine_TPCcam.j"
#include "MainEngine_TPCkeys.j"
#include "MainEngine_TPCmoving.j"
#include "MainEngine_Spells.j"
#include "MainEngine_NPC.j"
#include "PortableMiniInv.j"
#include "MainEngine_GameHelper.j"
#include "MainEngine_Quest.j"
#include "MainEngine_Death.j"
#include "MainEngine_DrinkMode.j"
#include "MainEngine_Reputation.j"
Это я всё к тому, что, прочитав название, подумал, что вполне реально всю эту байду перевести в луа
Хотя в итоге офк проще написать с нуля
Drulia_san #61 - 2 years ago 0
Голосов: +0 / -0
ScorpioT1000:
всё к тому, что, прочитав название, подумал, что вполне реально всю эту байду перевести в луа
Хотя в итоге офк проще написать с нуля
Если код слишком специфичен, то боюсь что да) Но вообще, можно переименовать внутренние функциии и переменные через массовую замену и попробовать сконвертировать, тогда по идее всё должно работать.
Если попытаться упаковывать автоматически на луа, потом придется тоже много руками править, дописывать имя библиотеки к вызовам и прочие неприятности, так что куда не поверни - аксиома Эскобара.
Drulia_san #62 - 2 years ago (изм. ) 0
Голосов: +0 / -0
Как и обещал, выпустил версию 1.09, в которой реализована поддержка структур, старался делать их код максимально совместимым с оригиналом кода, чтобы работали с остальным кодом.
Не поддерживается и не будет поддерживаться наследование, поддерживаются статические методы и относительно статические члены.
Пишите вы this.member, .member или просто member - не важно, оно поймет что где к чему относится. Конструктор если есть то обязан называться или new или create.
Если используются структуры не объявленные в текущем файле - объявите их в начале написав type StructName.
Можете тестировать и докладывать о багах
NazarPunk #63 - 2 years ago 1
Голосов: +1 / -0
Проэект ещё жив? Можно добавить галку для common.j и ему подобных файлов?

Две чёрточки нужно убрать

появился новый тип minimapicon

появился новый тип commandbuttoneffect

---@return nothing заменить на ---@return nil
Прикрепленные файлы
Drulia_san #64 - 2 years ago (изм. ) 2
Голосов: +2 / -0
NazarPunk:
Проэект ещё жив? Можно добавить галку для common.j и ему подобных файлов?

Две чёрточки нужно убрать

появился новый тип minimapicon

появился новый тип commandbuttoneffect

---@return nothing заменить на ---@return nil
Окей, я добавлю исправления, постараюсь на неделе
NazarPunk #65 - 2 years ago 0
Голосов: +0 / -0
Окей, я добавлю исправления, постараюсь на неделе
Спасибо. Исправленные ручками файлы можно найти здесь.
Doc #66 - 2 years ago 0
Голосов: +0 / -0
Тебе нужно обрабатывать ключевые слова в переменных, иначе код ломается, например "in", "end", etc.

Ну и хоть базовая поддержка library бы не помешала
exAres #67 - 11 months ago 3
Голосов: +3 / -0
if udg_MBcount[udg_player[i]+10]==0 then
превращается в
if udg_MBcount[udg_playeri] + 10 == 0 then
Это норм?)
Drulia_san #68 - 11 months ago (изм. ) 0
Голосов: +0 / -0
exAres:
if udg_MBcount[udg_player[i]+10]==0 then
превращается в
if udg_MBcount[udg_playeri] + 10 == 0 then
Это норм?)
Классическая бажина. К сожалению я без понятия когда захочу/смогу исправить и захочу ли я вообще. Warcraft я забросил далеко и надолго из-за нецелесообразности Reforged. Занят другим проектом на Dota 2.
Если кто-то всё таки захочет исправить\улучшить утилиту за меня - в посте снизу есть ссылка на гитхаб, рассмотрю любые pull реквесты, протестирую, опубликую новую версию, могу ответить на технические вопросы если что.
Nikolay36 #69 - 5 days ago 0
Голосов: +0 / -0
exAres, кажется это программа не конвентирует массивы