1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Стартап Пишем плагин на Groovy

Тема в разделе "Разработка плагинов для новичков", создана пользователем DPOH-VAR, 15 авг 2014.

  1. Автор темы
    DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Добрый день!

    Я покажу, как можно написать свой плагин на Groovy.
    Необходимо:
    - Установленная IntelliJ IDEA не ниже 11й версии
    - bukkit плагин GroovyLoader (cкачать с репозитория)
    - Умение писать плагины на java
    - Желание изучить / использовать язык groovy

    Теория:

    IntelliJ IDEA лучше всех подходит для groovy.
    Можете использовать любую другую IDE на свое усмотрение.

    Плагин GroovyLoader необходим для того, чтобы bukkit смог загрузить классы плагина, которые используют groovy. Он скачивает (если необходимо) все библиотеки groovy и подключает к своему загрузчику классов.
    Ваш плагин на groovy должен иметь жесткую зависимость от GroovyLoader, иначе он не сможет загрузиться.

    Язык groovy очень похож на java, но при этом вносит большое число синтаксического сахара.
    В результате этого количество кода уменьшается в несколько раз, а разработка становится проще.
    Подробнее тут: http://groovy.codehaus.org/
    Из недостатков применения groovy нужно отметить, что становится проще допустить синтаксические ошибки.
    Тут спасает только подсветка синтаксиса IDE и всплывающие подсказки.

    Практика:

    1) Создайте новый проект на Groovy
    02-create-groovy.png
    * Скачать JDK можно тут: http://www.oracle.com/technetwork/java/javase/downloads/index.html
    * Скачать Groovy тут: http://groovy.codehaus.org/Download **
    ** Устанавливать groovy целиком (GROOVY_HOME, PATH и т.д.) не обязательно, если не хотите его использовать в других целях. Достаточно только наличия библиотек в проекте.

    2) Добавьте в список зависимостей библиотеку bukkit
    03-libraries.png
    Добавить зависимости можно в настройках структуры проекта (Ctrl+Alt+Shift+S) или FIle -> Project structure...
    Скачать библиотеку можно отсюда: http://dl.bukkit.org/ или http://repo.bukkit.org/

    3) Создайте файл plugin.yml
    ПКМ на директории -> New -> File
    Желательно, чтобы файл располагался в директории ресурсов

    4) заполните plugin.yml
    Код:
    name: GroovyPlugin
    version: 1.0
    description: Плагин для тестирования груви
    author: DPOH-VAR
    main: ru.dpohvar.groovyplugin.Plugin
    depend: [GroovyLoader]
    
    commands:
      test-plugin:
        description: Тестирование работы плагина
    Обязательно нужно указать зависимость от плагина GroovyLoader :)6:0)

    5) Создайте главный класс плагина
    ПКМ на пакете -> New -> Groovy class

    После этого структура проекта будет выглядеть примерно так:
    04-project-structure.png

    Пример плагина:
    Код:
    package ru.dpohvar.groovyplugin
    
    import org.bukkit.plugin.java.JavaPlugin
    import static org.bukkit.ChatColor.*
    
    class Plugin extends JavaPlugin {
    
        void 'onEnable' () {
            getCommand('test-plugin').executor = { sender, cmd, alias, args ->
                sender.sendMessage "${AQUA}Плагин ${UNDERLINE}работает!"
                return true
            }
        }
    }
    6) Настройте экспорт плагина
    как на картинке ниже:
    05-artifact.png
    В качестве Output directory можно указать папку plugins локального сервера bukkit.
    Архив плагина должен содержать plugin compile output а также plugin.yml
    plugin.yml добавляется в архив вручную (значок [+] -> File )

    7) Соберите проект
    Собрать проект можно с помощью комбинации клавиш Ctrl + F9
    jar архив должен собраться автоматически вместе с проектом

    8) Запустите сервер bukkit
    Теперь плагин на Groovy вполне рабочий.
    06-console.png
     
    smilesdc нравится это.
  2. konfyciu98

    konfyciu98 Старожил Пользователь

    Баллы:
    123
    Skype:
    wwwixelsor9
    Имя в Minecraft:
    konfyciu
    Разработка идет быстрее за счет более легкого синтаксиса? Объясните мне этот момент, пожалуйста! Лично я не вижу ничего сложного в синтаксисе Java.
     
  3. Автор темы
    DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Синтаксис Java не сложный, но громоздкий.
    Java не является функциональным языком (Java 8 еще не у всех), поэтому некоторые действия приходится решать примитивно (преобразование массива, свертка, фильтр, карринг и т.д.).

    Вот примеры на груви:
    Код:
    def blocks = region.getBlocks()
    // найти и заменить все блоки воды на лаву
    blocks.findAll {it.type == WATER} .each {it.type = LAVA}
    Код:
    //построчный список игроков в формате: Имя (жизни)
    def message = Bukkit.onlinePlayers
        .collect {"$it.name (${it.health as int})"} 
        .join ('\n')
    А еще из вкусностей у груви есть перегрузка операторов (спрашивали уже).
    К тому же, существующим классам можно добавить новые методы с помощью метаклассов и расширений.
     
  4. fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    @DPOH-VAR
    Т.е. получается, что можно взять, скажем класс Creeper добавить ему дополнительные методы, а какие-то существующие переопределить?!

    Покажи примером, пожалуйста.

    Вообще супер!
     
  5. Автор темы
    DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Запросто!
    Например, добавим ему метод superExplosion(float power)

    Вариант 1, с метаклассами:
    Код:
    Creeper.metaClass.superExplosion = { float power ->
        def loc = (delegate as Creeper).location
        loc.world.createExplosion(loc.x, loc.y, loc.z, power)
    }
    Можно делать это динамически, в любой момент добавить новый метод и в любой момент его изменить.
    Можно и переопределить методы. но тогда другие плагины, использующие груви, тоже начнут его вызывать. Поэтому не рекомендую так делать. Оригинальный метод останется доступен только через рефлексии (или java-код).
    Недостаток в том, что IDE не будет подсвечивать синтаксис.

    Вариант 2, с модулем расширения:
    Нужно создать произвольный класс с одним методом:
    Код:
    static superExplosion(Creeper creeper, float power){
        def loc = creeper.location
        loc.world.createExplosion(loc.x, loc.y, loc.z, power)
    }
    А затем его специальным образом зарегистрировать
    http://groovy.codehaus.org/Creating an extension module
    Подсветка синтаксиса работает, IDE подсказывает эти методы.
    Но переопределить оригинальный метод таким способом нельзя.

    Bukkit не подгружает их своим загрузчиком (т.е. плевать он хотел на META-INF)
    Можно загрузить любую другую jar с расширениями - тогда все отлично будет работать.
    Хотелось бы хранить META-INF в самом плагине... над этим бьюсь.
    И, собственно, добился.
    Чтобы второй метод работал, это нужно вставить в главный класс плагина.
    Код:
    static {
        Map<CachedClass, List<MetaMethod>> map = [:]
        def classLoader = Plugin.classLoader
        def resources = classLoader.getResources(MetaClassRegistryImpl.MODULE_META_INF_FILE)
        resources.each { url ->
            def properties = new Properties()
            url.withInputStream { input ->
                properties.load input
                def registry = GroovySystem.metaClassRegistry as MetaClassRegistryImpl
                registry.registerExtensionModuleFromProperties properties, classLoader, map
            }
        }
        map.each { cls, methods -> cls.setNewMopMethods methods }
    }
    PS: спасибо гуглу и разработчикам grails

    Вариант 3: с помощью примесей
    Очень похож на первый способ, но сначала составляется расширяющий класс, а затем "вливается" в оригинальный. У него куча недостатков, поэтому даже не буду говорить о нем подробнее.
    Вообще, в документации описано много способов расширения языка.
    http://groovy.codehaus.org/User Guide в разделе Dynamic Groovy
     
    Последнее редактирование: 16 авг 2014
    smilesdc нравится это.
  6. konfyciu98

    konfyciu98 Старожил Пользователь

    Баллы:
    123
    Skype:
    wwwixelsor9
    Имя в Minecraft:
    konfyciu
    Молодец!
     
  7. CraftCoder

    CraftCoder Старожил Пользователь

    Баллы:
    108
    Имя в Minecraft:
    CraftCoderr
    :good:
     
  8. ql_Nik_lp

    ql_Nik_lp Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    q-nik-p
    Имя в Minecraft:
    ql_Nik_lp
    Aw...
    Нравится мне такое, но больше хотелось бы увидеть в чистой Java
    А что вы там про 8 говорили?

    За тему большое спасибо.
    И если не секрет, то что за IDE? Intellij Idea?
    Я так понял это Linux
     
  9. Автор темы
    DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Java 8 поддерживает лямбды. Это нечто похожее на замыкания в груви.
    Лямбда выражения - это очень модно. EcmaScript 6, Java 8, Swift ... скоро они будут везде. Но это совсем другая история.
    Чего нового есть в java 8: http://habrahabr.ru/post/216431/
    Но я не советую переходить на нее. Рано. Еще не у всех фреймворков/плагинов есть поддержка.
    Например, MCPC+ на Java 8 не может грузить многие Bukkit плагины. Grails вообще отказывается работать. Таких примеров множество.
    Intellij Idea 13.1.4 с темой Darcula, Ubuntu 14.04. Дело вкуса. Ничто не мешает скачать и установить IntelliJ Idea на Windows.
     
  10. ql_Nik_lp

    ql_Nik_lp Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    q-nik-p
    Имя в Minecraft:
    ql_Nik_lp
    Спасибо за подробный ответ
    Возможно ли использовать Груви вместе с Java в одном проекте? (Что-то по типу php в html)
     
  11. Автор темы
    DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Да.
    Исходники желательно разнести по разным директориям в зависимости от языка. gradle и maven, например, предлагают сделать так:
    src/main/java/ - для java
    src/main/groovy/ - для groovy
    src/main/resources/ - для ресурсов

    Трудности возникнут при сборке проекта с помощью maven (решается плагином, в 20 строк xml)
    Если собирать с помощью gradle, нужно всего лишь добавить строчку:
    apply plugin: 'groovy'

    По типу php в html не получится: внутри .java файла нельзя встраивать код на groovy.

    PS:
    GroovyShell позволяет динамически подгружать скрипты на groovy и исполнять их.
    В него можно передать набор переменных, которые будут в скоупе скрипта.
    У него есть куча настроек (предопределенный импорт, права доступа, режим песочницы, и т.д.)
    Но это уже идея для новой версии VarScript ;-)
     
  12. ql_Nik_lp

    ql_Nik_lp Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    q-nik-p
    Имя в Minecraft:
    ql_Nik_lp
    Где кнопка лайк на этом форуме? :rolleyes:
     
  13. Автор темы
    DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Небольшой хинт для тех, кто использует мавен:
    Выкладываю примеры помки и plugin.yml

    ./pom.xml
    Код:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <!-- В разделе прапертей указываем некоторые данные -->
        <properties>
            <plugin-version>1.2</plugin-version> <!-- версия плагина -->
            <plugin-description>My simple plugin</plugin-description> <!-- описание плагина -->
            <plugin-author>DPOH-VAR</plugin-author> <!-- автор плагина -->
            <plugin-website>http://varscript.ru/artifactory/simple/release/ru/dpohvar/varscript/BukkitExt/</plugin-website>
            <java-version>1.7</java-version><!-- версия java -->
            <groovy-version>2.2.2</groovy-version><!-- версия groovy -->
            <bukkit-version>1.7.9-R0.2-SNAPSHOT</bukkit-version><!-- версия bukkit -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- кодировка файлов -->
        </properties>
    
        <!-- Ваши groupId, artifactId -->
        <groupId>ru.dpohvar.varscript</groupId>
        <artifactId>BukkitExt</artifactId>
        <version>${plugin-version}</version>
        <packaging>jar</packaging>
    
        <!-- Нам необходим репозиторий bukkit -->
        <repositories>
            <repository>
                <id>bukkit-repo</id>
                <url>http://repo.bukkit.org/content/groups/public/</url>
            </repository>
        </repositories>
    
        <!-- список зависимостей -->
        <dependencies>
            <dependency>
                <groupId>org.codehaus.groovy</groupId>
                <artifactId>groovy-all</artifactId>
                <version>${groovy-version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.bukkit</groupId>
                <artifactId>bukkit</artifactId>
                <version>${bukkit-version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    
        <build>
    
            <finalName>${artifactId}</finalName>
    
            <!-- настройка фильтра для ресурсов -->
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
    
            <plugins>
    
                <!-- плагин для компиляции java -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>${java-version}</source>
                        <target>${java-version}</target>
                    </configuration>
                </plugin>
    
                <!-- плагин компиляции groovy -->
                <plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>compile</id>
                            <phase>compile</phase>
                            <configuration>
                                <tasks>
                                    <mkdir dir="${basedir}/src/main/groovy"/>
                                    <taskdef name="groovyc"
                                             classname="org.codehaus.groovy.ant.Groovyc">
                                        <classpath refid="maven.compile.classpath"/>
                                    </taskdef>
                                    <mkdir dir="${project.build.outputDirectory}"/>
                                    <groovyc destdir="${project.build.outputDirectory}"
                                             srcdir="${basedir}/src/main/groovy/" listfiles="true">
                                        <classpath refid="maven.compile.classpath"/>
                                    </groovyc>
                                </tasks>
                            </configuration>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>test-compile</id>
                            <phase>test-compile</phase>
                            <configuration>
                                <tasks>
                                    <mkdir dir="${basedir}/src/test/groovy"/>
                                    <taskdef name="groovyc"
                                             classname="org.codehaus.groovy.ant.Groovyc">
                                        <classpath refid="maven.test.classpath"/>
                                    </taskdef>
                                    <mkdir dir="${project.build.testOutputDirectory}"/>
                                    <groovyc destdir="${project.build.testOutputDirectory}"
                                             srcdir="${basedir}/src/test/groovy/" listfiles="true">
                                        <classpath refid="maven.test.classpath"/>
                                    </groovyc>
                                </tasks>
                            </configuration>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
    
                    </executions>
                </plugin>
    
                <!-- плагин для составления groovydoc -->
                <plugin>
                    <groupId>com.bluetrainsoftware.maven</groupId>
                    <artifactId>groovydoc-maven-plugin</artifactId>
                    <version>1.2</version>
                    <executions>
                        <execution>
                            <id>site</id>
                            <phase>site</phase>
                            <goals>
                                <goal>generate</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <additionalSourceDirectories>
                            <additionalSourceDirectory>src/main/groovy</additionalSourceDirectory>
                        </additionalSourceDirectories>
                    </configuration>
                </plugin>
    
            </plugins>
        </build>
    
    
    </project>
    ./src/main/resources/plugin.yml
    Код:
    name: ${artifactId}
    version: ${version}
    description: ${plugin-description}
    author: ${plugin-author}
    website: ${plugin-website}
    database: false
    main: ru.dpohvar.package.Plugin
    Теперь plugin.yml будет зависеть от настроек прапертей в pom.xml.
    Чтобы собрать плагин - достаточно выполнить mvn package, при этом в архив соберутся исходники ./src/main/java, ./src/main/groovy а также ресурсы /src/main/resources после обработки паттерна ${}
    Для составления документации выполняем mvn site, но groovydoc иногда ведет себя непредсказуемо.
     
    Последнее редактирование: 20 авг 2014
  14. smilesdc

    smilesdc Няша Модератор

    Баллы:
    153
    Имя в Minecraft:
    smilesdc
    Есть еще язык Scala.
    Очень сильно упрощает коддинг.
     
  15. Автор темы
    DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    раз - http://dev.bukkit.org/bukkit-plugins/scala-loader/
    два - http://dev.bukkit.org/bukkit-plugins/scala-plugin-api/
    Уже давно есть загрузчики для скалы, может ими кто-то и пользуется.
    Лично мне этот язык не приглянулся вообще никак.
    Возможно скоро сделаю плагин, работающий с Ivy
    чтобы скачивать и загрузать зависимости для остальных плагинов до их загрузки.
    Хочу нечто похожее на Groovy Grape
    плагин Hedera http://www.rubukkit.org/threads/79466/
    Позволяет добавить в зависимости что угодно.
    В принципе может заменить GroovyLoader, а также любые другие загрузчики, в том числе и Scala
     

Поделиться этой страницей