Туториал “От а до я” Создания плагина Minecraft

Для Майнкрафт: 1.5.2, 1.6.4, 1.7.2, 1.7.10

Мод CJB API сам по себе ничего не делает в Майнкрафт, он необходим для работы всех других модов, которые основаны на этом АПИ. Установив его просто так вы никаких изменений не заметите, а вот если еще доустановить его мод, то нажав в игре на кнопку «i» перед вами откроется меню настроек.

Все CJB моды.

image

Установка

  1. Во первых устанавливаем Forge, без него никак.
  2. Качаем этот вот мод.
  3. Переходим в папку %appdata%.minecraftmods и переносим туда скачанный файл.
  4. Заходим в игру или устанавливаем другой мод под это api.

Скачать:

Ссылки: image Проверено Dr.Web: без вирусов

Программы / Утилиты / Разное / API Guide

 
Разработчик: The KPD-Team (cм. другие программы)
Версия: 3.7.854
Сайт: API Guide
Лицензия: Бесплатная
Скачать API Guide

Обзор API Guide (автоматический перевод)

API-Guide является API-база-данных со всеми API-functions API-списка. API-Guide имеет более чем 900 функций, все задокументированные, и объяснил с примером. Несколько функций также имеют dotNET эквивалентный и dotNET пример кода. Используя API-Guide довольно просто. Примеры The могут быть, копируют/вставляют в Visual Basic, и большинство из них может работать без потребности редактирования источника сначала. Однако редактирование источника иногда необходимо, прежде чем Вы сможете выполнить программу. Обычно, всегда объясняется в комментариях, что должно быть изменено.

 Самые популярные программы категории Утилиты / Разное

Nero 9 Lite Бесплатная
GoToAssist Corporate Платная
Citrix Receiver Бесплатная
Pokki Download Helper Бесплатная
Syncios Платная
DriverDoc Платная
Autodesk Network License Manager Бесплатная

Другие программы компании The KPD-Team

API-Guide

©

Чит-мод для обновленной версии The Forest 1.0.5 ModAPI 1.0.5

Скопировать и распаковать в корневую папку с игрой

Потом запускаем в папке с читом exe файл после чего выставляем слева на панели нужные вам галочки и нажимаем StartGame

Чит меню F1

Интерактивная карта M “отображаются аборигены находящиеся рядом, питьевые источники и т.д.”

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

Чит-моды

Используя Express и Node.js, мы можем реализовать полноценный API в стиле REST для взаимодействия с пользователем. Архитектура REST предполагает применение следующих методов или типов запросов HTTP для взаимодействия с сервером:

  • GET
  • POST
  • PUT
  • DELETE

Зачастую REST-стиль особенно удобен при создании всякого рода Single Page Application, которые нередко используют специальные javascript-фреймворки типа Angular, React или Knockout.

Рассмотрим, как создать свой API. Для нового проекта создадим новую папку, которая пусть будет называться webapp. Сразу определим в проекте файл package.json:

 {   "name": "webapp",   "version": "1.0.0",   "dependencies": {     "body-parser": "^1.16.0",     "express": "^4.14.0"   } } 

В проекте нам понадобятся express и body-parser для парсинга полученных данных.

Далее перейдем к этому каталогу в командной строке/терминале и для добавления всех нужных пакетов выполним команду:

 npm install 

В данном случае мы создадим экспериментальный проект, который будет хранить данные в файле json и который призван просто показать создание API в Node.js в стиле REST. А пока добавим в папку проекта новый файл users.json со следующим содержанием:

 [   {     "id": 1,     "name": "Tom",     "age": 24   },   {     "id": 2,     "name": "Bob",     "age": 27   },   {     "id": 3,     "name": "Alice",     "age": "23"   } ] 

Для чтения и записи в этот файл мы будем использовать встроенный модуль fs. Для обработки запросов определим в проекте следующий файл app.js:

 var express = require('express') var bodyParser = require('body-parser') var fs = require('fs')  var app = express() var jsonParser = bodyParser.json()  app.use(express.static(__dirname + '/public')) // получение списка данных app.get('/api/users', function (req, res) {   var content = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(content)   res.send(users) }) // получение одного пользователя по id app.get('/api/users/:id', function (req, res) {   var id = req.params.id // получаем id   var content = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(content)   var user = null   // находим в массиве пользователя по id   for (var i = 0; i <</span> users.length; i++) {     if (users[i].id == id) {       user = users[i]       break     }   }   // отправляем пользователя   if (user) {     res.send(user)   } else {     res.status(404).send()   } }) // получение отправленных данных app.post('/api/users', jsonParser, function (req, res) {   if (!req.body) return res.sendStatus(400)    var userName = req.body.name   var userAge = req.body.age   var user = { name: userName, age: userAge }    var data = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(data)    // находим максимальный id   var id = Math.max.apply(     Math,     users.map(function (o) {       return o.id     })   )   // увеличиваем его на единицу   user.id = id + 1   // добавляем пользователя в массив   users.push(user)   var data = JSON.stringify(users)   // перезаписываем файл с новыми данными   fs.writeFileSync('users.json', data)   res.send(user) }) // удаление пользователя по id app.delete('/api/users/:id', function (req, res) {   var id = req.params.id   var data = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(data)   var index = -1   // находим индекс пользователя в массиве   for (var i = 0; i <</span> users.length; i++) {     if (users[i].id == id) {       index = i       break     }   }   if (index > -1) {     // удаляем пользователя из массива по индексу     var user = users.splice(index, 1)[0]     var data = JSON.stringify(users)     fs.writeFileSync('users.json', data)     // отправляем удаленного пользователя     res.send(user)   } else {     res.status(404).send()   } }) // изменение пользователя app.put('/api/users', jsonParser, function (req, res) {   if (!req.body) return res.sendStatus(400)    var userId = req.body.id   var userName = req.body.name   var userAge = req.body.age    var data = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(data)   var user   for (var i = 0; i <</span> users.length; i++) {     if (users[i].id == userId) {       user = users[i]       break     }   }   // изменяем данные у пользователя   if (user) {     user.age = userAge     user.name = userName     var data = JSON.stringify(users)     fs.writeFileSync('users.json', data)     res.send(user)   } else {     res.status(404).send(user)   } })  app.listen(3000, function () {   console.log('Сервер ожидает подключения...') }) 

Для обработки запросов определено пять методов для каждого типа запросов: app.get()/app.post()/app.delete()/app.put()

Когда приложение получает запрос типа GET по адресу api/users, то срабатывает следующий метод:

 app.get('/api/users', function (req, res) {   var content = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(content)   res.send(users) }) 

В качестве результата обработки мы должны отправить массив пользователей, которые считываем из файла. Для упрощения кода приложения в рамках данного экспериментального проекта для чтения/записи файла применяются синхронные методы fs.readFileSync()/fs.writeFileSync(). Но в реальности, как правило, работа с данными будет идти через базу данных, а далее мы все это рассмотрим на примере MongoDB.

И чтобы получить данные из файла с помощью метода fs.readFileSync() считываем данные в строку, которую парсим в массив объектов с помощью функции JSON.parse(). И в конце полученные данные отправляем клиенту методом res.send().

Аналогично работает другой метод app.get(), который срабатывает, когда в адресе указан id пользователя:

 app.get('/api/users/:id', function (req, res) {   var id = req.params.id // получаем id   var content = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(content)   var user = null   // находим в массиве пользователя по id   for (var i = 0; i <</span> users.length; i++) {     if (users[i].id == id) {       user = users[i]       break     }   }   // отправляем пользователя   if (user) {     res.send(user)   } else {     res.status(404).send()   } }) 

Единственное, что в этом случае нам надо найти нужного пользователя по id в массиве, а если он не был найден, возвратить статусный код 404: res.status(404).send().

При получении запроса методом POST нам надо применить парсер jsonParser для извлечения данных из запроса:

 // получение отправленных данных app.post('/api/users', jsonParser, function (req, res) {   if (!req.body) return res.sendStatus(400)    var userName = req.body.name   var userAge = req.body.age   var user = { name: userName, age: userAge }    var data = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(data)    // находим максимальный id   var id = Math.max.apply(     Math,     users.map(function (o) {       return o.id     })   )   // увеличиваем его на единицу   user.id = id + 1   // добавляем пользователя в массив   users.push(user)   var data = JSON.stringify(users)   // перезаписываем файл с новыми данными   fs.writeFileSync('users.json', data)   res.send(user) }) 

После получения данных нам надо создать новый объект и добавить его в массив объектов. Для этого считываем данные из файла, добавляем в массив новый объект и перезаписываем файл с обновленными данными.

При удалении производим похожие действия, только теперь извлекаем из массива удаляемый объект и опять же перезаписываем файл:

 app.delete('/api/users/:id', function (req, res) {   var id = req.params.id   var data = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(data)   var index = -1   // находим индекс пользователя в массиве   for (var i = 0; i <</span> users.length; i++) {     if (users[i].id == id) {       index = i       break     }   }   if (index > -1) {     // удаляем пользователя из массива по индексу     var user = users.splice(index, 1)[0]     var data = JSON.stringify(users)     fs.writeFileSync('users.json', data)     // отправляем удаленного пользователя     res.send(user)   } else {     res.status(404).send()   } }) 

Если объект не найден, возвращаем статусный код 404.

Если приложению приходит PUT-запрос, то он обрабатывается методом app.put(), в котором с помощью jsonParser получаем измененные данные:

 app.put('/api/users', jsonParser, function (req, res) {   if (!req.body) return res.sendStatus(400)    var userId = req.body.id   var userName = req.body.name   var userAge = req.body.age    var data = fs.readFileSync('users.json', 'utf8')   var users = JSON.parse(data)   var user   for (var i = 0; i <</span> users.length; i++) {     if (users[i].id == userId) {       user = users[i]       break     }   }   if (user) {     user.age = userAge     user.name = userName     var data = JSON.stringify(users)     fs.writeFileSync('users.json', data)     res.send(user)   } else {     res.status(404).send(user)   } }) 

Здесь также для поиска изменяемого объекта считываем данные из файла, находим изменяемого пользователя по id, изменяем у него свойства и сохраняем обновленные данные в файл.

Таким образом, мы определили простейший API. Теперь добавим код клиента. Итак, как установлено в коде, Express для хранения статических файлов использует папку public, поэтому создадим в проекте подобную папку. В этой папке определим новый файл index.html, который будет выполнять роль клиента. В итоге весь проект будет выглядеть следующим образом:

Далее определим в файле index.html следующий код:

 <!DOCTYPE html> <</span>html>   <</span>head>     <</span>meta charset="utf-8" />     <</span>meta name="viewport" content="width=device-width" />     <</span>title>Список пользователей</</span>title>     <</span>link       href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"       rel="stylesheet"     />     <</span>script src="https://code.jquery.com/jquery-2.2.4.min.js"></</span>script>   </</span>head>   <</span>body>     <</span>h2>Список пользователей</</span>h2>     <</span>form name="userForm">       <</span>input type="hidden" name="id" value="0" />       <</span>div class="form-group">         <</span>label for="name">Имя:</</span>label>         <</span>input class="form-control" name="name" />       </</span>div>       <</span>div class="form-group">         <</span>label for="age">Возраст:</</span>label>         <</span>input class="form-control" name="age" />       </</span>div>       <</span>div class="panel-body">         <</span>button           type="submit"           class="btn btn-sm btn-primary"         >           Сохранить         </</span>button>         <</span>a id="reset" class="btn btn-sm btn-primary"           >Сбросить</</span>a         >       </</span>div>     </</span>form>     <</span>table       class="table table-condensed table-striped table-bordered"     >       <</span>thead>         <</span>tr>           <</span>th>Id</</span>th>           <</span>th>Имя</</span>th>           <</span>th>возраст</</span>th>           <</span>th></</span>th>         </</span>tr>       </</span>thead>       <</span>tbody></</span>tbody>     </</span>table>      <</span>script>       // Получение всех пользователей       function GetUsers() {         $.ajax({           url: '/api/users',           type: 'GET',           contentType: 'application/json',           success: function (users) {             var rows = ''             $.each(users, function (index, user) {               // добавляем полученные элементы в таблицу               rows += row(user)             })             $('table tbody').append(rows)           },         })       }       // Получение одного пользователя       function GetUser(id) {         $.ajax({           url: '/api/users/' + id,           type: 'GET',           contentType: 'application/json',           success: function (user) {             var form = document.forms['userForm']             form.elements['id'].value = user.id             form.elements['name'].value = user.name             form.elements['age'].value = user.age           },         })       }       // Добавление пользователя       function CreateUser(userName, userAge) {         $.ajax({           url: 'api/users',           contentType: 'application/json',           method: 'POST',           data: JSON.stringify({             name: userName,             age: userAge,           }),           success: function (user) {             reset()             $('table tbody').append(row(user))           },         })       }       // Изменение пользователя       function EditUser(userId, userName, userAge) {         $.ajax({           url: 'api/users',           contentType: 'application/json',           method: 'PUT',           data: JSON.stringify({             id: userId,             name: userName,             age: userAge,           }),           success: function (user) {             reset()             $(               "tr[data-rowid='" + user.id + "']"             ).replaceWith(row(user))           },         })       }        // сброс формы       function reset() {         var form = document.forms['userForm']         form.reset()         form.elements['id'].value = 0       }        // Удаление пользователя       function DeleteUser(id) {         $.ajax({           url: 'api/users/' + id,           contentType: 'application/json',           method: 'DELETE',           success: function (user) {             console.log(user)             $("tr[data-rowid='" + user.id + "']").remove()           },         })       }       // создание строки для таблицы       var row = function (user) {         return (           " +           user.id +           "'>" +           user.id +           '' +           '' +           user.name +           ' ' +           user.age +           '' +           " +           user.id +           "'>Изменить | " +           " +           user.id +           "'>Удалить"         )       }       // сброс значений формы       $('#reset').click(function (e) {         e.preventDefault()         reset()       })        // отправка формы       $('form').submit(function (e) {         e.preventDefault()         var id = this.elements['id'].value         var name = this.elements['name'].value         var age = this.elements['age'].value         if (id == 0) CreateUser(name, age)         else EditUser(id, name, age)       })        // нажимаем на ссылку Изменить       $('body').on('click', '.editLink', function () {         var id = $(this).data('id')         GetUser(id)       })       // нажимаем на ссылку Удалить       $('body').on('click', '.removeLink', function () {         var id = $(this).data('id')         DeleteUser(id)       })        // загрузка пользователей       GetUsers()     </</span>script>   </</span>body> </</span>html> 

Основная логика здесь заключена в коде javascript. Для упрощения взаимодействия с сервером здесь применяется библиотека jquery. При загрузке страницы в браузере получаем все объекты из БД с помощью функции GetUsers:

 function GetUsers() {   $.ajax({     url: '/api/users',     type: 'GET',     contentType: 'application/json',     success: function (users) {       var rows = ''       $.each(users, function (index, user) {         // добавляем полученные элементы в таблицу         rows += row(user)       })       $('table tbody').append(rows)     },   }) } 

Для добавления строк в таблицу используется функция row(), которая возвращает строку. В этой строке будут определены ссылки для изменения и удаления пользователя.

Ссылка для изменения пользователя с помощью функции GetUser() получает с сервера выделенного пользователя:

 function GetUser(id) {   $.ajax({     url: '/api/users/' + id,     type: 'GET',     contentType: 'application/json',     success: function (user) {       var form = document.forms['userForm']       form.elements['id'].value = user.id       form.elements['name'].value = user.name       form.elements['age'].value = user.age     },   }) } 

И выделенный пользователь добавляется в форму над таблицей. Эта же форма применяется и для добавления объекта. С помощью скрытого поля, которое хранит id пользователя, мы можем узнать, какое действие выполняется – добавление или редактирование. Если id равен , то выполняется функция CreateUser, которая отправляет данные в POST-запросе:

 function CreateUser(userName, userAge) {   $.ajax({     url: 'api/users',     contentType: 'application/json',     method: 'POST',     data: JSON.stringify({       name: userName,       age: userAge,     }),     success: function (user) {       reset()       $('table tbody').append(row(user))     },   }) } 

Если же ранее пользователь был загружен на форму, и в скрытом поле сохранился его id, то выполняется функция EditUser, которая отправляет PUT-запрос:

 function EditUser(userId, userName, userAge) {   $.ajax({     url: 'api/users',     contentType: 'application/json',     method: 'PUT',     data: JSON.stringify({       id: userId,       name: userName,       age: userAge,     }),     success: function (user) {       reset()       $("tr[data-rowid='" + user.id + "']").replaceWith(         row(user)       )     },   }) } 

Запустим приложение, обратимся в браузере по адресу http://localhost:3000 и мы сможем управлять пользователями, которые хранятся в файле json:

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

  • Среда разработки Java-приложений Eclipse;
  • Api Spigot: https://hub.spigotmc.org/nexus/content/groups/public/org/spigotmc/spigot-api/ .
  • Документация по Bukkit API.

Так же понадобятся базовые знания по Java. Если таковых нет, то вот ссылки по “поднятию скила”:

  • Основы Java для начинающих Сайт рассчитан на тех, кто только начинает изучать Java
  • Java (Beginner) Programming Tutorials Видео-туториал по Ява, рассчитанный для новичков(я начинал с него).
  • Справочник по java Я бы назвал это шпаргалкой по яве
  • Java эксперт И пусть вас не пугает название. Здесь можно найти множество примеров решения на те или иные задачи.

Установка и настройка Eclipse Если вы уже знакомы с Eclipse или увас другая IDE, то пропускайте этот раздел. Проблем с установкой эклипса возниктуть не должно: его нужно просто распаковать в любоую папку и запустить. Сразу после этого, эклипс попросит указать, какое рабочее пространство(workspace) сейчас открыть. Это папка, в которой будут сохранятся все созданные проекты и где ее располагать – лично ваше решение. Если вам всеранво, то оставляйте все как есть. Если вдруг захотите изменить рабочее пространстро, то не переживайте: при каждом следующем запуске, эклипс сново спросит вас о рабочем пространстве. Таких пространств можно наделать сколько угодно и каждое может быть настроено по разному, под какие-то определенные цели. К примеру у меня есть 2 рабочих пространства: для написания обычных java-приложений и для написания плагинов под “ведро”. Если вдруг вам надоест это сообщение, там есть галочка «Use this as the default and do not ask again», что позволяет задать workspace по-умолчанию.+ Как только вы определитесь с выбором места и загрузится Eclipse, то мы увидим пригласительную вкладку… которую сразу же закрываем. Она нам ни к чему. Теперь же мы видим рабочее пространство самого эклипса. Из всего этого, нам понадобится только следующие панели: Последние 2 описанные панели можно вообще свернуть, т.к. пользоваться ими будем редко. Рабочее место почти готово. Осталось только поставить еще 2 галочки в настройках. Переходим в меню Window -> Preferences, далее по древу General -> Editor -> Text Editors и выставляем галочку «Show line numbers», чтобы включить отображение нумерации строк. Теперь переходим в General -> Workspace и в группе «Text file encoding» выставляем кодировку UTF-8, самым установив кодировку по-умолчанию. С установкой и настройкой покончено. Теперь поясню, как создавать новый проект для плагина. Это можно сделать одим из 3-х способов:

  • Меню File -> New -> Java Project
  • Кнопка на панели инструментов
  • Правый клик в Package Explorer

Перед нами откроется окно New Java Project. В Project name указываем название нашему проекту Нажимаем Next. В появившемся окне, переходим на вкладку Libraries, нажимаем кнопку Add External JARs и выбираем скаченный Bukkit API Жмем Finish. Слева, в Package Explorer, показался наш проект с папкой src, в которой будут храниться наши исходные коды. Теперь созданим новый класс. Делается это точно так же, как и с Java Project. В окне New Java Class нам понадобятся только следующие графы:

  • Package указывается пакет, в котором будет хранится наш класс. Формат имени должен быть примерно такой: ru.dmitriymx.bukkit.tutorial. Если в двух словах и на пальцах, то пакеты в ява – это пространство имен(namespace) или «виртуальные папки», в которые помещаются классы. Подробнее про это можно прочитать здесь: [1], [2], [3].

Все остальные пункты оставляем как есть и жмем Finish. Вот теперь переходим непосредственно к коду. Пишем простой плагин Как только мы создали новый класс, нашему взору предстает уже готовый пустой шаблон Пока это всего лишь пустой класс, который абсолютно бесполезен в быту. Будем это исправлять. Изменяем вот это на это Эклипс подчеркнет нам JavaPlugin, указывая на ошибку в коде. Если подвести мышь к такому подчеркнутому коду, то откроется окошко с описанием ошибки и способы ее решения. В данном случае нам нужно импортировать класс из Bukkit API, для чего выбираем пункт «Import ‘JavaPlugin’(org.bukkit.plugin.java)» Сразу же замечаем, как над всем нашим кодом вписалась строчка Немного теоретического материала. У плагинов есть 3 основных метода: onEnable(), onDisable() и onLoad(). Первые два отвечают за включение и отключение плагина, а последний срабатывает когда плагин непосредственно подгружается в память сервера. Из этого следует, что onLoad выполняется самым первым, но сам плагин начинает работать только после вызова onEnable со стороны сервера. По выключению или перезагрузки сервера, вызывается метод onDisable. С “точками входа-выхода” разобрались. Давайте теперь напишем что-нибудь более-менее работоспособное. Приведем общий код класса к следующему виду: кому невидна вторая часть: о что мы сейчас написали – готовый плагин. Все что он делает – это пишет в чат о приходе и уходе игрока на сервер. Разбираться в его работе будем по порядку(а как иначе?). Сперва обращу внимание на строку объявления класса. Как видно, к нашему классу добавилось расширение Listener. Не углубляясь в дебри явы, скажу проще: указывая данное расширение, мы тем самым расширяем область применения класса не только как плагина(JavaPlugin), но и как обработчика событий(Listener). А вот как раз в методе onEnable() мы регистрируем наш класс на сервере как обработчик событий(this – это указание «на самого себя», если кто забыл). Далее следует 2 наших обработчика событий onJoin() и onQuit(). Первый отвечает а событие входа игрока на сервер, а второй – за уход. С помощью метода event.getPlayer().sendMessage(), мы можем отправить сообщение тому игроку, которое вызвал данное событие(в нашем случае игроку, который зашел). Статический класс ChatColor хранит в себе константы цветов для окраски. Думаю как им пользоваться уже видно из примера. Так же, оба наших обработчка оповещают других игроков на сервере о произошетших событиях, но делают это по разному. В onJoin() с помощью метода event.setJoinMessage() мы меняем привычное сообщение «Player joined the game» на любое другое. А в onQuit() мы поступили инача(в целях примера): убрали вывод сообщения о выходе и сообщаем об этом через метод getServer().broadcastMessage(), который просто посылает всем игрокам на сервере указанное сообщение.+ Дело осталось за малым: написание важного файлика plugin.yml и упаковка всего этого в jar-файл. plugin.yml – это файл описания плагина. В нем задается название плагина, главный класс, описание и какие комманды зарегестрировать за плагинов(об этом позже) и т.д. В нашем случае, файлик должен выглядеть так: Ой, забфл сказать, где этот файлик должен находится. Жмем правой кнопкой мыши в PackageExplorer по папке src и через меню New выбираем File. В поле File name пишем plugin.yml и жмем Finish. В открывшемся текстовом редакторе, пишем то, что я указывал выше. Всё сохраняем и переходим к последней фазе: упаковке. Правый тык по папке src -> Export. В древе папок, открываем Java и выбираем JAR file и жмем Next. Из голочек оставляем только «Export generated class files and resources» и «Compress the contents of the JAR file». В поле JAR file указываем, куда будем сохранять полученный плагин. После нажатия на Finish, плагин можно класть в папку plugins, запускать сервер и проверять его работу. Видите? Это совсем просто. С практикой вы наберетесь больше опыта и сможете делать более крутые плагины, даже такие легендарные как WorldEdit и WorldGuard. Источник 1 2 3 4 http://dmitriymx.ru/blog/pishem-prostoj-plagin-dlya-bukkit

Оцените статью
Рейтинг автора
4,8
Материал подготовил
Максим Коновалов
Наш эксперт
Написано статей
127
А как считаете Вы?
Напишите в комментариях, что вы думаете – согласны
ли со статьей или есть что добавить?
Добавить комментарий