Войти на сайт

Авторизация, ждите ...
×

ТЕМА: ScriptLoader (Защита скриптов)

ScriptLoader (Защита скриптов) 9 года 7 мес. назад #73576

  • KageDesu
  • KageDesu аватар
  • Вне сайта
  • Мастер
  • Сообщений: 101
  • Спасибо получено: 346
По ходу работы над игрой с быстрой RTBS, задался вопросом уменьшения кода и защиты скриптов. Сделал небольшую скрипт - утилиту, интересно ваше мнение.

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

Как использовать?
Допустим у вас есть скрипт
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
module MY_SCRYPT
  #Хочу чтобы пользователь менял эти параметры
  FONT_SIZE = 62 
  TEXT = "ScriptLoader"
end

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

Вот так будет в результате:
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
Яндекс.Диск
Последнее редактирование: 9 года 7 мес. назад от KageDesu.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: DeadElf79, Ren310, strelokhalfer, caveman, MaltonTheWarrior, Eokati

ScriptLoader (Защита скриптов) 9 года 7 мес. назад #73591

  • DeadElf79
  • DeadElf79 аватар
  • Вне сайта
  • Звездный Страж
  • Сообщений: 3147
  • Спасибо получено: 2650
  • Проект месяца 1 местоПрограммист RubyУчитель3 местоПроект месяца 2 местоОрганизатор конкурсов1 место в ГотвВетеранПисатель 3 место
Раз уж на то пошло, то можно ли переводить киррилицу в utf-8 сразу при конвертации? или весь бинарный код строго в ANSI без вариантов идет? почему бы не записывать в utf-8 тогда?

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

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

ScriptLoader (Защита скриптов) 9 года 7 мес. назад #73592

  • KageDesu
  • KageDesu аватар
  • Вне сайта
  • Мастер
  • Сообщений: 101
  • Спасибо получено: 346
Добрый день DeadElf79.
Насчёт перевода в UTF-8 сразу при конвертации - это хорошая идея. Только на последних этапах тестирования я заметил разницу в кодировках, поэтому проблема не была решена в версии 1.0. В следующей версии подумаю над этим. Спасибо за совет.
Кстати, надеюсь, комментарии из кода при конвертации утилита удалаяет?

Конвертирование состоит из двух этапов. Необратимый процесс. На первом этапе всё удаляется: комментарии, переносы строк, пробелы, всё что только можно. Уже после этого этапа код человеком практически не читаем (одна длинная строка). Эту строку Ruby понимает, ему всё равно. А следующий этап дополнительно переводит это в двоичный код.
А что за проблема с регулярными выражениями?
Чтобы код в одной строке интерпретировался нормально как в C#, так и в Ruby, нужно "закрывать" escape последовательности правильно. В регулярных выражениях Ruby есть свои управляющие символы, чтобы их правильно "закрыть" нужно найти все регулярные выражения в коде (для этого нужно написать регулярное выражение :) ) и уже с ними работать. Пока ещё это у меня не получилось.
Почему не решена до сих пор?)
Из результатов тестирования (1 скрипт не работает из 110 стандартных ACE), решил что проблема не критична и уделил время разработке своей игры. Обновлять буду этот скрипт, но не в приоритете.
Администратор запретил публиковать записи гостям.

ScriptLoader (Защита скриптов) 9 года 7 мес. назад #73602

  • DeadElf79
  • DeadElf79 аватар
  • Вне сайта
  • Звездный Страж
  • Сообщений: 3147
  • Спасибо получено: 2650
  • Проект месяца 1 местоПрограммист RubyУчитель3 местоПроект месяца 2 местоОрганизатор конкурсов1 место в ГотвВетеранПисатель 3 место
Так, хорошо, а зачем тут интерпретация через сишарп? Или... погоди-ка, у тебя программа не только конвертирует xs обратно в строку для руби, но и пытается ее же интерпертировать перед передачей в RGSS? Я правильно понимаю?
Если да, то прошу пояснений, интересен ход мыслей, которые привели к такому решению.
Администратор запретил публиковать записи гостям.

ScriptLoader (Защита скриптов) 9 года 7 мес. назад #73639

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

ScriptLoader (Защита скриптов) 9 года 7 мес. назад #73652

  • DeadElf79
  • DeadElf79 аватар
  • Вне сайта
  • Звездный Страж
  • Сообщений: 3147
  • Спасибо получено: 2650
  • Проект месяца 1 местоПрограммист RubyУчитель3 местоПроект месяца 2 местоОрганизатор конкурсов1 место в ГотвВетеранПисатель 3 место
А, так вот в чем дело)) Что-то подобное и предполагал. Ждем обновлений с регулярками и прочими вкусностями ^_^
Администратор запретил публиковать записи гостям.
Модераторы: NeKotZima
Время создания страницы: 0.339 секунд