ScriptLoader (Защита скриптов)

Больше
11 года 8 мес. назад - 11 года 8 мес. назад #73576 от KageDesu
По ходу работы над игрой с быстрой RTBS, задался вопросом уменьшения кода и защиты скриптов. Сделал небольшую скрипт - утилиту, интересно ваше мнение.

Название: ScriptLoader
Версия: 1.0 (Тестовая)
Описание: Данный скрипт позволяет загружать скрипты из файлов (текстовых (.txt и .rb) и бинарных (.xs))
Зачем это нам нужно?
При помощи этого скрипта и утилиты, вы сможете сохранить целостность вашего кода, разделив ваш скрипт на две части interface и implementation (интерфейс и реализация). В часть интерфейса вынести все константы и значения, которые по вашей задумке пользователь может менять, чтобы настроить ваш скрипт под себя, а в часть реализации собственно весь код. Часть реализации с помощью утилиты превращается в бинарный файл и загружается в игру одной строчкой под частью интерфейса, а сам интерфейс как обычный скрипт вставляем в RPG VXA. Реализация находится в бинарном виде и никто не может увидеть ваш код, а он в свою очередь будет выполняться в игре.

Как использовать?
Допустим у вас есть скрипт
Code:
module MY_SCRYPT #Хочу чтобы пользователь менял эти параметры FONT_SIZE = 62 TEXT = "ScriptLoader" #По каким-либо причинам не хочу чтобы пользователь видел этот код и менял его. Может ему это и не нужно, а нагромождать будет. class MyScene < Scene_Base #-------------------------------------------------------------------------- # * Start Processing #-------------------------------------------------------------------------- def start super create_background create_test end #-------------------------------------------------------------------------- # * Frame Update #-------------------------------------------------------------------------- def update super update_test #EXIT if(Input.trigger?(:B)) SceneManager.return end end #-------------------------------------------------------------------------- # * Termination Processing #-------------------------------------------------------------------------- def terminate super dispose_background dispose_test end #-------------------------------------------------------------------------- # * Create Background #-------------------------------------------------------------------------- def create_background @background_sprite = Sprite.new @background_sprite.bitmap = SceneManager.background_bitmap @background_sprite.color.set(16, 16, 16, 128) end #-------------------------------------------------------------------------- # * Free Background #-------------------------------------------------------------------------- def dispose_background @background_sprite.dispose end def create_test @s = Sprite.new() @s.bitmap = Bitmap.new(Graphics.width,Graphics.height) @s.bitmap.font.size = MY_SCRYPT::FONT_SIZE @s.bitmap.draw_text(0,(Graphics.height/2)-100,Graphics.width,100,MY_SCRYPT::TEXT,1) end def update_test @s.update end def dispose_test @s.dispose end end

Разделяем скрипт на две части

ЧАСТЬ 1
Code:
module MY_SCRYPT #Хочу чтобы пользователь менял эти параметры FONT_SIZE = 62 TEXT = "ScriptLoader" end

ЧАСТЬ 2
Code:
module MY_SCRYPT class MyScene < Scene_Base #-------------------------------------------------------------------------- # * Start Processing #-------------------------------------------------------------------------- def start super create_background create_test end #-------------------------------------------------------------------------- # * Frame Update #-------------------------------------------------------------------------- def update super update_test #EXIT if(Input.trigger?(:B)) SceneManager.return end end #-------------------------------------------------------------------------- # * Termination Processing #-------------------------------------------------------------------------- def terminate super dispose_background dispose_test end #-------------------------------------------------------------------------- # * Create Background #-------------------------------------------------------------------------- def create_background @background_sprite = Sprite.new @background_sprite.bitmap = SceneManager.background_bitmap @background_sprite.color.set(16, 16, 16, 128) end #-------------------------------------------------------------------------- # * Free Background #-------------------------------------------------------------------------- def dispose_background @background_sprite.dispose end def create_test @s = Sprite.new() @s.bitmap = Bitmap.new(Graphics.width,Graphics.height) @s.bitmap.font.size = MY_SCRYPT::FONT_SIZE @s.bitmap.draw_text(0,(Graphics.height/2)-100,Graphics.width,100,MY_SCRYPT::TEXT,1) end def update_test @s.update end def dispose_test @s.dispose end end end

ЧАСТЬ 2 переводим в бинарный вид, а часть один вставляем в редактор, как обычный скрипт + вызываем метод загрузки второй части.

Вот так будет в результате:
Code:
module MY_SCRYPT FONT_SIZE = 62 TEXT = "ScriptLoader" end ScriptLoader.loadX("Имя файла с ЧАСТЬ2");

Это весь код.

Также можно не переводить свой скрипт в бинарный формат, а просто вынести в файл и загрузить (Например просто чтобы код не мешался). Подробнее в демке.

Описание ScriptLoader:

Утилита RGSS_ScriptToBin.exe переводит ваш в код в бинарный файл с разрешение .xs. (Просто перетащите на неё текстовый файл с кодом вашего скрипта)

Сам скрипт ScriptLoader должен иметь строгое (строгое!) имя "PKD_ScriptLoader" и быть самым первым в вашей базе скриптов (причём иметь строгий код!)
В демке всё есть и написано подробнее. Загружать же свои скрипты при помощи ScriptLoader можно где угодно.

В данной версии есть ограничения по переводу скриптов в бинарный формат
1) Русские символы в коде (в строке например) будут как "?" - решается, если вынести слова в константы в часть интерфейса
2) Регулярные выражения в коде и некоторые escape последовательности - скрипт не загрузиться - решается аналогично, выносим в константы (интерфейс)

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


Для работы требуется:
.NET Framework 4
Visual C++ Redistributable Packages 2013

Демка с пояснениями и утилита.
Ссылки:
DropBox
Яндекс.Диск
Последнее редактирование: 11 года 8 мес. назад пользователем KageDesu.
Спасибо сказали: DeadElf79, Ren310, strelokhalfer, caveman, MaltonTheWarrior, Eokati

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 1 место Программист Ruby Писатель 3 место 3 место Учитель Организатор конкурсов 1 место в Готв Ветеран Проект месяца 2 место
Больше
11 года 8 мес. назад - 11 года 8 мес. назад #73591 от DeadElf79
Раз уж на то пошло, то можно ли переводить киррилицу в utf-8 сразу при конвертации? или весь бинарный код строго в ANSI без вариантов идет? почему бы не записывать в utf-8 тогда?

Кстати, надеюсь, комментарии из кода при конвертации утилита удалаяет? А то их все равно никто не увидит, так что это просто ненужный хлам :laugh:

А что за проблема с регулярными выражениями? О.о Почему не решена до сих пор?)
Последнее редактирование: 11 года 8 мес. назад пользователем DeadElf79.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Больше
11 года 8 мес. назад #73592 от KageDesu
Добрый день DeadElf79.
Насчёт перевода в UTF-8 сразу при конвертации - это хорошая идея. Только на последних этапах тестирования я заметил разницу в кодировках, поэтому проблема не была решена в версии 1.0. В следующей версии подумаю над этим. Спасибо за совет.

Кстати, надеюсь, комментарии из кода при конвертации утилита удалаяет?


Конвертирование состоит из двух этапов. Необратимый процесс. На первом этапе всё удаляется: комментарии, переносы строк, пробелы, всё что только можно. Уже после этого этапа код человеком практически не читаем (одна длинная строка). Эту строку Ruby понимает, ему всё равно. А следующий этап дополнительно переводит это в двоичный код.

А что за проблема с регулярными выражениями?

Чтобы код в одной строке интерпретировался нормально как в C#, так и в Ruby, нужно "закрывать" escape последовательности правильно. В регулярных выражениях Ruby есть свои управляющие символы, чтобы их правильно "закрыть" нужно найти все регулярные выражения в коде (для этого нужно написать регулярное выражение :) ) и уже с ними работать. Пока ещё это у меня не получилось.

Почему не решена до сих пор?)

Из результатов тестирования (1 скрипт не работает из 110 стандартных ACE), решил что проблема не критична и уделил время разработке своей игры. Обновлять буду этот скрипт, но не в приоритете.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 1 место Программист Ruby Писатель 3 место 3 место Учитель Организатор конкурсов 1 место в Готв Ветеран Проект месяца 2 место
Больше
11 года 8 мес. назад #73602 от DeadElf79
Так, хорошо, а зачем тут интерпретация через сишарп? Или... погоди-ка, у тебя программа не только конвертирует xs обратно в строку для руби, но и пытается ее же интерпертировать перед передачей в RGSS? Я правильно понимаю?
Если да, то прошу пояснений, интересен ход мыслей, которые привели к такому решению.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Больше
11 года 8 мес. назад #73639 от KageDesu
C# библиотека содержит алгоритм перевода строки в бинарный формат и обратно. А также внутри этот библиотеки происходит выполнение этого кода. Механизм там такой, что Kernel.eval(код) используется косвенно, подробнее не могу объяснить :) Такой способ защищает выполнение кода от пользовательского переопределения (или alias) метода Kernel.eval.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 1 место Программист Ruby Писатель 3 место 3 место Учитель Организатор конкурсов 1 место в Готв Ветеран Проект месяца 2 место
Больше
11 года 7 мес. назад #73652 от DeadElf79
А, так вот в чем дело)) Что-то подобное и предполагал. Ждем обновлений с регулярками и прочими вкусностями ^_^

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Время создания страницы: 0.096 секунд
Работает на Kunena форум