Как написать свой скрипт? — различия между версиями
SalwadoR (обсуждение | вклад) |
SalwadoR (обсуждение | вклад) |
||
Строка 8: | Строка 8: | ||
Образец для учебника: | Образец для учебника: | ||
*Статистика смертей/убийств игрока. | *Статистика смертей/убийств игрока. | ||
− | |||
*Пишем в чат, кто и кого убил + его новую стату. | *Пишем в чат, кто и кого убил + его новую стату. | ||
− | *После респауна игрока награждаем его бутылочной ракетницей. | + | *После респауна игрока, награждаем его бутылочной ракетницей. |
Подберём список необходимых нам для этого функций и событий. | Подберём список необходимых нам для этого функций и событий. | ||
Строка 97: | Строка 96: | ||
module.exports = { | module.exports = { | ||
colors : { | colors : { | ||
− | die : new RGB(255,0,0), | + | die : new RGB(255,0,0), //Красный цвет |
− | kill : new RGB(50,255,50), | + | kill : new RGB(50,255,50), //Зелёный |
− | + | ||
} | } | ||
} | } | ||
Строка 114: | Строка 112: | ||
Ура! Теперь global.gm.colors.die будет красный цвет, как мы указали в colors.js. | Ура! Теперь global.gm.colors.die будет красный цвет, как мы указали в colors.js. | ||
+ | |||
+ | |||
+ | ==Часть 4.== | ||
+ | Регистрируем события в файле events.js. | ||
+ | Начинаем с уже знакомого образца. | ||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; | ||
+ | |||
+ | module.exports = { | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | |||
+ | Но на этот раз он будет слегка другим, т.к. colors была всего лишь таблицей - сейчас мы создаём класс. | ||
+ | |||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; | ||
+ | |||
+ | module.exports = class Name { | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | |||
+ | Сразу необходимо подготовить массив, в котором будет храниться статистика игроков. | ||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; | ||
+ | |||
+ | module.exports = class Name { | ||
+ | construct() { | ||
+ | this.PlayerStats = []; //Пустой массив PlayerStats | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | construct - постоянная функция, которая вызывается при использовании класса в функции new(), что нам и необходимо. | ||
+ | |||
+ | |||
+ | Далее приступаем к написанию функции которая меняет статистику игроков. | ||
+ | |||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; | ||
+ | |||
+ | module.exports = class Name { | ||
+ | construct() { | ||
+ | this.PlayerStats = []; //Пустой массив PlayerStats | ||
+ | } | ||
+ | changeStatCount (player,attacker) { | ||
+ | if (!!player) { | ||
+ | if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. | ||
+ | this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему | ||
+ | if (!!attacker) { //Если атакующий есть | ||
+ | if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; | ||
+ | this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце | ||
+ | } | ||
+ | else { //Атакующего нет | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | |||
+ | Далее пораскинув мозгами понимаем что ловим баг, после выхода игрока с сервера необходимо чистить его ячейку массива, что-бы игрок попавший на его ID не получил "чужую" статистику. | ||
+ | |||
+ | Нам необходимо событие "когда игрок выходит с сервера". | ||
+ | *[[onPlayerDisconnect]] - Событие отключения игрока. | ||
+ | |||
+ | Дополняем наш скрипт. | ||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; | ||
+ | |||
+ | module.exports = class Name { | ||
+ | construct() { | ||
+ | this.PlayerStats = []; //Пустой массив PlayerStats | ||
+ | } | ||
+ | changeStatCount (player,attacker) { | ||
+ | if (!!player) { | ||
+ | if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. | ||
+ | this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему | ||
+ | if (!!attacker) { //Если атакующий есть | ||
+ | if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; | ||
+ | this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце | ||
+ | } | ||
+ | else { //Атакующего нет | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | clearStats (player) { | ||
+ | if (!!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = null}; //Удаляем таковую, если имеется | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | |||
+ | Далее чего-то не хватает, точно, сообщения в чате! | ||
+ | А так же подключаем скрипт [[BroadcastMessage()]], для удобства. | ||
+ | |||
+ | Дополняем наш скрипт. | ||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; | ||
+ | |||
+ | module.exports = class Name { | ||
+ | construct() { | ||
+ | this.PlayerStats = []; //Пустой массив PlayerStats | ||
+ | } | ||
+ | broadcastMessage(color, message) { | ||
+ | if (!!color && !!message) { | ||
+ | for (let i = 0; i < bullymp.players.length; i++) { | ||
+ | if (!!bullymp.players[i]) { | ||
+ | bullymp.players[i].sendMessage(color, message); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | changeStatCount (player,attacker) { | ||
+ | if (!!player) { | ||
+ | if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. | ||
+ | this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему | ||
+ | var _playerStat = "(" + this.PlayerStats[player.id][0] + "/" + this.PlayerStats[player.id][1] + ")"; | ||
+ | if (!!attacker) { //Если атакующий есть | ||
+ | if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; | ||
+ | this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце | ||
+ | var _attackerStat = "(" + this.PlayerStats[attacker.id][0] + "/" + this.PlayerStats[attacker.id][1] + ")"; | ||
+ | attacker.sendMessage(global.gm.colors.kill,"[STATS] You kill " + player.name + " " + _playerStat + ".") | ||
+ | return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " was killed by " + attacker.name + " " + _attackerStat + ".") | ||
+ | } | ||
+ | else { //Атакующего нет | ||
+ | return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " doe.") | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | clearStats (player) { | ||
+ | if (!!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = null}; //Удаляем таковую, если имеется | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | |||
+ | Остаётся прикрепить функции к событиям? | ||
+ | |||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; | ||
+ | |||
+ | module.exports = class Name { | ||
+ | construct() { | ||
+ | this.PlayerStats = []; //Пустой массив PlayerStats | ||
+ | } | ||
+ | broadcastMessage(color, message) { | ||
+ | if (!!color && !!message) { | ||
+ | for (let i = 0; i < bullymp.players.length; i++) { | ||
+ | if (!!bullymp.players[i]) { | ||
+ | bullymp.players[i].sendMessage(color, message); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | changeStatCount (player,attacker) { | ||
+ | if (!!player) { | ||
+ | if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. | ||
+ | this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему | ||
+ | var _playerStat = "(" + this.PlayerStats[player.id][0] + "/" + this.PlayerStats[player.id][1] + ")"; | ||
+ | if (!!attacker) { //Если атакующий есть | ||
+ | if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; | ||
+ | this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце | ||
+ | var _attackerStat = "(" + this.PlayerStats[attacker.id][0] + "/" + this.PlayerStats[attacker.id][1] + ")"; | ||
+ | attacker.sendMessage(global.gm.colors.kill,"[STATS] You kill " + player.name + " " + _playerStat + ".") | ||
+ | return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " was killed by " + attacker.name + " " + _attackerStat + ".") | ||
+ | } | ||
+ | else { //Атакующего нет | ||
+ | return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " doe.") | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | clearStats (player) { | ||
+ | if (!!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = null}; //Удаляем таковую, если имеется | ||
+ | } | ||
+ | events_attach() { | ||
+ | eventHandlers.add("onPlayerDisconnect", this.clearStats); | ||
+ | eventHandlers.add("onPlayerKnockedOut", this.changeStatCount); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | |||
+ | Осталось заставить всё это работать? Возвращаемся к server_main.js и вписываем events.js. | ||
+ | |||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам. | ||
+ | |||
+ | global.gm = { | ||
+ | colors : require("/colors.js"), | ||
+ | events : require("/events.js") | ||
+ | }; //Глобальная таблица, охватывающая все скрипты в ресурсе. | ||
+ | |||
+ | function init() { | ||
+ | //Код который будет выполняться после запуска скрипта | ||
+ | } | ||
+ | |||
+ | function shutdown() { | ||
+ | //Код который будет выполняться после остановки скрипта | ||
+ | } | ||
+ | </syntaxhighlight></div> | ||
+ | |||
+ | Остаётся запустить global.gm.events.events_attach() из под init(), но не тут то было. | ||
+ | ''construct - постоянная функция, которая вызывается при использовании класса в функции new(), что нам и необходимо.'' | ||
+ | |||
+ | Поэтому events : require("/events.js") меняем на events : new (require("/events.js"))() | ||
+ | |||
+ | И в конце добавляем global.gm.events.events_attach() в функцию init(). | ||
+ | |||
+ | <div class="example_box"><syntaxhighlight lang="javascript"> | ||
+ | 'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам. | ||
+ | |||
+ | global.gm = { | ||
+ | colors : require("/colors.js"), | ||
+ | events : new (require("/events.js"))() | ||
+ | }; //Глобальная таблица, охватывающая все скрипты в ресурсе. | ||
+ | |||
+ | function init() { | ||
+ | global.gm.events.events_attach() | ||
+ | //Код который будет выполняться после запуска скрипта | ||
+ | } | ||
+ | |||
+ | function shutdown() { | ||
+ | //Код который будет выполняться после остановки скрипта | ||
+ | } | ||
+ | </syntaxhighlight></div> |
Версия 15:00, 29 апреля 2016
Для многих будет вопросом, как же создать собственный скрипт, и что для этого необходимо. В данной статье мы пробежимся по нескольким аспектам.
Содержание |
Часть 1.
Для начала необходимо определиться, что мы хотим от нашего скрипта.
Образец для учебника:
- Статистика смертей/убийств игрока.
- Пишем в чат, кто и кого убил + его новую стату.
- После респауна игрока, награждаем его бутылочной ракетницей.
Подберём список необходимых нам для этого функций и событий. Функции:
- player.giveWeapon() - Выдать оружие
- player.sendMessage() - Отправить сообщение
- eventHandlers.add() - Добавить событие
- broadcastMessage() - Будем использовать удобный вариант для рассылки сообщений всем
События:
- onPlayerKnockedOut - Событие смерти игрока.
- onPlayerSpawn - Событие респауна игрока.
Помимо этого ещё пригодится RGB(), для настройки цвета сообщений.
Часть 2.
Создаём новый файл с расширением .js и открываем его любым редактором. (Рекомендуется Notepad++)
Так как этот учебник должен быть больше правильным чем лёгким, будем делать так, как рекомендуется разработчиками.
'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам. global.gm = {}; //Глобальная таблица, охватывающая все скрипты в ресурсе. function init() { //Код который будет выполняться после запуска скрипта } function shutdown() { //Код который будет выполняться после остановки скрипта }
Сохраним данный файл под названием server_main.js в папке /myscript
Сам по себе скрипт не запустится, поэтому необходим файл meta.xml, который содержит в себе информацию о ресурсе, и всех его скриптах.
Примерно так будет выглядеть ваш meta.xml
<meta> <info name="Название ресурса" author="Имя автора" type="script" version="1.0"/> <script src="server_main.js" type="server" boot="true"/> </meta>
Про клиентскую и серверную сторону можете вкратце глянуть здесь: Ссылка
Про то как должна выглядеть meta.xml, что и зачем: Ссылка
Для примера, мы выведем части ресурса в другие скрипты, которые позже подключим с помощью require().
В Meta.xml добавляем 2 строки с названиями colors и events, обязательно до скрипта с тегом "boot".
В итоге получим следующее:
<meta> <info name="Название ресурса" author="Имя автора" type="script" version="1.0"/> <script src="colors.js" type="server"/> <script src="events.js" type="server"/> <script src="server_main.js" type="server" boot="true"/> </meta>
Далее создаём соответствующие файлы, и начинаем писать.
Часть 3.
Регистрируем цвета в глобальной таблице global.gm.
Для этого открываем colors.js и пишем:
'use strict'; module.exports = { }
module.exports - таблица которая будет читаться функцией require(), поэтому всё необходимое упаковываем в неё.
'use strict'; module.exports = { colors : { die : new RGB(255,0,0), //Красный цвет kill : new RGB(50,255,50), //Зелёный } }
Далее необходимо сделать так, что бы основной скрипт server_main.js зарегистрировал цвета. Делается это следующим образом:
В таблицу global.gm = {} вставляем функцию require() с ссылкой на наш скрипт colors.js.
global.gm = { colors : require("/colors.js") };
Ура! Теперь global.gm.colors.die будет красный цвет, как мы указали в colors.js.
Часть 4.
Регистрируем события в файле events.js. Начинаем с уже знакомого образца.
'use strict'; module.exports = { }
Но на этот раз он будет слегка другим, т.к. colors была всего лишь таблицей - сейчас мы создаём класс.
'use strict'; module.exports = class Name { }
Сразу необходимо подготовить массив, в котором будет храниться статистика игроков.
'use strict'; module.exports = class Name { construct() { this.PlayerStats = []; //Пустой массив PlayerStats } }
construct - постоянная функция, которая вызывается при использовании класса в функции new(), что нам и необходимо.
Далее приступаем к написанию функции которая меняет статистику игроков.
'use strict'; module.exports = class Name { construct() { this.PlayerStats = []; //Пустой массив PlayerStats } changeStatCount (player,attacker) { if (!!player) { if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему if (!!attacker) { //Если атакующий есть if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце } else { //Атакующего нет } } } }
Далее пораскинув мозгами понимаем что ловим баг, после выхода игрока с сервера необходимо чистить его ячейку массива, что-бы игрок попавший на его ID не получил "чужую" статистику.
Нам необходимо событие "когда игрок выходит с сервера".
- onPlayerDisconnect - Событие отключения игрока.
Дополняем наш скрипт.
'use strict'; module.exports = class Name { construct() { this.PlayerStats = []; //Пустой массив PlayerStats } changeStatCount (player,attacker) { if (!!player) { if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему if (!!attacker) { //Если атакующий есть if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце } else { //Атакующего нет } } } clearStats (player) { if (!!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = null}; //Удаляем таковую, если имеется } }
Далее чего-то не хватает, точно, сообщения в чате! А так же подключаем скрипт BroadcastMessage(), для удобства.
Дополняем наш скрипт.
'use strict'; module.exports = class Name { construct() { this.PlayerStats = []; //Пустой массив PlayerStats } broadcastMessage(color, message) { if (!!color && !!message) { for (let i = 0; i < bullymp.players.length; i++) { if (!!bullymp.players[i]) { bullymp.players[i].sendMessage(color, message); } } } } changeStatCount (player,attacker) { if (!!player) { if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему var _playerStat = "(" + this.PlayerStats[player.id][0] + "/" + this.PlayerStats[player.id][1] + ")"; if (!!attacker) { //Если атакующий есть if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце var _attackerStat = "(" + this.PlayerStats[attacker.id][0] + "/" + this.PlayerStats[attacker.id][1] + ")"; attacker.sendMessage(global.gm.colors.kill,"[STATS] You kill " + player.name + " " + _playerStat + ".") return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " was killed by " + attacker.name + " " + _attackerStat + ".") } else { //Атакующего нет return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " doe.") } } } clearStats (player) { if (!!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = null}; //Удаляем таковую, если имеется } }
Остаётся прикрепить функции к событиям?
'use strict'; module.exports = class Name { construct() { this.PlayerStats = []; //Пустой массив PlayerStats } broadcastMessage(color, message) { if (!!color && !!message) { for (let i = 0; i < bullymp.players.length; i++) { if (!!bullymp.players[i]) { bullymp.players[i].sendMessage(color, message); } } } } changeStatCount (player,attacker) { if (!!player) { if (!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = [0,0]}; //Если в массиве нет значений, создать "нулёвый". [0] = смерти, [1] = убийства. this.PlayerStats[player.id][0]++; //Добавляем +1 смерть погибшему var _playerStat = "(" + this.PlayerStats[player.id][0] + "/" + this.PlayerStats[player.id][1] + ")"; if (!!attacker) { //Если атакующий есть if (!this.PlayerStats[attacker.id]) {this.PlayerStats[attacker.id] = [0,0]}; this.PlayerStats[attacker.id][1]++; //Добавляем +1 убийство убийце var _attackerStat = "(" + this.PlayerStats[attacker.id][0] + "/" + this.PlayerStats[attacker.id][1] + ")"; attacker.sendMessage(global.gm.colors.kill,"[STATS] You kill " + player.name + " " + _playerStat + ".") return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " was killed by " + attacker.name + " " + _attackerStat + ".") } else { //Атакующего нет return this.broadcastMessage(global.gm.colors.die,"[STATS] " + player.name + " " + _playerStat + " doe.") } } } clearStats (player) { if (!!this.PlayerStats[player.id]) {this.PlayerStats[player.id] = null}; //Удаляем таковую, если имеется } events_attach() { eventHandlers.add("onPlayerDisconnect", this.clearStats); eventHandlers.add("onPlayerKnockedOut", this.changeStatCount); } }
Осталось заставить всё это работать? Возвращаемся к server_main.js и вписываем events.js.
'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам. global.gm = { colors : require("/colors.js"), events : require("/events.js") }; //Глобальная таблица, охватывающая все скрипты в ресурсе. function init() { //Код который будет выполняться после запуска скрипта } function shutdown() { //Код который будет выполняться после остановки скрипта }
Остаётся запустить global.gm.events.events_attach() из под init(), но не тут то было. construct - постоянная функция, которая вызывается при использовании класса в функции new(), что нам и необходимо.
Поэтому events : require("/events.js") меняем на events : new (require("/events.js"))()
И в конце добавляем global.gm.events.events_attach() в функцию init().
'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам. global.gm = { colors : require("/colors.js"), events : new (require("/events.js"))() }; //Глобальная таблица, охватывающая все скрипты в ресурсе. function init() { global.gm.events.events_attach() //Код который будет выполняться после запуска скрипта } function shutdown() { //Код который будет выполняться после остановки скрипта }