Алгоритмы, Наработки и Способности
Способ реализации:
Jass
Тип:
Алгоритм
Версия Warcraft:
любая

[WarCraft III] Jass identifier renamer

автор статьи: host_pi
автор программы: PT153
[WarCraft III] Jass identifier renamer - автопереименование функций и переменных в j коде
скрипт позволяет вернуть обфусцированному j коду читабельный вид, пакетно меняя имена функций и переменных
(например если у вас есть незащищённый код от другой версии карты или вы произвели реверс-инжиниринг кода и можете самостоятельно дать смысловые имена)

как юзнуть:

  1. регистрируетесь в реплите
  2. клонируете себе этот репл
  3. в war3map.j кидаете свой код, в main.py описываете имена, что хотите заменить и на что.
  4. запускаете main.py, в output.j результат.
кнопка клонирования справа сверху:
код main.py под спойлером:
Открыть
import re
from collections import Counter
from collections.abc import Iterable


WORDS_TO_REPLACE = {
    'fu': 'Test1',
    'ti': 'Test2',
    'jass': 'Test3',
    'hpea': 'Test4',
    'd': 'Test5',
}

words = '|'.join(re.escape(w) for w in WORDS_TO_REPLACE)
REGEX_WORDS = re.compile(rf'\b({words})\b')

REPLACEMENTS_N = Counter()
FOUND_IN_QUOTES = Counter()


def replacement(m: re.Match, /) -> str:
    word = m[0]
    start, end = m.span()
    assert start < end
    for s, e in SPANS:
        if s >= end: break

        if s <= start and end <= e:
            FOUND_IN_QUOTES[word] += 1
            return word

    REPLACEMENTS_N[word] += 1
    return WORDS_TO_REPLACE[word]


def find_quotes(content: str, /) -> Iterable[tuple[int, int]]:
    is_double = is_single = False
    start = end = -1
    for i, c in enumerate(content):
        if is_double:
            if c == '"':
                if content[i - 1] == '\\':
                    continue

                end = i + 1
                is_double = False

                assert start < end
                assert start > -1 and end > -1
                yield start, end
                start = end = -1
        elif is_single:
            if c == "'":
                if content[i - 1] == '\\':
                    continue

                end = i + 1
                is_single = False

                assert start < end
                assert start > -1 and end > -1
                yield start, end
                start = end = -1
        else:
            if c == '"':
                is_double = True
                start = i
            elif c == "'":
                is_single = True
                start = i


with open('war3map-actual.j') as f, open('output.j', 'w') as out:
    content = f.read()
    SPANS = tuple(find_quotes(content))
    out.write(REGEX_WORDS.sub(replacement, content))

col1_len = max(map(len, map(repr, REPLACEMENTS_N.keys() | FOUND_IN_QUOTES.keys())))
print('Replaced count:')
for w, n in sorted(REPLACEMENTS_N.items()):
    print(f'    {w!r:{col1_len}} -- {n}')
    
print('Found inside quotes:')
for w, n in sorted(FOUND_IN_QUOTES.items()):
    print(f'    {w!r:{col1_len}} -- {n}')
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
37
6 месяцев назад
Отредактирован ScorpioT1000
0
Поле "источник" создано не для этой цели. У тебя авторский контент, а по этому полю в дальнейшем может определяться дизайн страницы (авторское или нет)
1
28
6 месяцев назад
Отредактирован PT153
1
Автор скрипта я, так что если вас корёжит с его кода, все претензии писать мне)
0
18
6 месяцев назад
0
Интересно почему Iterable импортируется из collections, а не из typing
0
28
6 месяцев назад
Отредактирован PT153
0
Vlod, потому что импорт абстрактных коллекций из typing является устаревшим с 3.9.

host_pi, закинь код в саму статью по спойлер.
1
14
6 месяцев назад
1
PT153: код в саму статью по спойлер
закинуто
0
18
6 месяцев назад
0
Vlod, потому что импорт абстрактных коллекций из typing является устаревшим с 3.9.
Интересно почему типы не должны быть в typing) Если импорт из typing признан устаревшим можно линк
0
28
6 месяцев назад
0
Vlod, прочитав комментарий, я аж посмеялся)
typing это не types. Это другой модуль. И кстати, абстрактных коллекций в types нет и никогда не было. Они всегда были в collections.abc, где им и самое место.
Если импорт из typing признан устаревшим можно линк
Я напомню, что 3.9 вышел октябре 2020 в и его полноценная поддержка прекратилась в 2022 (осталась поддержка только для security issues до 2025). Вот статья What's new, раздел You should check for DeprecationWarning in your code:
Aliases to Abstract Base Classes in the collections module, like collections.Mapping alias to collections.abc.Mapping, are kept for one last release for backward compatibility. They will be removed from Python 3.10.
Впрочем, они передумали и алиасы оставили, о чём сказано в последней документации модуля typing, раздел Deprecated aliases:
This module defines several deprecated aliases to pre-existing standard library classes. These were originally included in the typing module in order to support parameterizing these generic classes using []. However, the aliases became redundant in Python 3.9 when the corresponding pre-existing classes were enhanced to support [] (see PEP 585).
The redundant types are deprecated as of Python 3.9. However, while the aliases may be removed at some point, removal of these aliases is not currently planned. As such, no deprecation warnings are currently issued by the interpreter for these aliases.
Чуть ниже расписан таймлайн устаревания и удаления из модуля:
Загруженные файлы
0
12
6 месяцев назад
0
Немного не понял сути программы. Допустим решил поменять что-то в карте с обфусцированный j файлом, всё равно, по итогу, нужно будет читать каждую строку и исходя из контекста давать название, что в целом можно сделать [ctrl + h].
Удобно, если б можно было бы менять строки не по имени, а по содержанию по типу local unit ${?} = GetTriggerUnit() => "local unit caster = GetTriggerUnit()"
1
28
6 месяцев назад
1
Daro, скрипт создан как ответ на этот вопрос. Поиск и замена в текстовых редакторах заменит такие же слова в строках и ASCII числах, что делать абсолютно не нужно. А каждый раз руками проходить по файлу в 100к строк такое себе. Поэтому ищешь в файле нужные функции, там находишь интересующие тебе имена и вбиваешь их в скрипт для переименовывания.
0
18
6 месяцев назад
0
абстрактных коллекций в types нет и никогда не было
Речь шла про typing, типы там были и есть сейчас, это также короче чем collections.abc
from typing import Awaitable, AsyncIterable, AsyncIterator
1
28
6 месяцев назад
Отредактирован PT153
1
Vlod, речь шла про
Интересно почему типы не должны быть в typing)
Потому что typing это не types. Типы находятся в types, typing - это модуль для аннотаций, а не для типов. Об этом сказано в документации модуля typing.
Это в целом странно и смешно слышать на адекватный и абсолютно верный ответ "потому что импорт абстрактных коллекций из typing является устаревшим с 3.9".

это также короче чем collections.abc
Продолжаешь юморить)
Нет никакой проблемы создать модуль t, и импортировать туда всё из collection.abc, чтобы потом писать
from t import Collecttion
Будет короче, чем из typing!

Как я уже сказал, импорт стандартных и абстрактных коллекций из typing устарел уже как 3 года, и нет никакой причины их оттуда импортировать (кроме кроссверсионности, но для этого есть typing_extensions). Что же будет, если всё таки это сделать? В typing находятся обёртки, а в collections.abc оригинальные классы. Таким образом:
  1. Обёртки по своему определению медленнее оригинальных классов и вот пруф.
  1. Обёртки возвращают False для isinstance(обёртка, type).
    • Как следствие, обёртки нельзя передать в issubclass в качестве первого аргумента.
Из-за этого некоторые библиотеки, которые считывают аннотации, могут неверно работать.
Загруженные файлы
0
37
6 месяцев назад
Отредактирован ScorpioT1000
0
это также короче чем collections.abc
Тайпскрипт это антоним короткого кода)
1
18
6 месяцев назад
1
PT153, просто не использовал collection.abc, возможно неявно из за необходимости кроссверсионности так как десятки сервисов и надо чтобы библиотеки работали везде. Насчет разного поведения было интересно, спасибо за развернутые ответы)
Чтобы оставить комментарий, пожалуйста, войдите на сайт.