Войти или зарегистрироваться

Плагин [ADMN/DEV/FUN] VarScript 1.2 - Пишем скрипты на Groovy

Пока что используйте Varscript 0.4.1.
Или есть небольшая модификация от MYXOMOPX (он добавил несколько команд для изменения Name и Lore у предметов)
Разработка Varscript 0.5 продвигается слишком медленно, я по 10 раз все переписываю. Но он должен оказаться на порядок мощнее предыдущей версии, за счет взаимодействия скриптов между собой, лямбда-функций, конструкторов. (потянуло меня на ООП, без него же никак)
Сейчас занимаюсь ядром языка VarScript. Как будет готово, выложу бету. Затем, как обещал, добавлю JavaScript.
 
  • Нравится
Реакции: stew
Varscript 0.4.2
NSETITEMNAME : ставит имя предмету
краткая форма: >NTNAME
Пример: /> ME "CustomName" NSETITEMNAME

NITEMNAME : кладет в стэк имя предмета
краткая форма: NTNAME
Пример: /> ME ME NTNAME MSG

NSETITEMLORE : ставит предмету lore
краткая форма: >NTLORE
Пример: /> ME [Lore1,Lore2,Lore3,Blablabla] >NTLORE

NITEMLORE : кладет в стэк lore предмета
краткая форма: NTLORE
Пример: /> ME ME NTLORE MSG
 
На текущий момент состояние плагина вот какое:
Новый движок языка varscript, готовы следующие плюшки:
- ООП
- Использование функций в качестве конструкторов
- Замыкания
- Глобальная область видимости переменных (общая для всех игроков)
- Обратная польская запись (без этого никак ;) )
- Многопоточность
- Динамическая компиляция и интерпретация:
каждую написанную функцию можно будет сохранить в byte[]
В итоге всего этого будет некая смесь Forth и ECMAScript

В разработке:
- Наследование на основе прототипов
- Куча команд управления
типа BEGIN REPEAT BREAK IF ELSE THEN START END STOP и т.д.
- Команды, относящиеся к Bukkit API
(пишет MYXOMOPX )

Планируется:
- Планировщик. (планируется планировщик... ха-ха)
От прошлого будет отличаться тем, что включить/отключить можно любую задачу и даже любой ее пункт. и + возможность объединения задач в группы.
- использование внешних пользовательских библиотек на java (./plugins/VarScript/lib/java)
Точно сделаю отдельную библиотеку для работы с MySQL, т.к. это нужно не всем.
- подключение движка Rhyno (JavaScript)
Rhyno дает больше возможностей благодаря рефлексиям, но в тоже время пользователь должен знать JavaScript и Bukkit API. Еще в нем отсутствует многопоточность, поэтому придется обходиться по старинке, регистрацией таймера.
- подключение других движков ScriptEngine (это в последнюю очередь)

Синтаксис varscript:
- Объявление функций
Функцию объявить можно будет внутри другой функции, как в JavaScript
Пример: KillRandomPlayer{ PLAYERS ARANDOM KILL }
Все, что внутри фигурных скобок - отдельная функция.
Допускаются безымянные.
- Переменные
Чтение переменной в стек: @x
Запись в переменную: значение %x
Запись в переменную и объявление ее локальной: значение %%x
Я не стал заморачиваться насчет анализа кода, поэтому переменная становится локальной в момент объявления (если она используется выше по коду до объявления, то считается глобальной)
Область видимости локальных переменных сохраняется в контексте исполнения функции. Могут использоваться в этой функции и любой внутренней, однако извне - недоступны.
- Потоки
Каждый отдельный поток содержит свой стек. "Общаться" между собой потоки могут через переменные.
Какой командой создавать потоки - еще не придумал.
- Управление списками
Для списков (java.util.List) будут доступны команды map, foreach и свертка, все на основе callback функций.
 
Продвижения есть, но были оооочень медленные.
Сейчас я набрал темп и пишу себе втихаря :D/ Буду делиться информацией в этой теме
http://www.rubukkit.org/threads/разработка-плагина-varscript.21863/page-5#post-555200


Большинство из админов не разберется, даже если им дать готовый скрипт и сказать, что в какую папочку надо скопировать. Им дай все готовое, настроенное, да побольше игроков.
Пусть это будет плагин для "элиты"
Требований у плагина не много: знать основы программирования, JavaScript, желательно Forth, изучить модель регистрации задач в планировщике и все.. ты бог своего сервера. Или же можно просто побаловаться командами /> ME "игрок" SETPASSENGER /> "игрок" 50 SETFIRE и т.д. Тут знаний не нужно

Вот эти команды — это правильно. Что бы плагин был более популярный, нужно побольше таких команд. И возможно - сделать предустановленные скрипты, запускаемые одной командой и выполняющие какие-то забавные и эффектные действия — народ будет ставить плагин ради них, а разобравшись (кому это нужно и вообще "дано") будет двигаться дальше. Обязательно это подумай, очень не хотелось бы чтобы такая глобальная разработка осталась малоизвестной.
Ну и главное - нужна максимальная информация на русском и на английском языках.
​
 
Вот эти команды — это правильно. Что бы плагин был более популярный, нужно побольше таких команд. И возможно - сделать предустановленные скрипты, запускаемые одной командой и выполняющие какие-то забавные и эффектные действия — народ будет ставить плагин ради них, а разобравшись (кому это нужно и вообще "дано") будет двигаться дальше. Обязательно это подумай, очень не хотелось бы чтобы такая глобальная разработка осталась малоизвестной.
​

Задумка у меня даже такая:
/plugins/VarScript/scheduler/ будет содержать задачи в виде yml файлов.
/plugins/VarScript/script/[language]/ тут будут скрипты на каком-либо языке.
/plugins/VarScript/lib/[language]/ тут пользовательские библиотеки (в основном jar файлы)

Так вот: чтобы исполнить какой-либо красивый трюк, нужно написать
/> параметры... *имяфайла
считается функция из файла /plugins/VarScript/script/vs/имяфайла.vs и запустится с переданными параметрами. Таким же образом из одного файла можно вызывать другой.

Создавать задачи чуть труднее, однако тоже можно научиться.

Достаточно всего-лишь скопировать нужные файлы в эти директории - и все настроено!
Для планировщика потребуется /scheduler reload
Для библиотек - перезагрузка всего плагина

Еще у меня в планах сотворить репозиторий скриптов, библиотек, вики на varscript.ru

... Ну и главное - нужна максимальная информация на русском и на английском языках.
​
Эх... конечно же самое главное... но и самое сложное(((
Я сразу добавляю описание к каждой команде на английском, сделал возможность поиск по ключевым словам. Но этого не достаточно
Если кому интересно, выкладываю тут прототип (просто побаловаться)
VarScriptTest 0.5.0.A
https://docs.google.com/file/d/0B50fBoyxANzsbHJhQ0dwR0lSem8/edit?usp=sharing

Инструкция:
ставим плагин на тестовый сервер, начинаем баловаться :D
справку по командам не делал, будет позже.

Основные команды:
  • PRINT - вывод на экран
  • ME - ты
  • "блабла" - строка с escape-форматированием; & заменяется на цвет; \& - экранирование символа &
  • DUP SWAP DROP ROT - как в предыдущих версиях
  • ## - комментарий до конца строки
Теперь самое интересное:
  • %x - запись в глобальную переменную
  • %%x - определение локальной переменной и запись в нее
  • @x - взять значение переменной
Предопределенные переменные (локальные на каждую программу): @Me @Location @Caller
  • Function{...} - создание функции.
Пример: Add500{500 +} %%add500## создаст функцию с именем Add500 и запишет в перем add500
  • %Function{...} - создание локальной функции.
%fun{...} почти аналогично записи fun{...} %%fun
  • RUN - запуск функции. Пример: 70 @add500 RUN PRINT ## выведет 570
  • THIS - текущий объект (а-ля javascript)
Объекты у нас являются Fieldable, т.е. содержат поля. об этом чуть ниже
  • OBJECT - создать новый объект (пустой). Пример: OBJECT %%object
  • .%поле - записать в поле объекта. (можно писать слитно с предыдущим операндом не-числом)
Пример: 10 @object.%value## аналогично javascript: object.value=10
(можно писать слитно с предыдущим операндом не-числом)
  • .поле - прочитать поле объекта. Пример: @object.value
  • NEW - запустить функцию-конструктор
Вот пример:
%Pet{ THIS.%age THIS.%name } ## это функция-конструктор
"MyLittlePony" 4 @Pet NEW %%mypet ## создали объект и записали в перем mypet
@mypet.name PRINT ## выведет MyLittlePony
@mypet.age PRINT ## выведет 4
  • @@конструктор - аналогично @конструктор NEW. т.е. @@Pet вместо @Pet NEW
  • :поле - взять поле-функцию и применить ее к объекту.
@someObject:execute Аналогия в JS someObject.execute()
И самое интересное:
При поиске полей объекта, если он не является Fieldable, то его поля и методы ищутся на основе рефлексий. Т.е. мы можем использовать:
/> ME:getHealth PRINT
/> 15 ME:setHealth
Если в рефлексиях нашлось два метода с одинаковым названием, мы можем выбрать:
/> ME:teleport/0
/> ME:teleport/1
/> ME:teleport/2
Вроде бы всё. Прототип тестирую на 1.6.2
Забыл еще упомянуть:
Замыкания, наследование, все в силе!
Чтобы получить прототип функции, юзаем @function.prototype
Чтобы взять конструктор: @object.constructor
UPD:
идеально подходит notepad++ с подсветкой синтаксиса Perl
Вот еще шпаргалка по синтаксису:
doggy.png
 
VarScriptTest 0.5.0.B
Добавлено:
  • Создание потоков, управление ими
  • Команды WAIT, TICKS, REGISTER, REGISTERPRIORITY, RETURN, STOP, END, FINISH, SLEEP, WAKEUP, команды для компиляции кода из файла и др.
Как со всем этим обращаться:

WAIT
Обычная команда, чтобы подождать сколько-то секунд.​
Пример:​
"Now" PRINT​
10.5 WAIT​
"10.5 sec later" PRINT​
Код, который исполняется после этой команды, работает асинхронно, т.е. вполне возможен ConcurrentModificationException. Зато не так страшно загнать программу в бесконечный цикл.​

TICKS
Аналогично предыдущему, но ждет сколько-то игровых тиков.​
После этой команды дальнейшее исполнение происходит в главном потоке. Можно не бояться за ConcurrentModification.​

RETURN
Завершить функцию.​

STOP
Завершить указанный поток.​
Пример:​
@someThread STOP​

THREAD
Положить в стек текущий поток​
PS: команды​
THREAD STOP​
не остановят текущий поток, а только пометят его как завершенный. Исполнение дойдет до конца или до следующего WAIT, TICKS. Чтобы избежать этого - см. команду ниже.​

FINISH
Остановить текущий поток. Исполнение прекращается неменденно​

END
Остановить текущую программу. Останавливаются все потоки, программа считается завершенной​
​
START
Запустить функцию в новом потоке.​
Пример:​
{ 1 WAIT "This is new thread" PRINT } START %%subThread​
Команда принимает из стека функцию, а кладет в него созданный поток.​

SLEEP
Поставить поток на паузу.​
​
WAKEUP
Продолжить тот поток, который стоит на паузе. Сложный пример:​
%Func1{ ## создаем функцию Func1​
5 WAIT ## которая подождет 5 секунд​
@mainThread WAKEUP ## и завершит главный поток​
## на этом моменте завершится поток subThread​
}​
THREAD %%mainThread ## записываем главный поток в переменную​
@Func1 START %%subThread ## запуск Func1 в новом потоке​
"Let's sleep" PRINT ## [varscript] Let's sleep​
SLEEP ## ставим главный поток на паузу​
"awaken" PRINT ## [varscript] awaken​
​

REGISTER
Регистрирует новый обработчик события​
Вход: функция, тип события.​
Выход: триггер​
Пример:​
%Listener{ ## создаем функцию-обработчик события​
## подменяем сообщение на капс​
@Evеnt:getMessage:toUpperCase @Evеnt:setMessage ​
}​
@Listener "PlayerChatEvent" REGISTER %%trigger ## регистрируем событие​
"CAPS IN CHAT!!!" PRINT ## [varscript] CAPS IN CHAT!!!​
30 WAIT ## ждем 30 секунд​
@trigger:unregister ## отключаем триггер события​
"Just kidding =)" PRINT ## [varscript] Just kidding =)​
В примере выше @Evеnt написано с ошибкой (специально)​
тип события указывается в виде текста​
либо полное название класса события "org.bukkit.event.player.PlayerChatEvent"​
либо сокращенное "PlayerChatEvent", "PlayerChat" - работает только для стандартных событий.​

REGISTERPRIORITY
аналогично предыдущему,​
Вход: функция, тип события, приоритет​
приоритет можно указать числом или текстом "NORMAL", "HIGH" и т.д.​

Загрузка функции из файла
Команда для считывания функции из файла: @*имяфайла​
Чтобы считать и запустить: *имяфайла​
Файлы располагаются в директории плагина /scripts/%язык%/​
Сначала ищется файл среди /scripts/vsbin/имяфайла.bin​
если не найден, то /scripts/vs/имяфайла.vs​
Пример:​
файл /scripts/vs/SetFullHp.vs​
TOENTITY %%e​
@e:getMaxHealth @e:setHealth​
Команды:​
/> ME *SetFullHp​
/> "PlayerName" *SetFullHp​
Упс, команда TOENTITY не работает :p​

Рабочий Пример:
ставим и запускаем плагин​
пишем в чат /> *DamageInfo​
бьем кого-нибудь​
На протяжении 10 секунд в чат будет отображаться информация о нанесенном уроне.​

UPD:
Обратиться к другим плагинам можно по имени как к переменной.
Например: @WorldEdit
А дальше - делаем что хотим.
 
Jampire ага, ты абсолютно прав.
я создал свой varscript с наследованием и замыканиями.

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

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

Найти подходящий плагин можно не всегда, а писать новый - долго и ресурсоемко.
На варскрипте каждая из задач выполняется в несколько строчек.
 
я создал свой varscript с наследованием и замыканиями.

в подпись тебе нужно запихнуть :D

Добиваюсь того, чтобы у Админов была возможность быстро создать сценарий игры, или же взять готовый и отредактировать под себя.
Похвально, но 90% админов не знают как настроить конфиг плагина)



Но все-же идея плагина просто незаменимая.
 
Новые возможности VarScript

я максимально интегрировал VarScript с Java при помощи рефлексий.

команда REFLECT - создает оболочку с доступом к объекту.
Эта оболочка имеет доступ:
- ко всем полям (в т.ч. статичным)
- ко всем методам (создается вспомогательный объект ReflectRunnable)
Reflect создается автоматически при доступе к полям не-варскриптового объекта

команда CLASS - создает оболочку с доступом к классу (в т.ч. enum)
Она имеет доступ:
- к конструктору (в зависимости от аргумента)
- ко всем статичным полям
- ко всем статичным методам

Примеры использования:

/> ## записываем в переменнуюColor оболочку класса ChatColor
/> "org.bukkit.ChatColor" CLASS %Color
/> @Color.RED "красный текст" S+ PRINT
/> "e" @Color:getByChar "а тут желтый" S+ PRINT
read2.png
/> ## записываем в переменную ItemStack оболочку класса ItemStack
/> "org.*********ventory.ItemStack" CLASS %Item
/> 7 @Item NEW PRINT
read3.png
Теперь на варскрипте можно сделать почти всё.

Например, можно вывести в чат содержимое страницы по ссылке:
Код:
"java.net.URL/2" CLASS %%URLC
"org.apache.commons.io.IOUtils" CLASS %%IOUtils
"http://dpohvar.ru/hello.htm" @URLC NEW %%myurl
@myurl:openConnection @IOUtils:toByteArray %%bytes
"READ: " @bytes S+ PRINT
read.png
 
в подпись тебе нужно запихнуть :D


Похвально, но 90% админов не знают как настроить конфиг плагина)



Но все-же идея плагина просто незаменимая.

А еще столько же админов не разберутся с VarScript с теми же базами. xD.
 
VarScript 0.5.2
Готов планировщик!
позже будет описание.
Столкнулся с проблемами на этапе компиляции, поэтому оставляю варскрипт таким, какой он сейчас есть.
Он полностью работоспособен благодаря рефлексиям и рабочему уже планировщику
/me ушел читать книгу красного дракона
UPD:
Надо бороться с перфекционизмом! Доделываю этот VS. Иначе он никогда не выйдет в свет...
 
Может ли VarScript сделать так что-бы при 1 заходе на сервер игрок писал определённую команду в чат, если может то выложите скрипт.
 
Может ли VarScript сделать так что-бы при 1 заходе на сервер игрок писал определённую команду в чат, если может то выложите скрипт.
Запросто!
.\plugins\VarScript\tasks\hello.yml

enabled: true
events:
- BUKKIT PlayerJoinEvent
actions:
- VARSCRIPT @Player:hasPlayedBefore/0 !IF @Player "Всем привет! Я новичок" SAY THEN
 
Надо ещё blindness периодически добавлять для усиления эффекта :)
 
Надо ещё blindness периодически добавлять для усиления эффекта :)

Эффект мерцания сделан именно с помощью него. Дается эффект на 23 тика.
Если ослепить надолго - игрок не увидит всех глюков)

Идет подготовка скрипта HellJump ;)
Тестируем быстродействие.
Задача скрипта - в радиусе 30 блоков найти все свободные платформы размером 2x2
Скорость работы каждой операции пишется в миллисекундах.
Модули
Модули в варскрипте - это фактически объекты - синглтоны, они загружаются вместе с плагином.
Доступ к модулям осуществляется как к обычным переменным.
Область видимости модулей - runtime (то есть везде)

Вот один из примеров модуля:
файл ./plugins/VarScript/scripts/vs/modules/Select.vs [pastebin] (с комментами)

Этот модуль позволяет положить в стек объект, который мы выделим мышкой.
/> @Select:block 1 EXPLODE - взорвет блок, который выберем.
/> @Select:entity BOLT - ударит молнией моба, на которого нажмем.
Есть короткие алиасы:
@Select:b вместо @Select:block и @Select:e вместо @Select:entity
или для совсем ленивых:
/> sb 1 EXPLODE
/> se BOLT

По умолчанию на выбор дается 10 секунд. Если ничего не выбрано - результат NULL
Узнать, сколько времени дается на выбор:
/> @Select:getTimeout PRINT
установить (пять с половиной секунд)
/> 5.5 @Select:setTimeout
 
Назад
Верх