Eklenti grameri
specVersion 1
Bir NimBlock eklentisi kod değildir: kuralları tanımlayan, herkes için bir kez yazılmış bir Paper motoru tarafından okunup çalıştırılan bir JSON dosyasıdır. Bu sayfa, içine tam olarak ne yazabileceğini söyler ve başka hiçbir şey mümkün değildir.
Bir kural, sadece bir kural
Tüm gramer tek bir cümleye sığar: bu gerçekleştiğinde, şu koşullar sağlanıyorsa, şunu yap. Bir eklenti kurallar listesidir; bir kural bir tetikleyici, sıfır ile 20 arası koşul ve bir ile 50 arası eylemden oluşur.
Hiçbir yerde Java üretilmez, hiçbir derleme yapılmaz: sunucu, spec'i okuyan bir motor yükler. Asıl önemli olan bu özelliktir, çünkü yeni bir Minecraft sürümünün bedeli sadece bu motorda ödenir, onunla yazılmış her eklentide değil.
Bir spec'in biçimi
{
"specVersion": 1,
"name": "Hoş Geldin",
"rules": [
{
"id": "hosgeldin",
"name": "Hoş geldin mesajı",
"match": "all",
"trigger": { "type": "player.join" },
"conditions": [
{ "type": "player.has_permission", "params": { "permission": "nimblock.vip" } }
],
"actions": [
{ "type": "player.send_message", "params": { "message": "&6Hoş geldin {player}!" } }
]
}
]
}
match, all (varsayılan) veya any
değerini alır ve bir koşul "not": true taşıyabilir.
enabled: false, bir kuralı etkinleştirmeden dosyada tutar.
Gramer, EBNF olarak
Aşağıdaki uç öğe (terminal) listeleri katalogdan üretilir: bunlar motorun çalıştırabildiği tanımlayıcıların ta kendisidir, elle yapılmış bir transkripsiyon değildir.
<plugin> ::= "{" "specVersion" ":" 1 ","
[ "id" ":" <slug64> "," ]
"name" ":" <label> ","
[ "description" ":" <text500> "," ]
"rules" ":" "[" <rule> { "," <rule> } "]" "}" (* 1..200 *)
<rule> ::= "{" [ "id" ":" <slug32> "," ]
"name" ":" <label> ","
[ "enabled" ":" <boolean> "," ] (* = true *)
[ "match" ":" ( "all" | "any" ) "," ] (* = "all" *)
"trigger" ":" <trigger> ","
[ "conditions" ":" "[" [ <condition>
{ "," <condition> } ] "]" "," ] (* 0..20 *)
"actions" ":" "[" <action>
{ "," <action> } "]" "}" (* 1..50 *)
<trigger> ::= "{" "type" ":" <trigger-id> [ "," "params" ":" <params> ] "}"
<condition> ::= "{" "type" ":" <condition-id> [ "," "not" ":" <boolean> ]
[ "," "params" ":" <params> ] "}"
<action> ::= "{" "type" ":" <action-id> [ "," "params" ":" <params> ] "}"
<params> ::= "{" [ <param-name> ":" <param-value>
{ "," <param-name> ":" <param-value> } ] "}"
<param-value> ::= <template> | <identifier> | <integer> | <number>
| <boolean> | <choice>
<template> ::= { <literal> | <variable> | <colour> } (* 0..2000 *)
<literal> ::= /[^{}]/ | "{{" | "}}"
<variable> ::= "{" /[a-zA-Z][a-zA-Z0-9_]*/ "}"
<colour> ::= "&" ( "0".."9" | "a".."f" | "k".."o" | "r" )
<identifier> ::= /[A-Za-z][A-Za-z0-9_:.\/-]{0,63}/
<slug32> ::= /[A-Za-z0-9_-]{1,32}/
<slug64> ::= /.{0,64}/
<label> ::= /.{1,64}/
<text500> ::= /.{0,500}/
<trigger-id> ::= "player.join"
| "player.quit"
| "player.chat"
| "player.death"
| "player.respawn"
| "block.break"
| "block.place"
| "command"
| "schedule.repeat"
<condition-id> ::= "player.has_permission"
| "player.is_op"
| "player.in_world"
| "player.health_below"
| "text.contains"
| "text.equals"
| "number.compare"
| "chance"
<action-id> ::= "player.send_message"
| "player.send_actionbar"
| "player.send_title"
| "player.play_sound"
| "player.give_item"
| "player.give_effect"
| "player.heal"
| "player.teleport"
| "player.kick"
| "broadcast"
| "server.run_command"
| "cancel_event"
| "log"
| "delay"
Bu üretim kurallarında görünmeyen iki şey vardır, çünkü bunlar biçimle
değil tutarlılıkla ilgilidir. Bir oyuncu gerektiren koşul veya eylem,
ancak bir oyuncu sağlayan bir tetikleyicinin altında yazılabilir:
"oyuncuyu iyileştir", "her N saniyede bir" altında bir anlam ifade etmez.
Ve cancel_event yalnızca iptal edilebilir bir tetikleyicinin
altında yazılabilir. İkisi de yazım sırasında reddedilir, çalışma
sırasında değil.
Şablonlar
text türündeki parametreler şablondur:
{player}, tetikleyicinin sağladığı değerle
değiştirilir, {{ gerçek bir küme parantezi
verir ve &a &l gibi renk kodları
çevrilir.
Tetikleyicinin tanımadığı bir değişken, metin değil bir hatadır. Her tetikleyici neyi sağladığını bildirir (aşağıdaki listeye bak): bu listenin dışında okunacak hiçbir şey yoktur ve bir yazım hatası, oyuncuların sohbetine düşmek yerine yazım sırasında reddedilir. Bir tetikleyicinin kendi parametreleri ise şablon değildir: bunlar sunucu başlarken, henüz değiştirilecek hiçbir şey yokken okunur.
Minecraft isimleri, neyi belirttiklerine göre iki şekilde yazılır. Bir
eşya, her iki yazımla da adlandırılabilir
(DIAMOND_SWORD veya diamond_sword). Bir
ses veya efekt ise Bukkit sabiti yerine
Minecraft anahtarıyla adlandırılır (entity.player.levelup,
speed): bu anahtar istemciye olduğu gibi gider ve sürümler
arasında değişmeden kalır.
Gramerin izin vermediği şeyler
Kapalıdır ve bunu her şeyden önce söylemek gerekir. Katalogda yer alan yapılabilir, geri kalanı imkânsızdır ve öyle kalacaktır: keyfi Java kodu çalıştırmanın hiçbir yolu yoktur. Bu da stüdyoyu anlık kılar (derlenecek hiçbir şey yok) ve bir spec'in nereden geldiğine bakılmaksızın kurulumunu zararsız hale getirir.
Koşullar iç içe geçmez: bu, 1. sürümün bilinçli olarak
kabul edilmiş bir sınırıdır, bir Boole ağacı bloklarla kötü çizilir ve
all / any / not neredeyse her
zaman yeterlidir. Tek çıkış kapısı, o sunucuda konsolun gücüne sahip
olan, ne fazlası ne eksiği "konsol olarak bir komut çalıştır" eylemidir.
Tetikleyiciler
Bir kuralı başlatan şey ve her birinin şablonlar için sağladığı değişkenler.
player.join
Bir oyuncu bağlanır
Oyuncu, dünyası yüklendikten sonra sunucuya girdiği an.
sağlar:
{player} Bağlanan oyuncu,
{world} Geldiği dünya
player.quit
Bir oyuncu ayrılır
Oyuncu sunucudan ayrıldığı an. Hâlâ ulaşılabilir durumdadır, ama gönderilen her mesaj kaybolur.
sağlar:
{player} Ayrılan oyuncu,
{world} Ayrıldığı dünya
player.chat
Bir oyuncu sohbete yazar
iptal edilebilir
Mesaj diğer oyunculara iletilmeden önce. İptal edilebilir: bu durumda mesajı kimse görmez.
sağlar:
{player} Mesajı yazan oyuncu,
{world} Dünyası,
{message} Yazılan mesaj
player.death
Bir oyuncu ölür
Oyuncu öldüğünde, yeniden doğma ekranından önce.
sağlar:
{player} Ölen oyuncu,
{world} Dünyası,
{killer} Sorumlu oyuncu, yoksa boş
player.respawn
Bir oyuncu yeniden doğar
Oyuncu öldükten sonra oyuna geri döndüğünde.
sağlar:
{player} Yeniden doğan oyuncu,
{world} Yeniden doğma dünyası
block.break
Bir oyuncu blok kırar
iptal edilebilir
Blok yok olmadan önce. İptal edilebilir: blok yerinde kalır.
sağlar:
{player} Kıran oyuncu,
{world} Dünyası,
{block} Blok türü (DIAMOND_ORE),
{x} Bloğun X koordinatı,
{y} Bloğun yüksekliği,
{z} Bloğun Z koordinatı
block.place
Bir oyuncu blok yerleştirir
iptal edilebilir
Blok yerleştirilmeden önce. İptal edilebilir: blok yerleştirilmez.
sağlar:
{player} Yerleştiren oyuncu,
{world} Dünyası,
{block} Yerleştirilen blok türü,
{x} Bloğun X koordinatı,
{y} Bloğun yüksekliği,
{z} Bloğun Z koordinatı
command
Bir oyuncu komut yazar
Sunucuda yeni bir komut oluşturur. ⚠️ Adı daha önce var olmayan bir komut, ancak sunucu yeniden başlatıldığında görünür: Paper yeni komut adlarını yalnızca başlangıçta kabul eder. Kuralın içeriği ise anında yeniden yüklenir.
-
nametext Komut adı, eğik çizgi olmadan -
descriptiontext isteğe bağlı Yardımda gösterilen açıklama -
permissiontext isteğe bağlı Gereken izin, herkes için boş
sağlar:
{player} Komutu yazan oyuncu,
{world} Dünyası,
{args} Komuttan sonra gelen her şey, olduğu gibi
schedule.repeat
Her N saniyede bir
Kuralı sunucu çalıştığı sürece tekrarlar. Hiçbir oyuncu söz konusu değildir: yalnızca oyuncu gerektirmeyen eylemler kullanılabilir.
-
secondsinteger [1..86400] Saniye cinsinden aralık
Koşullar
Filtreleyen şey. Kural başına sıfır ile 20 arası, match ile birleştirilir.
player.has_permission
Oyuncunun izni var
bir oyuncu gerektirir
-
permissiontext İzin
player.is_op
Oyuncu operatör
bir oyuncu gerektirir
player.in_world
Oyuncu dünyada
bir oyuncu gerektirir
-
worldtext Dünya adı
player.health_below
Oyuncunun X'ten az kalbi var
bir oyuncu gerektirir
Can puanı cinsinden: 20 puan 10 kalbe eşittir.
-
valuenumber [0..1024] Can puanı
text.contains
Bir metin içerir
-
texttext İncelenen metin -
searchtext İçinde aranan şey -
ignoreCaseboolean isteğe bağlı, varsayılan:trueBüyük/küçük harfi yok say
text.equals
Bir metin eşittir
-
texttext İncelenen metin -
valuetext Beklenen değer -
ignoreCaseboolean isteğe bağlı, varsayılan:trueBüyük/küçük harfi yok say
number.compare
İki sayıyı karşılaştır
Her iki taraf da birer şablondur: {y}, kod yazmadan 62 ile karşılaştırılır.
-
lefttext Sol taraf -
operator< | <= | == | != | >= | > Karşılaştırma -
righttext Sağ taraf
chance
Rastgele, zamanın %X'inde
-
percentnumber [0..100] Yüzde
Eylemler
Gerçekleşen şey. Kural başına bir ile 50 arası, sırayla çalıştırılır.
player.send_message
Oyuncuya mesaj gönder
bir oyuncu gerektirir
-
messagetext Mesaj
player.send_actionbar
Eylem çubuğunun üzerinde mesaj göster
bir oyuncu gerektirir
-
messagetext Mesaj
player.send_title
Büyük bir başlık göster
bir oyuncu gerektirir
-
titletext Başlık -
subtitletext isteğe bağlı Alt başlık -
fadeInnumber [0..60] isteğe bağlı, varsayılan:0.5Saniye cinsinden belirme süresi -
staynumber [0..600] isteğe bağlı, varsayılan:3Saniye cinsinden süre -
fadeOutnumber [0..60] isteğe bağlı, varsayılan:0.5Saniye cinsinden kaybolma süresi
player.play_sound
Oyuncu için bir ses çal
bir oyuncu gerektirir
-
soundidentifier Ses, Minecraft anahtarı olarak (entity.player.levelup) -
volumenumber [0..10] isteğe bağlı, varsayılan:1Ses düzeyi -
pitchnumber [0.5..2] isteğe bağlı, varsayılan:1Perde
player.give_item
Oyuncuya eşya ver
bir oyuncu gerektirir
Envantere sığmayanlar ayaklarının dibine düşer.
-
materialidentifier Eşya (DIAMOND_SWORD) -
amountinteger [1..2304] isteğe bağlı, varsayılan:1Miktar
player.give_effect
Oyuncuya bir efekt uygula
bir oyuncu gerektirir
-
effectidentifier Efekt, Minecraft anahtarı olarak (night_vision) -
secondsinteger [1..86400] isteğe bağlı, varsayılan:10Saniye cinsinden süre -
amplifierinteger [0..255] isteğe bağlı, varsayılan:0Seviye, 0'dan başlayarak
player.heal
Oyuncuyu iyileştir
bir oyuncu gerektirir
Can tamamen dolar, açlık giderilir.
player.teleport
Oyuncuyu ışınla
bir oyuncu gerektirir
-
xnumber [-30000000..30000000] X koordinatı -
ynumber [-512..1024] Yükseklik -
znumber [-30000000..30000000] Z koordinatı -
worldtext isteğe bağlı Dünya, oyuncununki için boş
player.kick
Oyuncuyu at
bir oyuncu gerektirir
-
reasontext Gösterilen sebep
broadcast
Tüm sunucuya duyur
-
messagetext Mesaj
server.run_command
Konsol olarak bir komut çalıştır
Dilbilgisinin çıkış kapısı: konsolun yapabildiği her şey. Bu, konsolun bu sunucu üzerindeki tüm gücüdür, o yüzden ne yaptığını bilerek yaz.
-
commandtext Komut, eğik çizgi olmadan
cancel_event
Az önce olanı iptal et
iptal edilebilir bir tetikleyici gerektirir
Yalnızca iptal edilebilir tetikleyicilerde bulunur: mesaj iletilmez, blok kırılmaz.
log
Sunucu konsoluna yaz
-
messagetext Mesaj -
levelinfo | warn isteğe bağlı, varsayılan:infoSeviye
delay
Bekle
Kuralın geri kalan eylemlerini duraklatır. Bekleyen bir kural artık hiçbir şeyi iptal edemez: "İptal et" ondan önce gelmelidir.
-
secondsnumber [0.05..3600] Saniye
Yayınlanan dosyalar
JSON Schema, her dağıtımda katalogdan üretilir ve makine tarafından okunabilir referans budur: onu izleyen bir metin editörü tanımlayıcıları tamamlar ve bilinmeyen parametreleri reddeder.
- plugin-1.schema.json : şema, JSON Schema draft 2020-12 biçiminde.
- catalogue-1.json : katalogun kendisi, geri kalan her şeyin türediği kaynak (doğrulayıcı, şema, editörün blokları ve Java motoru).
Katalog, kaynak dil olan Fransızca etiketleri taşır. Tanımlayıcılar ise çevrilmez: motorun çalıştırdığı onlardır.
Gramer değiştiğinde ne olur
Bir tetikleyici, koşul veya eylem eklemek hiçbir şeyi bozmaz: daha önce
yazılmış bir spec çalışmaya devam eder. Bir kırıcı
değişiklik ise specVersion'ı artırır ve motor,
anlamadığı şeyi yanlış çalıştırmak yerine reddeder, bunu sunucu
konsolunda belirtir.
Yukarıdaki URL'ler bu numarayı taşır:
plugin-1.schema.json, başka bir gramer var
olduğu gün bile her zaman bu grameri işaret edecektir.