Как написать свой скрипт? — различия между версиями

Материал из Bully Multiplayer Wiki
Перейти к: навигация, поиск
 
Строка 31: Строка 31:
  
 
<div class="example_box"><syntaxhighlight lang="javascript">
 
<div class="example_box"><syntaxhighlight lang="javascript">
'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам.
+
'use strict'; //Подробнее об этом на справочных ресурсах. Но мы же пишем "правильный" и "крутой" скрипт, поэтому оставляем тут.
  
 
global.gm = {}; //Глобальная таблица, охватывающая все скрипты в ресурсе.
 
global.gm = {}; //Глобальная таблица, охватывающая все скрипты в ресурсе.
Строка 292: Строка 292:
  
 
<div class="example_box"><syntaxhighlight lang="javascript">
 
<div class="example_box"><syntaxhighlight lang="javascript">
'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам.
+
'use strict'; //Подробнее об этом на справочных ресурсах. Но мы же пишем "правильный" и "крутой" скрипт, поэтому оставляем тут.
  
 
global.gm = {
 
global.gm = {
Строка 316: Строка 316:
  
 
<div class="example_box"><syntaxhighlight lang="javascript">
 
<div class="example_box"><syntaxhighlight lang="javascript">
'use strict'; //Особенности JavaScript, которые "заставляют" писать скрипт правильно. "Use Strict" более чувствителен к ошибкам.
+
'use strict'; //Подробнее об этом на справочных ресурсах. Но мы же пишем "правильный" и "крутой" скрипт, поэтому оставляем тут.
  
 
global.gm = {
 
global.gm = {

Текущая версия на 13:15, 30 апреля 2016

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


Содержание

Часть 1.

Для начала необходимо определиться, что мы хотим от нашего скрипта.

Образец для учебника:

  • Статистика смертей/убийств игрока.
  • Пишем в чат, кто и кого убил + его новую стату.

*После респауна игрока, награждаем его бутылочной ракетницей.

Подберём список необходимых нам для этого функций и событий. Функции:

События:

Помимо этого ещё пригодится RGB(), для настройки цвета сообщений.


Часть 2.

Создаём новый файл с расширением .js и открываем его любым редактором. (Рекомендуется Notepad++)

Так как этот учебник должен быть больше правильным чем лёгким, будем делать так, как рекомендуется разработчиками.

'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 не получил "чужую" статистику.

Нам необходимо событие "когда игрок выходит с сервера".

Дополняем наш скрипт.

'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'; //Подробнее об этом на справочных ресурсах. Но мы же пишем "правильный" и "крутой" скрипт, поэтому оставляем тут.
 
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'; //Подробнее об этом на справочных ресурсах. Но мы же пишем "правильный" и "крутой" скрипт, поэтому оставляем тут.
 
global.gm = {
	colors : require("/colors.js"),
	events : new (require("/events.js"))()
}; //Глобальная таблица, охватывающая все скрипты в ресурсе.
 
function init() {
	global.gm.events.events_attach()
	//Код который будет выполняться после запуска скрипта
}
 
function shutdown() {
	//Код который будет выполняться после остановки скрипта
}