HyperScript
Docs

Docs

Everything HyperScript can do, by subject. Type to filter instantly, pick a subject below, or say on the left what kind of thing you are looking for. Click any entry for an example.

The basics

How a script is laid out, and the handful of things every script is made of.

File structure

Guide and examples

How syntax is written on these pages. <name> stands for a value you put there. Something in square brackets, such as [or drop], may be left out. Round brackets with a slash, such as (below/above), mean one of those words. Everything else is written as it stands.

A script is a list of commands, event handlers, timers and functions. Blocks are formed by indentation (spaces or tabs, as long as you are consistent), and every line that opens a block ends with :.

A line that ends with a backslash carries on with the next one, so long text or a long condition can be spread over several lines:

on player join:
    send "&7Welcome to the server. Read the rules, " + \
        "be kind to each other, and have fun."

# starts a comment: everything after it on the line is ignored, so it is where you leave notes for yourself and for whoever edits the script next. A # inside quotes is ordinary text.

# Notes
#  - The reward is the number in /daily. Change it there.

options:
    <name>: <value>

function <name>(<locals>):
    <statements>

on load:
    <statements>

on <event>:
    <statements>

command /<name> [<argument description>]:
    <options>
    trigger:
        <statements>

every <duration>:
    <statements>

on discord command "/<name>":
    <statements>

on load: is not a server event. Its block runs once each time the file is loaded: when the server starts, on /hyperscript reload, and when the file is saved with hot reloading on. It runs with no player, like a console command, and after every script has been loaded, so it may call functions from other files. It is the place to set defaults and create teams:

on load:
    if {motd} is not set:
        set {motd} to "&aWelcome!"

Variables

Guide and examples

There are two kinds of variable, told apart by the first character of the name.

KindWritten asLifetimeExample
Global{name}Saved, and shared by every script{event_active}
Local{_name}One run of one trigger; never saved{_tempDamage}
set {event_active} to true
set {_tempDamage} to 4.5
set {%player%.coins} to 100
delete {%player%.coins}
  • Values are numbers, text, the booleans true and false, items, durations, locations, or a list of any of those. See Value types.
  • {name} is global: one saved value that any script can read and change.
  • {_name} is local: a name that begins with an underscore. It exists for one run of the command, event handler or function it appears in, starts unset every time, and nothing else can see it, not even another trigger in the same file.
  • A local may be written without its braces, as plain _name. It is the same variable either way, and a script may use both. The braces are how these pages write it, because every other variable has them too; scripts written the shorter way keep working as they are.
  • A local can be a small table: {_data.name} and {_data.kills} are named values inside the local {_data}. The whole table can be handed to a function, returned from one, and looped over with for each {_key}, {_value} in {_data}:. Like any local it is never saved.
  • Names are case-insensitive and may use letters, digits, _, - and ..
  • A global name that starts with a player belongs to that player. {%player%.coins} is the coins of the player of this trigger, {%arg.1%.coins} the coins of whoever was named in the command, and {%loop-player%.coins} the coins of each player in a loop all players. Everybody has their own value, it is stored with their account so it survives a name change, and it can be read and changed while they are offline.
  • A player is anyone online or anyone who has played on the server before. If the first part of a name is not a player, the variable is an ordinary global under the name as written. So for a table that is *not* about players, start the name with a fixed word: {warp.%arg.1%} rather than {%arg.1%.warp}.
  • Reading {%player%.<name>} when there is no player (a console command, a timer) gives unset; writing it is a runtime error.
  • {player.coins}, without the percent signs, is one global shared by everyone. The word player in a variable name is just part of the name; it is %player% that stands for the player.
  • A colon works like a dot in a variable's name, for those who prefer it: {%player%:role} is the same variable as {%player%.role}, and {stats::kills} the same as {stats.kills}.
  • Tables in lists. A local table can be put in a list and saved, which is how to keep records of several things each: set {_home.name} to "base", set {_home.spot} to player's location, append _home to {%player%.homes}. Looping gives each one back as a table: for each {_home} in {%player%.homes}: then {_home.name} and {_home.spot}. The list holds its own copy, so the local can be changed and used again for the next one.
  • Shared variables. With storage.shared-variables on, a variable whose name starts with shared. is the same on every server that uses the database; see The database.
  • Variables for a time. set {%player%.boost} to 2 for 10 minutes sets it and unsets it again by itself when the time is up. The time keeps counting while the server is off, and a variable whose time ran out then is gone when the server starts. Setting it for another time starts the time anew; setting it without for changes the value but not when it ends. This is for saved variables; a local one ends with its trigger anyway.
  • Temporary variables. A variable whose name starts with temp. is never saved. {temp.round} lasts until the server stops, and a player's own, {%player%.temp.combat}, is forgotten the moment they leave. Use them for things that should not outlive a session, such as "is in a fight" or "has a menu open", and there is nothing to tidy up when a player joins.
  • Unset variables count as 0 in math, as nothing when joined to text with +, and as false in conditions, so counters need no setup: add 1 to {%player%.joins} works the first time. Test for it explicitly with is set / is not set.
  • A variable may have any name that is not already a built-in placeholder. {%player%.coins} and {event.start_time} are fine; {player.name} is refused, because player.name is built in. The same name after %player%. is allowed: {%player%.name} is simply a per-player variable.
  • To put a variable in a string, wrap it in percent signs: "%{%player%.coins}%" and "%{_reward}%".
  • A value between percent signs may have a name in quotes of its own: "Mined: %quest progress "miner"%", "You have %plural({_n}, "home")%.". So inside text, %{...}% is a variable and %...% without braces is a placeholder.
  • A value written out works between percent signs too, as long as it is several words or a call: "You have %size of {_list}% items", "That is %round({_n})% coins". Something that does not read as a value is shown as it was written, so "50% off, 20% more" stays what it is. Text in quotes cannot stand inside it; put that in a local variable first.

Options

Guide and examples

Settings that a script uses in several places can be named once, at the top of the file, and used anywhere in it as {@name}:

options:
    prefix: "&8[&6Shop&8] "
    price: 50
    wait: 10 minutes

command /buy:
    cooldown: {@wait}
    trigger:
        if {%player%.coins} < {@price}:
            send "{@prefix}&cThat costs {@price} coins."
            stop
        subtract {@price} from {%player%.coins}
        give 1 diamond to player
        send "{@prefix}&aBought a diamond."
  • The options: block stands at the left margin, like a command. Each line in it is name: value.
  • An option is not a variable. Before a line is read, every {@name} in it is replaced by the option's value exactly as written, so an option can be a number, a duration, text, an item, a permission, or part of a header such as every {@interval}:.
  • Inside quotes, an option that is itself quoted text is put in without its quotes, which is why "{@prefix}&aBought" works.
  • Options belong to the file they are in and cannot be changed while the server runs. For something that changes, use a variable.
  • Using a name that is not in the block is an error when the script loads.

Saying which version a script needs. A comment # Requires: 1.5.7 among the notes at the top of a file makes an older plugin refuse the file with one clear message, "This script needs HyperScript 1.5.7 or newer", instead of an error about whichever line it does not understand. The scripts on the website's Scripts page all carry one.

Value types

Guide and examples

A variable holds whatever you put in it. Besides numbers, text, booleans and lists there are richer kinds of value: durations, locations and items, described here, and dates, which have a part of their own, Dates and times. All of them are saved with the rest of the variable data.

TypeWritten asPrints as
Itemdiamond sword, 3 golden apple, diamond sword named "&6Excalibur" with lore "line 1", "line 2"3 golden apple, diamond sword named &6Excalibur
Duration30 minutes, 2 hours, 1 hour 30 minutes, 5 ticks30 minutes, 1 hour 30 minutes
Locationplayer's locationworld 10.5, 64, -3.25
set {%player%.backpack.item} to diamond sword named "Storage"
set {event.start_time} to 30 minutes
set {%player%.home} to player's location
give {%player%.backpack.item} to player
teleport player to {%player%.home}

Items are Minecraft material names written as plain words, with spaces instead of underscores. The name is checked when the script loads, so a misspelt item is reported straight away.

PartMeaning
<amount> in frontHow many; the default is 1
named <text>Custom display name; & colour codes work
fireworkShort for firework rocket, wherever an item is named: give 3 firework to player
owned by <name>For a player head: whose head it is, so it shows their skin
textured <value>For a player head: a skin of its own, for heads that are decoration and nobody's face. The value is what such heads are passed around as: the address of the skin on textures.minecraft.net, the code at its end, or the long text websites with heads give. Needs Minecraft 1.18.1 or newer; on an older server the head stays plain
with potion <kind>For a potion, splash potion, lingering potion or tipped arrow: what it holds. Kinds are the game's own: strength, long_swiftness, strong_healing and so on
with lore <text>, <text>, ...Description lines, one per text
enchanted with <enchantment> <level>, ...Enchantments, the game's or your own: enchanted with sharpness 5, unbreaking 3
unbreakableIt never wears out
glowingIt shimmers as an enchanted item does, without being enchanted
tagged <text>A hidden mark scripts can tell it by
model <number>The custom model number a resource pack draws it with

An item value can be given with give, shown in a GUI slot (slot 5 is {%player%.backpack.item}), kept in a list, or adjusted when used: give player 5 {%player%.backpack.item} gives five of it. Items carry a material, amount, name, lore, enchantments, the unbreakable and glowing marks, a hidden tag, a custom model number, a head's owner and a potion's kind. How worn an item is, is not kept.

Durations are a number followed by ticks, seconds, minutes, hours or days (the unit must be written out in full inside a script line), and may be chained: 1 hour 30 minutes.

  • In math and comparisons a duration counts as its number of seconds: 30 minutes > 60 is true and server.time + 30 minutes is the moment half an hour from now.
  • Adding or subtracting two durations gives a duration; any other arithmetic gives a number of seconds.
  • Wherever a statement takes a time, any duration works: for 10 seconds, for 2 minutes.

Locations remember a world and a position. player's location is where the player stands. A location can be used anywhere a position is expected: teleport player to {%player%.home}, spawn particle "flame" at {%player%.home}.

The parts of a location can be read and changed one at a time:

set {_loc} to player's location
add 1 to y of {_loc}
set x of {_loc} to 0
send "Going to %{_loc}%"
teleport player to {_loc}
SyntaxMeaningExample
type of <item>An item's material, e.g. diamond_sword; an entity's kindtype of tool of player
amount of <item>How many are in the stackamount of tool of player
amount of <item> in inventory of <who>How many of them the player carries, all stacks together; 0 for noneamount of diamond in inventory of player
x of <location>, y of <location>, z of <location>One coordinate, as a numbery of player's location
world of <location>The world's nameworld of {spawn}
set y of <variable> to <number>Change one part; add and subtract work tooadd 5 to y of {_spot}

Mixing types up. Each kind of value can only do what makes sense for it. Adding a number to a whole location, or doing math on an item, stops the trigger and writes a warning to the log that names the script, the line and both kinds of value:

[HyperScript] kits.hs:14 Cannot add a number to a location (world 10.5, 64, -3.25). To change one coordinate, name it: add 1 to y of <variable>

These warnings are on by default. log-script-errors: false in config.yml hides them; the trigger still stops at the mistake, so leave them on unless the log is being flooded.

Conditions

Guide and examples
if {%player%.coins} >= 100:
    send "&aYou can afford it."
else if {%player%.coins} >= 50:
    send "&eAlmost there."
else:
    send "&cNot enough coins."
OperatorTrue whenExample
==Equalplayer.world == "world_nether"
!=Not equalarg.1 != "off"
> < >= <=Numeric comparisonplayer.health <= 5
containsLeft text includes right text, or left list includes right value; does not contain is the oppositemessage contains "help"
is between <a> and <b>A number is in that range, ends includedplayer.y is between 0 and 64
is in <list>The list contains the valuearg.1 is in ["on", "off"]
is emptyUnset, empty text or an empty list{queue} is empty
is a list / a location / an item / a date / an entity / a table / textWhat kind of value it is{home} is a location
is a playerThe name of someone who is onlinearg.1 is a player
is alphanumericOnly letters and digitsarg.1 is alphanumeric
is sneaking / sprinting / swimming / blocking / sleeping / on ground / in waterWhat a player is doingplayer is sneaking
<who> is [not] ridingThey sit on or in something: a horse, a boat, a minecart. vehicle of <who> is whatplayer is riding
<who> is [not] looking at <target>Their crosshair is on it, give or take a few degrees. The target is a location or somebody; up to 100 blocks awayplayer is looking at arg.1
<who> is [not] in biome <name>Where they stand is that biome; a location works in place of a playerplayer is in biome "desert"
<number> is [not] (even/odd)A whole number that two goes into, or does notlevel of player is even
<number> is [not] divisible by <n>It can be divided by that with nothing left overlevel of player is divisible by 5
is op / is onlineAlso true or false for someone offlinearg.1 is online
has played beforeThey have joined at least once before; has not played before is the oppositearg.1 has played before
has saved inventory <name> / does not have saved inventory <name>An inventory was put away for them with save inventoryplayer has saved inventory "before-arena"
is holding <item> / is wearing <item>In either hand, or in an armour slotplayer is holding diamond sword
is in region <name> / is not in region <name>The player is inside a region made with create regionplayer is in region "spawn"
is on cooldown <name> / is not on cooldown <name>A cooldown started with start cooldown is still running for themplayer is on cooldown "kit"
can see <player>The other player is not hidden from themplayer can see arg.1
<world> is raining / is day / is nightAbout a world, by nameplayer.world is night
<block> is solidThe block type can be stood onblock at {_loc} is solid
<block> is liquidIt is water or lavablock at {_loc} is liquid
<block> is passableIt can be walked through: air, water, grass, flowers, torchesblock at {_loc} is passable
<block> is airNothing is thereblock at {_loc} is air
has space for <item>The items would fit in the inventoryplayer has space for 5 diamond
is bedrock / is deadOn the Bedrock edition (through Floodgate) / dead and not yet respawnedplayer is bedrock
<a> if <condition> else <b>Not a test but a choice: one value or the other"on" if {flag} else "off"
starts with / ends withThe text begins or ends with the other, ignoring casemessage starts with "!"
matchesThe whole text fits a regular expressionarg.1 matches "[a-z0-9_]{3,16}"
chance of <n>%True about that often, at randomif chance of 25%:
chance of <n>%:The same as a block of its own: its lines run about that often. An if chance of <n>%: without the if; use the if when there is an elsechance of 10%:
has <item>The player's inventory holds at least that manyplayer has 5 diamond
does not have <item>It holds fewerplayer does not have 1 "%{_material}%"
has permissionThe player holds the permissionplayer has permission "shop.vip"
does not have permissionThe player lacks the permissionplayer does not have permission "shop.vip"
has effect / does not have effectThe player has that potion effectplayer has effect speed
is frozen / is vanished / is flyingSee Playersarg.1 is frozen
is tagged / is not taggedThe item carries that hidden tagtool of player is tagged "wand"
is banned / is not bannedThe player is on the server's ban listarg.1 is banned
is set / is not setThe value exists / does not{%player%.coins} is not set
is a number / is not a numberThe value is numericarg.1 is a number
is / is notThe same as == / !=event.cause is "FALL", {%player%.frozen} is true
bigger than / smaller thanThe same as > / <. Also greater than, more than, larger than, higher than, and less than, lower than, fewer than. With or without is in front{_players} bigger than 50, {%player%.coins} is less than 10
at least / at mostThe same as >= / <=. Also greater than or equal to and less than or equal tolevel of player is at least 30
is equal to / is not equal toThe same as == / !=arg.1 is equal to "red"
is above / is belowThe same as > / <y of player's location is below 0
is between <a> and <b>Not less than the one and not more than the other; both ends count. is not between is the oppositelevel of player is between 10 and 20
any of <list> <condition>The condition holds for at least one element of the list. What follows the list is any condition about one value; are and have may be written for is and hasany of {_scores} is above 100
all of <list> <condition>It holds for every element; for an empty list that is trueall of {team} are online
and, or, notCombine conditions{_a} > 1 and not {locked}

A comparison can be written with its sign or in words; both mean the same:

command /check:
    trigger:
        set {_players} to server.online_players
        if {_players} bigger than 50:
            send "&aBusy today."
        if {_players} smaller than 5:
            send "&7Quiet today."
        if level of player is at least 30:
            send "&6You may enter."
        if level of player at most 5:
            send "&7You are new here."
        if arg.1 is equal to "red":
            send "&cRed it is."
        if arg.1 is not equal to "red":
            send "&7Not red."
        if y of player's location is below 0:
            send "&8Deep down."
        if y of player's location is above 200:
            send "&bHigh up."
        if level of player is between 10 and 20:
            send "&eIn the middle."
        if {_players} is greater than or equal to 1 and {_players} is not more than 100:
            send "&7Somebody is here."
  • On one line: a short if can have its statement on the same line, after the colon: if arg.1 is not set: stop. It takes one statement and has no else.
  • else unless <condition>: joins the chain alongside else if.
  • Every is test has an is not form: player is not sneaking, arg.1 is not in {allowed}.
  • unless <condition>: is if the other way round; it runs its block when the condition is false:
unless player has permission "fly.use":
    send "&cYou cannot fly here."
    stop
  • A bare value is a condition too: if {event_active}: is true for true, any non-zero number, any non-empty list, and any text other than false or empty.
  • ==, != and contains ignore case for text, and == compares numerically when both sides are numeric ("5" == 5 is true).
  • not binds tighter than and, which binds tighter than or. Use parentheses when in doubt.
  • player has permission "x" checks whoever triggered the script, so it is true for the console. To check someone else, put a name on the left: arg.1 has permission "x".
  • has <item> counts across the whole inventory, armour and off hand included. A plain item such as 5 diamond matches any diamonds; an item written with a name or lore only matches stacks that carry them. A player who is offline has nothing. Take items away with remove 5 diamond from player; see Actions.

Loops

Guide and examples
loop 3 times:
    send "Hello!"

for each {_name} in sorted server.players:
    send "&7 - &f%{_name}%"

loop all players: runs its block once for every player who is online:

loop all players:
    add 10 to {%loop-player%.coins}
    send "&a%player.name% gave you 10 coins!" to loop-player

Inside any loop, loop-value is what the loop is on: the number of the round, the element of the list, the player.

loop 3 times:
    send "&7Round %loop-value%"

loop from 10 to 1:
    send "&e%loop-value%..."
    wait 1 second
send "&aGo!"

loop from 0 to 100 by 25:
    send "&7%loop-value%%"

loop {queue}:
    send "&7%loop-index%. &f%loop-value%"

In a loop inside a loop the values are numbered from the outside in: loop-value-1 belongs to the first loop, loop-value-2 to the one inside it.

loop from 1 to 3:
    loop from 1 to 3:
        send "&7%loop-value-1% x %loop-value-2% = &f%loop-value-1 * loop-value-2%"

A loop can take some of what it goes through only, and say what to do when there was nothing:

loop all players with permission "staff.alerts":
    send "&c%player.name% needs help." to loop-player
else:
    send "&7No staff are online."

loop {queue} where loop-value is not player.name:
    send "&7%loop-index%. &f%loop-value%"

loop blocks within 3 blocks of player:
    if block at loop-value is "fire":
        set block at loop-value to air

A counter, and a table's names and values:

loop 5 times with {_i}:
    send "&7Round %{_i}%"

for each {_name}, {_place} in {warp}:
    send "&b%{_name}% &7is at %{_place}%"

break and continue steer a loop from inside:

for each {_name} in {queue}:
    if {_name} is "Steve":
        continue
    if size of {_picked} >= 3:
        break
    append {_name} to {_picked}

A while loop repeats for as long as its condition holds:

set {_n} to 3
while {_n} > 0:
    send "&e%{_n}%..."
    wait 1 second
    subtract 1 from {_n}
send "&aGo!"
  • loop <n> times: repeats its block. To protect the server it refuses more than 100,000 (loop-limit in config.yml changes that) repetitions.
  • for each {_item} in <list>: runs its block once per element, with the element in the local.
  • loop <n> times with {_i}: puts the number of the round, from 1, in the local.
  • loop from <a> to <b>: counts from the one number to the other, both included, and loop-value is the number: loop from 1 to 5 is 1, 2, 3, 4, 5 and loop from 5 to 1 is 5, 4, 3, 2, 1. by <n> is how far apart the numbers are: loop from 0 to 10 by 5 is 0, 5, 10, and loop from 0 to 1 by 0.25 works as well. Which way it counts is said by the two ends, so by is never negative, and it stops at the last number that does not pass the end: loop from 10 to 0 by 3 is 10, 7, 4, 1. The same limit as for loop <n> times applies.
  • loop <list>: goes through a list without a local to name: loop {queue}:, loop sorted server.players:. The element is loop-value. Given a number it goes round that many times, so loop {_n}: is loop {_n} times:.
  • loop-value is what the loop around the line is on. In loop <n> times and while that is the number of the round; in loop from the number; in for each and loop <list> the element (with for each {_key}, {_value} the value); in loop all players the player, like loop-player; in countdown the seconds left; in repeat the round. In text it is %loop-value%, and it can be written loop_value.
  • loop-index is which round the loop is on, from 1, whatever the loop goes through: "%loop-index%. %loop-value%" numbers a list.
  • In a loop inside a loop, loop-value-1 is the value of the outermost loop, loop-value-2 of the loop inside it, and so on; loop-index-1, loop-index-2 likewise. The plain loop-value is always the innermost loop's, the one the line is directly in. A number that no loop has (loop-value-3 inside two loops) is refused when the script loads, and so is loop-value outside a loop. To subtract from it, leave a space: loop-value - 1.
  • for each {_key}, {_value} in {table}: goes through every name under a table and the value stored there, for saved tables ({warp}, {%player%.homes}) and local ones ({_data}) alike.
  • repeat every <time> for <time>: runs its block, waits, and runs it again until the time is up; see Waiting.
  • countdown 10 seconds: is a repeat that counts: its block runs once a second and seconds left is 10, then 9, down to 1. The lines after the block run when it has reached the end, so they are where "Go!" belongs. break ends it early.
  • once every 5 seconds for player: runs its block at most that often for each player, which is a cooldown around any lines you like; else: under it is where "wait a moment" goes. It can also be written at most once every 5 seconds for player:.
  • once for player: runs its block the first time a player gets there and never again; once per day for player: once in each day by the server's calendar, so a reward taken at 23:59 can be taken again at 00:00. Put a name after once (once "daily" per day for player:) if the block may be moved or changed later: without one HyperScript tells the once blocks of a script apart by what they say, and one that is rewritten counts as new. else: works as after if.
  • loop all players: goes through whoever is online when it starts. Inside it, loop-player (in text, %loop-player%) is the name of the player the loop is on (it can also be written loop player or loop_player, which are the same word), and player is still whoever ran the command or caused the event. Everything that takes a player takes loop-player: loop-player's location, health of loop-player, {%loop-player%.coins}, send "..." to loop-player, loop-player has permission "x". loop-number is which round the loop is on, starting at 1; it is the same as loop-index and works in every loop.
  • loop all players takes what says which of them: with permission "<node>", in world "<name>", within <n> blocks of <location>, or where <condition>, in which loop-player is each player in turn: loop all players where health of loop-player < 5:. The same works wherever something is done to all players: send "..." to all players with permission "staff", send title "Go!" to all players in world "arena".
  • loop <list> where <condition>: goes through the elements the condition holds for only; in the condition loop-value is the element. loop-index then counts the ones that were kept.
  • Anything that gives a list can be looped over: loop blocks within 3 blocks of player: and loop blocks from {_a} to {_b}: (each loop-value is the location of a block, so block at loop-value is what is there), loop entities within 10 blocks of player:, loop players within 10 blocks of player:, loop items in inventory of player:. Blocks are counted before the loop starts, and more than loop-limit of them are refused.
  • else: directly under a loop runs when the loop never went round: the list was empty or was never set, nobody was online, the condition of a while did not hold the first time.
  • while <condition>: checks the condition before every round.
  • break loop 1 and continue loop 1 reach a loop further out, by the same numbers as loop-value-1: 1 is the outermost. break loop 1 leaves that loop and every loop inside it; continue loop 1 ends the loops inside it and starts its next round. They take a condition like the plain ones: break loop 1 if {_found} is set.
  • break leaves the loop it is in and carries on after it. continue skips the rest of this round and starts the next. In nested loops both act on the innermost one.
  • stop inside a loop ends the whole trigger, not just the loop.
  • All three take a condition on the same line: stop if {_coins} < 100, continue if loop-player is player.name, break unless {_found} is set. stop with <text> tells the player something first: stop with "&cNot enough coins." if {_coins} < 100.
  • A while loop that goes round 100,000 times (loop-limit in config.yml) without a wait is stopped with an error in the console, so a condition that never becomes false cannot freeze the server. A loop that waits each round may run for as long as you like.

Switch

Guide and examples

switch runs one block out of several, chosen by a value. It reads better than a chain of else if when a command has many subcommands:

switch arg.1:
    case "on", "enable":
        set {event_active} to true
    case "off", "disable":
        set {event_active} to false
    default:
        send "&eUsage: /event <on|off>"
  • The first case with a matching value runs, and only that one; there is no falling through.
  • A case may list several values, separated by commas. Text is compared ignoring case, as == does.
  • case 1 to 5: is every number from the one to the other, both included, and can stand in a list with others: case 1 to 5, 10, 20 to 30:.
  • default: runs when nothing matched. It is optional.

Functions

Guide and examples

A function is a block with a name. Write it once, at the left margin like a command, and call it from anywhere:

function reward({_who}, {_amount}):
    add {_amount} to {%{_who}%.coins}
    send "&a+%{_amount}% coins" to {_who}
    return {%{_who}%.coins}

command /daily:
    cooldown: 1 day
    trigger:
        set {_total} to reward(player.name, 50)
        send "&7You now have %{_total}% coins."
FormCan be called from
function <name>(<locals>):Any script
local function <name>(<locals>):Only the file it is written in
  • The values in the brackets arrive in the locals named there. A function with nothing to take is written function refresh(): and called refresh().
  • A parameter may have a default: function reward({_who}, {_amount} = 10): can be called as reward(player.name) or reward(player.name, 50). Parameters with a default come last.
  • Call a function on a line of its own (reward(player.name, 50)) or anywhere a value is expected (set {_total} to reward(player.name, 50), if is_rich(player.name):).
  • return <value> leaves the function and hands the value back; return on its own just leaves. A function that never returns a value gives unset.
  • Inside a function, player and the event values are those of whoever called it. Its locals are its own: it cannot see the caller's locals, and the caller cannot see its.
  • A plain function is shared by every script, in whatever order the files load, so two scripts may not both define a shared function of the same name; the second one is refused with a message naming the first. Use local function for helpers that only one file needs. When both exist, a file's own local function is the one it gets.
  • Function names are letters, digits and _, and may not be a word that starts a statement, such as send or give.
  • A function may call itself. Calls nested more than 64 deep are stopped with an error, so one that never ends cannot freeze the server.
  • A wait inside a function pauses the function only: the caller carries on at once, and gets whatever had been returned by then (normally nothing).

Waiting

Guide and examples

wait pauses the trigger it is in, then carries on with the next line. Only that trigger pauses; the server and every other script keep running.

command /launch:
    trigger:
        send "&eLaunching in 3 seconds..."
        wait 3 seconds
        execute console command "effect give %player.name% minecraft:levitation 2 20"
        wait 2 seconds
        send "&aEnjoy the view."
SyntaxMeaning
wait <duration>Any duration: wait 10 ticks, wait 5 seconds, wait 1 minute 30 seconds
wait <number> secondsThe number may be a variable: wait {_delay} seconds
  • wait works anywhere, including inside if, loops, GUI click blocks and async:. Local variables keep their values across it.
  • Time passes while a trigger waits. The player may have moved or logged out, and variables may have been changed by other scripts, so check again afterwards if it matters.
  • After a wait, the event that started the trigger is over: cancel event and statements that change the event, such as set join message, no longer have any effect.
  • The shortest wait is one tick (a twentieth of a second). Waits do not survive a server restart or a script reload.

Waiting for something. wait until pauses until a condition holds, looking again four times a second:

send "&7Stand on the gold block to start."
wait until block at (location below player's location) is "gold_block" for at most 30 seconds
send "&aGo!"

It gives up after the time given with for at most, or after five minutes if none is given, and the script carries on either way; test the condition again afterwards if it matters.

Doing something later, and again. run calls a function after a delay without making the rest of the trigger wait, and repeat runs a block at intervals for a while:

function unfreeze_later({_who}):
    unfreeze {_who}
    send "&aYou can move again." to {_who}

command /timeout <player>:
    permission: "staff.timeout"
    trigger:
        freeze arg.1
        run unfreeze_later(arg.1) in 30 seconds

command /countdown:
    trigger:
        set {_n} to 10
        repeat every 1 second for 10 seconds:
            send title "&e%{_n}%" to all players
            subtract 1 from {_n}
SyntaxEffect
wait until <condition> [for at most <duration>]Pause until it is true
wait between <duration> and <duration>Pause for some time between the two, another every time: wait between 1 and 3 seconds, wait between 10 ticks and 1 second
after <duration>:Run the block under it that much later, on its own: the lines below the block carry on at once. Inside it the local variables are as they were when the after was reached
run <function>(...) in <duration>Call a function later
run <function>(...) in <duration> as <name>The same, under a name it can be called off by
schedule <function>(...) in <duration>Like run ... in, but written down: the call still happens after a restart. Add as <name> to be able to replace it or call it off
cancel schedule <name>Call off a named schedule that has not happened yet
time until schedule <name>How long a named schedule still has; unset if nothing waits under that name, so is set says whether one is pending
cancel run <name>Call off a named run that has not happened yet
repeat every <duration> for <duration>:Run a block now and then again at each interval
countdown <duration>:Run a block once a second, with seconds left counting down to 1; what comes after the block runs when it is over
once for <who>:Run a block the first time only, for each player; else: under it runs every other time
once per day for <who>:The same once in each day; also per hour, per week, per month, or per 30 minutes for that long after the last time
once:Without for: once for the whole server

Handling errors

Guide and examples

Normally a line that cannot be done stops the trigger and reports the mistake. try: lets a script deal with it instead:

try:
    set {_data} to send get request to "https://hyperscript.monoforge.net/api/test"
    log "The website answered: %{_data}%"
on error:
    log "Could not reach the website: %{_error}%"

https://hyperscript.monoforge.net/api/test is a real address kept for trying requests out: it answers with the plain text Yup works.

  • If anything in the try: block fails, the rest of the block is skipped and the on error: block runs, with {_error} holding the message.
  • on error: is optional. Without it the failure is simply ignored and the script carries on.
  • fail "<text>" is a mistake of your own making: the trigger stops there as it does for any other, and a try: around it, also one in the code that called the function it is in, gets the text in {_error}. Outside a try: it ends the trigger and is written to the console.
  • Only mistakes made while running are caught. A line HyperScript cannot read still stops the whole file from loading.
  • A failure after a wait inside the block is not caught; put the try: after the wait.

Complete example: demo.hs

Show Complete example: demo.hs

This is the file installed to plugins/HyperScript/scripts/disabled_demo.hs on first start, switched off until /hyperscript enable demo (source). It uses commands, every event, math, persistent variables, a GUI, lists, an async block, world effects, cooldowns, titles, a boss bar, an opt-in sidebar driven by a timer, a custom item, a stored location, a text file per player, sounds, a protected region, time and weather, a web API lookup read with json value, fall-damage protection, a countdown built from while and wait, a function, parse, another player's variables, loop all players, inventory checks, and ends with Discord examples that are commented out until config.yml is set up.

# ==============================================================
#  demo.hs - a tour of HyperScript
#  Edit this file, then run /hyperscript reload
# ==============================================================

# ---- Events --------------------------------------------------

on player join:
    if {%player%.joins} is not set:
        set {%player%.joins} to 0
        set {%player%.coins} to 100
        broadcast "&6Welcome &e%player.name% &6to the server for the first time!"
    add 1 to {%player%.joins}
    send "&aHello %player.name%! &7Visit #%{%player%.joins}%, balance &e%{%player%.coins}% coins"
    send "&7Server %server.version% | TPS %server.tps% | Online %server.online_players%"
    if {event_active}:
        send "&d&lThe double coins event is active!"

on player quit:
    log "%player.name% left with %{%player%.coins}% coins (ping %player.ping% ms)"

on block break:
    # Regions made with /protect: only admins may break blocks inside them.
    if region at event's location contains "spawn":
        if player does not have permission "demo.admin":
            cancel event
            send "&cYou cannot break blocks inside the spawn region!"
            play sound "block.anvil.land" with pitch 0.5 and volume 1.0 at player's location
            stop
    set {_reward} to random integer between 1 and 3
    if event.block contains "ore":
        set {_reward} to {_reward} * 5
    if player has permission "demo.vip":
        set {_reward} to {_reward} + 2
    if {event_active}:
        set {_reward} to {_reward} * 2
    add {_reward} to {%player%.coins}
    add 1 to {%player%.blocks}
    # Every 50th block pays a bonus.
    if {%player%.blocks} % 50 == 0:
        add 25 to {%player%.coins}
        send "&b%{%player%.blocks}% blocks mined! &6+25 bonus coins"
        play sound "entity.player.levelup" with pitch 1.2 and volume 0.8 for player

on entity death:
    # The player here is the killer; there is none when a mob dies on its own.
    if event.killer is set:
        set {_bounty} to random integer between 5 and 15
        add {_bounty} to {%player%.coins}
        send "&6+%{_bounty}% coins &7for slaying a %event.entity%"

on player chat:
    # Inside an event, its values have short names: "message" is event.message.
    if message contains "free op":
        cancel event
        send "&cThat phrase is not allowed here."

on entity damage:
    # Fires for every hit on the server, so the cheapest test comes first.
    if cause is "FALL":
        if player has permission "demo.nofall":
            cancel event
            send action bar "&aFall damage negated!" to victim

on right click:
    # At most once every 2 seconds per player; clicks in between are ignored.
    cooldown: 2 seconds
    if event.item == "compass":
        send "&bWorld &f%player.world% &7| &bMode &f%player.gamemode% &7| &bHealth &f%player.health%"

# ---- Commands ------------------------------------------------

command /coins:
    description: Show your coin balance
    usage: /coins
    aliases: bal, balance
    trigger:
        if player is not set:
            send "&cOnly players have a balance."
            stop
        send "&6Balance: &e%{%player%.coins}% coins"

command /gamble:
    description: Bet coins on a 45% chance to double them
    usage: /gamble <amount>
    permission: demo.gamble
    permission message: "&cYou are not allowed to gamble."
    aliases: bet
    trigger:
        if player is not set:
            send "&cOnly players can gamble."
            stop
        if args.count != 1 or arg.1 is not a number:
            send "&cUsage: /gamble <amount>"
            stop
        set {_bet} to arg.1
        if {_bet} <= 0:
            send "&cThe bet must be more than 0."
        else if {_bet} > {%player%.coins}:
            send "&cYou only have %{%player%.coins}% coins."
        else if random integer between 1 and 100 <= 45:
            add {_bet} to {%player%.coins}
            send "&aYou won %{_bet}% coins! &7Balance: %{%player%.coins}%"
        else:
            subtract {_bet} from {%player%.coins}
            send "&cYou lost %{_bet}% coins. &7Balance: %{%player%.coins}%"

command /event:
    description: Toggle the double coins event
    usage: /event <on|off>
    permission: demo.admin
    trigger:
        if arg.1 == "on":
            set {event_active} to true
            broadcast "&d&lDouble coins event started!"
            create bossbar "event" titled "&d&lDouble Coins Event" with color purple with progress 100 for all players
        else if arg.1 == "off":
            set {event_active} to false
            broadcast "&7The double coins event has ended."
            remove bossbar "event"
        else:
            send "&eEvent active: %{event_active}% &7- usage: /event <on|off>"

# ---- GUIs, lists, async and world effects --------------------

command /shop:
    description: Open the coin shop
    usage: /shop
    trigger:
        if player is not set:
            send "&cOnly players can open the shop."
            stop
        open gui with title "&8Coin Shop" with 3 rows for player:
            slot 12 is "diamond" named "&bDiamond" lore "&7Price: &e50 coins|&7Click to buy":
                if {%player%.coins} < 50:
                    send "&cYou need 50 coins for that."
                else:
                    subtract 50 from {%player%.coins}
                    execute console command "give %player.name% diamond 1"
                    spawn particle "dust" colored "#55ffff" count 20 at player
                    send "&aBought a diamond. &7Balance: %{%player%.coins}%"
                close gui
            slot 14 is "gold_ingot" named "&6Balance: &e%{%player%.coins}% coins"
            slot 16 is "barrier" named "&cClose":
                close gui

command /who:
    description: List online players in alphabetical order
    usage: /who
    trigger:
        send "&6Online (%server.online_players%):"
        for each {_name} in sorted server.players:
            send "&7 - &f%{_name}%"

command /sethome:
    description: Remember where you are standing
    usage: /sethome
    trigger:
        if player is not set:
            stop
        # A variable can hold a location (world and coordinates) as one value.
        set {%player%.home} to player's location
        spawn text display "&e%player.name%'s home" at player for 10 seconds
        send "&aHome set."

command /home:
    description: Return to your home
    usage: /home
    trigger:
        if {%player%.home} is not set:
            send "&cUse /sethome first."
            stop
        teleport player to {%player%.home}
        send "&aWelcome home. &7(%{%player%.home}%)"

command /highscores:
    description: Show the balances recorded with /cashout
    usage: /highscores
    trigger:
        # {scores} is a list; /cashout appends to it.
        async:
            # Sorting and filtering run off the server thread...
            set {_ranked} to reversed sorted {scores}
            set {_count} to size of {_ranked}
            set {_best} to item 1 of {_ranked}
            set {_rich} to size of (filter {_ranked} where it >= 500)
            sync:
                # ...and the result is reported back on it.
                if {_count} == 0:
                    send "&7No scores yet. Use /cashout to record yours."
                else:
                    send "&6Best score: &e%{_best}% &7(%{_count}% recorded, %{_rich}% of 500 or more)"

command /cashout:
    description: Record your current balance on the high score list
    usage: /cashout
    trigger:
        if player is not set:
            stop
        append {%player%.coins} to {scores}
        send "&aRecorded &e%{%player%.coins}% &aon the high score list."

# ---- Functions, other players and parsing --------------------

# A function can be called from any script. Written as "local function"
# it could only be used in this file.
function pay({_from}, {_to}, {_amount}):
    subtract {_amount} from {%{_from}%.coins}
    add {_amount} to {%{_to}%.coins}
    return {%{_to}%.coins}

command /pay <player> <amount>:
    description: Give some of your coins to another player
    usage: /pay <player> <amount>
    trigger:
        if player is not set:
            stop
        # Arguments arrive as text; parse turns "52" into the number 52.
        set {_amount} to parse arg.2 as integer
        if {_amount} is not set or {_amount} < 1:
            send "&c'%arg.2%' is not an amount."
            stop
        # A name that starts with a player is that player's own variable,
        # whether they are online or not.
        if {%arg.1%.joins} is not set:
            send "&c%arg.1% has never played here."
            stop
        if {%player%.coins} < {_amount}:
            send "&cYou only have %{%player%.coins}% coins."
            stop
        set {_total} to pay(player.name, arg.1, {_amount})
        send "&aSent &e%{_amount}% &acoins to %arg.1%."
        send "&e%player.name% &asent you &e%{_amount}% &acoins. You now have &e%{_total}%&a." to arg.1

command /bonus <amount>:
    description: Give every online player some coins
    usage: /bonus <amount>
    permission: op
    trigger:
        set {_amount} to parse arg.1 as integer
        if {_amount} is not set:
            send "&cUsage: /bonus <amount>"
            stop
        # "player" is still whoever ran the command; "loop-player" is each player in turn.
        loop all players:
            add {_amount} to {%loop-player%.coins}
        send "&6Everybody received &e%{_amount}% &6coins from %player.name%!" to all players

command /sell:
    description: Sell 8 cobblestone for 4 coins
    usage: /sell
    trigger:
        if player does not have 8 cobblestone:
            send "&cYou need 8 cobblestone to sell."
            stop
        remove 8 cobblestone from player
        add 4 to {%player%.coins}
        send "&aSold 8 cobblestone for &e4 coins&a."

on player death:
    subtract 5 from {%player%.coins}
    send "&cYou died and lost 5 coins."

# ---- Cooldowns, titles, scoreboards and particle shapes ------

command /kit:
    description: Claim a starter kit once an hour
    usage: /kit
    cooldown: 1 hour
    cooldown message: "&cYou must wait %cooldown% before using /kit again!"
    trigger:
        if player is not set:
            send "&cOnly players can claim a kit."
            stop
        give 1 diamond to player
        give 16 bread to player
        send title "&6Kit claimed!" with subtitle "&eCome back in an hour" to player with fadein 10 stay 60 fadeout 20
        send action bar "&a+1 Diamond  +16 Bread" to player
        draw particle circle with radius 1.5 using particle "flame" at player's location

command /sidebar:
    description: Show or hide the stats sidebar
    usage: /sidebar
    trigger:
        if player is not set:
            stop
        if {%player%.sidebar}:
            set {%player%.sidebar} to false
            clear player's scoreboard
            send "&7Sidebar hidden."
        else:
            set {%player%.sidebar} to true
            send "&aSidebar shown."

# Runs once a second for every online player; only those who asked get the sidebar.
every 1 second for all players:
    if {%player%.sidebar}:
        set title of player's scoreboard to "&e&lHYPERSCRIPT"
        set line 1 of player's scoreboard to "&7Coins: &a%{%player%.coins}%"
        set line 2 of player's scoreboard to "&7Ping: &f%player.ping% ms"
        set line 3 of player's scoreboard to "&7Online: &f%server.online_players%"
        set line 4 of player's scoreboard to "&7TPS: &f%server.tps%"

# ---- Custom items, files and text ----------------------------

command /excalibur:
    description: Receive a named sword, once a day
    usage: /excalibur
    cooldown: 1 day
    trigger:
        if player is not set:
            send "&cOnly players can wield it."
            stop
        give player 1 diamond sword named "&6Excalibur" with lore "&7A legendary blade", "&7Forged in fire."
        # Items are values too: remember what was handed out.
        set {%player%.last_reward} to diamond sword named "&6Excalibur"
        send "&aYou received &f%{%player%.last_reward}%&a."

command /note:
    description: Save a note to a text file, or read it back
    usage: /note [text]
    trigger:
        if player is not set:
            stop
        # One file per player, named by UUID so nothing a player types ends up in the path.
        set {_path} to "plugins/HyperScript/notes/%player.uuid%.txt"
        if args.count > 0:
            set file at {_path} to args
            send "&aNote saved."
        else if file at {_path} exists:
            set {_note} to read file at {_path}
            set {_words} to split {_note} by " "
            set {_count} to size of {_words}
            set {_shout} to uppercase (first 20 characters of {_note})
            send "&eYour note (%{_count}% words): &f%{_note}%"
            send "&7Starts with: &f%{_shout}%"
        else:
            send "&7You have no note yet. Write one with /note <text>"

# ---- Worlds, regions, sounds and web requests ----------------

command /day:
    description: Set the time to day and clear the weather in your world
    usage: /day
    permission: demo.admin
    trigger:
        if player is not set:
            send "&cRun this as a player, so there is a world to change."
            stop
        set time in world "%player.world%" to 1000
        set weather in world "%player.world%" to clear
        broadcast "&e%player.name% set the time to day in %player.world%!"
        play sound "block.note_block.pling" with pitch 2.0 and volume 0.5 for all players in world "%player.world%"

command /protect:
    description: Protect the area within 5 blocks of you as the spawn region
    usage: /protect
    permission: demo.admin
    trigger:
        if player is not set:
            stop
        create region "spawn" from player.x - 5, 0, player.z - 5 to player.x + 5, 255, player.z + 5
        send "&aSpawn region set around you. Remove it with /unprotect."

command /unprotect:
    description: Remove the spawn region
    usage: /unprotect
    permission: demo.admin
    trigger:
        delete region "spawn"
        send "&7Spawn region removed."

command /lookup <player>:
    description: Look up a player's UUID using Mojang's web API
    cooldown: 5 seconds
    trigger:
        if args.count != 1:
            send "&cUsage: /lookup <player>"
            reset cooldown
            stop
        send "&eFetching data from the API..."
        # Web requests wait for an answer, so they belong in an async block.
        async:
            set {_response} to send get request to "https://api.mojang.com/users/profiles/minecraft/" + urlencoded arg.1
            # The answer is JSON such as {"id":"...","name":"..."}; pick the id out of it.
            set {_uuid} to json value "id" of {_response}
            sync:
                if {_uuid} is set:
                    send "&aUUID of %arg.1%: &f%{_uuid}%"
                else:
                    send "&cPlayer profile not found."

command /countdown:
    description: Count down from 3, one number a second
    usage: /countdown
    cooldown: 10 seconds
    trigger:
        set {_n} to 3
        # 'wait' pauses this trigger only; the server carries on as normal meanwhile.
        while {_n} > 0:
            send title "&e%{_n}%" to player with fadein 0 stay 20 fadeout 5
            play sound "block.note_block.pling" for player
            wait 1 second
            subtract 1 from {_n}
        send title "&aGo!" to player

# ---- Server list, tab list and chat (remove the leading '#' to use) ----
#
# on server ping:
#     set motd to random item of ["&6HyperScript demo server", "&bNow with double coins!"]
#     set max players to 100
#
# on player join:
#     set join message to "&a+ &f%player.name%"
#     set tab header of player to "&6&lMy Server"
#     set tab footer of player to "&7Online: %server.online_players%"
#
# on player chat:
#     set chat format to "&7[&bMember&7] &f%player.name%&7: &f%event.message%"

# ---- Resource packs (remove the leading '#' and use your own pack) ----
#
# on player join:
#     send resource pack "https://example.com/pack.zip" with hash "da39a3ee5e6b4b0d3255bfef95601890afd80709" to player
#
# on resource pack decline:
#     send "&cYou declined the resource pack. Some custom items may look wrong."
#
# on resource pack successfully loaded:
#     send "&aResource pack loaded!"

# ---- Discord (remove the leading '#' after setting up config.yml) ----
#
# Webhooks need a URL under discord.webhooks in config.yml:
#
# on player join:
#     send webhook "alerts" with content "%player.name% joined the server" as "HyperScript"
#
# Slash commands need discord.bot.enabled and a bot token:
#
# on discord command "/online":
#     reply "%server.online_players% player(s) online: %server.players%"

Working with values

Text, numbers, lists and dates, and the values the server hands a script.

Text

Guide and examples
SyntaxResultExample
split <text> by <separator>A list of the piecessplit "Coins:500" by ":" gives Coins, 500
join <list> with <separator>The elements as one textjoin {_names} with ", "
uppercase <text> / lowercase <text>Changed caseuppercase "hi" gives HI
trimmed <text>Without spaces at either endtrimmed " hi " gives hi
replace <a> with <b> in <text>Every <a> replacedreplace "_" with " " in "diamond_sword"
replace regex <pattern> with <b> in <text>Every part the regular expression fits, replacedreplace regex "\\d+" with "#" in "a12 b345" gives a# b#
regex matches of <pattern> in <text>A list of every part that fitsregex matches of "\\d+" in "a12 b345" gives 12, 345
regex groups of <pattern> in <text>What the brackets of the pattern caught in the first part that fits, as a list; the whole part if the pattern has no brackets; empty if nothing fitsregex groups of "(\\w+)=(\\d+)" in "coins=250" gives coins, 250
first <n> characters of <text>The start of the textfirst 3 characters of "Hello" gives Hel
last <n> characters of <text>The end of the textlast 2 characters of "Hello" gives lo
characters <a> to <b> of <text>A slice, counting from 1, both ends includedcharacters 2 to 4 of "Hello" gives ell
length of <text>Number of characterslength of "Hello" gives 5
rounded <number>The nearest whole numberrounded 2.5 gives 3
json of <value>A list, a local table, a number or text written out as JSON, ready to sendjson of ["a", 2] gives ["a",2]
json value <path> of <text>A value out of JSON text; see Web requestsjson value "id" of {_response}
parse <text> as numberThe text as a number; unset if it is not one. An amount written short counts: 1.5k is 1500, 2m two million, 1b a thousand millionparse "52" as number gives 52
parse <text> as integerThe same, rounded down to a whole numberparse "7.9" as integer gives 7
parse <value> as textA number or any other value as textparse 52 as text gives "52"
parse <text> as timeText such as "1h 30m", "90 seconds" or "2 days and 4 hours" as a duration; unset if it is not one. Also written as durationparse "1h 30m" as time gives 1 hour 30 minutes
bar of <part> out of <whole>A bar of ten characters, as much of it filled as part is of whole. Add with <n> characters, using "<character>" and colored "<filled>" and "<rest>" as wantedbar of 3 out of 10 gives &a███&7███████
random text of <n> charactersLetters and digits picked at random, without the ones that look alike (0 and O, 1 and l): for vouchers and codesrandom text of 8 characters gives something like kT7mQ2xp
random code of <n> digitsDigits onlyrandom code of 4 digits gives something like 0382
new idAn id that nothing else has, 36 characters longnew id
try parse <text> as numberThe same as parse, for those who like it said: text that is not a number gives unset, never an error. Works with integer and text tootry parse "abc" as number is not set
duration(<seconds>)Seconds as readable timeduration(125) gives 2 minutes 5 seconds
capitalized <text>The first letter in upper casecapitalized "hello" gives Hello
title case <text>Every word capitalised; underscores become spacestitle case "diamond_sword" gives Diamond Sword
uncoloured <text>Without colour codesuncoloured "&aHi" gives Hi
word <n> of <text>One word, counting from 1word 2 of "one two three" gives two
<text> repeated <n> timesThe text over and over"=" repeated 20 times
<text> padded to <n>Spaces added at the end (or in front, with padded left to), for lining things up"Name" padded to 12
<text> shortened to <n>Cut to that many characters, the last of them …, if it is longer; colour codes are not counted"Hello world" shortened to 8 gives Hello w…
<text> wrapped to <n>A list of lines no longer than that, broken between words, each going on in the colour the one before ended in. For lore and signs{_about} wrapped to 30
<text> centered to <n>Spaces on both sides, so that the text stands in the middle of that many characters; colour codes are not counted"SHOP" centered to 20
between(text, before, after)What stands between two pieces of a text; unset if either is not therebetween("Hello [world]!", "[", "]") gives world
<text> parsed as numberThe same as parse ... as number, written after the value; also integer, text, player, offlineplayerarg.1 parsed as number
<text> as offlineplayerA player by name, online now or not. For somebody who has played here it is the name as the server has it; has played before says whether they have. Also written as offline player, parsed as offlineplayer and parse <text> as offlineplayer"Progamer52" as offlineplayer
now formatted as <pattern>The date and time, written the way the pattern saysnow formatted as "HH:mm" gives 18:30
urlencoded <text>Made safe to put inside a URLurlencoded "a b&c" gives a%20b%26c
<text> contains <text>Whether one includes the other, ignoring casemessage contains "help"
<text> + <text>Joined"Level " + 5 gives Level 5
command /banner <text>:
    trigger:
        set {_title} to arg.1 centered to 30
        send "&8[&f%{_title}%&8]"
        for each {_word} in words of "red green blue":
            send "&7%{_word}%"
        set {_inner} to between("Hello [world]!", "[", "]")
        set {_bar} to lerp(0, 20, 0.25)
        send "&7%{_inner}% %{_bar}%"
set {_data} to "Coins:500"
set {_parts} to split {_data} by ":"
set {_coins} to item 2 of {_parts} + 100
send "You have %{_coins}% coins"
  • parse is how text that came from a player, a file or a web page becomes a number you can rely on. If the text is not a number the result is unset, which is easy to test for:
set {_amount} to parse arg.1 as number
if {_amount} is not set:
    send "&c'%arg.1%' is not a number."
    stop
  • Directly after send, the word title means a title on screen, so put title case in a variable first or in brackets: send (title case {_item}).
  • Any colour: besides &a style codes, text may use <#rrggbb> for an exact colour, as in "<#ff8800>Orange <#00c8ff>and blue". It works wherever colour codes do, on Minecraft 1.16 and newer.
  • now formatted as takes Java's date letters: yyyy year, MM month number, MMMM month name, d day, EEEE weekday name, HH hour, mm minute, ss second. "d MMMM yyyy 'at' HH:mm" gives 11 October 2026 at 18:30. Text inside single quotes is taken as it is.
  • The separator in split is taken literally, and splitting by "" gives the single characters.
  • Pieces of split text still work as numbers, as item 2 of {_parts} + 100 shows.
  • Slices that run past either end of the text are cut to fit; they never cause an error.
  • Each of these takes the single value right after it. To apply one to a longer expression, use parentheses: uppercase (first 3 characters of {_name}).
  • A new line in text is written %nl%, or %new line%: send "&6Rules%nl%&71. Be kind". It works in every text: chat, holograms, lore, files, and text in front of a player.

Math

Guide and examples
OperatorMeaningExampleResult
+Add7 + 29
-Subtract, or negate7 - 25
*Multiply7 * 214
/Divide7 / 23.5
%Modulo (remainder)7 % 21
( )Grouping(7 + 2) * 218
random integer between A and BWhole number, both ends includedrandom integer between 1 and 101..10
random number between A and BDecimal numberrandom number between 0 and 1e.g. 0.4217

*, / and % bind tighter than + and -, as usual.

FunctionResultExample
min(a, b, ...) / max(a, b, ...)The smallest / largest; also takes one listmax(1, {%player%.level})
abs(n)Without its signabs(-7) gives 7
round(n)The nearest whole numberround(2.5) gives 3
floor(n) / ceil(n)Rounded down / upceil(2.1) gives 3
rounded up <n> / rounded down <n>The same two, in wordsrounded up 2.1 gives 3
sqrt(n)Square rootsqrt(25) gives 5
pow(a, b)a to the power of bpow(2, 10) gives 1024
round(n, places)Rounded to that many decimal placesround(3.14159, 2) gives 3.14
percent(part, whole)What percentage the first is of the secondpercent(3, 12) gives 25
commas(n)A number with thousands separators, as textcommas(1234567) gives 1,234,567
ordinal(n)1st, 2nd, 3rd, ...ordinal(22) gives 22nd
plural(n, word)The number with the word, in the plural unless it is 1. A third value is the word for many, where an s is not itplural(5, "coin") gives 5 coins; plural(2, "wolf", "wolves") gives 2 wolves
roman(n)Roman numerals, 1 to 3999roman(14) gives XIV
format(n, pattern)The number written the way the pattern says: 0 is a digit that is always shown, # one that is shown only if neededformat(3.14159, "0.00") gives 3.14
clamp(n, least, most)The number, kept within the twoclamp(120, 0, 100) gives 100
lerp(from, to, t)The number that far along from the one to the other: t is 0 at the start and 1 at the endlerp(10, 20, 0.25) gives 12.5
random(a, b)A random number from a to b; whole if both are wholerandom(1, 6)
duration(seconds)A number of seconds as a duration, which reads as words in a messageduration(90) gives 1 minute 30 seconds
short(n)A large number in a few characters: k for thousands, then M, B, Tshort(1250) gives 1.3k, short(3400000) gives 3.4M
money(n)An amount of money, with commas and two decimals, the way money-format in config.yml says: "$%amount%" unless changedmoney(1250.5) gives $1,250.50
lerp(a, b, t)With two colours, the colour t of the way from the one to the other; with two locations, the place. With numbers it is the number, as beforelerp("#ff0000", "#0000ff", 0.5) gives #800080
mix(a, b)The colour between two; a third value says how much of the second, from 0 to 1mix("#ff0000", "#0000ff") gives #800080
lighten(colour, amount)The colour that far towards white, from 0 to 1; 0.2 if left outlighten("#ff0000", 0.5) gives #ff8080
darken(colour, amount)The colour that far towards blackdarken("#ff0000", 0.5) gives #800000
rainbow(t)A colour of the rainbow: red at 0, green at a third, blue at two thirds, red again at 1, and round again from thererainbow(0.33) is green
rgb(red, green, blue)A colour from three numbers, 0 to 255 eachrgb(255, 136, 0) gives #ff8800
sin(angle), cos(angle), tan(angle)The sine, cosine and tangent of an angle in degrees, as the game's own angles aresin(90) gives 1
asin(n), acos(n), atan(n)The angle, in degrees, that has that sine, cosine or tangentatan(1) gives 45
atan2(up, along)The angle of a slope that goes that far up over that far along; right all the way roundatan2(1, 1) gives 45
distance between <a> and <b>Blocks between two locations; unset if they are in different worldsdistance between player's location and {spawn}
horizontal distance between <a> and <b>The same on the map alone, whatever the two heightshorizontal distance between player's location and {spawn}
set {%player%.coins} to {%player%.coins} + 50
set {_rand} to random integer between 1 and 10
set {_tax} to ({%player%.coins} - 100) * 0.05
add 5 to {%player%.coins}            # shorthand for set ... to ... + 5
subtract {_tax} from {%player%.coins}  # shorthand for set ... to ... - {_tax}

Details:

  • + adds when both sides are numbers and joins text otherwise: "Level " + 5 is Level 5. Text that looks like a number counts as a number, so arg.1 + 1 adds.
  • Numbers print without a trailing .0; other decimals are shown to at most 4 places.
  • Dividing (or taking a modulo) by zero, or doing math on non-numeric text, stops the trigger and logs a warning with the script name and line.
  • These functions come with the language, so a script cannot define a function called min, round and so on.
  • duration(...) is how a number of seconds becomes readable: set {_left} to duration({%player%.ready} - server.time) then send "Wait %{_left}%." says "Wait 9 minutes 30 seconds." In math it still counts as seconds.
  • The upper bound of random ... between A and B extends to the end of the arithmetic, so random integer between 1 and 10 + 5 means 1 to 15. Use parentheses to say otherwise: (random integer between 1 and 10) + 5.

Lists

Guide and examples
set {_nums} to [5, 3, 9, 1]
set {_names} to ["Steve", "Alex"]
set {_empty} to []
SyntaxResultExample with {_nums} = [5, 3, 9, 1]
sorted <list>Ascending copy: numbers first, then text A-Z ignoring case1, 3, 5, 9
reversed <list>Copy in reverse order1, 9, 3, 5
reversed sorted <list>Descending copy9, 5, 3, 1
filter <list> where <condition>Elements for which the condition holds; it is the elementfilter {_nums} where it > 4 gives 5, 9
size of <list>Number of elements (or characters, for text)4
item <n> of <list>The n-th element, counting from 1; unset if there is noneitem 2 of {_nums} gives 3
{_list.<n>}The same, for a list in a local variable; handy inside text as %{_nums.2}%{_nums.2} gives 3
<list> contains <value>Whether the value is in the list{_nums} contains 9 is true
<list> + <value>Copy with the value at the end5, 3, 9, 1, 7
random item of <list>One element picked at random; unset for an empty listrandom item of {_nums}
random <n> of <list>That many different elements, in no order; all of them if the list has fewerrandom 3 of server.players

Statements that change a list variable:

StatementEffect
append <value> to <variable>Add to the end. An unset variable becomes a one-element list.
set item <n> of <variable> to <value>Replace one element, counting from 1. The list must already have that many
add <value> to <variable>Same as append if the variable already holds a list; otherwise arithmetic
remove <value> from <variable>Remove the first matching element
append player.name to {winners}
set {_top} to reversed sorted {scores}
set {_rich} to filter {_top} where it >= 500
send "Best: %{_top}% (of which %{_rich}% are 500 or more)"
if {winners} contains player.name:
    send "You already won."
  • A list prints as its elements joined by , .
  • Lists can be stored in global and player variables and are saved like any other value.
  • Operations never modify a list in place; they produce a new one. set {_b} to {_a} followed by a change to {_b} leaves {_a} alone.
  • More ways to take a list apart:
SyntaxResultExample
items <a> to <b> of <list>A part of the list, counting from 1, both ends includeditems 1 to 5 of {_ranked}
index of <value> in <list>Where the value is; unset if it is not thereindex of player.name in {queue}
closest match of <text> in <list>The element most like the text, for "did you mean": a letter or two off, or what it begins with. Unset if nothing is closeclosest match of arg.1 in keys of {warp}
<list> as sentenceThe elements as people write a list: Steve, Alex and Bobserver.players as sentence
random item of <list>One element, picked at randomrandom item of {announcements}
random item of <list> weighted by <list>The same, but not evenly: the second list gives each element its chance, so [70, 25, 5] makes the first fourteen times as likely as the last. Unset if every chance is 0random item of {loot} weighted by {chances}
first <n> of <list> / last <n> of <list>The beginning or the end of a listfirst 3 of {queue}
numbers from <a> to <b>A list of whole numbers, counting up or downnumbers from 1 to 5
count of <value> in <list>How many times it occurs; works on text toocount of "a" in {letters}
min of <list> / max of <list>The smallest or largest number in itmax of {scores}
<list> without <value>The list with the first such value taken outserver.players without player.name
<list> sorted by {<name>}Player names ordered by each one's own variable, highest firstserver.players sorted by {coins}
<list> sorted by <value>Ordered by anything that can be said of one element, which is loop-value there: lowest first, or highest first when that is written behind it. Text is ordered by the alphabet{_words} sorted by length of loop-value
map each <list> to <expression>A new list, each element changed the same way; it is the elementmap each {prices} to it * 2
random playerThe name of a random online player; unset if nobody is ongive 1 diamond to random player
shuffled <list>The same elements in a random ordershuffled server.players
unique <list>Without repeats; the first of each is keptunique {visitors}
sum of <list> / average of <list>Its numbers added up, or their meansum of {donations}
players within <n> blocks of <location>The names of the players that close, nearest firstplayers within 10 blocks of player
blocks within <n> blocks of <location>The location of every block that close, nearest first; block at says what is thereblocks within 3 blocks of player
blocks from <location> to <location>The location of every block in the box between two opposite cornersblocks from {_a} to {_b}
entities within <n> blocks of <location>The creatures that close, nearest first, players not among them. Each can be given to anything that takes a creatureentities within 10 blocks of player
entities of <kind> within <n> blocks of <location>The same for one kind of creatureentities of zombie within 20 blocks of player
nearest block of <type> within <n> blocks of <location>Where the closest block of that kind is, as a location; unset if there is none that closenearest block of diamond ore within 10 blocks of player
nearest player to <location>The name of the player closest to a place, in that world; unset if nobody is there. nearest other player to player leaves out the player the trigger runs fornearest other player to player
nearest entity to <location>The closest creature that is not a player, up to 256 blocks away; a kind may be named instead of entitynearest zombie to player
words of <text>The words of a text as a listwords of "one two three"
keys of {<table>}The names under a table; see Records and tableskeys of {warp}
  • keys of {warp} looks at every saved variable whose name starts with warp. and gives the next part of each name: with {warp.spawn} and {warp.arena} set, it is the list arena, spawn. That is how a script loops over a table it has built. It works for a player's own tables as well: keys of {%player%.homes}.
  • filter reads to the end of the condition, including any and / or. Wrap it in parentheses to use the result in a larger expression: size of (filter {_nums} where it > 4).

Records and tables (custom data)

Guide and examples

HyperScript has no user-defined types. Structured data is built from variable names instead, in two ways that combine freely.

Records: group related values under one prefix.

set {%player%.home.x} to player.x
set {%player%.home.y} to player.y
set {%player%.home.z} to player.z

Tables: put a run-time value inside the name with %...%, giving one variable per key.

set {balance.%player.name%} to 250
set {_target} to arg.1
send "%{_target}% has %{balance.%{_target}%}% coins"

The inserted part is lower-cased like the rest of the name, so Steve and steve are the same key. Combined with lists (below), this covers most data a script needs to keep.

Dates and times

Guide and examples

now is the present moment as a value. It can be stored, compared, and moved forward or back with a duration.

command /daily:
    trigger:
        if {%player%.next_daily} is set and now < {%player%.next_daily}:
            set {_left} to time until {%player%.next_daily}
            send "&cCome back in %{_left}%."
            stop
        set {%player%.next_daily} to now + 1 day
        give 3 diamond to player
        send "&aSee you again on " + ({%player%.next_daily} formatted as "EEEE 'at' HH:mm")
SyntaxResultExample
nowThe present momentset {%player%.joined} to now
today / tomorrowMidnight at the start of today, or of tomorrowif {%player%.voted} < today:
<date> + <duration> / <date> - <duration>A later or an earlier datenow + 7 days
<date> - <date>The time between them, as a durationnow - {%player%.joined}
time since <date>How long ago it wastime since {%player%.last_death}
time until <date>How long until then; zero if it has passedtime until {event_start}
<date> formatted as <pattern>The date written out your waynow formatted as "d MMMM yyyy"
first join date of <who> / last seen of <who>When a player first joined and was last on; works offlinelast seen of arg.1
  • A date prints as 11 October 2026 18:30 unless you format it. The letters for formatted as are Java's: yyyy year, MM month number, MMMM month name, d day, EEEE weekday, HH hour, mm minute, ss second. Text inside single quotes is taken as it is.
  • Dates compare with < and >, and can be saved in variables like any other value.
  • In arithmetic with plain numbers a date counts as seconds since 1970, the same scale as server.time, so the two mix: now > server.time - 60.
  • Times follow the clock of the machine the server runs on.

Another place's clock. <date> formatted as "<pattern>" in time zone "<zone>" writes a moment as the clock shows it somewhere else: now formatted as "HH:mm" in time zone "Europe/Berlin". The zone is one of the world's names for them, such as "America/New_York", "Asia/Tokyo" or "UTC".

Messages in several languages

Guide and examples

A script that speaks to players can keep its texts in one place, once for each language, and let every player read their own:

messages:
    en:
        welcome: "&aWelcome, %player%!"
        no-money: "&cYou cannot afford that."
    de:
        welcome: "&aWillkommen, %player%!"
        no-money: "&cDas kannst du dir nicht leisten."

on player join:
    send message "welcome"
WrittenMeaning
messages:At the left margin. Under it a language, written as the game writes it (en, de, pt_br), and under that name: "text" lines
message <name>The text of that name in the player's language. message <name> for <who> in someone else's
  • The language is the one the player has set in Minecraft. de_at uses de if there is no de_at; a language or a message that is missing falls back on the first language in the block, so write the complete one first.
  • A text may use colours, placeholders and saved variables (%player%, %{%player%.coins}%) but not local variables: put a value that changes into a saved variable, or add it after the message with +.
  • The messages belong to the file they are written in. The name must be written out in quotes (message "welcome"), and a name the block does not have is a mistake found when the file loads.
  • In a file without a messages: block, message keeps its other meaning: what was said in chat.

Built-in placeholders

Guide and examples

Placeholders are read-only live values that HyperScript provides, such as the player's name or the server's TPS. They are written in two ways, depending on where they stand:

WhereWrittenExample
In codeThe plain nameif player.health < 6:
Inside textThe name between percent signssend "Hello %player.name%!"

Braces are never used for placeholders. {...} always means a variable of your own; see Variables.

PlaceholderValueType
%server.version%Minecraft version, e.g. 1.20.4text
%server.tps%Recent ticks per second, 2 decimals, max 20number
%server.online_players%Players onlinenumber
%server.max_players%Player slot limitnumber
%server.players%Names of the players onlinelist
%server.time%The current time as seconds since 1970, for timestampsnumber
%server.worlds%The names of the loaded worldslist
%server.operators%, %server.banned%, %server.whitelist%Names of operators, banned and whitelisted playerslist
%server.plugins%The names of the installed pluginslist
%server.uptime%How long the server has been runningduration
%server.memory_used%, %server.memory_max%Memory in megabytesnumber
%server.date%Today's date, e.g. 2026-10-11text
%server.clock%The time of day, e.g. 18:30text
%server.weekday%The day of the week in lower case, e.g. sundaytext
%server.hour%, %server.minute%The hour (0 to 23) and the minute, as numbersnumber
%player.name%Player nametext
%player.uuid%Player UUIDtext
%player.ping%Latency in ms (-1 if unavailable)number
%player.health%Health, 1 decimal (20 = full by default)number
%player.world%Name of the world the player is intext
%player.gamemode%survival, creative, adventure or spectatortext
%player.x%, %player.y%, %player.z%Position, 2 decimalsnumber
%arg.1%, %arg.2%, ...Command argument by positiontext
%args%All command arguments joined by spacestext
%args.count%Number of command argumentsnumber
%event.message%Chat message (on player chat)text
%event.block%Block type, e.g. diamond_ore (on block break, on right click)text
%event.power%The redstone power a block has now, 0 to 15 (on redstone)number
%event.item%Held item type, e.g. compass (on right click)text
%event.entity%Entity type, e.g. zombie (on entity death)text
%event.killer%Name of the killing player (on entity death)text
%event.world%, %event.x%, %event.y%, %event.z%The block the event is about (on block break, on right click); as one value: event's locationtext / number
%discord.user%Discord user name (on discord command)text
%discord.user_id%Discord user ID (on discord command)text
%discord.channel%Discord channel name (on discord command)text

The table lists each placeholder as it is written inside text. In code, leave the percent signs off: server.tps, arg.1, event.block. (The percent form is accepted in code as well, so %arg.1% == "on" still works.)

Two more describe the player as a whole: player is the player, for use wherever a player is expected (send "hi" to player), and inside text %player% is their name. player.location is where they stand, as a location.

Writing a placeholder in braces, as in {player.name} or %{player.name}%, is an error that says how to write it instead. That was the syntax before version 1.5.4, so scripts from older versions need those places changed.

"The player" is whoever caused the trigger: the player who joined, broke the block, ran the command, clicked the GUI slot, or, for on entity death, the killer. A placeholder with nothing to report (for example %player.name% when the console runs a command) is unset and prints as <none>.

send "TPS is %server.tps% and your ping is %player.ping% ms"
if player.health < 6:
    send "&cYou are badly hurt!"

Commands and events

What sets a script off: a command, something that happens, or the clock.

Commands

Guide and examples
command /heal:
    description: Restore your health
    usage: /heal [player]
    permission: demo.heal
    permission message: "&cYou cannot use /heal."
    aliases: h, mend
    trigger:
        execute console command "effect give %player.name% minecraft:instant_health 1 10"
        send "&aHealed."
OptionRequiredMeaning
trigger:yesThe code to run
permission:noPermission node needed to run the command, or op for server operators only
permission message:noShown to players who lack the permission
usage:noUsage text shown in /help
description:noDescription shown in /help
aliases:noComma-separated alternative names
cooldown:noHow long each player must wait between uses, e.g. 30 seconds
cooldown message:noShown to a player who is still waiting; %cooldown% is the time left
warmup:noHow long a player has to stand still before the trigger runs, e.g. 3 seconds, with the time counting down above the hotbar. Moving or being hurt calls it off. The console does not wait
cost:noWhat running the command costs: 100 of the server's money (with Vault and an economy plugin), or 5 gems of a currency of the script's own. Somebody who has not got it is told so and the trigger does not run; otherwise it is taken first
cost message:noWhat they are told then; %cost% is the cost as written
worlds:noThe worlds the command works in: worlds: "survival", "resource". Somewhere else the player is told so and the trigger does not run. The console is let through
worlds message:noWhat they are told then
tab complete: <list>noWhat Tab offers for the first argument; tab complete 2: for the second, and so on
disabled: truenoKeep the command in the file without adding it to the server
subcommand <name>:noA command inside the command, with options and a trigger of its own
players only: truenoThe console is told it cannot use the command. players only: alone says the same
console only: truenoPlayers are told they cannot use the command

A number within limits. An argument that is a number can say what it has to lie between: <amount:number 1 to 10000>, <level:integer at least 1>, [percent:number at most 100]. A player who gives another number is told amount must be between 1 and 10000. and the trigger does not run.

command /pay <target:player> <amount:number 1 to 10000>:
    trigger:
        subtract arg.2 from {%player%.coins}
        add arg.2 to {%arg.1%.coins}
        send "&aYou paid %arg.1% %money(arg.2)%."

The command line may describe its arguments after the name, as in command /pay <player> <amount>:. It becomes the usage text unless a usage: line is given, and it decides what pressing Tab offers while the command is typed:

Written in the headerTab offers
`<onoff>, <redbluegreen>`Those words
<player> or <target>The players who are online
Anything else, such as <amount>Nothing

Subcommands. A command with several jobs can give each one its own block instead of a switch on the first argument. Each subcommand has its own permission, description, checked arguments and trigger, and arg.1 inside it is the first word *after* its name:

command /warp <name>:
    tab complete: keys of {warp}
    trigger:
        teleport player to {warp.%arg.1%}
    subcommand set <name>:
        permission: "warps.manage"
        trigger:
            set {warp.%arg.1%} to player's location
            send "&aWarp %arg.1% set."
    subcommand list:
        trigger:
            send "&7Warps: &f" + join keys of {warp} with ", "
  • /warp set base runs the set block; /warp base runs the command's own trigger.
  • A command may consist of subcommands only. Used without one, it answers with their names.
  • Tab offers the subcommands a player is allowed to use, then each one's own arguments.
  • tab complete: takes any list and is worked out when Tab is pressed, so it can offer warp names, team names or anything else a script keeps.

What Tab offers, argument by argument. tab complete: can also be a block. Its lines run each time Tab is pressed, and set arg.1 to ... in it says what is offered for the first argument, set arg.2 to ... for the second, and so on. The lines are ordinary code, so what is offered for one argument can depend on what was typed for the ones before it:

command /rank [action] [target] [rank]:
    permission: "ranks.admin"
    tab complete:
        set arg.1 to "set", "remove", "list"
        set {_online} to server.players
        if arg.1 is "set" or arg.1 is "remove":
            set arg.2 to {_online}
        if arg.1 is "set":
            set arg.3 to "owner", "admin", "moderator", "vip"
    trigger:
        send "&7You typed: %args%"

What stands after to may be values written one after the other, a list, or both.

  • Typing /rank and pressing Tab offers set, remove and list; after /rank set Steve it offers the ranks; after /rank list nothing, because the block set nothing for that.
  • An argument the block says nothing about is offered what the command's header says: the players who are online for <player>, the words of <on|off>.
  • Only what begins with what has been typed so far is shown, whatever the capitals.
  • The block runs on every press of Tab, so keep it to working out what to offer. It is not the place to send messages or change variables.
  • Outside this block an argument cannot be set: in a trigger arg.1 is what was typed.

Checked arguments. Give an argument a type and HyperScript checks it before the trigger runs, answering with what is wrong, and the usage line for a missing argument or a number that is not one:

command /pay <target:player> <amount:number> [note]:
    players only: true
    trigger:
        subtract arg.2 from {%player%.coins}
        add arg.2 to {%arg.1%.coins}
Written in the headerChecked
<name:player>Must be someone who is online; Tab offers their names
<name:number>Must be a number
<name:integer>Must be a whole number. Both kinds of number may be typed short, 1.5k or 2m, and reach the trigger written out
<name:duration>Must be a length of time: 30s, 10m, 2h, 1h30m, or a bare number of seconds. In the trigger the argument is that many seconds, so it goes wherever a time does: mute arg.1 for arg.2
<name:boolean>true, yes or on, or false, no or off; in the trigger it is true or false. Tab offers the two
<name:item>Must be the name of an item of the game, as in diamond_sword
<name:world>Must be a world that is loaded; Tab offers their names
<name:offline player>Must be somebody who has played here, online or not
<name:text>Everything from there to the end of the line as one argument, spaces and all. It has to be the last one
`<onoff>`One of the words, and nothing else: anything other is answered with the usage
[name:type]In square brackets: may be left out, but is checked when given
[name:type = value]What the argument is when it is left out: with [amount:number = 1], arg.2 is 1 for a player who gave no amount. Works without a type as well, [note = "a gift"]. Only arguments at the end are filled in

An argument without a type is not checked, as before. The types are not shown in the usage line.

A command declared without any arguments keeps the server's default, which is player names. The arguments are still read with %arg.1%, %arg.2% and so on, and are not checked for you.

A short command can also simply use a switch on the first argument, without subcommand blocks:

command /kit <starter|food>:
    trigger:
        switch arg.1:
            case "starter":
                give 1 stone sword to player
            case "food":
                give 16 bread to player
            default:
                send "&eUsage: /kit <starter|food>"

Commands can be run from the console; there is then no player. players only: true keeps the console out, or test if player is not set: yourself.

Permissions

Guide and examples

A command can be limited to players holding a permission node, or to server operators:

command /fly:
    permission: "server.fly"
    trigger:
        execute console command "fly %player.name%"

command /shutdown:
    permission: op
    trigger:
        execute console command "stop"
permission: valueWho may run the command
a node, such as "server.fly"Players who have that permission. Quotes are optional
opServer operators and the console, whatever permissions plugin is installed
not givenEveryone

Scripts can also hand out permissions themselves:

command /buyfly:
    trigger:
        if {%player%.coins} < 500:
            send "&cFlying costs 500 coins."
            stop
        subtract 500 from {%player%.coins}
        permission player add "server.fly"
        send "&aYou can now use /fly."
StatementEffect
permission <who> add <node>Give the permission. It lasts across relogs and restarts
permission <who> add <node> for <duration>Give it for a time: afterwards it is taken back by itself, also if the player was away or the server off meanwhile
permission <who> remove <node>Take back a permission given this way
<who> has permission <node>A condition; also does not have permission
  • <who> is player, all players, or a player name; the player has to be online.
  • Granted permissions are saved with the player's data and applied again each time they join.
  • remove only undoes what add gave. A permission the player has from a rank or another plugin stays; change that in the plugin that manages your ranks.

Cooldowns

Guide and examples

A cooldown limits how often each player can run a command or trigger an event.

command /kit:
    cooldown: 1 hour
    cooldown message: "&cYou must wait %cooldown% before using this again!"
    trigger:
        give 1 diamond to player

On an event, the cooldown lines come first inside the block:

on right click:
    cooldown: 2 seconds
    send "&7Click!"
LineMeaning
cooldown: <duration>Time between uses. Units: ticks, seconds, minutes, hours, days, or short forms such as 90s and 1h 30m
cooldown message: <text>Sent instead of running the trigger. %cooldown% becomes the time left, e.g. 59 minutes 30 seconds
worlds: <name>, <name>At the top of an event's block: the block runs only when it happens in one of those worlds
permission: <node>At the top of an event's block: it runs only for a player who has that permission
reset cooldownA statement: gives the player their cooldown back, for when the trigger decides not to do anything
limit: <n> per <duration>At most that many runs in that long for each player: limit: 5 per second, limit: 20 per 10 seconds, limit: 1 per minute. Runs beyond it are dropped without a word. Goes where cooldown: goes, on a command or as the first line of an event
start cooldown <name> of <duration>Starts a cooldown of your own for the player, by any name you like. Add for <who> to start it for someone else. Starting it again replaces the time left
end cooldown <name>Ends it early; for <who> as above
cooldown <name>An expression: the time left, or unset once it is over. cooldown <name> of <who> for someone else
  • Commands have a default message if none is given. Events stay silent unless one is given, since an event is usually not something the player asked for.
  • limit: or cooldown:? A cooldown makes a player wait after one use and can tell them how long. A limit lets a burst through and stops a flood: it is for events a player can set off many times a second (chat, clicks, movement), where a script that does real work on every one of them would be made to work as hard as the player cares to click. Limits are not saved.
  • cooldown: or start cooldown? cooldown: is for the common case, one wait per command or event. start cooldown is for everything else: a wait that starts only when the trigger succeeds, one shared by several commands, or one on an item or a menu button. Test it with player is on cooldown "<name>". These too are saved and survive restarts.
  • The cooldown starts when the trigger starts. If your trigger can refuse (wrong arguments, not enough coins), use reset cooldown before stop so the player is not charged for nothing.
  • Cooldowns are saved with the player's data, so they survive relogs and server restarts.
  • The console is never on cooldown. Players with the permission hyperscript.cooldown.bypass are not either; it is not granted to anyone by default, not even operators.
  • The expiry time is stored in an ordinary player variable, {%player%.hs.cooldown.command.<name>} for commands. Deleting it ends the cooldown: delete {%player%.hs.cooldown.command.kit}.

Events

Guide and examples
EventFires whenCan be cancelled
on player join:A player joinsno
on first join:Someone joins who has never played here beforeno
on left click:A player left-clicks air or a blockyes
on player sneak:A player starts sneakingyes
on player sprint:A player starts sprintingyes
on player swim:A player starts swimmingyes
on flight toggle:A player starts or stops flyingyes
on hand swap:A player swaps the items in their handsyes
on slot change:A player selects another hotbar slotyes
on item break:A player's tool or armour breaksno
on book edit:A player writes in or signs a bookyes
on gamemode change:A player's game mode is about to changeyes
on hunger change:A player's hunger bar changesyes
on player heal:A player regains healthyes
on experience gain:A player gains experience pointsno
on effect gained:A player gets a potion effectyes
on effect ended:A potion effect on a player endsyes
on player kick:A player is about to be kickedyes
on advancement:A player completes an advancementno
on player kill:One player kills another; the player is the killerno
on projectile shoot:A player shoots or throws somethingyes
on projectile hit:Something a player shot landsno
on totem use:A totem of undying saves a playeryes
on block burn:Fire destroys a blockyes
on explosion:Something explodesyes
on leaves decay:Leaves disappear after a tree is cutyes
on redstone:The redstone power of a block changesno
on piston extend:A piston pushes outyes
on piston retract:A piston pulls backyes
on dispense:A dispenser or dropper puts out an itemyes
on hopper move:A hopper or the like moves an item between containersyes
on crop grow:A crop or plant grows a stageyes
on bucket fill:A player fills a bucketyes
on bucket empty:A player empties a bucketyes
on weather change:Rain starts or stops in a worldyes
on entity tame:A player tames an animalyes
on entity breed:Two animals have a babyyes
on shear:A player shears a sheepyes
on mob target:A mob picks a player as its targetyes
on player move:A player moves into another block; runs very often, so keep it shortyes
on portal use:A player is about to go through a nether or end portalyes
on bed leave:A player gets out of a bedno
on item damage:An item a player is using loses durabilityyes
on harvest:A player picks berries or the like from a block without breaking ityes
on glide toggle:A player starts or stops gliding with an elytrayes
on entity mount:A player gets onto a creature or vehicleyes
on entity dismount:A player gets off what they were ridingyes
on vehicle enter:A player gets into a vehicleyes
on vehicle exit:A player gets out of a vehicleyes
on inventory open:A player opens a containeryes
on inventory close:A player closes a containerno
on enchant item:A player enchants an item at a tableyes
on furnace smelt:A furnace finishes smelting an itemyes
on console command:A command is run from the consoleyes
on shield block:A player's raised shield takes a blow completelyno
on anvil use:A player takes the finished item out of an anvilyes
on villager trade:A player takes the goods out of a tradeyes
on server start:Once, when the server has started and every script is loaded; not on a reloadno
on server stop:Once, as the server shuts downno
on player quit:A player leavesno
on player login:Someone is connecting, before they are in the game; see Moderationwith refuse login
on player death:A player diesPaper only
on player respawn:A player comes back after dyingno
on item pickup:A player picks an item up off the groundyes
on item drop:A player drops an itemyes
on world change:A player arrives in another worldno
on player command:A player types any command, before the server runs ityes
on block break:A player breaks a blockyes
on block place:A player places a blockyes
on sign change:A player finishes writing on a signyes
on player teleport:A player is about to be teleportedyes
on entity click:A player right-clicks a mob, animal or playeryes
on craft:A player takes the result out of a crafting gridyes
on consume:A player finishes eating or drinkingyes
on fish:A player reels in a catchyes
on level up:A player's experience level goes upno
on bed enter:A player gets into a bedyes
on region enter:A player comes into a script region; see Worlds and regionsno
on region leave:A player leaves a script regionno
on combat start:A player gets into a fight with another player; see Combat and being awayno
on combat end:The fight is over: nobody hit anybody for combat-timeno
on afk:A player has done nothing for afk-timeno
on afk return:A player who was away does something againno
on kill streak:A player kills another player; %event.streak% is how many in a rowno
on blocked word:A player writes a word in chat that a script blocked; %event.word% is the wordno
on brew:A brewing stand finishes brewing; there is no playeryes
on entity death:Any living entity dies; the player is the killer, if there was onePaper only
on player chat:A player sends a chat messageyes
on right click:A player right-clicks air or a block, with either hand. Not when they are looking at a creature or another player in reach: that is on entity click:yes
on right click with <item>:The same, but only for a player holding that item in either hand. on left click with <item>: likewiseyes
on right click on <block>:The same, but only for a click on that kind of block: on right click on gold block:. on left click on <block>: likewise, and with <item> may follow: on right click on gold block with stick:yes
on entity damage: (or on hit:)Any entity takes damageyes
on player jump:A player jumpsyes
on mob spawn:A living creature spawnsyes
on inventory click:A player clicks in an inventory windowyes
on server ping:A client refreshes its server list; see Server listno
on resource pack accept:A player agrees to download a resource packno
on resource pack decline:A player refuses a resource packno
on resource pack successfully loaded:A player's game has finished applying the packno
on resource pack failed:The download or the pack itself failedno

Several scripts (or several blocks in one script) may handle the same event; they run in file-name order. on load: looks like an event but is not one: it runs when the script is loaded, as described under File structure.

Right-clicks. on right click: runs once for each click, whichever hand it was made with and whatever is in it, on a block or in the air. It does not run when the player is looking at a creature or another player that is near enough to click: that click is on entity click:. One case cannot be seen by any plugin: right-clicking the air with a completely empty hand. The game does not tell the server about that click at all. Holding anything, or clicking a block, works.

Events of your own. fire event "<name>" runs every on event "<name>": block, wherever it is, so scripts can tell each other that something happened without knowing about each other:

# In Bosses.hs
on entity death:
    if event.entity is "wither" and player is set:
        set {_boss} to "the Wither"
        fire event "boss killed" with {_boss}

# In Rewards.hs
on event "boss killed":
    add 500 to {%player%.coins}
    broadcast "&6%player.name% &eslew %{_boss}%!"

Inside the block, player is the player of the trigger that fired the event (if it had one), and each local variable handed over with with is there under the same name.

Short names. The word player may be left out of an event's name wherever what is left still means only one event: on join: is on player join:, and likewise on quit:, on chat:, on death:, on respawn:, on command:, on move: and the rest.

Stepping on a block. on step on <block>: is on player move: for players who are standing on that kind of block, which is what a move handler is most often written for:

on step on magma block:
    ignite player for 3 seconds

on step on "slime_block":
    push player upward with force 1.5

Questions. While a script is waiting for an answer to ask or confirm, the player's next chat message is the answer and is not shown to anybody. The answers offered to click on run the command /hsanswer, which any player may use and which does nothing when no question is open.

Event values

Guide and examples

Each event makes its details available inside its block. Every value has a placeholder, and the common ones also have a one-word short form.

on entity damage:
    if event.cause is "FALL":
        if player has permission "hyperscript.nofall":
            cancel event
            send action bar "&aFall damage negated!" to victim

on player chat:
    if message contains "badword":
        cancel event
        send "&cPlease keep chat friendly!" to player
Short formPlaceholderEventsMeaning
attacker%event.attacker%entity damageWho dealt the damage: a player's name or a mob type; for a projectile, whoever shot it; unset if nobody did
victim%event.victim%entity damageWho was hurt: a player's name or a mob type
damage%event.damage%entity damageDamage taken after armour; 2 is one heart
cause%event.cause%entity damageFALL, FIRE, ENTITY_ATTACK, PROJECTILE and so on
cause%event.cause%player deathWhat killed the player, in the same words
message%event.message%player chatThe chat message
message%event.message%player deathThe death message everyone will see
message%event.message%player commandThe whole line as typed, e.g. /home set base
command%event.command%player commandThe command without the slash, in lower case: home
amount%event.amount%item pickup, item dropHow many items are in the stack
%event.gamemode%gamemode changeThe mode being changed to
%event.effect%effect gained, effect endedThe potion effect
%event.advancement%advancementThe advancement's id
%event.weather%weather changerain or clear
%event.inventory%inventory open, inventory closeThe kind of container
%event.region%region enter, region leaveThe name of the region
%event.opponent%combat startThe name of the other player; unset when a script started the fight
%event.streak%kill streakHow many players they have killed in a row since they last died
%event.word%blocked wordThe blocked word that was found in what the player wrote
%event.lines%sign changeA list of the sign's lines, top to bottom
%event.clicked%entity clickA player's name if a player was clicked, otherwise the entity type
%event.level%, %event.old_level%level upThe level reached, and the one before
%event.name%player loginThe name of whoever is logging in
%event.uuid%player loginTheir account id
%event.address%player login, server pingThe address they are connecting from
%event.from%world changeThe name of the world the player left
block%event.block%block break, right clickThe block type, e.g. diamond_ore
%event.power%redstoneThe power the block has now, 0 to 15
entity%event.entity%entity damage, entity death, mob spawnThe entity type, e.g. zombie
killer%event.killer%entity death, player deathName of the player who made the kill
reason%event.reason%mob spawnNATURAL, SPAWNER, SPAWNER_EGG, BREEDING, CUSTOM and so on
slot%event.slot%inventory clickThe slot clicked, counting from 1 like the slots of open gui
item%event.item%inventory click, right click, item pickup, item dropThe item type clicked, held, picked up or dropped
%event.click_type%inventory clickLEFT, RIGHT, SHIFT_LEFT, MIDDLE, DROP and so on
%event.recipients%player chatA list of the names of the players who will see the message
%event.drops%block break, entity deathA list of the items that are about to drop
%event.location%block break, right click, entity damage, mob spawn, player jumpWhere it happened, as a location; also written event's location
  • A value that does not apply to the current event is unset.
  • Comparisons ignore case, so cause is "fall" and cause is "FALL" are the same.
  • item on its own is the event's item. Followed by a number it is still the list lookup item 2 of <list>.
  • player in on entity damage is the player who was hurt, or, if the victim is not a player, the player who dealt the damage. victim and attacker are always exact.
  • on player death can rewrite or remove the message everyone sees: set death message to "&c%player.name% fell over" and hide death message. on entity death fires for players too, with player being the killer; on player death is the one where player is who died.
  • on player command sees every command before the server does, including ones that do not exist. cancel event stops the command from running, which makes it the way to block commands:
on player command:
    if command is "plugins" and player does not have permission "server.admin":
        cancel event
        send "&cThat command is not available."
  • on region enter and on region leave fire when a player crosses the edge of a region made with create region, on foot or by teleport. Movement is only watched while a loaded script has one of these blocks, and only when a player steps into a different block. Neither can be cancelled; to keep someone out, teleport them back.
  • block, item, entity and cause also work in the newer events: the block placed, the item crafted, eaten or caught, the entity clicked, and why a teleport is happening.
  • on entity damage and on mob spawn fire extremely often. Put the cheapest test first, as the example does, so that most runs end after one line.
  • on player jump works on Spigot and Paper. Cancelling it snaps the player back to where they were; because the jump has already started on their screen, a small hop may be visible.
  • on inventory click fires for every inventory, including the player's own and GUIs opened by scripts. Cancelling it means the click moves nothing.

The Docs page of the documentation site lists every event with its values, whether it can be cancelled, a working example, and a box for trying the values out. The same information is published for other tools as events_metadata.json.

Events reference

Timers

Guide and examples

every runs a block repeatedly for as long as the script is loaded.

every 5 minutes:
    broadcast "&7Remember to vote!"

every 1 second for all players:
    set line 1 of player's scoreboard to "&7Coins: &a%{%player%.coins}%"
FormRuns
every <duration>:Once per interval, with no player (like a console command)
every <duration> for all players:Once per interval for each online player, as that player
every day at <hh:mm>:Once a day at that time, by the server's clock
every monday at <hh:mm>:Once a week; any weekday name works
  • Durations use the same units as cooldowns; the shortest interval is 1 tick (a twentieth of a second).
  • Timers run on the server thread. Keep fast timers light, and use async: for anything heavy.
  • Timers are restarted on every reload, hot reload included.
  • Times of day are 24-hour and follow the clock of the machine the server runs on: every day at 18:00:, every friday at 20:30:. They do not drift with restarts the way a every 24 hours: timer does. A time that passes while the server is off is skipped, not caught up, and for all players may be added as with any timer.
every day at 00:00:
    delete {daily_reward_claimed}
    broadcast "&6Daily rewards are available again!"

Actions

Guide and examples
StatementEffect
set <variable> to <value>Assign
set <variable>, <variable> to <value>The same value for several: set {_a}, {_b} to 0
set <variable> to <value> for <duration>Assign for a time; afterwards it is unset again by itself, also across a restart. For saved variables
add <value> to <variable>Increase a number (or append to a list)
add <n>% to <variable> / subtract <n>% from <variable>Change a number by a share of itself: add 10% to {_price} makes 100 into 110
subtract <value> from <variable>Decrease a number
multiply <variable> by <value> / divide <variable> by <value>Change a number in place: multiply {_price} by 2. An unset variable counts as 0; dividing by 0 is refused
append <value> to <variable>Add to a list
remove <value> from <variable>Remove from a list
remove <item> from <who>Take items out of an inventory. The player may be in a variable: remove 5 diamond from {_target}
increase <variable> by <n> / decrease <variable> by <n>The same as add and subtract, in other words
toggle <variable>Flip between true and false; an unset variable becomes true
swap <variable> and <variable>Exchange two values
default <variable> to <value>Set it only if it has no value yet
delete <variable>Unset; several at once with commas: delete {_a}, {_b}
delete <variable> for all playersUnset a variable each player has, for everybody who has it, online or not: delete {coins} for all players. For the end of a season
set <variable> to <value> for all playersGive it that value for everybody who has ever played: set {coins} to 100 for all players
delete all variables of <who>Everything the scripts keep for one player. What HyperScript itself keeps for them, such as permissions it gave and saved inventories, stays
send <text>Message whoever triggered the script (player or console)
send <text> to playerThe same
send <text> to <player name>Message a named online player
tell <who> <text>Another way to say send <text> to <who>: tell player "Hello". message <who> <text> is the same
send <text> to all playersMessage every online player
send <text> to all players with permission <node>Only those who have it. Also in world <name>, within <n> blocks of <location> and where <condition> with loop-player as each of them. These work wherever all players does
send <text> with click command <text>A message that runs a command when clicked; see below
send <text> with hover <text>A message that shows more when the mouse is over it
send <text> with click copy <text>A message that puts the text on the clipboard of whoever clicks it: an address, a code
send <list> to <who> in pages of <n>A long list a page at a time, with arrows under it to click for the page before and after. titled <text> puts a heading over it, with the page beside it: send {_warps} to player in pages of 8 titled "&6Warps"
set chat slow mode to <duration>So long between one chat message of a player and their next; who writes sooner is told how long is left. set chat slow mode off ends it. It is kept across restarts, and players with the permission hyperscript.chat.bypass are not slowed
send <text> to <who> when they joinSaid now if they are online; if not, kept and said the next time they join. For somebody who has played here before. The last 50 are kept for each player
broadcast <text>Message every online player and the console. announce <text> is the same
log <text>Write to the server console
execute console command <text>Run a command as the console
execute player command <text>Run a command as the player
give <who> <item> or give <item> to <who>Put an item in an inventory; whatever does not fit is dropped at their feet
give <item> to <who> [or drop]The same: or drop only says out loud what happens when the inventory is full
set helmet of <who> to <item>Put an item on a player or in their hand; see below
set name of <place> to <text>Rename the item that is there, without making a new one: set name of tool of player to "&6Excalibur". The place is what an item can be read from: tool of player, helmet of player, inventory slot 3 of player
set lore of <place> to <text>, <text>Its description, a line for each text; a list gives as many lines as it has elements
add <text> to lore of <place>One more line under what it has
remove line <n> of lore of <place>Take one line out, counting from 1
delete lore of <place>Take all of it away
clear inventory of <who>Empty an inventory
save inventory of <who> as <name>Put a copy of everything they carry away under a name: the inventory, the armour and the off hand. Saving again under the same name replaces it
restore inventory of <who> from <name>Give it back, in place of what they carry now. The copy is kept until it is deleted
save state of <who> as <name>Put away everything a game changes about a player, under a name: what they carry, health, food, experience, game mode and where they stand
restore state of <who> from <name>Give all of it back and take them to where they stood. The copy is kept, so it can be given back again
delete saved inventory <name>Throw the copy away; of <who> for someone else
teleport <who> to <position>Move a player. tp for short: tp player to {spawn}
heal, feed, apply <effect>, freeze, vanishSee Players
kick, ban, unbanSee Moderation
add <who> to team <name>See Teams
set block at <position> to <block>Place or replace a block; see Worlds and regions
set block at <position> to <block> for <duration>The same for a time: afterwards what was there is put back. Also put back when the scripts are reloaded or the server stops, so nothing is left behind
summon [<amount>] <entity> [named <text>] at <position>Spawn mobs or other entities
summon ... at <position> with health <n> holding <item> dropping <item>, ...A creature with details of its own, written after the position in any order; see Entities
permission <who> add <node> / permission <who> remove <node>Give or take back a permission; see Permissions
play sound <name> ...Play a sound; see Sounds
send resource pack <url> ...Offer a resource pack; see Resource packs
set time in world ..., set weather in world ...See Worlds and regions
create region ..., delete region ...See Worlds and regions
send get request to ..., send post request to ...See Web requests
create file, set file at, append ... to file at, delete file atWork with text files; see Files
fire event <name>Run every on event "<name>": block, in this script and every other. Add with {_a}, {_b} to hand local variables over; the blocks read them under the same names
cancel eventCancel the current event, where the event allows it
wait <duration>Pause this trigger; see Waiting
break / continueLeave a loop, or skip to its next round; see Loops
stopEnd the trigger immediately
stop if <condition> / stop unless <condition>End it there if the condition holds, or unless it does. break and continue take the same
stop with <text> [if <condition>]Send the text to the player, then end the trigger
return [<value>]Leave a function, handing back a value; see Functions
return if <condition> / return unless <condition>Leave the function there, handing nothing back, if the condition holds or unless it does

Colours. Anywhere text is shown (chat, titles, sidebars, the tab list, item names, holograms) three kinds of colour work:

send "&aGreen, &lbold&r and plain again"
send "&#ff5555Any colour by its hex number, or <#55ffff>written like this"
send "<gradient:#ff5555:#ffaa00:#55ff55>A gradient through three colours</gradient>"
set tab name of player to "<gradient:#4ade9f:#6aa9ff>&l%player.name%</gradient>"
  • &0 to &9, &a to &f, &l bold, &o italic, &n underline, &m strikethrough, &k scrambled, &r back to normal.
  • &#rrggbb and <#rrggbb> are the same thing: any of sixteen million colours. They need Minecraft 1.16 or newer on the player's side, as every supported server has.
  • <gradient:#from:#to>text</gradient> shades the text letter by letter. Give more colours for more stops. A format code inside, such as &l, applies to the whole gradient after it.
  • uncolored <text> takes all of them out again.

send and broadcast translate & colour codes (&a, &l, ...). Inside a string, write \" for a quote, \\ for a backslash and \n for a line break. On-screen text, GUI, world, async and Discord statements are described in their own sections below.

Giving items. give puts an item in a player's inventory; anything that does not fit is dropped at their feet. The recipient may be written first or last:

give player 1 diamond sword named "&6Excalibur" with lore "&7A legendary blade", "&7Forged in fire."
give 16 bread to player
give 3 golden apple to all players
give {%player%.backpack.item} to arg.1

The item is anything described under Value types: plain words, a variable holding an item, or text holding a material name ("%{_material}%"). Up to 2304 can be given at a time. Recipient-first works with player and all players; to give to a named player, put them last after to.

Enchantments. After an item's name and lore come its enchantments and two flags:

give 1 diamond sword named "&6Excalibur" enchanted with sharpness 5, fire aspect 2 unbreakable to player
give player 1 stick glowing
set {reward} to 1 bow enchanted with power 3

enchanted with takes one or more enchantments with a level each (1 if left out). Names are Minecraft's own, written as words (fire aspect, protection) and checked when the script loads. Levels above the normal maximum are allowed. unbreakable makes the item never wear out, and glowing makes it shimmer like an enchanted item without being one. All of it is kept when the item is stored in a variable.

Tags and models. Two more things can follow an item:

give 1 blaze rod named "&dMagic wand" tagged "wand" to player
give 1 paper named "&6Ticket" model 12 to player
on right click:
    if tool of player is tagged "wand":
        apply levitation 2 to player for 3 seconds

tagged "<name>" puts a hidden label on the item. It stays with the item wherever it goes, players cannot see it, and an anvil cannot fake it, so it is how a script recognises its own items: <item> is tagged "wand", or tag of <item> for the label itself. player has 1 stick tagged "wand" and remove ... from only count items with that tag, whatever name or lore the item has. model <number> sets the custom model number a resource pack uses to draw the item differently.

Wearing and holding. What a player wears and holds can be read and set directly:

set helmet of player to 1 diamond helmet enchanted with protection 4
set tool of player to 1 stone sword
if helmet of player is not set:
    send "&7You are not wearing a helmet."
delete boots of player
clear inventory of player
PlaceMeaning
helmet, chestplate, leggings, bootsThe four armour places
toolWhat is in the main hand
offhandWhat is in the other hand
inventory slot <n>One of the 36 inventory slots; 1 to 9 are the hotbar

Each is written <place> of <who>. Reading gives an item, or unset when the place is empty; set ... to <item> replaces what is there (it is not dropped); delete empties it.

Naming an item once. An item that several lines need can be described once, at the left margin of a file, and then asked for by name wherever an item is expected, in that file or any other:

item magic wand:
    blaze rod named "&dMagic wand" with lore "&7Right-click to cast" glowing

command /wand:
    trigger:
        give player magic wand

on right click with magic wand:
    apply levitation 2 to player for 3 seconds

Under the header goes one line: an item exactly as give takes it. The name is one to five plain words and may not be the name of a Minecraft item. give player 3 magic wand, player has magic wand, player is holding magic wand and slot 5 is magic wand all work, and more can be added for one use: magic wand named "&6Golden wand".

Such an item carries its name as a hidden tag (magic_wand), so it is still recognised after a player renames it on an anvil, and a plain blaze rod is never mistaken for it. on right click with <item>: and on left click with <item>: run only for players holding that item, in either hand; any item can be written there, not only a named one.

Tools. What a player is holding can be worn down, mended and enchanted in place:

damage tool of player by 25
repair tool of player
enchant tool of player with efficiency 5

Clickable messages. A chat message can do something when clicked and show more when the mouse is over it:

send "&a[Go home]" with click command "/home" with hover "&7Teleports you home"
send "&b[Our website]" with click url "https://example.com" to all players
send "&7[Reply]" with click suggestion "/msg %player.name% " to arg.1
PartEffect
with click command <text>Runs the command as the player who clicks
with click suggestion <text>Puts the text in their chat box without sending it
with click url <text>Offers to open the web page
with hover <text>Shown while the mouse is over the message

The whole message is clickable. Write with before each part, as in the first example; to <who> may come before or after them.

Taking items. remove takes items out of an inventory, and has tests for them first:

if player has 5 diamond:
    remove 5 diamond from player
    add 100 to {%player%.coins}

It takes up to the amount given and simply stops when there is no more, so test with has when the amount matters. remove 1 diamond from all players and remove 1 diamond from arg.1 work too. What comes after from decides the meaning: a variable is a list to take a value out of, anything else is a player. For a player whose name is in a variable, write it as text: remove 1 diamond from "%{_who}%".

Teleporting. teleport player to {%player%.home} or teleport player to 0, 80, 0 in "world" moves a player and keeps the direction they are facing.

Summoning. summon spawns entities at a position:

summon zombie at player's location
summon 3 chicken at event's location
summon iron golem named "&6Town Guard" at 0, 80, 0 in "world"
summon {boss_type} at {arena}

The entity is a Minecraft entity type written as plain words (zombie, iron golem), checked when the script loads, or any value holding a type name. Up to 50 can be summoned at a time, and named gives them a visible custom name.

Who a statement is for. Statements that take a recipient accept player (the player of this trigger), all players, or anything that gives a player name such as %arg.1% or "Alex".

Players

What a player is and has, and players together.

Players

Guide and examples

What a player is like right now can be read and changed.

command /heal:
    permission: "staff.heal"
    trigger:
        heal player
        feed player
        send "&aYou feel much better."

on player join:
    if level of player < 5:
        apply speed 1 to player for 2 minutes
        send "&7A little speed boost for a new player."
SyntaxMeaning
heal <who> / feed <who>Full health (and no longer burning) / a full hunger bar
health of <who>Health in half hearts; 20 is ten hearts. Setting it to 0 kills
max health of <who>The most health they can have
food of <who>Hunger, 0 to 20
level of <who>Experience level
gamemode of <who>survival, creative, adventure or spectator
flight of <who>Whether they may fly: true or false
apply <effect> [<level>] to <who> [for <duration>]Give a potion effect; level 1 and 30 seconds unless said otherwise
clear effects of <who> / clear <effect> effect of <who>Take every effect away, or one
ignite <who> [for <duration>] / extinguish <who>Set on fire (5 seconds unless said otherwise), or put out
freeze <who> / unfreeze <who>Hold a player in place; they can still look around
respawn <who>Bring a dead player back at once, skipping the death screen
show <who> a book titled <text> with pages <text>, <text>Open a book on their screen; nothing is put in their inventory
hide <who> from tab list of <who>Take a player off the list another player sees when they hold Tab. They are still seen in the world; only the list changes. Needs a Paper server, 1.20 or newer
show <who> in tab list of <who>Put them back on it. show <who> from tab list of <who> means the same
set <who>'s yaw to <number>Turn them left or right: the same as set yaw of <who> to. 0 is south, 90 west, 180 north, -90 east
set <who>'s pitch to <number>Make them look up or down: the same as set pitch of <who> to. -90 is straight up, 90 straight down
hide <who> from <who> / show <who> to <who>Make one player invisible to another, or visible again
clear title of <who>Remove a title from the screen
tab name of <who>Their name in the tab list; settable
free slots of <who>How many of their inventory slots are empty
ping of <who>Their connection delay in milliseconds. Unset on servers older than 1.17, where %player.ping% still works
send toast <text> [with icon <item>] [as goal] [to <who>]The pop-up in the top corner that advancements use. as task (the default), as goal or as challenge picks the frame and sound
give head of <name> to <who>A player head wearing that player's skin
set item cooldown of <item> for <who> to <duration>Grey out an item so it cannot be used for a while, as ender pearls are. item cooldown of <item> for <who> reads what is left
stop sound <name> [for <who>] / stop all sounds [for <who>]Cut a sound short. stop all sounds needs Minecraft 1.17 or newer
location of <who>Where another player is, as a location; for the player of the trigger, player's location
yaw from <location> to <location>Which way to turn at the first place to face the second, as the game counts it: 0 is south, 90 west
pitch from <location> to <location>How far to look up or down: below nothing is up
<location> moved <n> blocks towards <location>The place that far along the way from one to the other; never beyond it
<who>'s locationThe same, written after the player: loop-player's location, arg.1's location, {_name}'s location
absorption of <who>Their golden extra hearts, in half hearts; settable
protocol version of <who>The number of the game version their client speaks, e.g. 754 for 1.16.5. Asked from ViaVersion if it is installed, otherwise from Paper; unset on plain Spigot
client brand of <who>What their game calls itself: vanilla, fabric, forge. Paper only
ask <who> <text> into <variable>Ask a question and wait for the answer. The next thing the player says in chat is the answer and nobody else sees it. Add for at most 30 seconds to change how long to wait (a minute by default); with no answer the variable is unset
ask <who> <text> as number into <variable>The same, for an amount: an answer that is no number is said to be none and the question asked again. 1.5k counts
ask <who> <text> with options <text>, <text> into <variable>The same, with answers to click on. Typing one in chat works too
ask <who> <text> with anvil into <variable>The question opens as an anvil with a box to type in; what the player types and takes out is the answer. Good inside menus, where chat is out of the way. The question stands on top of the window and the box starts empty, so the answer is simply typed; on an older server, where the question has to stand in the box, it is taken off the answer if it was left there. Needs a Paper server; elsewhere the question is asked in chat. Closing the anvil gives an empty answer
confirm <text>:Ask yes or no; the block runs only if the player answers yes. confirm <text> for <who>: asks someone else
items in ender chest of <who>A list of the items in their ender chest
items in inventory of <who>A list of the items they carry, without the armour and the other hand
add <item> to ender chest of <who> / clear ender chest of <who>Put items in an ender chest, or empty it
make <who> say <text>Send a chat message, or run a command if it starts with /, as that player
open workbench for <who> / open enderchest for <who>Show a crafting grid or their ender chest
fly speed of <who> / walk speed of <who>From -1 to 1; the usual values are 0.1 for flying and 0.2 for walking
tool durability of <who>How many uses the thing in their hand has left; unset for what does not wear out. set tool durability of player to 50 sets it
set time of <who> to <ticks>The time of day that player sees, standing still, whatever the world's clock says: 1000 day, 6000 noon, 13000 night, 18000 midnight. Nobody else sees it. reset time of <who> gives them the world's own again
set weather of <who> to rainThe weather that player sees: rain or clear. reset weather of <who> gives them the world's own again
saturation of <who> / air of <who>Hidden hunger reserve; seconds of breath left (15 is full)
held slot of <who>The selected hotbar slot, 1 to 9
compass target of <who>Where their compass points
bed location of <who>Where they respawn; unset without a bed. Change it with set bed spawn of <who> to <location>
yaw of <who> / pitch of <who> / direction of <who>Which way they face; direction is north, east, south or west
game version of <who>What their game calls its version, e.g. 1.21.4, for servers that let several versions in. From the number in protocol version of; one the list does not know yet comes as protocol <n>
ip of <who> / locale of <who>Their address and game language, e.g. en_us
time played of <who>Total time on the server, as a duration
fall distance of <who>How far they have fallen so far
vanish <who> / unvanish <who>Hide a player from everyone else, or show them again

The ones written <something> of <who> are values: read them, set them, and add to or subtract from the numeric ones.

set gamemode of player to creative
set flight of arg.1 to true
add 5 to level of player
subtract 4 from health of player
if health of player < 6:
    send "&cYou are badly hurt!"
ConditionTrue when
<who> has effect <effect> / does not have effect <effect>They have that potion effect
<who> is frozen / is vanished / is flyingAs it says; is not works too
<who> is falling / is glidingComing down through the air, or flying with an elytra
  • Effects are Minecraft's own names written as words: speed, jump boost, night vision, regeneration, slowness, invisibility and so on. They are checked when the script loads.
  • Giving an effect a player already has replaces it, so a shorter one really is shorter.
  • freeze and vanish last until they are undone or the player logs out. Someone who joins while a player is vanished does not see them.
  • All of these need the player to be online. For an offline player the values are unset and the statements do nothing.

Offline players

Guide and examples

A player is somebody who is online or who has played here before, and much of what a script knows about a player it also knows when they are away:

command /coins <player>:
    trigger:
        set {_who} to arg.1 as offlineplayer
        if {_who} has not played before:
            send "&c%arg.1% has never played here."
            stop
        send "&e%{_who}% &7has &f%{%{_who}%.coins}% &7coins."
SyntaxMeaning
<text> as offlineplayerThat player, online or not. If they have played here, the name is written the way the server has it: "progamer52" as offlineplayer gives Progamer52. A name that has never joined stays as written
<who> has played beforeWhether they have ever joined this server
uuid of <who>Their id, which stays the same when they change their name
name of <who>Their name as the server has it
all offline playersA list of the names of everybody who has ever played here, online or not
  • Works for someone offline: their own variables ({%{_who}%.coins}), uuid of, name of, first join date of, last seen of, balance of with an economy plugin, is online, is op, is banned, has played before, ban, unban and the top lists.
  • Needs them online: everything about where they are and what they carry: location, health, inventory, effects, messages, titles and teleporting. Asked of someone offline, a value is unset and a statement does nothing.
  • as offlineplayer only looks at who has played on this server. It never asks Mojang, so it does not slow the server down. A name that has never joined is kept as it was written, because it can still be banned before it ever joins; has not played before tells the two apart.
  • all offline players reads the server's list of players from disk. On a server with many thousands of them, ask for it in an async: block.

Tab list, names and chat

Guide and examples
on player join:
    set join message to "&a+ &f%player.name%"
    set tab header of player to "&6&lMy Server"
    set tab footer of player to "&7Online: %server.online_players%"
    if player has permission "rank.vip":
        set display name of player to "&6[VIP] %player.name%"

on player quit:
    hide quit message

on player chat:
    set chat format to "&7%player.name% &8>> &f%event.message%"
StatementWhereEffect
set tab header of <who> to <text>anywhereText above the player list. \n makes more lines
set tab footer of <who> to <text>anywhereText below it
set display name of <who> to <text>anywhereThe name used in chat and in the tab list
set join message to <text>on player joinReplaces "Steve joined the game"
set quit message to <text>on player quitReplaces "Steve left the game"
hide join message / hide quit messagethose eventsShows nothing
set chat format to <text>on player chatThe whole chat line, built from placeholders
set chat message to <text>on player chatReplaces what the player said
  • To keep a header or footer up to date, set it from a timer: every 5 seconds for all players:.
  • A display name lasts until the player logs out; set it again in on player join.
  • The name above a player's head cannot be changed this way. Minecraft ties it to the account name; only the chat and tab list names change.
  • set chat format writes the line exactly as given, so include %event.message% where the message should go. Other chat plugins that set a format of their own may override it.
  • The event statements only work in their own event and before any wait; elsewhere they log a warning.

Teams

Guide and examples

A team colours its players' names in chat, in the tab list and above their heads, and can put a tag in front of them.

on load:
    set color of team "red" to red
    set prefix of team "red" to "&c[Red] "
    set friendly fire of team "red" to false

command /red:
    trigger:
        add player to team "red"
        send "&cYou joined the red team."
SyntaxEffect
add <who> to team <name>Put a player in a team, leaving the one they were in
remove <who> from teamTake a player out of their team
remove <who> from team <name>The same, but only if they are in that team
set color of team <name> to <colour>The colour of names: red, dark_blue, gold, or a code such as "&a"
set prefix of team <name> to <text> / set suffix of team <name> to <text>Text before or after each name
set friendly fire of team <name> to <true or false>Whether team mates can hurt each other
delete team <name>Remove a team; its players are in no team afterwards
team of <who>The name of a player's team; unset if they have none
players of team <name>A list of the names in a team, online or not
  • A team is created the first time it is used. Names are up to 16 characters.
  • Teams are kept on the server's main scoreboard, so the server saves them and they survive restarts. Set them up in on load: so that they exist as soon as the script is loaded.
  • A player is in one team at a time.
  • Players who have a script sidebar see the same teams; HyperScript copies them onto each sidebar.
  • A team's colour is what changes the name above a player's head.

Parties and queues

Guide and examples

A party is a group of players with a leader. HyperScript keeps track of who is in which; what being in one means (a shared chat, teleporting together, friendly fire) is up to your scripts.

command /party <invite|accept|leave> [player]:
    players only: true
    trigger:
        if arg.1 is "invite":
            invite arg.2 to party
            send "&7%player% invites you to a party. &f/party accept" to arg.2
        else if arg.1 is "accept":
            accept party invite
            send "&a%player% joined the party." to party of player
        else:
            leave party
SyntaxMeaning
invite <who> to partyThe player invites someone. Whoever invites without a party becomes the leader of a new one when the first invitation is accepted. An invitation stands for a minute
accept party invite / decline party inviteThe player answers the newest invitation they have; add from <who> to answer a particular one
leave partyThe player leaves. If they led it, whoever joined after them leads; a party of one is no party
remove <who> from partyThe leader takes someone out
disband partyThe leader ends it
party of <who>A list of the names of everyone in their party, the leader first; empty for someone without one. It can be sent to: send "..." to party of player reaches every member who is online
party leader of <who>The leader's name; unset without a party
party invites of <who>The names of those who have invited them
<who> is in a partyA condition; is not in a party likewise

A queue collects players until there are enough, and then runs a block with them:

on queue "duels" of 2:
    set {_a} to item 1 of {_players}
    set {_b} to item 2 of {_players}
    broadcast "&6%{_a}% &7fights &6%{_b}%&7!"

command /duel:
    players only: true
    trigger:
        add player to queue "duels"
        send "&7Waiting for an opponent..."
SyntaxMeaning
on queue <name> of <n>:At the left margin: runs each time n players are waiting. They are taken out of the queue and handed over as the list {_players}, first come first
add <who> to queue <name>Put someone in the line; nothing happens if they are in it already
remove <who> from queue <name>Take them out. remove <who> from all queues for every queue at once
queue <name>A list of the names of those waiting
<who> is in queue <name>A condition
  • Parties and queues last while the server runs. A player who leaves the server leaves their party and every queue.
  • A queue's block runs as the console, since it is about several players: say who a line is for (send "..." to {_a}, or loop over {_players}).

Moderation

Guide and examples
command /mute-kick <player>:
    permission: "staff.kick"
    trigger:
        kick arg.1 because "&cPlease calm down."

on player login:
    if {maintenance} and {%player%.staff} is not set:
        refuse login because "&eThe server is being worked on. Back soon!"
SyntaxEffect
kick <who> [because <text>]Disconnect a player with a message
ban <who> [for <duration>] [because <text>]Ban by name, for good or for a while, and kick them if online
unban <who>Lift a ban
<who> is banned / is not bannedA condition
refuse login [because <text>]Inside on player login:, turn the player away
  • ban ... for 7 days ends by itself. Without for, the ban lasts until unban.
  • Bans are the server's own (the same list /ban and /pardon use), so they work for players who are offline and survive restarts.
  • on player login: runs while someone is connecting, before they are in the game. There is no player yet, so send reaches nobody and player.name is unset; use %event.name% for their name. {%player%.<name>} does work and is the variables of whoever is logging in, which is what makes checks such as a ban of your own or a whitelist possible.

Top lists

Guide and examples

top orders every player who has ever played by one of their own variables, highest first, whether they are online or not:

command /baltop:
    trigger:
        send "&6Richest players"
        set {_place} to 0
        for each {_name} in top 10 players by {coins}:
            add 1 to {_place}
            send "&e#%{_place}% &f%{_name}% &7- %{%{_name}%.coins}% coins"
        set {_mine} to rank of player by {coins}
        send "&7You are #%{_mine}%"
SyntaxResult
top <n> players by {<name>}A list of up to n player names, best first
rank of <who> by {<name>}Where that player stands, 1 being the best; unset if they have no value
  • The variable is each player's own: {coins} here means the same as {%player%.coins}, and both spellings are accepted.
  • Only players who have a number in that variable are listed.
  • The first time a list is asked for after a restart, HyperScript reads every player's data to build it, which on a large server with a database can take a moment. After that it is kept up to date as values change and costs almost nothing.

A currency of your own

Guide and examples

Money without another plugin: currency "gems" of player is a balance that is saved with the player, never goes below nothing, and can be ranked.

currency "gems":
    start: 10
    max: 100000

command /gems:
    players only: true
    trigger:
        set {_gems} to currency "gems" of player
        send "&7You have &b%{_gems}% &7gems."

command /givegems <player> <amount>:
    permission: "gems.admin"
    trigger:
        set {_amount} to parse arg.2 as integer
        if {_amount} is not set:
            send "&cThat is not a number."
            stop
        add {_amount} to currency "gems" of arg.1
        set {_now} to currency "gems" of arg.1
        send "&a%arg.1% now has %{_now}% gems."

command /paygems <player> <amount>:
    players only: true
    trigger:
        set {_amount} to parse arg.2 as integer
        if {_amount} is not set or {_amount} < 1:
            send "&cHow many?"
            stop
        if currency "gems" of player < {_amount}:
            send "&cYou do not have that many gems."
            stop
        pay {_amount} of currency "gems" from player to arg.1
        send "&aYou paid %arg.1% %{_amount}% gems."
SyntaxMeaning
currency "<name>":At the left margin: says what a new player starts with (start: 10) and the most anybody can have (max: 100000). Optional: without it a currency starts at 0 and has no most
currency <name> of <who>What they have. Change it with set, add and subtract; it stops at nothing and at the most
pay <n> of currency <name> from <who> to <who>Move that much from one player to the other. Nothing happens if the first does not have it
  • A balance is the player's own saved variable {%player%.currency.<name>}. So it works for someone who is offline, top 10 players by {currency.gems} ranks it, and other plugins can show it as %hyperscript_player_currency.gems%.
  • pay to a player who is already at the most moves what fits and the rest is lost; check first if that can happen on your server.
  • This is separate from an economy plugin. balance of player is Vault's money; a currency here is the script's own. The addon HyperEconomy makes the two one: it hands Vault a currency of yours as the server's money.

What players see

Everything a script can put on a player's screen or in their ears.

Action bars and titles

Guide and examples
send action bar "&a+100 Coins!" to player
send title "&6Victory!" with subtitle "&eYou won!" to player with fadein 10 stay 70 fadeout 20
send title "&cServer restarting" to all players
PartMeaning
send action bar <text> [to <who>]Text above the hotbar; it fades after a couple of seconds. send actionbar, in one word, is the same
send title <text>Large text in the middle of the screen
with subtitle <text>Optional smaller line underneath. with description <text> is the same
to <who>Optional; the default is the player of this trigger
with fadein <n> stay <n> fadeout <n>Optional timings in ticks (20 ticks = 1 second). Any of the three may be left out; the defaults are 10, 70 and 20

An action bar fades after a couple of seconds. To keep one, say how long: send action bar "&cIn combat" to player for 10 seconds, or until <condition> or while <condition>, which look at the condition four times a second. The text is the one it had when the line ran; for a text that changes, resend it from a timer: every 1 second for all players:. Sending another action bar ends one that was staying.

Boss bars

Guide and examples
create bossbar titled "&r&lEvent Boss" with color red with progress 100 for all players
create bossbar "raid" titled "&cRaid: %{_left}% left" with progress {_left} / 8 * 100 for player for 30 seconds
remove bossbar "raid"
PartMeaning
create bossbar [<id>]The id names the bar so it can be updated or removed later; without one the id is default
titled <text>The text on the bar
with color <colour>pink, blue, red, green, yellow, purple or white (the default)
with progress <0-100>How full the bar is, in percent; the default is 100
with segments <n>Notches along the bar: 6, 10, 12 or 20. Any other number gives a plain bar
for <who>Who sees it
for <n> secondsOptional: remove the bar after this long
for <n> seconds counting downThe bar empties by itself as the time runs, and is removed at the end
remove bossbar [<id>]Remove the bar for everyone
  • Creating a bar whose id already exists updates it (title, colour, progress) and adds the new viewers, so a countdown is just the same create bossbar line run again with a new progress.
  • A bar shown to all players is also shown to players who join later.
  • Bars are removed when the plugin is disabled; they do not survive a restart.

Scoreboards

Guide and examples

Each player can have their own sidebar, built line by line.

set title of player's scoreboard to "&e&lSERVER NAME"
set line 1 of player's scoreboard to "&7Coins: &a%{%player%.coins}%"
set line 2 of player's scoreboard to "&7Rank: &bVIP"
StatementEffect
set title of <who>'s scoreboard to <text>The heading of the sidebar
set line <n> of <who>'s scoreboard to <text>Line 1 is the top line; there are 15
update scoreboard of <who> every <duration>:The lines under it run now, and again that often, for as long as that player is on the server: a sidebar that keeps itself up to date, without a timer of its own. Asking again for the same player replaces what was running
stop updating scoreboard of <who>It is no longer kept up to date; what it shows stays
delete line <n> of <who>'s scoreboardRemove one line
clear <who>'s scoreboardRemove the sidebar and return to the server's normal scoreboard

The red numbers Minecraft puts beside every line are left out, on a Paper server for Minecraft 1.20.3 or newer; older servers and Spigot cannot hide them. sidebar-numbers: true in config.yml shows them again.

<who> is player or anything that gives a player name, such as {_name}'s scoreboard.

  • Animated sidebars. A line can be rewritten as often as every tick without flickering, so an animated or live-updating sidebar is a timer that sets the lines again:
every 1 second for all players:
    set title of player's scoreboard to "&e&lMY SERVER"
    set line 1 of player's scoreboard to "&7Coins: &a%{%player%.coins}%"
    set line 2 of player's scoreboard to "&7Ping: &f%player.ping% ms"
    set line 3 of player's scoreboard to "&7Online: &f%server.online_players%"
  • Lines can be about 120 characters long including colour codes; longer text is cut off.
  • A player sees one scoreboard at a time. While a HyperScript sidebar is shown it replaces the sidebar, name tags and tab-list teams of other scoreboard plugins for that player.
  • Sidebars disappear when the player logs out; set them again on join, which is also where update scoreboard of player every ...: belongs.

GUIs

Guide and examples

open gui builds a chest menu and shows it to a player. Each slot line places an item; a slot line that ends with : gets a block that runs when the slot is clicked.

open gui with title "&8Coin Shop" with 3 rows for player:
    slot 12 is "diamond" named "&bDiamond" lore "&7Price: &e50 coins|&7Click to buy":
        if {%player%.coins} < 50:
            send "&cYou need 50 coins for that."
        else:
            subtract 50 from {%player%.coins}
            execute console command "give %player.name% diamond 1"
        close gui
    slot 14 is "gold_ingot" named "&6Balance: &e%{%player%.coins}% coins"
    slot 16 is "barrier" named "&cClose":
        close gui
PartMeaning
with title <text>Window title; & colour codes work
with <n> rowsOptional, 1 to 6; the default is 3
for playerWho sees it. Use a name instead to show it to someone else: for %arg.1%
slot <n> is "<item>"Slots are numbered from 1, left to right, top to bottom (row 2 starts at 10)
owned by <name>In a menu, for a "player_head": whose face it shows. Comes before named
named <text>Optional item name
lore <text>Optional description lines, separated by |
close guiCloses the window for the player
slots <a> to <b> are <item>The same button in several slots at once: slots 1 to 9 are "black_stained_glass_pane", slots 11, 13, 15 are "barrier" named "&cLocked". With a block under it, clicking any of them runs it
slot <n> takes items:A slot a player can put an item into, from their cursor or by shift-clicking it in their own inventory. The block under it runs then, with the item as {_item}; the item is taken, so give it back if they should keep it. shown as <item>, named <text> and lore <text> say what the empty slot looks like
fill empty slots with <item>In the block: every slot no slot line took shows that item, with no name and nothing to click. It may stand anywhere in the block
border with <item>The same for the slots along the edge only
on close:In the block: the lines under it run when the window closes, as the player it was open for, with the local variables as they were. Opening another window closes this one too
refresh every <duration>In the block: while the window is open it draws itself again that often, on the page it is on, so that a time or a balance in it stays right
  • Item names are Minecraft material names in quotes, such as "diamond" or "oak_planks". An unknown name shows a barrier and logs a warning.
  • Items in a GUI are buttons. They cannot be taken, moved or shift-clicked out.
  • Titles, names and lore are filled in when the GUI opens. To refresh what a GUI shows, open it again.
  • The block under open gui is ordinary code in which every slot line adds a slot, so slots can come out of a loop or sit behind an if:
open gui with title "&8Warps" with 3 rows for player:
    set {_slot} to 0
    for each {_name} in keys of {warp}:
        add 1 to {_slot}
        slot {_slot} is "ender_pearl" named "&b%{_name}%" lore "&7Click to go":
            teleport player to {warp.%{_name}%}
            close gui
    if player has permission "warps.admin":
        slot 27 is "anvil" named "&eManage warps"
  • Pages. A gui knows which page it is showing. gui page is that number, starting at 1, and a click can turn it. The gui is drawn again in the same window, without closing:
open gui with title "&8Warps" with 5 rows for player:
    set {_names} to keys of {warp}
    set {_slot} to 0
    for each {_name} in page (gui page) of {_names} with 36 per page:
        add 1 to {_slot}
        slot {_slot} is "ender_pearl" named "&b%{_name}%":
            teleport player to {warp.%{_name}%}
            close gui
    if gui page > 1:
        slot 37 is "arrow" named "&ePrevious":
            previous page
    if gui page < pages of {_names} with 36 per page:
        slot 45 is "arrow" named "&eNext":
            next page
SyntaxMeaning
gui pageThe page being shown
page <n> of <list> with <k> per pageThe part of a list that page n shows
pages of <list> with <k> per pageHow many pages the list needs; at least 1
next page / previous pageIn a click block: show the page after or before
set gui page to <n>In a click block: jump to a page
refresh guiIn a click block: draw the gui again on the same page, after the click changed what it shows
  • Turning a page or refreshing runs the whole open gui block again, with the local variables as they were when the gui was first opened, so the list is looked up afresh each time.
  • A slot may be given a whole item instead of a name in quotes, which is how a button gets a glow: slot 5 is 1 nether star glowing named "&dRewards".
  • A click block runs as the player who clicked. It sees the local variables as they were when its slot line ran, so each slot made in a loop remembers its own round; saved variables such as {%player%.coins} are always current.

Trading

Guide and examples

The window villagers trade in, with offers of your own:

command /blacksmith:
    players only: true
    trigger:
        open trades "&6Blacksmith":
            5 emerald for 1 iron sword
            8 emerald and 1 stick for 1 diamond sword named "&bFrostbite" enchanted with sharpness 2
            1 diamond for 12 emerald
WrittenMeaning
open trades <title>:Opens the trading window for the player; open trades <title> for <who>: for someone else. The lines under it are the offers
<cost> for <result>An offer: what is paid on the left, what is got on the right. Any item with its amount, name and enchantments, or one named with item <name>:
<cost> and <cost> for <result>An offer that takes two things
  • The game does the trading itself: it checks that the player has what an offer costs, takes it and hands over the result, as with a villager. Nothing has to be scripted for that.
  • An offer can be used as often as the player can pay. A script that wants to sell something only once gives it out with give instead.
  • Money from an economy plugin cannot be an offer's cost: offers are item for item. Sell for money from a menu, with balance of player.

Advancements

Guide and examples

A script can add advancements of its own to the game's advancement screen, and hand them out:

advancement "first kill":
    title: "&cFirst blood"
    description: "Win a fight against another player"
    icon: iron sword
    frame: challenge

on player kill:
    grant advancement "first kill" to player
WrittenMeaning
advancement "<name>":At the left margin. The name is what it is granted by
title: / description:What players read. Without a title, the name is shown
icon: <item>The item drawn in its frame; a book unless said otherwise
frame: task, goal or challengeThe shape of the frame, and how grandly it is announced
parent: "<name>"The advancement it hangs under in the screen. Without one it hangs under the server's own first entry
announce: falseDo not tell everybody in chat
hidden: trueOut of sight until somebody has it
grant advancement <name> to <who>Give it. The pop-up, the sound and the line in chat are the game's own
revoke advancement <name> from <who>Take it back
<who> has advancement <name>A condition; does not have advancement likewise
  • Nothing in the game can earn these: only grant advancement does. That makes them a way of remembering as well; player has advancement "first kill" is saved by the game itself.
  • All of a server's own advancements share one tab in the advancement screen.
  • They are added when the scripts load. A player's progress is kept by the game and survives restarts; an advancement that is taken out of its script is gone from the screen.

Sounds

Guide and examples
play sound "entity.experience_orb.pickup" with pitch 1.8 and volume 1.0 at player's location
play sound "block.note_block.pling" with pitch 2.0 and volume 0.5 for player
play sound "ui.toast.challenge_complete" for all players in world "world"
PartMeaning
play sound <name>A Minecraft sound id such as "entity.player.levelup", or a custom one from your resource pack
with pitch <n>Optional, 0.5 (low) to 2.0 (high); the default is 1.0
and volume <n>Optional; the default is 1.0. Above 1.0 the sound is not louder but carries further
at <position>Play it in the world: everyone within earshot hears it coming from that spot
for <who>Play it to those players only, wherever they are
for all players in world <name>To everyone in one world
for players within <n> blocks of <location>To everyone that close to a place, each hearing it as if it were beside them

Pitch and volume may be given in either order, or one without the other (with volume 0.5). With neither at nor for, the sound is played to the player of the trigger. An unknown sound id plays nothing and is not reported, because the server cannot know which sounds a client's resource pack adds.

Resource packs

Guide and examples
on player join:
    send resource pack "https://example.com/pack.zip" with hash "da39a3ee5e6b4b0d3255bfef95601890afd80709" to player

on resource pack accept:
    send action bar "&aDownloading server resource pack..." to player

on resource pack decline:
    send "&cYou declined the resource pack! Some custom items may appear incorrectly."

on resource pack successfully loaded:
    send "&aResource pack loaded successfully!"
    play sound "ui.toast.challenge_complete" at player's location
PartMeaning
send resource pack <url>A direct download link to the pack's .zip file
with hash <sha1>Optional: the file's SHA-1 hash, which is 40 hexadecimal characters
to <who>Optional; the default is the player of this trigger
  • The hash lets a player's game verify the download and reuse a copy it already has. Without it, the pack is downloaded again on every join.
  • A hash that is not 40 hexadecimal characters is not a SHA-1 hash (32 characters is an MD5 hash, for instance). HyperScript logs a warning and sends the pack without a hash, because a wrong hash would make every client reject the pack.
  • The four events tell you how each player responded. A player normally produces accept and then either successfully loaded or failed; decline comes instead of all of those.

The world

Blocks, places, creatures and things that float in the air.

Worlds and regions

Guide and examples

Time and weather

set time in world "%player.world%" to 1000
set weather in world "%player.world%" to clear
StatementEffect
set time in world <name> to <ticks>Time of day: 0 is sunrise, 1000 day, 6000 noon, 13000 night, 18000 midnight
set weather in world <name> to <weather>clear, rain or thunder

Blocks

set block at 0, 64, 0 in "world" to gold block
set block at player's location to air
set block at {%player%.home} to "oak_planks"
if block at event's location is "bedrock":
    cancel event
SyntaxMeaning
set block at <position> to <block>Replace the block there. The block is a Minecraft block name in plain words (gold block, oak planks, air), checked when the script loads, or any value holding one
set <variable> to <block name>Keep a kind of block in a variable, by its name in plain words: set {_block} to red concrete. Capitals do not matter, and the name is checked when the script loads. set block at {_spot} to {_block} then places it
place <block> at <position>Another way to say set block at <position> to <block>: place stone at {_loc}
block data at <position>The block that is there with its details: which way stairs face, whether a door is open, which half a slab is. Keep it in a variable and set block at {_loc} to {_data} puts the same block back, the same way round. What is inside a chest and what a sign says are not part of it
block at <position>The type of block that is there now, as Minecraft names it: stone, gold_block. Comparing takes "gold block" and "gold_block" for the same name

A position is player, player's location, event's location, a variable holding a location, or <x>, <y>, <z> followed by in "<world>" (without it, the player's world is used).

Whether a world is there can be asked before it is used:

command /arena:
    trigger:
        if world "arena" exists:
            teleport player to spawn of world "arena"
        else:
            send "&cThe arena has not been made yet."
  • at player and at player's location mean the block the player's feet are in.
  • Changing a block happens at once and drops nothing. Changing many blocks in one go is slow; do a few at a time and wait between them.
  • block at reads the world, which is only safe on the server thread: inside async: put it in a sync: block.

Regions are named boxes in a world. HyperScript only keeps track of where they are; what happens inside one is up to your scripts.

create region "spawn_protection" from -20, 0, -20 to 20, 255, 20 in "world"

Once a region exists, any trigger can ask which regions a location is in:

on block break:
    if region at event's location contains "spawn_protection":
        if player does not have permission "hyperscript.admin":
            cancel event
            send "&cYou cannot break blocks inside the spawn region!"
            play sound "block.anvil.land" with pitch 0.5 and volume 1.0 at player's location
SyntaxMeaning
create region <name> from <location> to <location>Define (or redefine) a region by two opposite corners; both corner blocks are included
delete region <name>Remove it
spawn firework at <location>Launch a firework; add colored red, blue, shaped star and with power 2 as wanted
play effect <name> at <location>A built-in visual such as smoke, ender_signal or mobspawner_flames
set line <n> of sign at <location> to <text>Write on a sign; line <n> of sign at <location> reads it
items in chest at <location>A list of the items in a chest or other container
add <item> to chest at <location> / clear chest at <location>Put items in a container, or empty it
remove <item> from chest at <location>Take items of that kind out of a container: as many as are asked for, and no more than there are. remove 5 diamond from chest at {_chest}
number of <item> in chest at <location>How many of that item the container holds, over all its slots
chest slot <n> at <location>The item in one slot of a container, counting from 1; unset for an empty slot. It can be set: set chest slot 1 at {_chest} to diamond sword, and emptied with delete chest slot 1 at {_chest}
set gamerule <name> of world <name> to <value>Change a game rule; gamerule <name> of world <name> reads it. Old and new rule names both work on every version: keepInventory or keep_inventory, doDaylightCycle or advance_time
set difficulty of world <name> to <level>peaceful, easy, normal or hard; difficulty of world <name> reads it
set pvp of world <name> to <true or false>Whether players can hurt each other in that world
set pvp of region <name> to <true or false>The same for one region; HyperScript stops the fighting itself
set build of region <name> to <true or false>Whether blocks can be broken and placed in a region
players in region <name>A list of the names of the players inside
entities in region <name>A list of the creatures inside, players not among them
random location in region <name>A place somewhere inside the region, in the middle of a block; unset if there is no such region
spawn of world <name>The world's spawn point, as a location
create hologram <name> at <location> with lines <text>, <text>Floating text. Creating one under a name that exists replaces it, which is also how to move it
set line <n> of hologram <name> to <text>Rewrite one line; a line past the end is added
delete hologram <name>Take a hologram away
hologramsA list of the names of every hologram
set fake block at <position> to <block>Show one player a block that is not really there. Only their game is told; the world is not changed, and nobody else sees it. Add for <who> or for all players to show someone else
clear fake block at <position>Show the player what is really there again; for <who> as above
set fake blocks from <location> to <location> to <block>A whole box of fake blocks, between two opposite corners; for <who> as above. Up to 32768 at once
clear fake blocks from <location> to <location>Shows what is really in that box again
clear all fake blocksEvery fake block scripts have shown the player, wherever it is; for <who> or for all players likewise
strike lightning at <location>A real bolt; strike fake lightning at only looks like one
create explosion at <location> [with power <n>]Power 4 is TNT. Add without breaking blocks and with fire as needed
fill from <location> to <location> with <block>Set every block in a box, up to 32,768 at once
fill from <location> to <location> with <block> replacing <block>Only the blocks of that kind are changed, the rest of the box stays: fill from {_a} to {_b} with air replacing stone
fill from <location> to <location> with <block> hollowOnly the outside of the box: walls, floor and roof, with what is inside left as it is. Goes together with replacing
break blocks from <location> to <location>Break every block of a box, 4,096 at most, each the way break block at does. over <duration>, without particles and without drops work here too; with more than 256 blocks the cracks and the crumbs are left out
show cracks <n> on block at <location>The block looks that broken, from 1 to 10, to everybody within 64 blocks; it is not harmed. The game lets cracks fade after about twenty seconds, so show them again to keep them. Needs a Paper server, or Spigot 1.19.4 or newer
clear cracks on block at <location>Take them away again
drop block <block> at <location>The block falls from there the way sand does, and settles where it lands. drop falling <block> at <location> says the same
copy blocks from <location> to <location> as <name>Remember every block in a box under a name, up to 250,000 of them. copy region <name> as <name> does the same for a region made with create region
paste <name>Put the blocks back where they were copied from, or somewhere else with at <location>, which becomes the lowest corner
delete copy <name>Forget a copy
break block at <location>As if mined: it drops what it would, with the crumbs and the sound of a block breaking
break block at <location> over <duration>The block cracks the way one being mined does, a little more all the time, and breaks when the time is up: break block at {_loc} over 5 seconds. The lines after it run at once; they do not wait. A block that somebody mines or changes in the meantime is left alone. without particles may be added. The cracks need a Paper server, or Spigot 1.19.4 or newer; elsewhere the block simply breaks when the time is up
break block at <location> without dropsThe block breaks and leaves nothing lying there. Goes together with the others: break block at {_loc} over 3 seconds without drops, break block at {_loc} without particles and drops
break block at <location> without particlesThe same, but silently and without the crumbs: the block is gone and its drops lie there
grow tree at <location>Needs dirt below and room above
drop <item> at <location>Put an item on the ground
drop loot <table> at <location>Drop what one of the game's own loot tables gives, such as "entities/zombie" or "chests/simple_dungeon"
fill chest at <location> with loot <table>Put what a loot table gives into the chest, barrel or other container there, spread over its slots as the game does
create world <name>Make a new world, or load it if it was made before. Add any of flat, void, amplified, large biomes, nether, end, with seed <value> and without structures. Making a world takes the server a few seconds
load world <name> / unload world <name>Bring a world into memory, or let go of it. Players inside are sent to the main world first. unload world <name> without saving throws away what changed since it was last saved
delete world <name>Unload a world and delete its files for good. Only worlds a script made can be deleted
created worldsA list of the names of the worlds scripts have made or brought in with load world, loaded or not
world <name> existsWhether there is a world of that name: one that is loaded, or one whose folder is on the server and can be loaded
set spawn of world <name> to <location>Where new players and bedless respawns appear
set world border of world <name> to <size> [over <duration>]Width in blocks; over makes it move there gradually
region at <location>A list of the names of every region containing that location
event's locationThe block an event is about: the block being broken or clicked

Where somebody stands and what they look at:

on player jump:
    if block below player is "slime_block":
        push player upward with force 2
        play sound "entity.slime.jump" for players within 10 blocks of player's location
    if block above player is "glass":
        send action bar "&7Mind your head." to player

command /scan <player>:
    trigger:
        if player is looking at arg.1:
            send "&aYou have %arg.1% in your sights."
        if player is not looking at target block of player:
            send "&7You are looking at nothing in reach."
        if player is riding:
            set {_mount} to vehicle of player
            send "&7You are riding something."
        if player is in biome "desert":
            send "&eIt is hot here."
        if level of player is even:
            send "&7An even level."
        if level of player is odd:
            send "&7An odd level."
        if level of player is divisible by 5:
            give 1 diamond to player or drop
        chance of 10%:
            give player 1 emerald
            send "&aLucky!"

Containers, the creatures around, and regions:

command /bank:
    trigger:
        set {_chest} to target block of player
        set {_gold} to number of gold ingot in chest at {_chest}
        send "&7This chest holds &6%{_gold}% &7gold."
        if {_gold} is at least 5:
            remove 5 gold ingot from chest at {_chest}
            add 1 diamond to chest at {_chest}
        set chest slot 1 at {_chest} to paper named "&fReceipt"
        if chest slot 2 at {_chest} is not set:
            send "&7The second slot is empty."
        delete chest slot 3 at {_chest}

on inventory open:
    # A chest somebody locked with /lock opens for them alone.
    if nbt "owner" of block at event's location is set:
        if nbt "owner" of block at event's location is not player.name:
            cancel event
            send "&cThis chest is locked."

command /sweep:
    permission: "sweep.use"
    trigger:
        for each {_mob} in entities of zombie within 20 blocks of player:
            kill {_mob}
        set {_left} to size of entities within 20 blocks of player
        send "&7%{_left}% creatures are left around you."
        set {_friend} to nearest other player to player
        if {_friend} is set:
            send "&7Closest to you: &f%{_friend}%"
        set {_threat} to nearest zombie to player
        if {_threat} is set:
            make player look at location of {_threat}
        set {_any} to nearest entity to player's location

command /arena:
    trigger:
        set {_spot} to random location in region "arena"
        if {_spot} is set:
            teleport player to {_spot}
        set {_inside} to size of entities in region "arena"
        send "&7%{_inside}% creatures are in the arena."
        set {_far} to horizontal distance between player's location and {_spot}

command /restart-in <minutes>:
    permission: "restart.use"
    trigger:
        if time until schedule "restart" is set:
            set {_left} to time until schedule "restart"
            send "&cA restart is already coming in %{_left}%."
            stop
        schedule stop_server() in arg.1 * 60 seconds as "restart"

function stop_server():
    execute console command "stop"

A location here is player's location, event's location, a variable holding a location, or <x>, <y>, <z> followed by in "<world>" (without it, the player's world is used).

Whether a world is there can be asked before it is used:

command /arena:
    trigger:
        if world "arena" exists:
            teleport player to spawn of world "arena"
        else:
            send "&cThe arena has not been made yet."
  • Holograms are saved: one made by a command is still there after a restart, and is listed in plugins/HyperScript/holograms.yml. A hologram a script keeps up to date is best made in on load:, which simply replaces the old one.
  • Copies are for putting a place back the way it was: copy an arena once, and paste it after every round. A copy is the blocks themselves, with which way they face and whether they are open or lit; what is *inside* chests, and what is written on signs, is not kept. It is saved in plugins/HyperScript/copies/ and stays until it is deleted. Pasting sets every block at once, so a large copy makes the server pause for a moment; nothing falls or flows because of it.
  • Fake blocks exist only on one player's screen. The server still has the real block, so the player cannot stand on a fake one over air, and the real block comes back by itself when they click it, when it changes, or when they leave the area and return. They are for showing things: a path to follow, an outline, a block that looks mined out. position is written as for set block: at player, at event's location, at 10, 64, -5 in "world".
  • Worlds of your own. create world "skyblock" void makes a world and remembers it: it is listed in plugins/HyperScript/worlds.yml and loaded again every time the server starts (unless it was last let go with unload world), before any script runs, so locations saved in it stay good. A world is one of normal (the default), flat, void (nothing but one block to stand on), amplified or large biomes, in the overworld, the nether or the end. Everything that works on a world works on these: teleport player to spawn of world "skyblock", game rules, difficulty, time, weather, borders and regions. Creating one that exists does nothing, so an on load: block may do it every time.
  • Region rules. set pvp of region "spawn" to false and set build of region "spawn" to false make HyperScript itself stop fighting and building there, so a script does not have to cancel events. Players with the permission hyperscript.region.bypass (operators by default) may still build. The rules are saved; set them once, for example in on load:.
  • region at ... gives a list because regions may overlap; test it with contains.
  • For block events, check event's location rather than player's location. The player can stand outside a region and still reach a block inside it.
  • Region names ignore case. Regions are saved with the other variable data and survive restarts.
  • This is HyperScript's own region list. It does not read WorldGuard regions.

Places

Guide and examples

Ways to get from one location to another, and to ask about one.

on player sneak:
    set {_ahead} to location 3 blocks in front of player
    if block at {_ahead} is "air":
        set block at {_ahead} to stone
SyntaxResult
<location> offset by <x>, <y>, <z>The place that far away
location above <location> / location below <location>One block up or down
location <n> blocks in front of <who>Where they are looking, that far away
location <n> blocks behind <who>That far behind them, on the level, from where they stand. location behind <who> is one block
location <n> blocks left of <who>That far to their left, likewise; right of for the other side, and location left of <who> is one block
midpoint between <a> and <b>Halfway between two places
highest block at <location>The top block of that column, as a location
biome at <location>The biome's name, e.g. plains
light level at <location>0 (dark) to 15 (bright)
target block of <who>The block they are looking at, up to 100 blocks away, as a location
block (below/above) <who>The kind of block under their feet, or over their head, such as gold_block. A location works in place of a player: the block one lower or higher
vehicle of <who>What they are riding, as a creature; unset if they are on foot
<location> is within <n> blocks of <location>A condition
<location> is loadedWhether that part of the world is loaded

Coordinates can be written out wherever a line ends with a place: set {spawn} to 0, 64, 0 in "world".

Entities

Guide and examples

A mob or animal can be kept in a variable and told what to do, just like a player.

command /boss:
    permission: op
    trigger:
        summon zombie at player's location with health 100
        set {_boss} to last summoned entity
        set name of {_boss} to "&c&lThe Boss"
        make {_boss} target player

on entity damage:
    if attacker is "zombie":
        push victim entity backward with force 0.8
SyntaxMeaning
last summoned entityThe creature the last summon of this trigger made
event entityThe creature the current event is about
victim entity / attacker entityIn on entity damage: the creatures themselves, not their names
clicked entityIn on entity click
target entity of <who>What they are looking at, up to 50 blocks away
name of <entity> / health of <entity>Read or set. How much health it can have is given when it is summoned: with health <n>
kill <who>Works on a player or an entity
kill <who> as <who>The same, but the server takes it for a kill by the second one, a player or a creature: the death message names them, %event.killer% is them, and they get the drops, the experience and the credit other plugins give for a kill. kill arg.1 as player
make <creature> follow <who>It walks after them until told otherwise, or until either is gone. make <creature> stop following ends it. Needs a Paper server
make <creature> walk to <location>It finds its own way there, if there is one. Needs a Paper server
make <creature> stay still / make <creature> move againTakes away its own will, so it neither walks nor turns nor is pushed; and gives it back
make <who> look at <location>Turn a player or a creature so that they face that place. The place is a location, x, y, z, or somebody: make player look at arg.1 looks them in the eyes. They stay where they are; only where they look changes
make <who> look northTurn them straight north, east, south or west, or make them look up or down
make <who> ride <creature> / make <who> dismountSeat a player, or another creature, on top of one
make <who> swing armThe movement of a hit, without hitting anything
damage <who> by <n>Hurt by that much; 2 is one heart
push <who> upward / downward / forward / backward [with force <n>]Shove in a direction. forwards, backwards, upwards and downwards are read the same, and at speed <n> says what with force <n> does: push player forwards at speed 2
push <who> towards <location> [with force <n>]Shove towards a place
push <who> away from <location> [with force <n>]Shove the other way: away from an explosion, a boss, a wall
push <who> left / right [with force <n>]Shove sideways, as they stand
launch <who> [upward] [at speed <n>] [without fall damage]A push, upward unless another direction is named. With without fall damage the landing does not hurt, which is what a jump pad wants; push takes those words too
make <entity> target <who>Send a mob after someone
remove entity <entity>Make it disappear
remove all <type> within <n> blocks of <location>Clear out every creature of a kind nearby
  • An entity prints as its name, or its type if it has none, so "%{_boss}%" works in text.
  • Everything in this table takes a player too: push player upward with force 1.2, kill arg.1. <who> means a player or an entity; <entity> means it only makes sense for one.
  • An entity is only good while it exists. Once it has died or its chunk has unloaded, acting on it does nothing. For that reason entities are for local variables, not saved ones.
  • remove all takes zombie, zombies, any other type, mobs (every hostile and passive mob) or entities (everything but players), up to 128 blocks away. Players are never removed.
  • Force is in blocks per tick: 0.5 is a nudge, 1.5 throws someone high into the air.

Creatures of your own. After the position, summon takes any of these, in any order:

WrittenEffect
with health <n>Its health, in half hearts, up to 2048. It starts at full health
with speed <n>How fast it moves, as a multiple of what is normal for it: 2 is twice as fast, 0.5 half
with damage <n>How hard it hits, in half hearts. Only creatures that attack have it
holding <item>What it has in its hand
wearing <item>, <item>Its armour; each piece goes where it belongs, and anything that is not armour goes on its head
dropping <item>, <item>What it leaves behind when it dies, instead of what such a creature usually drops. dropping nothing for nothing at all
glowing, silent, babyAn outline that shows through walls; no sounds; a young one
invisibleIt cannot be seen; what it holds and wears still can. Minecraft 1.16.3 or newer
small, marker, with arms, without gravity, without base plateFor an armor stand: half size; nothing can touch or select it; arms to hold things in; it floats where it was put; no stone plate under it. without gravity works on any creature
  • Write glowing, silent and baby before the items. After an item, glowing belongs to the item (dropping 1 stick glowing drops a shimmering stick).
  • What a creature holds and wears is its own and does not fall when it dies; say what it leaves behind with dropping.
  • What it drops stays with the creature, so it is still right after a restart.

What a creature leaves behind can also be changed when it dies, in on entity death::

on entity death:
    if event.entity is "zombie":
        add 1 emerald to drops
    if event.entity is "creeper":
        set drops to 3 gunpowder, 1 tnt
StatementEffect
set drops to <item>, <item>Replace what falls. set drops to nothing, or clear drops, for nothing
add <item> to dropsOne more thing, on top of the rest
make <who> shoot a <projectile>The same as shoot <projectile> from <who>, said the other way round. Add at speed <n>: make player shoot an arrow at speed 3
shoot <projectile> from <who>Launch an arrow, snowball, egg, fireball, small fireball, ender pearl, trident or the like, the way they are looking. Add with speed <n>: 1 is a gentle throw, 3 a fully drawn bow

%event.drops% is the list of what is about to fall, in on entity death: as in on block break:.

Shooting, turning and the tab list:

command /blast:
    trigger:
        set player's pitch to 0
        set player's yaw to -90
        make player shoot a small fireball at speed 2
        make player shoot an arrow

command /ghost <player>:
    permission: "ghost.use"
    trigger:
        hide player from tab list of arg.1
        send "&7%arg.1% no longer sees you on the list."
        wait 30 seconds
        show player in tab list of arg.1

A kill that counts for somebody:

command /smite <player>:
    permission: "smite.use"
    trigger:
        if arg.1 is not a player:
            send "&c%arg.1% is not online."
            stop
        strike fake lightning at player's location
        kill arg.1 as player
        send "&eYou smote %arg.1%."

Turning somebody to face a place, a player or a direction:

command /lookat <player>:
    trigger:
        make player look at arg.1
        make arg.1 look at player's location

command /spawnview:
    trigger:
        make player look at 0, 80, 0
        wait 2 seconds
        make player look north

Mobs of your own

Guide and examples

A mob block describes a creature once: what it is, how strong, what it carries and drops, and what happens when it dies. spawn mob then makes one wherever you like.

mob "&bFrost Giant":
    type: zombie
    health: 100
    damage: 8
    holding: diamond axe
    wearing: diamond helmet, diamond chestplate
    drops: 3 diamond, 1 ice
    experience: 50
    on death:
        broadcast "&bThe Frost Giant has fallen to %player.name%!"
    on hit:
        apply slowness 2 to player for 3 seconds

command /giant:
    permission: "mobs.spawn"
    players only: true
    trigger:
        spawn mob "Frost Giant" at player's location
Inside the blockMeaning
type: <creature>What kind of creature it is: zombie, skeleton, iron golem. A zombie if left out
name: <text>The name shown above it; the block's own name if left out, and name: none for no name
health: <n>Its health, in half hearts, up to 2048
damage: <n>How hard it hits, for a creature that attacks
speed: <n>How fast it is, as a multiple of what such a creature usually is: 1.5 is half as fast again
holding: <item>What it has in its hand
wearing: <item>, <item>Its armour; each piece goes where it belongs
drops: <item>, <item>What it leaves when it dies, in place of what such a creature usually drops. drops: nothing for nothing
experience: <n>The experience it leaves
glowing: true / silent: true / baby: trueAs it says
on spawn:Runs when one is spawned. player is whoever's script spawned it, if anybody
on death:Runs when one dies. player is who killed it; there is none if nobody did
on hit:Runs when it hurts a player, who is player
on hurt:Runs when a player hurts it; player is that player
SyntaxMeaning
spawn mob <name> at <location>Make one of a described mob there. last summoned entity is the creature
mob name of <entity>Which mob block a creature was made from, as its name; unset for any other creature
  • Inside the four blocks {_mob} is the creature and {_name} its mob's name; in on hit: and on hurt: {_damage} is how much damage was done. cancel event in those two stops the damage.
  • A mob is known by its name without colours, whatever capitals it is written with: the block above is spawned as "Frost Giant" or "frost giant".
  • A creature remembers which mob it is. After a restart or a reload its blocks still run, as long as a script still has a mob block of that name.
  • The block's lines are worked out when one is spawned, so health: {boss.health} takes the saved variable as it is then. Local variables cannot be used in them.
  • For creatures with skills, phases and models of their own, the MythicMobs plugin and the HyperMobs addon go further.

Characters

Guide and examples

A character is a creature that stands where you put it, cannot be hurt or pushed, and runs a block of your script when a player clicks it: a shopkeeper, a quest giver, a guide.

on load:
    create npc "&aGuide" at 10.5, 64, -3.5 in "world"

on npc click "guide":
    send "&aGuide: &fWelcome, %player%! The shop is to your left."
SyntaxMeaning
create npc <name> at <location>Make a character there, a villager unless said otherwise. With a name that is taken, the character is moved. Colours in the name are shown; it is known by the name without them, in lower case
create npc <name> as <entity> at <location>The same as another creature: as iron golem, as armor stand
delete npc <name>Take a character away
on npc click <name>:At the left margin: runs when a player right-clicks that character; without a name, any character. {_npc} is its name
npc <name>The creature itself, for what works on a creature: set name of npc "guide" to "...", make player ride npc "guide", remove entity npc "guide". To move a character, create npc it again at the new place
all npcsA list of the names of every character
  • Characters are remembered: they are still there, and still known by their names, after a restart. Making one in on load: is safe, because making it again only moves it.
  • A character here cannot look like a player. That takes the Citizens plugin and the HyperCitizens addon, which also give characters that walk routes and follow players. With HyperCitizens installed, create npc and on npc click are its, and make Citizens characters.

Display entities and particles

Guide and examples
spawn text display "&6Welcome, %player.name%!" at player for 10 seconds
spawn block display "diamond_block" at 0, 80, 0 in "world"
spawn particle "flame" at player
spawn particle "dust" colored "#ff8800" count 20 at player.x, player.y + 2, player.z
StatementEffect
spawn text display <text> at <position>Floating text that always faces the viewer
spawn block display <block> at <position>A floating block that cannot be walked into or broken
spawn particle <name> at <position>One particle
... colored "<#rrggbb>"Hex colour, for the "dust" particle
... count <n>Number of particles (1 to 1000), spread slightly around the position
... for <n> secondsDisplays only: remove it after this long
show text <text> in front of <who>Text that floats in front of a player's face and follows where they look. Only that player sees it
show text <text> in front of <who> for <duration>The same, gone after that long
show text <text> in front of <who> until <condition>The same, gone as soon as the condition holds
show text <text> in front of <who> while <condition>The same, gone as soon as the condition no longer holds
show text <text> in front of <who> at distance <n>How many blocks in front of the eyes, from 0.5 to 16; 2.2 when it is not said. Goes before for, until or while
show text <text> in front of <who> lockedThe same, fastened to the player: it keeps up with them as they walk and turn instead of gliding after them. Goes before for, until or while too
hide text in front of <who>Take it away now

A position is either at player or at <x>, <y>, <z>, optionally followed by in "<world>". Without a world, the player's world is used. at player places a display just above the player's head and a particle at body height.

Text in front of a player. show text ... in front of <who> puts text before one player's eyes. It moves with them and turns as they look around, nobody else sees it, and it goes when they leave the server.

command /tutorial:
    trigger:
        show text "&6Welcome!%nl%&7Open the chest in front of you" in front of player until player is sneaking
        wait 1 second
        send "&7Sneak to close the hint."

on player death:
    show text "&cYou died%nl%&7Respawning..." in front of victim for 3 seconds
  • Lines. %nl% in the text starts a new line; a list gives a line for each element: show text ["&6Shop", "&7Right-click to buy"] in front of player.
  • How long. Without anything more it stays until hide text in front of <who> or until the player leaves or dies. for 10 seconds gives it a time. until <condition> looks at the condition four times a second and takes the text away once it is true; while <condition> is the other way round. for and one of the two can be used together, and whichever comes first ends it.
  • The condition is read with what the trigger knew when the text was shown: its player and its {_local} variables, with the values they had at the end of the trigger.
  • Locked. Without it the text glides after the player, which looks soft and trails a little when they run. With locked it is put where the player is about to be, going on as they are going, and gets there within a tick: show text "&aSaved." in front of player locked for 3 seconds. It is as quick as a server can make it; what the player sees still depends on their connection.
  • A player has one such text at a time; showing another replaces it.
  • On Minecraft 1.19.4 and newer the text is a text display. Before that it is name tags, a line each. Showing it to one player only needs 1.18; on 1.16 and 1.17 everybody nearby sees it.

Numbers that float up. show floating text <text> at <position> puts text there that drifts up a block and is gone after a second or so (for 2 seconds to say how long). Everybody nearby sees it. It is how damage numbers are made:

on entity damage:
    show floating text "&c-%event.damage%" at victim

on block break:
    add 5 to {%player%.coins}
    show floating text "&6+5" at player

Each one is put a little to one side, so that several do not hide one another.

Pointing the way. point <who> to <location> draws a short trail of sparks from the player towards a place, which only they see and which moves as they do. It ends when they are within a few blocks of the place, when they change world, with stop pointing <who>, or with for, until or while as above.

command /quest:
    trigger:
        point player to {quest.chest} until {%player%.quest} is "done"
        send "&7Follow the sparks."

A glow one player sees. make <entity> glow for <who> gives a creature or a player the white outline that shows through walls, for that one player only; for 30 seconds gives it a time, and make <entity> stop glowing for <who> takes it away.

on entity click:
    make event entity glow for player for 10 seconds

This one talks to the game in a way the server has no official means for, so it needs a Paper server, version 1.20.5 or newer. Anywhere else it does nothing and says so once in the log. The outline is white; a colour of one's own is not possible this way.

  • Display entities need Minecraft 1.19.4 or newer. On older servers a text display becomes an invisible armour stand with a visible name, which looks almost the same. Block displays have no older equivalent; the statement logs a warning and does nothing.
  • A display without for ... seconds stays until the server restarts or the plugin is disabled. Displays are never written to the world file, so they cannot be left behind.
  • Particle names are the server's own, such as "flame", "heart", "cloud", "end_rod". Use "dust" for coloured particles; it works on every supported version.
  • Many particles were renamed in Minecraft 1.20.5 (villager_happy became happy_villager, spell_witch became witch, fireworks_spark became firework, and so on). Either name works on every version. /hyperscript particle lists the ones your server has, and /hyperscript particle flame shows one in front of you.
  • A particle that cannot be shown, because there is none of that name or it cannot be made, is said to the admins who are online as well as in the console, with the names that come close.
  • A position may also be written player's location, which means the same as player, or be a location held in a variable: at {%player%.home}.

Particle shapes

Guide and examples

draw particle renders a whole shape in one statement.

draw particle circle with radius 2 using particle "flame" at player's location
draw particle sphere with radius 3 using particle "dust" colored "#00ffaa" with 200 points at 0, 80, 0
draw particle line from player to 0, 80, 0 using particle "end_rod"
ShapeSyntaxResult
circledraw particle circle with radius <r> using particle <name> at <position>A flat ring. Around a player it lies on the ground at their feet
spheredraw particle sphere with radius <r> using particle <name> at <position>A hollow ball with evenly spread points
linedraw particle line from <position> to <position> using particle <name>A straight line; both ends must be in the same world

Options, written after the particle name: colored "<#rrggbb>" (for "dust") and with <n> points. Without a point count the shape picks a density that looks solid for its size. A shape never uses more than 1000 particles.

  • Particles last about a second. For a lasting shape or a trail, draw from a timer:
every 5 ticks for all players:
    if {%player%.trail}:
        draw particle circle with radius 0.6 using particle "dust" colored "#ff66cc" at player

More shapes.

ShapeSyntaxDraws
boxdraw particle box from <position> to <position> using particle <name>The edges of a box between two corners
outlinedraw particle outline of region <name> using particle <name>The edges of a script region
helixdraw particle helix with radius <r> and height <h> using particle <name> at <position>A coil that winds upwards; add and 3 turns to say how often
spiraldraw particle spiral with radius <r> using particle <name> at <position>A flat line winding outwards from the middle
stardraw particle star with radius <r> using particle <name> at <position>A flat star with five tips
heartdraw particle heart with size <n> using particle <name> at <position>A heart standing upright, turned towards the player of the trigger
beamdraw particle beam from <position> to <position> using particle <name>A short stretch of light that travels from one end to the other; over 1 second says how long it takes
textdraw particle text <text> using particle <name> at <position>Letters made of particles, turned towards the player of the trigger; with size 2 after the text for bigger ones

What can follow any shape, after its place:

WrittenDoes
for <duration>The shape stays that long instead of fading after a second
until <condition> / while <condition>It stays until the condition holds, or while it does
around <who> (in place of at <position>)It stays with that creature or player as they move
visible to <who>Only they see it; only for <who> says the same
spinningIt turns round its middle; spinning at speed 2 for two turns a second
growing to radius <r> over <duration>It grows (or shrinks) from its radius to that one: a shockwave
rising <n> blocks over <duration>It lifts that far

What can follow the particle's name, in spawn particle and in a shape:

WrittenDoes
colored "<#rrggbb>"The colour, for "dust"
colored "<#a>" to "<#b>"A shape that runs from one colour at its start to another at its end
fading to "<#rrggbb>"Each particle changes to that colour while it lives. Needs Minecraft 1.17 or newer
of <block or item>For "block" and "item": what the crumbs are made of, as in "block" of stone
count <n>How many at each point
with speed <n>How fast they fly apart
spread <n> or spread <x>, <y>, <z>How far from the point each may appear
command /aura:
    trigger:
        draw particle circle with radius 1 using particle "dust" colored "#ff66cc" to "#66ccff" around player spinning for 30 seconds

on player death:
    draw particle circle with radius 0.5 using particle "cloud" at victim's location growing to radius 5 over 1 second

command /show <region>:
    trigger:
        draw particle outline of region arg.1 using particle "end_rod" visible to player for 10 seconds

Trails. give <who> a trail of <particle> leaves particles where a player walks, until remove trail of <who>, or with for, until or while. Standing still leaves none.

command /trail:
    trigger:
        give player a trail of "dust" colored "#ffaa00" for 5 minutes

Effects with a name. A particle effect "<name>": block, at the left margin like a function, holds the particle lines of one effect; play particle effect "<name>" at <position> plays it there. Inside the block, effect location is that place.

particle effect "level up":
    draw particle helix with radius 1 and height 2 using particle "end_rod" at effect location rising 1 blocks over 1 second
    draw particle circle with radius 0.5 using particle "flame" at effect location growing to radius 3 over 1 second

on level up:
    play particle effect "level up" at player

Things to know:

  • A shape that stays is drawn again several times a second, which costs more than one puff. Up to 200 can be going at once on a server; a new one beyond that takes the place of the oldest.
  • Everything ends when the scripts are reloaded or the server stops.
  • Text has capital letters, digits and ! ? . - + :; small letters are drawn as capitals, and it takes up to 24 characters.
  • "block" and "item" are the crumbs of breaking a block and of eating; the game calls them block_crack and item_crack before 1.20.5, and either name works.

Noise

Guide and examples

Noise is a number for every place that changes smoothly from one place to the next: the thing hills, caves, ore veins and patches of flowers are made of. A noise generator is a value like any other, kept in a variable and asked for a number wherever one is needed. That number is always between 0 and 1.

command /hills:
    permission: "hills.make"
    trigger:
        set {_hills} to noise generator "perlin" with seed 42 and scale 24 and octaves 3
        loop 16 times:
            set {_x} to x of player's location + loop-number
            loop 16 times:
                set {_z} to z of player's location + loop-number
                set {_height} to round(noise of {_hills} at {_x}, {_z} * 12)
                set block at {_x}, y of player's location + {_height}, {_z} to stone
        send "&aHills made."
SyntaxWhat it does
noise generator <kind>Makes a generator. The kind is "perlin" (soft hills), "simplex" (the same, rounder), "value" (blockier blobs), "cells" (0 at points scattered about and rising between them: cracked ground, islands), "ridged" (sharp lines: ridges, rivers) or "white" (every block on its own: static)
noise generator <kind> with seed <number>Which noise it is. The same seed gives the same numbers every time, on every server; without one each generator is different. A text works as a seed too
noise generator <kind> with scale <blocks>How many blocks one hill spans; 32 if nothing is said. Larger is smoother
noise generator <kind> with octaves <n>How many layers are laid over each other, each finer than the last: 1 to 8, and 1 if nothing is said. More gives more detail
noise of <generator> at <location>The number there, between 0 and 1, as on a map: only x and z count, so it is the same at every height
noise of <generator> at <x>, <z>The same for two numbers, and at <x>, <y>, <z> for three
solid noise of <generator> at <location>The number at that exact spot, height included: for caves and anything else that is not a surface
on player join:
    # The same generator every time, because it has a seed.
    set {flowers} to noise generator "cells" with seed "meadow" with scale 8
    set {_here} to noise of {flowers} at player's location
    if {_here} < 0.2:
        send "&dYou are standing in a flower patch."
    set {_cave} to noise generator "simplex" with seed 7
    if solid noise of {_cave} at player's location > 0.6:
        send "&7It feels hollow here."
    set {_static} to noise generator "white" with seed 1
    set {_ridge} to noise generator "ridged" with seed 3 with scale 64 with octaves 4
    set {_blobs} to noise generator "value" with octaves 2
    send "%noise of {_static} at 1, 2% %noise of {_ridge} at 1, 2, 3% %noise of {_blobs} at 5, 5%"
  • Several settings are joined with with or and: with seed 42 and scale 24 and octaves 3.
  • A generator can be kept in a saved variable such as {hills}; it is the recipe that is kept, not a table of numbers, so it costs nothing to store.
  • To turn the number into something else, multiply it: noise of {_n} at {_x}, {_z} * 20 is a height between 0 and 20, and if noise of ... > 0.7: picks out about the highest third.
  • Asking is fast, but a loop over a large area asks very often: keep areas to a few thousand blocks at a time, as with any loop that sets blocks.

Scenes

Guide and examples

For an entrance, an introduction or the moment a boss appears: a camera that glides through the world, and a border only one player has.

command /intro:
    players only: true
    trigger:
        set {_from} to player's location offset by 0, 20, -30
        set {_to} to player's location offset by 0, 6, -6
        move camera of player from {_from} to {_to} over 6 seconds looking at player's location
        wait 6 seconds
        send title "&6Welcome" to player
StatementEffect
move camera of <who> from <location> to <location> over <duration>They watch from a point that travels between the two places, starting and stopping gently. Add looking at <location> to keep something in view; otherwise the camera looks the way it travels
stop camera of <who>End it early
set border of <who> to <n> blocks around <location>A world border only they have, n blocks from edge to edge. Needs Minecraft 1.18.2 or newer
reset border of <who>They get the world's own border back
  • While the camera has a player they are a spectator and cannot move themselves. When it is over they are put back where they stood, in the game mode they had. The same happens if they log out in the middle, or the server stops: nobody is left a spectator far from home.
  • The camera does not wait: the lines after it run at once. Follow it with wait for as long as it takes, as above, when the next thing should happen at the end.
  • A border of one's own is only drawn, like a fake block: it stops the player walking through it but the server does not enforce it. It lasts until it is reset or they change world or log out.

Items

Items of your own making.

Enchantments of your own

Guide and examples

A script can make up an enchantment: a name, and what happens when an item that carries it is used.

enchantment lifesteal:
    max level: 3
    on hit:
        add {_level} to health of player

command /vampire:
    trigger:
        give player 1 iron sword enchanted with lifesteal 2
LineMeaning
enchantment <name>:At the left margin. One to four plain words, not the name of one of the game's enchantments
max level: <n>The highest level that counts, 5 unless you say otherwise; an item with more acts as if it had this many
on hit:Runs when a player hits something with the item in their main hand. victim, damage and the rest are there as in on hit:
on hurt:Runs when a player is hurt by someone while wearing the item, or holding it in either hand
on block break:Runs when a player breaks a block with the item in their main hand
  • Inside those blocks {_level} is the level on the item, and player is whoever holds it.
  • An item gets it the way it gets any other: enchanted with lifesteal 2, alone or among the game's own (enchanted with sharpness 5, lifesteal 1), in give, in an item <name>:, or with enchant tool of player with .... Any script can use an enchantment another file defines.
  • The game does not know these enchantments. An item shows one as a grey line at the top of its description (Lifesteal II) and has no enchantment shimmer because of it; add glowing for that. They cannot be had from an enchanting table or combined on an anvil.

Recipes

Guide and examples

A script can add crafting recipes to the server:

item magic wand:
    blaze rod named "&dMagic wand" glowing

recipe for magic wand:
    shape: " d ", " s ", " s "
    d: diamond
    s: stick

recipe for 4 oak planks:
    ingredients: oak log
LineMeaning
recipe for <item>:At the left margin. What is made: any item, with an amount if more than one, such as 4 oak planks or an item of your own
shape: "<row>", "<row>", "<row>"One to three rows of the crafting grid, each one to three characters and all the same length. A letter is an ingredient, a space is an empty square
<letter>: <item>What a letter of the shape stands for, such as d: diamond
ingredients: <item>, <item>Instead of a shape: what is needed, in any arrangement. 2 stick counts twice; nine at most
smelting recipe for <item>:At the left margin: a furnace recipe. Under it from: <item> says what is smelted; time: 10 seconds and experience: 0.5 may follow
  • A recipe has a shape: or ingredients:, not both.
  • Ingredients are plain Minecraft items. An item of your own can be what a recipe makes, but not what it takes: the game matches ingredients by kind only.
  • Recipes are added when the scripts load and taken away again when they are reloaded or the file is removed. recipe for is for the crafting table and smelting recipe for for the furnace; smithing recipes are not covered.
  • A shape smaller than the grid may be placed anywhere in it, as with Minecraft's own recipes.

Brewing. A brewing recipe for <item>: says what a brewing stand makes: from: is what stands in the bottles' place, and with: what is put in on top.

brewing recipe for 1 gold block:
    from: stone
    with: diamond

Brewing recipes need a Paper server, version 1.18 or newer; elsewhere the script says so when it loads. on brew: runs whenever a stand finishes, on every server. Potions themselves are items like any other: give player 1 potion with potion "swiftness".

NBT and data on things

Guide and examples

Data can be kept on a thing itself: on the item in somebody's hand, on a creature or a player, or on a block that holds something (a chest, a sign, a furnace). The server saves it in the thing's NBT, so it travels with the item from player to player and is still there after a restart.

command /soulbind:
    trigger:
        set nbt "owner" of tool of player to player.name
        set nbt "kills" of tool of player to 0
        send "&dThis item is yours now."

on entity death:
    if killer is set:
        if nbt "owner" of tool of player is player.name:
            set {_kills} to nbt "kills" of tool of player + 1
            set nbt "kills" of tool of player to {_kills}
            send action bar "&7Kills with this item: &f%{_kills}%" to player

on right click:
    if nbt "locked" of block at event's location is true:
        if nbt "owner" of block at event's location is not player.name:
            cancel event
            send "&cThis is not yours."

command /lock:
    trigger:
        set {_chest} to target block of player
        set nbt "locked" of block at {_chest} to true
        set nbt "owner" of block at {_chest} to player.name
        set nbt "visits" of player to nbt "visits" of player + 1
        delete nbt "tutorial" of player
        send "&7%nbt of tool of player%"

command /trophy:
    permission: "trophy.give"
    trigger:
        set {_trophy} to gold ingot named "&6Trophy" with nbt "winner" player.name with nbt "year" 2026
        give player {_trophy}
        set {_winner} to nbt "winner" of {_trophy}
        send "&7It says: %{_winner}%"
        set nbt of tool of player to "{Unbreakable:1b}"

on mob spawn:
    if event.entity is "zombie":
        set nbt of event entity to "{Silent:1b}"

command /fillchest:
    permission: "fill.use"
    trigger:
        set nbt of block at target block of player to "{Lock:\"secret\"}"
SyntaxWhat it does
nbt <key> of tool of <who>What is kept under that key on the item in their hand; unset if there is nothing. It can be set and deleted: set nbt "kills" of tool of player to 5, delete nbt "kills" of tool of player
nbt <key> of block at <location>The same on a block that can keep data: a chest, a barrel, a sign, a furnace and the like. A plain block such as stone cannot
nbt <key> of <who>The same on a player or a creature
<item> with nbt <key> <value>An item that carries that data from the start: give player diamond sword with nbt "owner" player.name. It may be said several times, and goes with named, with lore and the rest
nbt <key> of <item>The same read from an item in a variable: nbt "owner" of {_item}
nbt of tool of <who>The whole NBT of the item as one text, to look at; nbt of <who> likewise for a creature. Only where the server can say it; elsewhere it is unset
set nbt of tool of <who> to <text>Lays the game's own tags over what the item has, written as the game writes them: "{Unbreakable:1b}". On Minecraft 1.20.5 and newer an item's tags are written in square brackets, as /give takes them
set nbt of <creature> to <text>The same for a creature: set nbt of {_mob} to "{NoAI:1b,Silent:1b}". The game does not let a player's own NBT be changed
set nbt of block at <location> to <text>The same for a block that has NBT, such as a chest or a spawner
  • A value is a text, a number, or true / false.
  • Whether something is there is asked with is set: if nbt "owner" of tool of player is not set:.
  • A key written plainly, such as "kills", is HyperScript's own and no other plugin touches it. A key written with a colon, such as "otherplugin:level", is what another plugin keeps under that name, and can be read and changed the same way.
  • Keys and whole NBT are two things. A key (nbt "kills" of ...) is data of your own, kept apart from the game's, and it is what a script should use for its own bookkeeping. The whole NBT (set nbt of ... to "{...}") is the game's own tags, for what has no statement of its own. What is written there is handed to the game as it is, so a tag the game does not know is refused by the game, and the console says so.
  • For what there is a statement for, use the statement: set health of, enchanting an item, unbreakable. They work the same on every version; the names of the game's tags do not.
  • Data on an item belongs to that one item. tagged and with model are still the simple way to mark an item a script hands out; see Players.

Data and the outside

Keeping things, and talking to everything that is not this server.

Files

Guide and examples

Scripts can keep plain text files inside the plugin folder.

create file "proplayer300data.txt" at "plugins/HyperScript/"
set file at "plugins/HyperScript/proplayer300data.txt" to "Coins:500"
set {_proplayer300data} to read file at "plugins/HyperScript/proplayer300data.txt"
set {_parts} to split {_proplayer300data} by ":"
SyntaxEffect
create file <name> [at <folder>]Create an empty file, with any missing folders. An existing file is left untouched
set file at <path> to <text>Replace the file's content, creating the file if needed. A list is written one element per line
append <text> to file at <path>Add to the end of the file; write "%nl%..." to start a new line
read file at <path>The file's whole text; unset if the file does not exist
file at <path> existsA condition: if file at {_path} exists:
delete file at <path>Remove the file; no error if it is not there
lines of file at <path>The file's lines as a list, to loop over or count; unset if the file does not exist
size of file at <path>How large the file is, in bytes; unset if it does not exist
last modified of file at <path>When it was last written to, as a date; unset if it does not exist
copy file at <path> to <path>A second copy under another name or in another folder. What is there already is replaced
move file at <path> to <path>The same file somewhere else, or under another name: this is how a file is renamed
files in <folder>The names of the files in a folder, as a list in the order of the alphabet
folders in <folder>The names of the folders in it
all files in <folder>Every file in the folder and the folders inside it, each as its path from that folder: logs/monday.txt
folder at <path> existsA condition: if folder at "plugins/HyperScript/logs" exists:
create folder <path>Make a folder, with any missing folders around it. One that is there is left as it is
delete folder at <path>Remove an empty folder. Add with its files to remove one with everything in it
yaml value <key> of file at <path>One value out of a YAML file, such as another plugin's config.yml, by its path written with dots: yaml value "shop.prices.diamond" of file at "plugins/Shop/config.yml". A number, text, true or false, a list, or for a section a table of what is in it; unset if there is nothing there. Read only, and within the folders scripts may read
csv of file at <path>The rows of a .csv file as a list, each row a list of its cells: item 2 of item 1 of {_rows} is the second cell of the first row. Unset if the file does not exist
csv of file at <path> with headersThe same with the first row as the names of the columns: each later row is a table, read as {_row.price}
column <which> of <rows>One column of such rows, top to bottom: by its number, or by its name for rows read with headers
csv of <rows>Rows as CSV text, to write with set file at. A list of lists is a line each; a list of tables gets a first line with the names
parse <text> as csvText with commas in it as rows; add with headers as above

CSV files. A .csv file is what a spreadsheet saves: a line for each row, commas between the cells. csv of file at reads one into rows, and the rows are lists inside a list, so every cell is reached with item:

command /prices:
    trigger:
        set {_rows} to csv of file at "plugins/HyperScript/prices.csv" with headers
        for each {_row} in {_rows}:
            send "&e%{_row.item}% &7costs &f%{_row.price}%"
        set {_prices} to column "price" of {_rows}
        send "&7All prices: %{_prices}%"

command /export:
    trigger:
        set {_rows} to [["player", "coins"]]
        for each {_name} in server.players:
            add [{_name}, {%{_name}%.coins}] to {_rows}
        set file at "plugins/HyperScript/coins.csv" to csv of {_rows}
        send "&aWritten."
  • A cell that is written as a number is a number, true and false are themselves, an empty cell is not set, and everything else is text. 007 stays text, so that ids keep their zeros.
  • With with headers, the names of the columns are taken in lower case: a column Price is {_row.price}.
  • A cell with a comma, a quote or a line break in it is written in quotes, as spreadsheets do, and read back the same. Files that use semicolons or tabs between the cells, as spreadsheets write where the comma is the decimal point, are read as well.
  • At most 100,000 rows are read from one file.

Paths are written relative to the server folder, with forward slashes, as in "plugins/HyperScript/notes.txt".

command /notes:
    permission: "notes.read"
    trigger:
        set {_folder} to "plugins/HyperScript/notes"
        set {_names} to files in {_folder}
        if size of {_names} == 0:
            send "&7There are no notes."
            stop
        send "&6%size of {_names}% notes:"
        for each {_name} in {_names}:
            set {_path} to "%{_folder}%/%{_name}%"
            set {_lines} to lines of file at {_path}
            set {_when} to last modified of file at {_path}
            set {_day} to {_when} formatted as "d MMM"
            send " &f%{_name}% &8- &7%size of {_lines}% lines, changed %{_day}%"

command /archive <text>:
    permission: "notes.admin"
    trigger:
        set {_from} to "plugins/HyperScript/notes/%arg.1%.txt"
        if not file at {_from} exists:
            send "&cThere is no note called %arg.1%."
            stop
        move file at {_from} to "plugins/HyperScript/archive/%arg.1%.txt"
        send "&aArchived."

command /backupnotes:
    permission: "notes.admin"
    trigger:
        set {_notes} to "plugins/HyperScript/notes"
        set {_backup} to "plugins/HyperScript/notes-backup"
        if folder at {_backup} exists:
            delete folder at {_backup} with its files
        create folder {_backup}
        set {_bytes} to 0
        for each {_path} in all files in {_notes}:
            copy file at "%{_notes}%/%{_path}%" to "%{_backup}%/%{_path}%"
            add size of file at "%{_notes}%/%{_path}%" to {_bytes}
        set {_groups} to folders in {_notes}
        send "&aCopied %{_bytes}% bytes from %size of {_groups}% folders of notes."

on load:
    # An empty folder left over from last time goes; one with something in it is left alone.
    if size of (files in "plugins/HyperScript/temp") == 0:
        delete folder at "plugins/HyperScript/temp"
  • A folder that is not there has no files in it: files in gives an empty list, not a mistake.
  • files in and folders in may be asked of "plugins/HyperScript" itself; HyperScript's own files and folders are left out of the answer. A listing has at most 1000 names.
  • move file and copy file make the folders the new place needs.

Scripts that look after scripts. The scripts folder is closed to the statements above, so that a path made from what a player typed can never reach it. A script that sets a server up can still see which scripts there are, take one out, and read and change another's options:

command /cleanup:
    permission: "hyperscript.admin"
    trigger:
        for each {_script} in all scripts:
            if {_script} is not this script:
                delete script {_script}
        send "&aEvery other script was taken out."

command /servername <text>:
    permission: "hyperscript.admin"
    trigger:
        if not script "Sidebar" exists:
            send "&cThere is no Sidebar.hs here."
            stop
        set {_old} to option "name" of script "Sidebar"
        set option "name" of script "Sidebar" to arg.1
        send "&aThe sidebar was called %{_old}% and is now called %arg.1%."
SyntaxEffect
all scriptsThe names of the files in the scripts folder, as a list: Kits.hs, games/Duels.hs
this scriptThe name of the file the line is in
script <name> existsA condition. The name may be written with or without .hs
enabled scriptsThe scripts that are switched on, as a list. disabled scripts for those that are not, by the names they have when they are on
script <name> is enabledA condition; is disabled for the other. A script that is not there is neither
error of script <name>What a script failed to load with, such as line 12: Expected 'to' but found 'too'; unset for one that loaded
disable script <name>Switch a script off, the way /hyperscript disable does: its file is kept, with disabled_ in front of its name, and the scripts are read again a moment later. enable script <name> switches it back on
delete script <name>Take a script out of the scripts folder. It is not destroyed: it is moved to plugins/HyperScript/removed-scripts, from where it can be put back
option <name> of script <name>What that script's options: block says for one option, without quotes; unset if it has no such option
set option <name> of script <name> to <value>Write another value into that script's options: block. The rest of the file, and a note after the value, stay as they are
  • With hot reloading on, a script that was changed or taken out is loaded again by itself; otherwise run /hyperscript reload, which a script can do with execute console command "hyperscript reload".
  • An option a script does not have is not added: set option stops the trigger and says so. Ask first with option ... of script ... is set.
  • These follow files.enabled like everything else here.
  • Scripts can only reach files inside plugins/HyperScript/. A path that leads anywhere else, including through .. or an absolute path, stops the trigger with a warning in the console.
  • Inside that folder, HyperScript's own files are off limits: config.yml, data.json, the database, and the scripts and backups folders.
  • These limits exist because paths are often built from what players type. Even so, prefer names you control, such as %player.uuid%, over raw player input in a path.
  • Files are read as UTF-8 text. read file refuses files larger than 1 MB.
  • File access happens immediately, on the thread the script is running on. That is fine for small files; put work on large ones inside async:.
  • For data that belongs to a player or to the server as a whole, variables are usually the better tool: they are saved, backed up and cached for you. Files are for things other programs read or write, such as logs and exports.
  • files.enabled: false in config.yml turns all of this off.

The database

Guide and examples

When HyperScript keeps its variables in a database (storage.type is sqlite, h2 or mysql), scripts can ask that database questions of their own: read what a website or another plugin wrote, or keep a table that is theirs.

on load:
    run sql "CREATE TABLE IF NOT EXISTS purchases (player VARCHAR(16), item VARCHAR(40), day VARCHAR(10))"

command /bought:
    players only: true
    trigger:
        async:
            set {_rows} to sql rows of "SELECT item, day FROM purchases WHERE player = ?" with player.name
            send "&7You have bought %size of {_rows}% thing(s)."
SyntaxMeaning
run sql <statement>Run a statement that changes something: INSERT, UPDATE, DELETE, CREATE TABLE
sql rows of <query>Run a SELECT. The result is a list with a table for each row, its columns by their names in lower case. Up to 10,000 rows
with <value>, <value>After either: the values for the question marks in the statement, in order
  • Put what players type after with, never into the statement itself. ... WHERE name = ? with arg.1 is safe whatever arg.1 is; gluing arg.1 into the text lets a player rewrite your question.
  • The database answers while the server waits. A question that may take a moment belongs in an async: block, as above.
  • This is the database HyperScript's own variables are in, in the tables hyperscript_variables and hyperscript_shared. Leave those two to HyperScript.
  • With storage.type: json or csv there is no database, and these two say so when they run.

Variables several servers have in common. With storage.shared-variables: true and every server using the same database, a variable whose name starts with shared. is the same on all of them: set {shared.event} to "double coins" on one server is what {shared.event} gives on the others a couple of seconds later (storage.shared-refresh). Every other variable stays each server's own. A shared variable is written the moment it changes; two servers changing the same one at the same moment do not add up, the later one wins, so add 1 to {shared.votes} from several servers at once can lose a count. A player's shared value is written with their name or id in it: {shared.coins.%player.uuid%}.

Web requests

Guide and examples

Scripts can call web APIs. A request waits for the server on the other end, so one whose answer you use has to be inside an async: block; HyperScript refuses to run it on the server thread rather than freeze the game.

command /lookup <player>:
    trigger:
        send "&eFetching data from the API..."
        async:
            set {_response} to send get request to "https://api.mojang.com/users/profiles/minecraft/" + urlencoded arg.1
            set {_uuid} to json value "id" of {_response}
            sync:
                if {_uuid} is set:
                    send "&aFound UUID for %arg.1%: &f%{_uuid}%"
                else:
                    send "&cPlayer profile not found."

command /postanalytics:
    trigger:
        send post request to "https://api.example.com/v1/analytics" with body "{\"event\":\"command_used\",\"player\":\"%player.name%\"}"
SyntaxMeaning
send get request to <url>Fetch a URL; the value is the response body as text
send post request to <url> with body <text>Send data. A body starting with { or [ is sent as JSON, anything else as plain text
headers <text>, <text>, ...Optional, after the body: lines such as "Authorization: Bearer abc"
  • Used as a value (set {_r} to send get request ...), a request must be in async:. Used as a statement, where nothing reads the answer, it may appear anywhere and is sent in the background.
  • The value is unset if the request could not be made (no connection, unknown host, timeout); the reason is logged. An error response such as 404 still gives you its body.
  • Most APIs answer in JSON. json value "<path>" of <text> picks a value out of it, as the example does; see below.
  • Always put player input through urlencoded before adding it to a URL, as above. Otherwise a player can type characters that change which address or parameters the request uses.
  • Requests can only go to public internet addresses. Addresses on the server's own machine or local network (localhost, 192.168.x.x, 10.x.x.x and similar) are refused, so a URL built from player input cannot be used to reach private services. Set web.allow-private-addresses: true in config.yml if your scripts need to call something on your own network.
  • Redirects are not followed, timeouts are 5 seconds to connect and 10 to answer, and answers are cut off at 1 MB. web.enabled: false turns web requests off.

Reading JSON. json value takes a path and JSON text and gives the value found there.

set {_json} to "{\"name\":\"Steve\",\"stats\":{\"kills\":12},\"friends\":[\"Alex\",\"Bob\"]}"
log json value "name" of {_json}
log json value "stats.kills" of {_json}
log json value "friends.2" of {_json}
log size of (json value "friends" of {_json})

That logs Steve, 12, Bob and 2.

Path stepPicks
a name, such as statsThat field of an object. Capitals are ignored if there is no exact match
a number, such as 2That element of a list, counting from 1 like the rest of HyperScript
steps joined by dots, stats.killsOne inside the other
  • Numbers, text and true/false come out as ordinary values, and a JSON list comes out as a list.
  • A JSON object comes out as JSON text, which you can read further with another json value.
  • If the text is not JSON, or there is nothing at that path, the result is unset, so if {_value} is set: tells you whether it worked.

Being called from outside. HyperScript can also listen: a voting site, a web shop or a Discord bot calls an address of the server, and a script runs.

on web request "/vote":
    set {_name} to json value "username" of {_body}
    broadcast "&a%{_name}% voted for the server!"

It is off until web.server.enabled is true in config.yml, and it needs web.server.token set to a secret of at least 12 characters. The address is then http://<your server>:8765/vote (the port is web.server.port), and every request has to carry the token: as a header Authorization: Bearer <token> or X-Token: <token>, or as ?token=<token> in the address.

In the blockWhat it holds
{_body}What was sent, as text; json value "<path>" of {_body} reads from it if it is JSON
{_method}GET, POST, ...
{_path}The address asked for, e.g. /vote
{_query}What came after ? in the address, without the token
{_address}Where the request came from
  • on web request: without an address hears every request.
  • The caller is answered ok when a block ran and 404 when none listens at that address; a script cannot choose the answer. Without the right token the answer is 401 and no script runs.
  • A request may carry up to 64 KB, and no more than twenty are taken in a second.
  • The block runs as the console. Open the port in your firewall or with your host if the caller is not on the same machine, and prefer bind: "127.0.0.1" when it is.

Async blocks

Guide and examples

Everything in a trigger normally runs on the server thread, where slow code makes the whole server stutter. async: moves a block to a background thread; sync: inside it returns to the server thread.

command /highscores:
    trigger:
        async:
            set {_ranked} to reversed sorted {scores}
            set {_best} to item 1 of {_ranked}
            sync:
                send "&6Best score: &e%{_best}%"
        send "&7Working on it..."
  • The trigger does not wait: in the example, "Working on it..." is sent first.
  • An async: block works on its own copy of the local variables, taken when the block starts. Changes it makes are visible inside the block (including a nested sync:), not after it. Saved variables are shared as usual.
  • You do not have to use sync: just to talk to the server. send, broadcast, execute, open gui and spawn are handed to the server thread automatically when used inside async:. Use sync: when several statements must happen together in one tick.
  • cancel event has no effect inside async: because the event has already finished.
  • What it is for: sorting or filtering large lists, long loops, heavy math. Reading and writing variables is already fast (they are in memory, and storage I/O always happens in the background), so ordinary scripts do not need it.

Server list

Guide and examples

on server ping runs whenever a client refreshes its server list, and can change what that client sees: the message of the day, the player counts and the icon.

on server ping:
    set motd to "&6My Server &7- &a%server.online_players% online\n&eDouble coins weekend!"
    set max players to 100
    set shown players to server.online_players + 20
    set player list to "&6Welcome!", "&7Survival and minigames", "&7discord.gg/example"
StatementChangesServer
set motd to <text>The message of the day. \n starts the second line; & colour codes workSpigot and Paper
set max players to <number>The limit shown after the slash. The real limit stays as it isSpigot and Paper
set shown players to <number>The online count shownPaper
set player list to <text>, <text>, ...The lines shown when the mouse rests on the player count; a list value works tooPaper
hide player countShows ??? instead of the countsPaper
set server icon to <path>The icon: a 64 by 64 pixel PNG inside the plugin folder, such as "plugins/HyperScript/icon.png"Spigot and Paper

%server.motd% is the MOTD from server.properties, and %event.address% the IP address of the client asking. To rotate messages, pick one at random:

on server ping:
    set motd to random item of ["&6Welcome!", "&bNew: sky islands", "&dVote for rewards"]
  • There is no player in this event. The client has not logged in yet, so {%player%.*} variables and the player placeholders are unset. Global variables work.
  • It runs very often, and not on the server thread, so every refresh of every client's list triggers it. Keep the block to a few set lines: no loops, files or web requests.
  • A statement marked Paper does nothing on Spigot except log one warning.
  • Clients cache the icon and refresh the list at their own pace, so a change can take a moment to show.

Other plugins

Guide and examples

HyperScript works with two widely used plugins when they are installed. Neither is required.

Vault (money). With Vault and an economy plugin, balance of <who> is a player's money, and it can be changed like a variable:

if balance of player >= 500:
    subtract 500 from balance of player
    give player 1 diamond
add 100 to balance of arg.1
set balance of player to 0

PlaceholderAPI. With PlaceholderAPI, placeholder <text> fills in other plugins' placeholders:

set {_rank} to placeholder "%vault_rank%"
send placeholder "&7Your rank: %vault_rank% &8| &7Playtime: %statistic_time_played%"
set {_theirs} to placeholder "%player_level%" for arg.1

It also works the other way round. Any plugin that understands PlaceholderAPI can show script variables:

PlaceholderShows
%hyperscript_<name>%The global {<name>}
%hyperscript_player_<name>%The viewing player's own {%player%.<name>}
placeholder "<name>":At the left margin of a script: a value worked out for whoever looks, shown by other plugins as %hyperscript_<name>%
placeholder "rank_colour":
    if player has permission "rank.vip":
        return "&6"
    return "&7"

placeholder "coins_short":
    if {%player%.coins} >= 1000:
        set {_thousands} to round({%player%.coins} / 1000)
        return "%{_thousands}%k"
    return {%player%.coins}

A placeholder block is a function without anything handed to it. It runs each time another plugin asks, with player as the player the text is shown to, and what it returns is what is shown; colour codes work. A scoreboard or chat plugin may ask many times a second and not always from the server's own thread, so keep the block to reading values and working something out: no wait, and nothing that changes the world.

  • balance of and placeholder ... for take player or a name, and work for players who are offline. Without Vault and an economy plugin a balance is unset and cannot be changed; without PlaceholderAPI the text comes back unchanged. Either case is reported once in the console.
  • A balance never goes below zero: taking more than a player has leaves them with nothing.
  • Write another plugin's placeholders inside placeholder "..." only. In ordinary text HyperScript leaves an unknown %name% exactly as written.

Discord

Guide and examples

Webhooks post a message to a Discord channel. They need no bot: create a webhook in the channel's settings, then give it a name in config.yml.

discord:
  webhooks:
    alerts: "https://discord.com/api/webhooks/123/abc"
on player join:
    send webhook "alerts" with content "%player.name% joined the server" as "HyperScript"
PartMeaning
send discord message <text> to channel <id>The bot writes in that channel. The id is the long number from Discord's "Copy Channel ID". & colour codes are removed, and nobody is pinged
on discord message <id>:Runs when somebody writes in that channel; without an id, in any channel the bot can read. {_message} is the text, {_user} who wrote it, {_user_id}, {_channel} and {_channel_id}
send webhook <name or URL>A name from config.yml, or a full https:// URL
with content <text>The message, up to 2000 characters; & colour codes are removed
as <text>Optional: the name the message is posted under
  • Sending happens in the background and never slows the server. Failures are logged as warnings.
  • Messages cannot ping @everyone, roles or users, whatever text players manage to put in them.
  • A webhook URL is a password for the channel. Prefer names from config.yml over URLs in scripts.

Slash commands let Discord users run script code. They need a bot: create an application at the Discord developer portal, add a bot, invite it to your server with the applications.commands scope, and put its token in config.yml.

discord:
  bot:
    enabled: true
    token: "your-bot-token"
    guild-id: "123456789012345678"
on discord command "/online":
    reply "%server.online_players% player(s) online: %server.players%"

on discord command "/link":
    if arg.1 is not set:
        reply "Usage: /link <code>  (get a code with /link in game)"
        stop
    if {link.code.%arg.1%} is not set:
        reply "That code is not valid."
        stop
    set {_player} to {link.code.%arg.1%}
    set {link.discord.%{_player}%} to discord.user_id
    delete {link.code.%arg.1%}
    reply "Linked to Minecraft account %{_player}%."
  • reply <text> answers the person who ran the command. Reply at least once; if a trigger ends without replying, HyperScript answers "Done." so Discord is not left waiting.
  • Every slash command has one optional text option, args. It is split on spaces into %arg.1%, %arg.2% and so on, exactly like an in-game command.
  • There is no Minecraft player in a Discord trigger, so {%player%.*} variables are unavailable. Use global variables or tables keyed by name, as the /link example does.
  • With guild-id set, commands appear in that server immediately. Without it they are registered globally, which Discord can take up to an hour to show.
  • Slash commands are registered and removed as scripts load, including on hot reload.
  • The bot uses the JDA library, which the server downloads on first start (see Installation and setup).

A bot that writes and listens. With the bot switched on (discord.bot in config.yml), send discord message lets a script write in any channel the bot is in, which a webhook cannot do without one address per channel. To hear what is written there, also set discord.bot.read-messages: true, and first switch on "Message Content Intent" for the bot in Discord's developer portal: without that, Discord refuses the connection. The bot never hears itself or other bots, so a script that answers cannot answer itself for ever.

More

Topics that have no group yet.

Combat and being away

Guide and examples

HyperScript keeps track of two things about every player by itself, so that a script only has to ask.

SyntaxMeaning
<who> is in combatThey hit another player, or were hit by one, in the last 15 seconds
<who> is afkThey have done nothing for 5 minutes: not moved, looked around, clicked, chatted or run a command
put <who> in combatCount them as fighting from now, as if they had been hit. for 30 seconds to say how long
take <who> out of combatThe fight is over for them now
teleport <who> to <location> after <duration>Take them there once that time is over; it counts down on their action bar
teleport <who> to <location> after <duration> unless they moveThe same, called off if they walk away meanwhile
command /spawn:
    trigger:
        if player is in combat:
            send "&cNot while you are fighting."
            stop
        teleport player to spawn of world "world" after 5 seconds unless they move

on combat start:
    send action bar "&cIn combat with %event.opponent%" to player while player is in combat

on player quit:
    if player is in combat:
        broadcast "&c%player.name% logged out in a fight."

on afk:
    broadcast "&7%player.name% is away."
  • Both times are in config.yml: combat-time: "15s" and afk-time: "5m". 0 switches one off.
  • A fight is between players. A mob does not put anybody in combat; put victim in combat in on entity damage: does, if you want that.
  • on combat start: runs once when a fight begins, not at every hit, and on combat end: when it is over. %event.opponent% is who the fight is with.
  • on afk: and on afk return: run when a player goes away and comes back. Turning the head counts as doing something; being pushed along by water does not.
  • What a waiting teleport says is in config.yml under messages:, and can be changed or left empty. A second teleport ... after for the same player takes the place of the first.

Things kept track of for you

Guide and examples

More that HyperScript remembers about every player by itself.

SyntaxMeaning
mute <who>They cannot chat, or use the commands for talking, until unmute <who>. for 10 minutes gives it an end and because "<reason>" a reason they are told. Works for somebody who is offline, and lasts through restarts
unmute <who>They can talk again
<who> is mutedWhether they are; mute time left of <who> and mute reason of <who> say the rest
make <who> invulnerableNothing hurts them. for 5 seconds, until <condition> or while <condition> to say how long
make <who> vulnerableThey can be hurt again; also written unmake <who> invulnerable
<who> is invulnerableWhether a script made them so
kill streak of <who>How many players they have killed in a row since they last died; reset kill streak of <who> sets it back
last location of <who>Where they were before they were last taken somewhere: a teleport of more than a few blocks, or to another world. Unset if there was none
death location of <who>Where they last died
start stopwatch <name>Start counting for the player, under a name; for <who> for somebody else
stop stopwatch <name>Stop it. It goes on saying how long it ran
stopwatch <name> of <who>How long it has run, or ran until it was stopped, as a duration; unset if it was never started
stopwatch <name> of <who> is runningWhether it is counting now
reset stopwatch <name>As if it had never been started
keep inventoryIn on player death:: whoever died keeps what they carried, and nothing is dropped
keep experienceIn on player death:: they keep their levels
random safe location within <n> blocks of <location>A place around there to put a player: ground to stand on, room for the body, nothing that burns or drowns. Unset if none was found
command /rtp:
    cooldown: 1 minute
    trigger:
        set {_place} to random safe location within 2000 blocks of spawn of world "world"
        if {_place} is not set:
            send "&cNo safe place was found. Try again."
            stop
        teleport player to {_place} after 3 seconds unless they move

command /back:
    trigger:
        set {_place} to last location of player
        if {_place} is not set:
            send "&cThere is nowhere to go back to."
            stop
        teleport player to {_place}

on player respawn:
    make player invulnerable for 5 seconds

on player death:
    if player has permission "vip.keep":
        keep inventory
        keep experience

on kill streak:
    if event.streak is 5:
        broadcast "&6%player.name% is on a killing spree!"
  • Muting. A muted player who tries to talk is told so, with the reason and how long is left; the words are messages.muted in config.yml. The commands that count as talking are mute-commands there: /msg, /tell, /w, /me, /r and a few more.
  • Invulnerable is HyperScript's own and lasts while the server runs: it is not the "Invulnerable" a player's file can carry, so nobody stays unhurtable after a crash. Falling out of the world still kills. It ends when the player leaves or dies.
  • Kill streaks count players killed by players. on kill streak: runs at every kill, with %event.streak% and %event.opponent%; ask for the number you want with if.
  • Stopwatches are kept with the player's saved variables, so one that is running goes on through a restart, and through the player being away.
  • A safe place is looked for in up to thirty spots, and each one loads its chunk, which the server waits for. Put a cooldown: on a command that uses it. In the Nether it looks under the roof.
  • These are kept under names that start with hs. among the player's saved variables ({%player%.hs.kill_streak}, {%player%.hs.last_location} and so on). Read them if you like; change them with the lines above.

Quests

Guide and examples

A quest is something to do a number of times, counted for each player. HyperScript does the counting, keeps it with the player's saved variables, and runs the reward when it is done.

quest "miner":
    name: "&6Miner"
    goal: break 50 stone
    reward:
        give 5 diamond to player
        send "&aQuest done: 50 stone mined."

command /quest:
    trigger:
        if quest state "miner" is "none":
            start quest "miner"
            send "&eNew quest: mine 50 stone."
        else if quest state "miner" is "active":
            set {_mined} to quest progress "miner"
            set {_goal} to quest goal "miner"
            send "&7Stone mined: &f%{_mined}% &7of %{_goal}%"
        else:
            send "&aYou have done that quest."

on quest complete "miner":
    broadcast "&6%player.name% finished the Miner quest!"
SyntaxEffect
quest "<name>":At the left margin: makes a quest. Under it comes goal:, and name: and reward: if you want them
goal: break <n> <block>Counted when the player breaks that block. Also place <n> <block> and kill <n> <creature>. any in place of the block or creature counts whichever it is
goal: craft <n> <item>Counted when the player crafts that item
goal: fish <n>Counted for each catch
goal: walk <n> blocksCounted for each block they walk into
goal: reach <n> {<variable>}Done when a saved variable of the player's, such as {coins}, gets to that number; how far they are is what the variable is. Looked at every two seconds
repeat: dailyThe quest may be done again: daily on each new day, weekly in each new week, or a length of time after it was done (repeat: 12 hours). Until then it stays "done"; after that it is "none" again and can be started
time limit: <duration>How long the player has. When the time is up the quest is "none" again, as if it had been stopped
goal: do <n>A quest a script counts itself, with advance quest: for talking to somebody, winning a game, anything the server cannot see by itself
reward:The lines under it run as the player when they reach the goal
start quest <name>The player has the quest, from the beginning; for <who> for somebody else. Starting it again starts it over
stop quest <name>They no longer have it, and what was counted is gone
advance quest <name>Counts one towards it; by <n> counts more. Nothing happens for a player who does not have the quest
quest progress <name>How far the player is, as a number; of <who> for somebody else
quest goal <name>How many the quest asks for
quest state <name>"none", "active" or "done"; of <who> for somebody else
all questsThe names of every quest scripts have made
active questsThe names of the quests the player has and has not finished; of <who> for somebody else
on quest progress "<name>":Runs each time a player gets further with a quest. {_quest} is its name, {_progress} how far they are and {_goal} how far they have to get. Without a name it runs for every quest
on quest complete "<name>":Runs when a player reaches the goal, after the reward. player is who did it and {_quest} the quest's name. Without a name it runs for every quest
  • Only what a player does while the quest is "active" is counted. A quest that is done stays done until it is started again.
  • What is counted is the block or creature by the game's name for it, in plain words: break 20 oak log, kill 5 zombie.
  • Progress is kept across relogs and restarts.
  • A ready-made /quests menu that lists every quest with how far the player is comes as the script Quests.hs on the website.

Kits

Guide and examples

A kit is a handful of items under a name, with how often it may be taken. It is written at the left margin, like a command:

kit "starter":
    cooldown: 1 day
    items:
        1 stone sword
        16 bread
        1 diamond sword named "&bFrost"

command /kit:
    trigger:
        claim kit "starter"
Under kit "<name>":NeededMeaning
items:yesA line for each item, written as give takes them
cooldown: <duration>noHow long until the same player may claim it again
once: truenoIt can be claimed one time only
permission: "<node>"noWho may claim it
trigger:noWhat else happens when the kit is handed over, after the items
SyntaxMeaning
claim kit <name>The player gets the kit if they may, and is told why if not: the cooldown with how long is left, that they had it already, or that they lack the permission. for <who> for somebody else
give kit <name> to <who>Hands the items over without asking: no cooldown, no permission, nothing written down
<who> can claim kit <name>A condition: whether claim kit would hand it over now. Also cannot claim kit
cooldown of command <name>How long until the player may use a command again that has a cooldown:, as a duration; unset if they may now. for <who> for somebody else. The name is the command's own, with or without its slash: cooldown of command "/kit"
cooldown of kit <name>How long until the player may claim it again, as a duration; unset if they may now. for <who> for somebody else
reset kit <name>The player may claim it again now; for <who> for somebody else
kitsThe names of all kits, as a list
  • What claim kit says when it does not hand the kit over is in config.yml under messages: (kit-cooldown, kit-once, kit-permission); leave one empty to say nothing.
  • When a player last claimed a kit is kept with their saved variables, as {%player%.hs.kit.<name>}, so it lasts through restarts.
  • A kit's name is its own: two scripts cannot both make a kit "starter".

Dialogue

Guide and examples

A dialogue "<name>": block, at the left margin like a function, holds a conversation: what is said, and choice "<answer>": blocks for the player to answer by. The answers are shown in chat to click, or to type.

dialogue "blacksmith":
    send "&6Blacksmith: &fWhat do you need?"
    choice "A sword":
        give 1 iron sword to player
        send "&6Blacksmith: &fHere you go."
    choice "Nothing":
        send "&6Blacksmith: &7Come back any time."

command /blacksmith:
    trigger:
        start dialogue "blacksmith"
SyntaxMeaning
dialogue <name>:A conversation under a name. Anything a trigger can do can stand in it
choice <text>:One of the answers. The choice blocks that follow one another are offered together, and the block of the one that is picked runs. What comes after them runs next
start dialogue <name>Begin it with the player of the trigger
  • choice works anywhere a script runs for a player, not only inside a dialogue: it is the quick way to ask "which one?".
  • A choice can hold further choices, which is how a conversation branches.
  • The player has a minute to answer; with no answer nothing is picked and the lines after the choices run. The line above the answers is messages.choose in config.yml.

The server's own counts and lists

Guide and examples
SyntaxMeaning
statistic <name> of <who>One of the game's own statistics for a player, online or not: "deaths", "jump", "play_one_minute", "mob_kills", "player_kills", "walk_one_cm" and the rest, as the game names them
statistic <name> of <who> for <thing>For the statistics that are kept for each block, item or creature: statistic "mine_block" of player for "stone", statistic "kill_entity" of player for "zombie". Without for, all of them added up
all commandsEvery command the server has, each with its slash, as a list
commands of <who>The ones that player may use
all permissions of <who>Every permission a player has, as a list; permissions of <who> says the same
give selection wand to <who>A golden axe that marks: left-click a block for the first corner, right-click for the second
selection start of <who>The first corner they marked, as a location; unset if they did not
selection end of <who>The second corner
selection size of <who>How many blocks lie between the two, both included; unset until both are marked
clear selection of <who>Forget both corners
save structure <name> from <position> to <position>Keep everything between two corners in a file, as the game's structure blocks do
place structure <name> at <position>Put it back somewhere, its lowest corner at that place. rotated 90, 180 or 270 turns it
structure <name> existsA condition
delete structure <name>Remove the file
block word <text>Chat with that word in it is starred, or kept back; a list blocks several
unblock word <text>It may be said again
blocked wordsThe words that are blocked, as a list
command /makearena <name>:
    permission: op
    trigger:
        if selection size of player is not set:
            send "&cMark two corners with the wand first."
            stop
        create region arg.1 from selection start of player to selection end of player
        save structure arg.1 from selection start of player to selection end of player
        send "&aMade %arg.1%."

on blocked word:
    add 1 to {%player%.warnings}
    if {%player%.warnings} >= 3:
        mute player for 10 minutes because "language"
  • Structures need Minecraft 1.17.1 or newer. A structure may have up to 250,000 blocks (limits.structure-blocks); saving a large one makes the server wait. The files are the game's own and lie in the main world's folder, under generated/hyperscript/structures.
  • Blocked words are found however they are dressed up: b4dw0rd, b.a.d.w.o.r.d, baaadword. A word has to stand by itself, so blocking ass leaves class alone. word-filter in config.yml says whether the message is sent with stars (censor, the default) or not sent (block). Players with the permission hyperscript.words.bypass are left alone, and the list is kept through restarts.
  • The wand remembers its corners until the player leaves. It is recognised by a mark on the item, so one that is renamed still works and an ordinary golden axe does not.

HyperBedrock

An addon: a separate plugin whose words work once it is installed.

Who is on Bedrock HyperBedrock

Guide and examples
on player join:
    if platform of player is "bedrock":
        send "&7Welcome from %device of player%! Menus open as forms for you."

command /platform <player>:
    trigger:
        if platform of arg.1 is not set:
            send "&c%arg.1% is not online."
            stop
        send "&7%arg.1% plays on &f%platform of arg.1%&7."
        if platform of arg.1 is "bedrock":
            send "&7Device: &f%device of arg.1% &7Input: &f%input of arg.1%"
            send "&7Gamertag: &f%bedrock name of arg.1% &7Version: &f%bedrock version of arg.1%"
            send "&7Xbox id: &f%xuid of arg.1% &7Language: &f%bedrock language of arg.1%"

command /bedrock:
    trigger:
        send "&7On Bedrock now: &f" + join bedrock players with ", "
SyntaxResult
platform of <who>bedrock or java; unset for someone who is not online
device of <who>What they play on, as Bedrock names it: Android, iOS, Windows, Xbox One, PlayStation, Switch and so on. Unset on Java
input of <who>How they play: touch, controller or keyboard mouse. Unset on Java
bedrock name of <who>Their gamertag, without the prefix Floodgate puts in front of the name on your server
xuid of <who>Their Xbox id, which never changes
bedrock version of <who>The version of their game
bedrock language of <who>The language of their game, such as en_US
bedrock playersA list of the names of everybody online who is on Bedrock
  • Everything but platform of and bedrock players is unset for a Java player, so is set works as a test as well.
  • A Bedrock player's name on the server usually starts with a dot. Use player, arg.1 and the like as with anyone else; nothing here needs the dot written out.

Forms HyperBedrock

Guide and examples
command /kits:
    players only: true
    trigger:
        show form "kits" to player titled "&lKits" with text "Pick a kit" with buttons "Warrior", "Archer", "Miner"

on form "kits":
    if {_button} is "Warrior":
        give 1 iron sword to player
    else if {_button} is "Archer":
        give 1 bow to player
    else:
        give 1 iron pickaxe to player
    send "&aYou took the %{_button}% kit."

on form closed "kits":
    send "&7Maybe later."

command /resetme:
    players only: true
    trigger:
        show question form "reset" to player titled "Reset" with text "Really delete your home?" with buttons "Yes, delete it", "No"

on form "reset":
    if {_index} is 1:
        delete {%player%.home}
        send "&aYour home was deleted."

command /report:
    players only: true
    trigger:
        show input form "report" to player titled "Report a player" with label "Staff read every report.", input "Who?" hint "Their name", dropdown "Why?" of ["Cheating", "Chat", "Other"], toggle "Urgent", slider "How bad?" from 1 to 5

on form "report":
    set {_who} to item 1 of {_answers}
    set {_why} to item 2 of {_answers}
    log "%player.name% reported %{_who}% for %{_why}% (urgent: %item 3 of {_answers}%, %item 4 of {_answers}% of 5)"
    send "&aThank you. Staff have been told."
SyntaxEffect
show form <id> to <who> titled <text> with buttons <text>, <text>A list of buttons under a title. Add with text <text> before with buttons for a line above them
show question form <id> to <who> titled <text> with text <text> with buttons <text>, <text>A question with exactly two buttons
show input form <id> to <who> titled <text> with <part>, <part>A form to fill in; the parts are listed below
on form "<id>":Runs when a player answers the form of that id. player is who answered
on form closed "<id>":Runs when they close it without answering

What an input form is made of:

PartIt is
input <label>A box to type in. Add hint <text> for the grey text shown while it is empty
toggle <label>A switch, off to begin with; toggle <label> on starts it on
dropdown <label> of <list>One of several choices: dropdown "Kit" of ["Warrior", "Archer"] or a list in a variable
slider <label> from <n> to <n>A number between two ends, in whole steps; step <n> after it for other steps
label <text>A line of text, nothing to fill in
  • The <id> ties a form to its blocks: show form "kits" is answered in on form "kits":. It is never shown to the player.
  • In on form, for a button or question form {_button} is what the pressed button says and {_index} its number, counting from 1. For an input form {_answers} is a list of what was filled in, in the order of the parts: text for an input and a dropdown, true or false for a toggle, a number for a slider. Labels are not counted.
  • A form shown to a Java player does nothing: they have no forms. Ask platform of player first, as in the example at the top.
  • The buttons may also be given as one list: with buttons {kit.names}.
  • Colour codes work in titles, text and buttons.

Buttons with a picture, and another server HyperBedrock

Guide and examples
command /hub:
    trigger:
        if platform of player is not "bedrock":
            send "&7This menu is for Bedrock players."
            stop
        show form "hub" to player titled "&lWhere to?" with buttons "Survival" with image "https://example.com/icons/survival.png", "Skyblock" with image "textures/items/diamond", "Stay here"

on form "hub":
    if {_button} is "Survival":
        transfer player to bedrock server "survival.example.com"
    else if {_button} is "Skyblock":
        transfer player to bedrock server "skyblock.example.com" port 19133
SyntaxEffect
"<text>" with image "<address>"In with buttons: a picture beside what the button says. An address that begins with http is fetched by the player's game; anything else is a path in a resource pack, such as textures/items/diamond. A button without it has no picture. Not for the two buttons of a question form
transfer <who> to bedrock server <address>Send a Bedrock player to another Bedrock server. The port is 19132 unless port <n> follows, or the address ends in :<n>. A Java player stays where they are
  • In on form "<id>": {_button} is what the button says, without the picture.
  • A transfer hands the player's game an address to connect to: the other server has to be one a Bedrock client can reach from where the player is.

HyperCitizens

An addon: a separate plugin whose words work once it is installed.

Clicking an NPC HyperCitizens

Guide and examples
on npc click "Shopkeeper":
    execute player command "shop"

on npc click "Healer":
    cooldown: 30 seconds
    heal player
    make npc "Healer" say "There you go."

on npc left click "Guard":
    make npc "Guard" say "Hands off."

on npc click:
    log "%player.name% clicked %{_name}% (number %{_npc}%)"
SyntaxEffect
on npc click "<name>":Runs when a player right-clicks the NPC of that name
on npc left click "<name>":Runs when a player hits it
on npc click:Without a name: runs for every NPC
  • Inside the block, player is whoever clicked, as in HyperScript's own events. {_npc} is the NPC's number and {_name} its name.
  • The name is compared without colours and without regard to capitals, so "Guide" finds an NPC called &aGuide. If two NPCs share a name, the block runs for both.
  • A cooldown line works as on any event, per player.

Making and removing HyperCitizens

Guide and examples
command /setguide:
    permission: "npcs.manage"
    players only: true
    trigger:
        create npc "&aGuide" at player's location
        set skin of npc last created npc to "Notch"
        set {guide} to last created npc
        send "&aThe guide stands here now (number %{guide}%)."

command /setcow:
    permission: "npcs.manage"
    players only: true
    trigger:
        create npc "Bessie" as "cow" at player's location

command /nameguide <name>:
    permission: "npcs.manage"
    trigger:
        rename npc {guide} to arg.1
        send "&aThe guide is now called %arg.1%."

command /removeguide:
    permission: "npcs.manage"
    trigger:
        delete npc "Guide"
SyntaxEffect
create npc <name> at <location>Make an NPC that looks like a player
create npc <name> as <kind> at <location>Make one that is a creature: "villager", "cow", "zombie" and so on
delete npc <npc>Remove an NPC for good
rename npc <npc> to <name>Give it another name; colour codes work
set skin of npc <npc> to <player name>For an NPC that looks like a player: whose skin it wears
last created npcThe number of the NPC create npc made most recently
  • <npc> is an NPC's number or its name: delete npc 3, delete npc "Guide". A name is compared without colours. The number never changes and is the safe one to keep in a variable.
  • An NPC nobody knows is reported in the console and nothing happens.
  • Run create npc once, from a command; an on load: block would make another one at every reload.

Moving and talking HyperCitizens

Guide and examples
command /tour:
    players only: true
    trigger:
        make npc "Guide" say "Follow me to the market."
        make npc "Guide" walk to {market}
        wait 10 seconds
        make npc "Guide" look at player's location
        make npc "Guide" say "Here we are."

every 5 minutes:
    teleport npc "Guide" to {spawn}
SyntaxEffect
teleport npc <npc> to <location>Put it somewhere at once
make npc <npc> walk to <location>Have it find its way there on foot
make npc <npc> look at <location>Turn it to face a place
make npc <npc> say <text>Players within 16 blocks see Name: text in chat
  • Walking only works over ground the NPC can cross, and not too far; for long trips teleport it.

How an NPC looks and behaves HyperCitizens

Guide and examples
command /setguard:
    permission: "npcs.manage"
    players only: true
    trigger:
        create npc "&cGuard" at player's location
        set {guard} to last created npc
        set tool of npc {guard} to diamond sword
        set helmet of npc {guard} to iron helmet
        set chestplate of npc {guard} to iron chestplate
        add hologram line "&7Right-click to talk" to npc {guard}
        make npc {guard} watch players

command /guardpatrol:
    permission: "npcs.manage"
    trigger:
        make npc {guard} patrol {gate.north}, {gate.south}

command /pet:
    players only: true
    trigger:
        create npc "Rex" as "wolf" at player's location
        make npc last created npc follow player

command /petstay:
    trigger:
        make npc "Rex" stop following

command /guardrest:
    permission: "npcs.manage"
    trigger:
        make npc {guard} stop patrolling
        make npc {guard} stop watching
        set tool of npc {guard} to nothing
        clear hologram of npc {guard}
SyntaxEffect
set tool of npc <npc> to <item>What it holds. Also offhand, helmet, chestplate, leggings and boots; to nothing empties the slot
add hologram line <text> to npc <npc>A line of floating text above it
clear hologram of npc <npc>Take that text away
make npc <npc> watch playersIt turns to look at whoever comes near
make npc <npc> stop watchingIt looks ahead again
make npc <npc> follow <who>It walks after a player
make npc <npc> stop followingIt stays where it is
make npc <npc> patrol <location>, <location>It walks from place to place and round again; give two or more
make npc <npc> stop patrollingIt stops where it is
hide npc <npc> from <who>That player no longer sees the NPC; everybody else still does. from all players hides it from everyone who is on now
show npc <npc> to <who>They see it again
make npc <npc> swing armOne swing of its arm, as when it hits something
  • Equipment, floating text, watching and following are kept by Citizens and are still there after a restart. A patrol is kept by HyperCitizens only while the server runs: start it again from an on server start: block.
  • An item given as equipment keeps its name; an enchanted or glowing one shimmers.

Finding NPCs HyperCitizens

Guide and examples
command /npcs:
    trigger:
        for each {_id} in all npcs:
            send "&7%{_id}%: &f" + name of npc {_id}

command /guide:
    players only: true
    trigger:
        set {_id} to npc named "Guide"
        if {_id} is not set:
            send "&cThere is no guide yet."
            stop
        teleport player to location of npc {_id}
SyntaxResult
all npcsA list of the numbers of every NPC
npc named <name>The number of the NPC of that name; unset if there is none
name of npc <npc>Its name, without colours
location of npc <npc>Where it is, as a location

The nearest NPC, and its name HyperCitizens

Guide and examples
command /whoisthat:
    trigger:
        set {_npc} to nearest npc to player's location
        if {_npc} is not set:
            send "&7There is no NPC in this world."
            stop
        send "&7The nearest NPC is &f%name of npc {_npc}%&7."
        make npc {_npc} look at player's location

command /rest <npc>:
    permission: "npc.admin"
    trigger:
        if npc spawned arg.1:
            despawn npc arg.1
            send "&7The NPC is resting."
        else:
            spawn npc arg.1 at player's location
            send "&aThe NPC is back, here."

command /wave:
    trigger:
        for each {_npc} in npcs within 8 blocks of player's location:
            make npc {_npc} swing arm

command /nameless <npc>:
    permission: "npc.admin"
    trigger:
        hide name of npc arg.1

command /named <npc>:
    permission: "npc.admin"
    trigger:
        show name of npc arg.1
SyntaxEffect
nearest npc to <location>The NPC closest to that place, in the same world, among those that are in the world right now; unset if there is none
npcs within <n> blocks of <location>The NPCs that near a place, the nearest first
despawn npc <npc>Take it out of the world without deleting it: it keeps its name, its skin and everything it was told
spawn npc <npc> at <location>Put it back in the world. Without at, where it was; one that is in the world already is moved to the place
npc spawned <npc>True while it is in the world
hide name of npc <npc>The name over its head is no longer shown, for an NPC that has a hologram instead, or is to pass for a player
show name of npc <npc>The name is shown again

More examples HyperCitizens

Guide and examples
command /ghost <target:player>:
    permission: "staff.ghost"
    trigger:
        hide npc "ghost" from arg.1
        send "&7%arg.1% no longer sees the ghost."

command /unghost <target:player>:
    permission: "staff.ghost"
    trigger:
        show npc "ghost" to arg.1

command /salute:
    trigger:
        make npc "guard" swing arm

HyperEconomy

An addon: a separate plugin whose words work once it is installed.

One money for scripts and plugins HyperEconomy

Guide and examples

Describe the currency in any script, as you would without this addon:

currency "coins":
    start: 100
    max: 1000000

command /coins:
    trigger:
        set {_has} to currency "coins" of player
        send "&7You have &6%economy format of {_has}%&7."

command /pay <player> <number>:
    trigger:
        set {_amount} to parse arg.2 as number
        if {_amount} is not set or {_amount} <= 0:
            send "&cHow much?"
            stop
        if currency "coins" of player < {_amount}:
            send "&cYou do not have that much."
            stop
        pay {_amount} of currency "coins" from player to arg.1
        send "&aPaid %economy format of {_amount}% to %arg.1%."

Everything HyperScript does with a currency works as before: currency "coins" of player, set, add, subtract, pay, top. What HyperEconomy adds is that a plugin which pays a player through Vault changes the same number.

  • A new player starts with what the block's start: says, for other plugins too.
  • A payment that would take a player past max: is refused, and nothing is paid in.
  • A plugin cannot take out more than a player has.
  • There are no banks. A plugin that asks for one is told so.

When another plugin moves money HyperEconomy

Guide and examples
on economy deposit:
    send "&a+%economy format of {_amount}%" to player
    if {_balance} >= 1000000:
        broadcast "&6%{_name}% &7is a millionaire."

on economy withdraw:
    log "%{_name}% paid %{_amount}% %{_currency}% and has %{_balance}% left"
SyntaxEffect
on economy deposit:Runs when another plugin pays a player through Vault. player is that player, if they are online
on economy pay:Runs when another plugin moves money from one player to another: taken from the one and, in the same moment, the same sum given to the other. player is who paid; {_payer}, {_receiver} and {_amount} say the rest
on economy withdraw:Runs when another plugin takes money from a player through Vault
  • Inside the blocks: {_amount} is what was moved, {_balance} what the player has now, {_currency} the currency's name and {_name} the player's name, which is there for a player who is offline too.
  • They run for what other plugins do. A script that changes currency "coins" of player itself does not set them off.

Amounts and the currency HyperEconomy

Guide and examples
command /worth <number>:
    trigger:
        send "&7That is &6%economy format of arg.1%&7 in &f%economy currency%&7."

command /usegems:
    permission: economy.admin
    trigger:
        set economy currency to "gems"
        send "&aThe server now pays in %economy currency%."
SyntaxEffect
economy format of <number>The amount as other plugins show it: 1,250 coins, 1 coin, 2.50 coins
economy currencyThe name of the currency that is the server's money
set economy currency to "<name>"Makes another currency the server's money, at once and after a restart. Balances are not moved: each currency keeps its own

The richest, the total, and what was last moved HyperEconomy

Guide and examples
command /rich:
    trigger:
        send "&6Richest players"
        set {_place} to 0
        for each {_name} in top balances:
            add 1 to {_place}
            if {_place} <= 10:
                send "&e#%{_place}% &f%{_name}% &7- %economy format of balance of {_name}%"
        send "&7In all there are %economy format of economy total%."
        set {_mine} to economy rank of player
        if {_mine} is set:
            send "&7You are #%{_mine}%."

command /moves:
    trigger:
        set {_moves} to transactions of player
        if size of {_moves} is 0:
            send "&7No plugin has moved your money since the server started."
            stop
        send "&6Your last payments"
        for each {_move} in {_moves}:
            send "&7%{_move}%"
SyntaxEffect
top balancesThe names of the players with the most of the server's money, richest first, up to 100. Everybody who has played here counts, online or not
economy rank of <who>Where a player stands among everybody by how much they have: 1 for the richest. Unset for somebody who has nothing
economy totalAll the money there is: what everybody has, added up
transactions of <who>What other plugins last paid that player or took from them, newest first, as text such as +50 coins and -20 coins; twenty at most. economy transactions of <who> says the same
  • top balances and economy total ask about every player who has ever joined, so the answer is kept for ten seconds and can be that far behind.
  • transactions of knows what went through Vault since the server started: a shop, /pay, a job. What a script itself adds to the variable is not a payment by another plugin and is not in the list, and the list is empty again after a restart.

HyperEdit

An addon: a separate plugin whose words work once it is installed.

Schematics HyperEdit

Guide and examples
command /savearena:
    permission: "arena.admin"
    trigger:
        save schematic "arena" from {arena.corner} to {arena.far}
        set {_size} to size of schematic "arena"
        send "&aSaved: %{_size}% blocks along x, y and z."

command /house:
    permission: "build.house"
    players only: true
    trigger:
        if not schematic exists "house":
            send "&cThere is no schematic called house."
            stop
        paste schematic "house" at player's location rotated 90 skipping air
        send "&aBuilt. %blocks changed by last edit% blocks were placed."

command /schematics:
    permission: "arena.admin"
    trigger:
        send "&7Schematics: &f" + join all schematics with ", "

command /delschematic <name>:
    permission: "arena.admin"
    trigger:
        delete schematic arg.1
SyntaxEffect
save schematic <name> from <location> to <location>Write every block in the box between two corners to a schematic. One of that name is replaced
paste schematic <name> at <location>Put it into the world, so that what was at the first corner comes to that place
paste schematic <name> at <location> rotated <degrees>The same, turned: 90, 180 or 270, clockwise seen from above
paste schematic <name> at <location> skipping airLeave what is there wherever the schematic has air
delete schematic <name>Remove the file
all schematicsA list of the names of every schematic
schematic exists <name>Whether there is one of that name
size of schematic <name>A list of three numbers: how many blocks it is along x, y and z
  • A name is letters, digits, - and _. Anything else is refused, so a script cannot write outside the schematics folder.
  • rotated and skipping air can be combined, in that order.
  • Entities (animals, item frames, armour stands) are not saved.

Changing many blocks HyperEdit

Guide and examples
command /floor:
    permission: "build.floor"
    trigger:
        edit fill from {hall.a} to {hall.b} with smooth stone
        send "&a%blocks changed by last edit% blocks set."

command /melt:
    permission: "build.melt"
    trigger:
        edit replace ice from {lake.a} to {lake.b} with "water"

command /cage:
    permission: "build.cage"
    players only: true
    trigger:
        edit walls from player's location offset by -3, 0, -3 to player's location offset by 3, 4, 3 with glass
        edit sphere at player's location radius 6 with glass hollow

command /tower:
    permission: "build.tower"
    players only: true
    trigger:
        edit cylinder at player's location radius 4 height 20 with stone bricks hollow
        edit outline from {vault.a} to {vault.b} with obsidian

command /oops:
    permission: "build.floor"
    trigger:
        undo last edit
        send "&7Taken back."

command /again:
    permission: "build.floor"
    trigger:
        redo last edit
        send "&7Done again."
SyntaxEffect
edit fill from <location> to <location> with <block>Set every block in the box
edit replace <block> from <location> to <location> with <block>Change only the blocks of one kind in the box, to the block named last
edit walls from <location> to <location> with <block>The four sides of the box, without floor or roof
edit outline from <location> to <location> with <block>All six faces of the box
edit sphere at <location> radius <n> with <block>A ball around that place; hollow at the end for a shell
edit biome from <location> to <location> to <biome>Make the box between two corners that biome, by the game's name for it: "desert", "snowy_taiga". Players see it when the chunks are sent to them again
edit cylinder at <location> radius <n> height <n> with <block>A pillar standing on that place; hollow at the end for a tube
undo last editTake the last edit or paste back. Again for the one before, up to fifteen
redo last editDo again what was just taken back
edit count of <block> from <location> to <location>How many blocks of that kind are in the box between two corners
blocks changed by last editHow many blocks the last edit or paste changed
  • A block is written as in the rest of HyperScript: stone, oak planks. Blocks that are not also items go in quotes: "air", "water", "lava", "fire".
  • HyperScript's own fill from ... with stops at 32,768 blocks; edit fill goes up to max-blocks.
  • A large edit holds the server up while it is made, as the same edit does in WorldEdit. With FastAsyncWorldEdit it does not.
  • undo last edit knows the edits scripts have made since the server started, not those players made with WorldEdit's own commands.

Pyramids and repeating a box HyperEdit

Guide and examples
command /pyramid <height:number>:
    permission: "edit.use"
    trigger:
        edit pyramid at player's location height arg.1 with sandstone
        send "&a%blocks changed by last edit% blocks placed."

command /tomb:
    permission: "edit.use"
    trigger:
        edit pyramid at player's location height 12 with sandstone hollow

command /opengate:
    permission: "edit.use"
    trigger:
        edit move from {gate.a} to {gate.b} 4 blocks up
        wait 5 seconds
        undo last edit

command /bridge:
    permission: "edit.use"
    trigger:
        edit line from {%player%.a} to {%player%.b} with oak planks

command /snow:
    permission: "edit.use"
    trigger:
        edit overlay from {%player%.a} to {%player%.b} with snow

command /dry <radius:number>:
    permission: "edit.use"
    trigger:
        edit drain at player's location radius arg.1

command /fence <copies:number>:
    permission: "edit.use"
    trigger:
        if {%player%.a} is not set or {%player%.b} is not set:
            send "&cMark the two corners first."
            stop
        edit stack from {%player%.a} to {%player%.b} arg.1 times east
        send "&aRepeated %arg.1% times to the east. /undo takes it back."
SyntaxEffect
edit pyramid at <location> height <n> with <block>A pyramid that many blocks high, standing on that place. hollow at the end leaves it empty inside
edit stack from <location> to <location> <n> times <direction>Repeat the box that many times, each copy straight after the last: north, south, east, west, up or down. Air is copied too. For a wall, a row of pillars, the floors of a tower
edit move from <location> to <location> <n> blocks <direction>Move the box that far, leaving air where it was: a door that opens, a lift, a wall that slides
edit line from <location> to <location> with <block>A line of blocks from one place to the other, in whichever direction
edit overlay from <location> to <location> with <block>Put one layer of that block on top of whatever is highest in each column of the box: snow on a roof, carpet on a floor
edit drain at <location> radius <n>Take away the water and lava within that many blocks that is connected to the place
  • All of these count against max-blocks, and all are taken back by undo last edit.

More examples HyperEdit

Guide and examples
command /mineleft:
    trigger:
        set {_a} to player's location offset by -5, -5, -5
        set {_b} to player's location offset by 5, 5, 5
        set {_left} to edit count of stone from {_a} to {_b}
        send "&7Stone around you: &f%{_left}%"

command /desert:
    permission: "staff.biome"
    trigger:
        set {_a} to player's location offset by -8, -8, -8
        set {_b} to player's location offset by 8, 8, 8
        edit biome from {_a} to {_b} to "desert"

HyperGrim

An addon: a separate plugin whose words work once it is installed.

When Grim flags somebody HyperGrim

Guide and examples
on alert:
    add 1 to {%player%.warns}
    if {%player%.warns} > 10:
        ban player for 7 days because "&cCheating (automatic ban)"

on alert "Reach":
    log "%player.name% failed Reach (%{_violations}% so far): %{_verbose}%"

on grim flag:
    loop all players:
        if loop-player has permission "staff.alerts":
            send "&c%player.name% &7was flagged for &f%{_check}%" to loop-player

on grim punish:
    log "Grim ran for %player.name%: %{_command}%"
SyntaxEffect
on alert:Runs every time Grim flags a player: each time one of its checks fails. player is who was flagged
on alert level <n>:Runs once when the violations of a check reach that number, whichever check it is: on alert level 10:. It needs a number
on alert level <n> "<check>":The same for one check: on alert level 10 "Reach":
on alert "<check>":The same for one check only, by the name Grim gives it: "Reach", "Simulation", "BadPacketsA"
on grim flag:Another way of writing on alert:; both run
on grim punish:Runs when Grim carries out one of the commands its punishments are made of
  • Inside the blocks {_check} is the name of the check, {_violations} how many violations of it the player has by now, {_verbose} what Grim noted about this one (often empty), and {_description} what the check is for. In on grim punish: there is {_command} as well.
  • on alert level 10: saves the counting: it runs the one time a player's violations of a check get to 10, and again only if they fall and climb back. The values inside are the same as in on alert:.
on alert level 10 "Reach":
    loop all players:
        if loop-player has permission "staff.alerts":
            send "&c%player.name% has 10 Reach violations" to loop-player

on alert level 25:
    kick player because "&cToo many violations of %{_check}%"
  • Grim flags often. One player who is cheating can set on alert: off many times a second, and an honest one on a bad connection sets it off now and then. Count before you act, as the example does, and let the count fade:
on alert:
    add 1 to {%player%.warns}

every 5 minutes for all players:
    if {%player%.warns} > 0:
        subtract 1 from {%player%.warns}
  • The blocks run a moment after the flag, on the server's own thread, so a script cannot stop the flag itself or what Grim does about it; Grim's own punishments.yml is where that is set. If the player has left by then, the block does not run.

What Grim knows about a player HyperGrim

Guide and examples
command /check <target:player>:
    permission: "staff.check"
    trigger:
        send "&7%arg.1%: &f%grim violations of arg.1% &7violations"
        send "&7Failed: &f%grim checks of arg.1%"
        set {_reach} to grim violations of arg.1 for "Reach"
        send "&7Of those for Reach: &f%{_reach}%"
        send "&7Client: &f%client brand of arg.1% %client version of arg.1%"
        send "&7Ping: &f%grim ping of arg.1% ms"
        send "&8Grim %grim version%"
SyntaxMeaning
grim violations of <who>How many violations the player has, all checks together
grim violations of <who> for <check>For one check: grim violations of player for "Reach"
grim checks of <who>The names of the checks the player has violations of, as a list
grim ping of <who>Their ping as Grim measures it, in milliseconds
client brand of <who>What their game says it is: vanilla, fabric, lunarclient
client version of <who>Which version of Minecraft they play with
grim versionWhich version of Grim the server runs
  • In a sum, put the whole in brackets: (grim violations of player) + 1.
  • These are about players who are online. For somebody who is not, the numbers are unset and the list is empty.
  • Violations are Grim's own count and fade as Grim lets them. They are not kept through a restart; keep your own count in a variable if it has to last.

Telling Grim to look away, forget or be quiet HyperGrim

Guide and examples
on step on slime block:
    exempt player from grim for 3 seconds
    push player upward with force 2

command /pardon <target:player>:
    permission: "staff.pardon"
    trigger:
        reset grim violations of arg.1
        send "&aGrim has forgotten what it held against %arg.1%."

command /forgetreach <target:player>:
    permission: "staff.pardon"
    trigger:
        reset grim violations of arg.1 for "Reach"

command /quietgrim:
    permission: "staff.alerts"
    trigger:
        turn grim alerts of player off
        send "&7You no longer see Grim's alerts. /loudgrim brings them back."

command /loudgrim:
    permission: "staff.alerts"
    trigger:
        turn grim alerts of player on
SyntaxEffect
exempt <who> from grim for <duration>Grim leaves that player alone for the time: no flags and no pulling back. For what a script does to a player itself, such as a jump pad or a launch. Without for it is 5 seconds; 10 minutes is the most
reset grim violations of <who>Their violations of every check are none again. for <check> after it resets one check only
turn grim alerts of <who> onWhether that player sees Grim's alerts in chat; off for the other
  • exempt gives the player, for that long, the permissions Grim itself has for being left alone (grim.exempt, grim.nosetback), and takes them away again by itself. It needs a Grim that knows those permissions.
  • Not every version of Grim lets its violations be reset or its alerts be switched from outside. Where it does not, the line does nothing and the console says so once.

HyperGuard

An addon: a separate plugin whose words work once it is installed.

Where players are HyperGuard

Guide and examples
command /where:
    players only: true
    trigger:
        set {_regions} to guard regions of player
        if size of {_regions} == 0:
            send "&7You are in the wild."
        else:
            send "&7You are in: &f" + join {_regions} with ", "

command /arena:
    trigger:
        send "&7In the arena: &f" + join players in guard region "arena" with ", "

command /regions [world]:
    permission: "regions.list"
    trigger:
        if arg.1 is set:
            send "&7Regions in %arg.1%: &f" + join all guard regions in world arg.1 with ", "
        else:
            send "&7Regions here: &f" + join all guard regions with ", "

on block break:
    if guard regions at event's location contains "museum":
        cancel event
        send "&cLook, do not touch."
SyntaxResult
guard regions of <who>A list of the regions the player is standing in, the highest priority first
guard regions at <location>The same for any place
players in guard region <name>A list of the names of the online players inside
all guard regionsThe names of every region in the player's world
all guard regions in world <name>The same for a world you name
  • These are lists like any other: contains, size of, for each, item 1 of all work.
  • A place in no region gives an empty list. The world-wide __global__ region is left out.
  • Region names are not case sensitive, as in WorldGuard.

Entering and leaving HyperGuard

Guide and examples
on guard region enter "arena":
    set gamemode of player to adventure
    broadcast "&c%player.name% &7entered the arena."

on guard region leave "arena":
    set gamemode of player to survival

on guard region enter:
    log "%player.name% entered %{_region}%"
SyntaxEffect
on guard region enter "<name>":Runs when a player comes into that region, by walking, teleporting or joining inside it
on guard region leave "<name>":Runs when a player leaves it
on guard region enter:Without a name: runs for every region
  • Inside the block, player is the player, as in HyperScript's own events, and {_region} is the region's name.
  • These events report what happened; they cannot stop it. To keep players out of a region, use WorldGuard's own entry flag, which a script can set (below).
  • A player who logs out inside a region does not "leave" it.

Owners and members HyperGuard

Guide and examples
command /trust <target:player>:
    players only: true
    trigger:
        set {_plot} to item 1 of guard regions of player
        if {_plot} is not set or owners of guard region {_plot} does not contain player.name:
            send "&cStand on a plot you own."
            stop
        add arg.1 to guard region {_plot}
        send "&a%arg.1% can now build on %{_plot}%."

command /plotinfo:
    players only: true
    trigger:
        set {_plot} to item 1 of guard regions of player
        if {_plot} is not set:
            send "&7There is no plot here."
            stop
        send "&7Owners: &f" + join owners of guard region {_plot} with ", "
        send "&7Members: &f" + join members of guard region {_plot} with ", "

command /giveplot <target:player> <plot>:
    permission: "plots.manage"
    trigger:
        add arg.1 to guard region arg.2 as owner
        send "&a%arg.1% now owns %arg.2%."

command /untrust <target>:
    players only: true
    trigger:
        set {_plot} to item 1 of guard regions of player
        if {_plot} is set and owners of guard region {_plot} contains player.name:
            remove arg.1 from guard region {_plot}
            send "&e%arg.1% can no longer build on %{_plot}%."
SyntaxEffect
owners of guard region <name>A list of the owners' names
members of guard region <name>A list of the members' names
add <who> to guard region <name>Make a player a member
add <who> to guard region <name> as ownerMake a player an owner
remove <who> from guard region <name>Take a player out, as member and as owner
  • <who> is player, all players, or a name. A named player may be offline.
  • A region is looked for in the world of the player who caused the trigger first, then in every other world. A name WorldGuard does not know is reported in the console and nothing changes.
  • WorldGuard saves the change itself, a little later, as it does for /rg addmember.

Flags HyperGuard

Guide and examples
command /arena <open|close>:
    permission: "arena.manage"
    trigger:
        if arg.1 is "open":
            set guard flag "pvp" of region "arena" to true
            set guard flag "greeting" of region "arena" to "&cFight!"
            clear guard flag "entry" of region "arena"
        else:
            set guard flag "pvp" of region "arena" to false
            set guard flag "entry" of region "arena" to "deny"
        send "&7Arena: %arg.1%"

on entity damage:
    if guard flag "pvp" at event's location is "deny":
        send action bar "&7No fighting here" to player
SyntaxEffect
guard flag <flag> at <location>What the flag comes to at that place: allow or deny, or the flag's own value; unset if no region sets it
set guard flag <flag> of region <name> to <value>Set a flag on a region, as /rg flag does
clear guard flag <flag> of region <name>Take the flag off the region again
  • The flag is written in quotes: "pvp", "entry", "greeting", "mob-spawning".
  • true and false mean allow and deny. Any other value is given as text, written the way it would be typed after /rg flag <region> <flag>.
  • A flag WorldGuard does not have, or a value the flag does not take, is reported in the console and nothing changes.

Making regions HyperGuard

Guide and examples
command /claim:
    players only: true
    trigger:
        set {_name} to "plot_%player.name%"
        set {_low} to player's location offset by -8, 0, -8
        set {_high} to player's location offset by 8, 0, 8
        if size of guard regions between {_low} and {_high} full height > 0:
            send "&cThat would overlap someone else's land."
            stop
        create guard region {_name} from {_low} to {_high} full height
        add player to guard region {_name} as owner
        send "&aThis land is yours now."

command /unclaim:
    players only: true
    trigger:
        delete guard region "plot_%player.name%"
        send "&eYour land is free again."

on block break:
    unless guard allows building at event's location:
        send action bar "&cThis land belongs to someone else" to player

command /canbuild <target:player>:
    permission: "plots.manage"
    players only: true
    trigger:
        if guard allows building at player's location for arg.1:
            send "&a%arg.1% may build where you stand."
        else:
            send "&c%arg.1% may not build where you stand."

command /plotsetup <plot>:
    permission: "plots.manage"
    trigger:
        set priority of guard region arg.1 to 10
        set parent of guard region arg.1 to "city"
        send "&7Priority: &f" + priority of guard region arg.1
        send "&7Parent: &f" + parent of guard region arg.1
SyntaxEffect
create guard region <name> from <location> to <location>Make a box-shaped region between two corners. With a name that exists, the region is replaced
create guard region <name> from <location> to <location> full heightThe same, from the bottom of the world to the top
delete guard region <name>Remove a region
guard regions between <location> and <location>A list of the regions that touch the box between two corners; add full height as above
guard allows building at <location>Whether WorldGuard lets the player build there, with owners, members, flags and bypass all considered
guard allows building at <location> for <who>The same for another player who is online
priority of guard region <name>The region's priority; settable with set priority of guard region <name> to <n>
parent of guard region <name>The region it inherits from; set parent of guard region <name> to <name>, or clear parent of guard region <name>
  • Both corners must be in the same world. The region is made in that world.
  • A new region has no owners, members or flags. Add the owner right after making it.
  • guard allows building at is the question to ask before a script places or breaks a block for a player; WorldGuard itself already stops the player's own building.

Whether there is such a region HyperGuard

Guide and examples
command /makezone <name>:
    permission: "zones.admin"
    trigger:
        if guard region exists arg.1:
            send "&cThere is a region called %arg.1% already."
            stop
        create guard region arg.1 from {%player%.a} to {%player%.b}
        send "&aMade %arg.1%."
SyntaxEffect
guard region exists <name>True if WorldGuard has a region of that name, in any world. For asking before making one, or before using a name a player typed; nothing is said in the console when there is none

Claiming land HyperGuard

Guide and examples

One line that does what a plot script otherwise checks by hand: is the name free, does the land touch anyone else's, and does the player already own as much as they may?

command /claimland:
    players only: true
    trigger:
        set {_low} to player's location offset by -8, 0, -8
        set {_high} to player's location offset by 8, 0, 8
        claim guard region "land_%player.name%" from {_low} to {_high} full height
        if guard claim result is "claimed":
            send "&aThis land is yours now."
        else if guard claim result is "overlaps":
            send "&cThat would touch someone else's land."
        else if guard claim result is "limit reached":
            send "&cYou already own as much land as you may."
        else:
            send "&cYou have claimed land here before."

command /myland:
    players only: true
    trigger:
        send "&7You own: &f" + join guard regions owned by player with ", "
SyntaxEffect
claim guard region <name> from <location> to <location>Make a region and make the player its owner, if the name is free, the box touches no other region and the player is under their limit. full height as above; for <who> to claim for someone else who is online
guard claim resultWhat the last claim came to: claimed, name taken, overlaps, limit reached, or failed when the corners or the player were no good
guard regions owned by <who>A list of the regions a player owns, in every world
  • The limit is claim-limit in plugins/HyperGuard/config.yml, 3 unless changed; -1 is no limit. Players with the permission hyperguard.claim.unlimited are never held back.
  • Every region a player owns counts towards the limit, however it was made.

Where a region is HyperGuard

Guide and examples
command /arena:
    players only: true
    trigger:
        teleport player to random location in guard region "arena"

command /regioninfo <region>:
    trigger:
        send "&7Middle: &f" + center of guard region arg.1
        send "&7Blocks: &f" + size of guard region arg.1
        set {_corners} to corners of guard region arg.1
        send "&7From &f" + item 1 of {_corners} + " &7to &f" + item 2 of {_corners}

command /grow <region> <blocks:number>:
    permission: "regions.manage"
    trigger:
        expand guard region arg.1 by arg.2 parsed as number blocks sideways
        send "&aDone."

command /bringregion <region>:
    permission: "regions.manage"
    players only: true
    trigger:
        move guard region arg.1 to player's location
SyntaxEffect
center of guard region <name>The middle of the region, as a location
random location in guard region <name>A place inside it: on the ground where the ground is within the region, otherwise on the region's floor. For arenas and for spawning creatures
size of guard region <name>How many blocks it holds
corners of guard region <name>A list of two locations: its lowest and its highest corner
expand guard region <name> by <n> blocksMake it larger on every side; a negative number makes it smaller. Add sideways to leave its height alone
move guard region <name> to <location>Move it so that its middle is there. Its size, owners, members and flags stay
  • Expanding and moving work on box-shaped regions, and within the region's own world.

Working with HyperScript's own areas HyperGuard

Guide and examples

HyperScript can copy a piece of the world and put it back, and show blocks that only one player sees. These do the same for the box of a WorldGuard region:

command /savearena:
    permission: "arena.manage"
    trigger:
        copy guard region "arena" as "arena-clean"

command /resetarena:
    permission: "arena.manage"
    trigger:
        paste "arena-clean"

command /showplot:
    players only: true
    trigger:
        set fake blocks in guard region "land_%player.name%" to "glass"
        wait 5 seconds
        clear fake blocks in guard region "land_%player.name%"
SyntaxEffect
copy guard region <name> as <name>Remember every block in the region's box, to put back with HyperScript's paste <name>. Needs HyperScript 1.7.15 or newer
set fake blocks in guard region <name> to <block>Show the player the whole box as that block, without changing the world; for <who> for someone else. Needs HyperScript 1.7.14 or newer
clear fake blocks in guard region <name>Show what is really there again
  • The limits are HyperScript's: a copy holds up to 250,000 blocks and fake blocks come up to 32,768 at a time, so these are for arenas and plots rather than whole cities.

When WorldGuard says no HyperGuard

Guide and examples
on guard build denied:
    send action bar "&cYou cannot build in %{_region}%" to player

on guard pvp denied:
    send "&cNo fighting here. %{_victim}% is safe."
EventWhenIn the block
on guard build denied:WorldGuard has stopped a player breaking or placing a block{_region} (the region there, empty in the wilderness), {_action} (break or place), {_location}
on guard pvp denied:WorldGuard has stopped one player hurting another; the player is the attacker{_region}, {_victim}
  • Both can be given a region to listen for, like the events above: on guard build denied "spawn":.
  • WorldGuard still sends its own message. To have only yours, clear the region's deny-message flag: set guard flag "deny-message" of region "spawn" to "".
  • These rely on events inside WorldGuard that are not in every version of it. If yours has none, HyperGuard says so in the console when it starts, and everything else works.

HyperHolograms

An addon: a separate plugin whose words work once it is installed.

Making and changing HyperHolograms

Guide and examples
command /sethub:
    permission: "holo.manage"
    players only: true
    trigger:
        create holo "hub" at player's location with lines "&b&lWelcome", "&7Players online: %server.online_players%"
        send "&aThe hub hologram is here now."

every 30 seconds:
    if holo exists "hub":
        set line 2 of holo "hub" to "&7Players online: %server.online_players%"

command /hubnews <text>:
    permission: "holo.manage"
    trigger:
        add line "&e%arg.1%" to holo "hub"
        set {_lines} to lines of holo "hub"
        send "&aAdded. It has %size of {_lines}% lines now."

command /hubclear:
    permission: "holo.manage"
    trigger:
        remove line 3 of holo "hub"

command /movehub:
    permission: "holo.manage"
    players only: true
    trigger:
        move holo "hub" to player's location

command /delhub:
    permission: "holo.manage"
    trigger:
        delete holo "hub"
SyntaxEffect
create holo <name> at <location> showing top <n> by {<variable>}A list of the players who have the most of a variable of their own, such as {coins}, best first, up to 25. It is worked out again every half minute. titled <text> puts a line over it. Make it in on load:, since it is the script that keeps it up to date
create holo <name> at <location> with lines <text>, <text>Make a hologram. With a name that is taken, it is moved there and given the new lines
delete holo <name>Remove it for good
move holo <name> to <location>Put it somewhere else
set line <n> of holo <name> to <text>Rewrite one line; the line after the last one is added
add line <text> to holo <name>Add a line at the bottom
remove line <n> of holo <name>Take one line out
make holo <name> follow <who>The hologram stays over that player's head as they move, until told otherwise. Add <n> blocks above to say how high over their feet: make holo "tag" follow player 3 blocks above
stop holo <name> followingIt stays where it is
command /crown <player>:
    permission: "crown.give"
    trigger:
        create holo "crown" at player's location with lines "&6&lKING"
        make holo "crown" follow arg.1 3 blocks above
        send "&6%arg.1% wears the crown."

command /uncrown:
    permission: "crown.give"
    trigger:
        stop holo "crown" following
        delete holo "crown"
  • A name is letters, digits, - and _.
  • A hologram that follows a player goes by one name, so each player needs a hologram of their own: name it after them, as in create holo "tag-%player.name%" .... While the player is offline it waits where it was; following is not remembered over a restart, so start it again in on player join:.
  • Lines are DecentHolograms' own, so everything it understands works in them: colours, PlaceholderAPI placeholders, and #ICON: diamond for a floating item.
  • Making one in on load: is safe: making it again only moves it.

Pages and who sees it HyperHolograms

Guide and examples
on load:
    create holo "help" at {help.spot} with lines "&6&lHelp", "&7Click for the next page"
    if pages of holo "help" < 2:
        add page to holo "help" with lines "&6&lCommands", "&f/spawn &7- go to spawn", "&f/shop &7- open the shop"

on holo click "help":
    if {_page} is 1:
        show page 2 of holo "help" to player
    else:
        show page 1 of holo "help" to player

on player join:
    if player has permission "staff.see":
        show holo "staffnotes" to player

command /hidenotes:
    permission: "staff.see"
    trigger:
        hide holo "staffnotes" from all players

command /shownotes:
    permission: "staff.see"
    trigger:
        show holo "staffnotes" to all players
SyntaxEffect
add page to holo <name> with lines <text>, <text>Give it another page
show page <n> of holo <name> to <who>Turn it to that page for one player; others see what they saw
show holo <name> to <who>Let a player see it
hide holo <name> from <who>Hide it from a player
show holo <name> to all players / hide holo <name> from all playersFor everybody, and for whoever joins later
  • To show a hologram to a few players only: hide holo ... from all players once, then show holo ... to player for those who should see it.

Asking and clicking HyperHolograms

Guide and examples
command /holos:
    permission: "holo.manage"
    trigger:
        for each {_name} in all holos:
            send "&e%{_name}% &7at %location of holo {_name}%"

on holo click "daily":
    if {_click} is "right":
        execute player command "daily"

on holo click:
    log "%player.name% clicked the hologram %{_holo}% (%{_click}%)"
SyntaxResult
all holosA list of the names of every hologram
holo exists <name>Whether there is one of that name
location of holo <name>Where it is, as a location
lines of holo <name>A list of the lines of its first page
pages of holo <name>How many pages it has
on holo click "<name>":Runs when a player clicks that hologram. Without a name: any hologram
  • Inside the click block player is who clicked, {_holo} the hologram's name, {_click} one of left, right, shift left and shift right, and {_page} the page they were looking at.

For a time, the nearest, and how far it is seen HyperHolograms

Guide and examples
on player death:
    create holo "grave-%player.name%" at player's location with lines "&7Here fell", "&f%player.name%" for 30 seconds

command /nearholo:
    trigger:
        set {_holo} to nearest holo to player's location
        if {_holo} is set:
            send "&7The nearest hologram is &f%{_holo}%&7."
        else:
            send "&7There is no hologram in this world."

command /clearholos:
    permission: "holo.admin"
    trigger:
        for each {_holo} in holos within 10 blocks of player's location:
            delete holo {_holo}

command /holorange <name> <blocks:number>:
    permission: "holo.admin"
    trigger:
        set view distance of holo arg.1 to arg.2
SyntaxEffect
create holo <name> at <location> with lines <text>, <text> for <duration>A hologram that deletes itself when the time is up, and when the server stops. Made again under the same name, the time starts over
nearest holo to <location>The name of the hologram closest to that place, in the same world; unset if there is none
holos within <n> blocks of <location>The names of the holograms that near a place, the nearest first
set view distance of holo <name> to <n>From how many blocks away it is shown, 1 to 256

More examples HyperHolograms

Guide and examples
command /richest:
    permission: "staff.holo"
    trigger:
        create holo "richest" at player's location showing top 10 by {coins} titled "&6&lRichest players"

HyperLog

An addon: a separate plugin whose words work once it is installed.

Looking things up HyperLog

Guide and examples
command /history:
    permission: "staff.history"
    trigger:
        async:
            set {_lines} to block changes at player's location in the last 7 days
            loop {_lines}:
                send "&7%loop-value%"
            else:
                send "&7Nothing happened to this block."

command /griefcheck <target>:
    permission: "staff.griefcheck"
    trigger:
        async:
            set {_did} to block changes by arg.1 in the last 1 hour within 50 blocks of player
            send "&7%arg.1% changed &f%size of {_did}% &7blocks near you in the last hour."
SyntaxMeaning
who last changed block at <location>The name of whoever last placed or broke the block there; unset if nobody is on record
block changes at <location>What happened to that block, newest first, as a list of lines such as Steve placed stone, 5 minutes ago. Looks back 30 days
block changes at <location> in the last <duration>The same, as far back as you say
block changes by <who> in the last <duration>What that player placed and broke in that time, newest first, each line with its place
... within <n> blocks of <location>Behind block changes by: only around a place
  • Put lookups in an async: block, as the examples do. CoreProtect reads its database to answer, and that should not hold up the server.
  • <who> is a name, and it need not be somebody who is online. Where a location is asked for, player stands for where the player is.
  • size of a list of changes is how many there were.

Taking it back HyperLog

Guide and examples
command /undohere:
    permission: "staff.undo"
    trigger:
        rollback everything for 10 minutes within 20 blocks of player

command /redo <target> <time:duration>:
    permission: "staff.undo"
    trigger:
        restore arg.1 for arg.2
SyntaxEffect
rollback <who> for <duration>Take back what that player placed and broke in that time, everywhere
rollback <who> for <duration> within <n> blocks of <location>Only around a place
rollback everything for <duration> within <n> blocks of <location>Whoever did it. Everything can only be taken back around a place
restore <who> for <duration>Put back what a rollback took away. within and everything work as for rollback
  • A rollback is done by CoreProtect in the background and can take a while; the lines after it run at once. If it fails, the console says why, with the script and line.
  • It is about blocks that were placed and broken. Chests, kills and the rest of what CoreProtect can take back are left to its own /co rollback.
  • A rollback changes the world. Give the commands that do it a permission.

Who placed it, who broke it HyperLog

Guide and examples
on right click with stick:
    if event.block is not set:
        stop
    set {_placed} to who placed block at event's location
    set {_broke} to who broke block at event's location
    if {_placed} is set:
        send "&7Placed by &f%{_placed}%"
    if {_broke} is set:
        send "&7Last broken by &f%{_broke}%"
    if {_placed} is not set and {_broke} is not set:
        send "&7Nobody is on record for this block."
SyntaxEffect
who placed block at <location>The name of whoever last placed a block there; unset if nobody is on record. Not the same as who last changed block at, which may be whoever broke it
who broke block at <location>The name of whoever last broke a block there

More examples HyperLog

Guide and examples
command /lastchange:
    permission: "staff.who"
    trigger:
        set {_name} to who last changed block at player's location
        send "&7Last changed by &f%{_name}%"

HyperMobs

An addon: a separate plugin whose words work once it is installed.

Spawning and removing HyperMobs

Guide and examples
command /summonking:
    permission: "bosses.spawn"
    players only: true
    trigger:
        if not mythic mob exists "SkeletonKing":
            send "&cMythicMobs has no SkeletonKing."
            stop
        spawn mythic mob "SkeletonKing" at player's location level 5
        set {boss} to last mythic mob
        send "&aThe Skeleton King is here, at level %mythic level of {boss}%."

every 10 minutes:
    if mythic mobs alive of "SkeletonMinion" < 5:
        spawn mythic mob "SkeletonMinion" at {arena.middle}

command /clearbosses:
    permission: "bosses.spawn"
    trigger:
        remove mythic mobs "SkeletonKing"
        send "&7%mythic mobs alive% mythic mobs are left."
SyntaxEffect
spawn mythic mob <name> at <location>Spawn one of that mob
spawn mythic mob <name> at <location> level <n>The same, at a level
remove mythic mobs <name>Take away every living mob of that kind. Without a name: every mythic mob
last mythic mobThe creature spawn mythic mob made most recently, to keep in a variable
mythic mob exists <name>Whether MythicMobs has a mob of that name
all mythic mobsA list of the names of every mob MythicMobs has
mythic mobs aliveHow many mythic mobs are alive now
mythic mobs alive of <name>The same for one kind
  • A name MythicMobs does not know is reported in the console and nothing is spawned.
  • A mob kept in a variable is an entity like any other: health of {boss}, teleport, make {boss} target player and the rest of HyperScript work on it.

Skills and levels HyperMobs

Guide and examples
command /roar:
    permission: "bosses.spawn"
    trigger:
        cast mythic skill "Roar" from {boss}
        set mythic level of {boss} to 10
        send "&7The " + mythic mob type of {boss} + " is now level 10."

command /mythiclist:
    permission: "bosses.spawn"
    trigger:
        send "&7MythicMobs has: &f" + join all mythic mobs with ", "

on right click:
    if player is holding blaze rod:
        cast mythic skill "FireBlast" from player
SyntaxEffect
cast mythic skill <name> from <who>Have a creature or a player cast one of MythicMobs' skills
mythic mob type of <entity>Which mythic mob a creature is, as its internal name; unset for an ordinary creature
mythic level of <entity>Its level; unset for an ordinary creature
set mythic level of <entity> to <n>Change its level
  • <who> is an entity in a variable, or a player: from player, from arg.1.
  • A skill is meant by the name it has in plugins/MythicMobs/Skills. One that does not exist, or that cannot be cast by that creature, is reported in the console.

Events HyperMobs

Guide and examples
on mythic mob death "SkeletonKing":
    broadcast "&6%player.name% &ehas slain the Skeleton King!"
    add 500 to {%player%.coins}

on mythic mob death:
    log "A level %{_level}% %{_type}% died at %{_location}%"

on mythic mob spawn "SkeletonKing":
    broadcast "&cThe Skeleton King has risen!"
    set {boss} to {_mob}
SyntaxEffect
on mythic mob death "<name>":Runs when a mob of that kind dies. player is who killed it, if a player did
on mythic mob spawn "<name>":Runs when one spawns, however it was spawned. There is no player
  • Without a name, a block runs for every mythic mob.
  • Inside the blocks {_mob} is the creature, {_type} its internal name, {_level} its level and {_location} where it is.
  • A mob that dies of something other than a player has no player; test if player is set: before giving a reward.

Items, signals and being hurt HyperMobs

Guide and examples
command /crown <target:player>:
    permission: "mythic.give"
    trigger:
        if mythic item exists "KingsCrown":
            give mythic item "KingsCrown" to arg.1
            give 3 of mythic item "HealingDraught" to arg.1
        else:
            send "&cMythicMobs has no item called KingsCrown."

on mythic mob damage "SkeletonKing":
    send action bar "&c-%{_damage}% &7to the king" to player
    if {_damage} > 10:
        signal mythic mob {_mob} with "enrage"

on mythic mob damage:
    add {_damage} to {%player%.mythic_damage}

on mythic mob death "SkeletonKing":
    drop mythic item "KingsCrown" at {_location}

command /rally:
    permission: "mythic.give"
    trigger:
        for each {_mob} in mythic mobs within 30 blocks of player's location:
            signal mythic mob {_mob} with "rally"
        send "&7MythicMobs has %size of all mythic items% items."
SyntaxEffect
give mythic item <name> to <who>Give one of the items MythicMobs has under that name. What does not fit is dropped at their feet. The console says so if there is no such item
give <n> of mythic item <name> to <who>The same, that many
drop mythic item <name> at <location>Put one on the ground there
all mythic itemsThe names of every item MythicMobs has
mythic mobs within <n> blocks of <location>The mythic mobs that near a place, as creatures, the nearest first: for signal mythic mob, mythic mob type of, or anything HyperScript does with a creature
mythic item exists <name>True if MythicMobs has an item of that name
signal mythic mob <entity> with <text>Send a mythic mob a signal, which its own skills can wait for with ~onSignal:<text>
on mythic mob damage "<name>":Runs when a mythic mob of that type is hurt. {_damage} is how much, {_cause} what did it, and {_mob}, {_type}, {_level} and {_location} are as in the other events. player is who hurt it, if a player did, also with an arrow. Without a name it runs for every mythic mob
  • on mythic mob damage: runs for every hit on every mythic mob, so keep what is in it short.

HyperModels

An addon: a separate plugin whose words work once it is installed.

Items HyperModels

Guide and examples
command /ruby <player> <amount>:
    permission: "models.give"
    trigger:
        if not model exists "ruby":
            send "&cThere is no item called ruby."
            stop
        set {_amount} to parse arg.2 as integer
        give {_amount} of model "ruby" to arg.1
        send "&aGiven."

command /sellrubies:
    players only: true
    trigger:
        set {_have} to amount of model "ruby" of player
        if {_have} < 1:
            send "&cYou have no rubies."
            stop
        take {_have} of model "ruby" from player
        add {_have} * 25 to {%player%.coins}
        send "&aSold %{_have}% rubies."

on right click:
    if held model of player is "magic_wand":
        cancel event
        strike lightning at target block of player

command /payruby:
    players only: true
    trigger:
        if amount of model "ruby" of player < 1:
            send "&cThat costs one ruby."
            stop
        take model "ruby" from player
        send "&aPaid."

on player death:
    drop model "ruby" at player's location

command /models:
    permission: "models.give"
    trigger:
        send "&7%size of all models% custom items: &f" + join all models with ", "
SyntaxEffect
give model <id> to <who>Give one of a custom item. What does not fit is dropped at their feet
give <n> of model <id> to <who>Give several
take model <id> from <who>Take one out of their inventory, if they have it
take <n> of model <id> from <who>Take up to that many
drop model <id> at <location>Drop one on the ground
held model of <who>The id of the custom item in their main hand; unset for an ordinary item or an empty hand
amount of model <id> of <who>How many of it they carry
model exists <id>Whether any of the plugins has an item of that id
all modelsA list of every id, in alphabetical order
  • An id that no plugin knows is reported in the console and nothing is given.
  • These are the plugin's own items, with their name, look and abilities; nothing is copied.

Blocks and furniture HyperModels

Guide and examples
command /rubyore:
    permission: "models.build"
    players only: true
    trigger:
        place model block "ruby_ore" at target block of player
        send "&aPlaced."

command /clearore:
    permission: "models.build"
    players only: true
    trigger:
        if model block at target block of player is set:
            remove model block at target block of player

command /chair:
    permission: "models.build"
    players only: true
    trigger:
        place model furniture "chair" at player's location
SyntaxEffect
place model block <id> at <location>Put a custom block there
remove model block at <location>Take the custom block there away; an ordinary block is left alone
model block at <location>The id of the custom block there; unset for an ordinary block
place model furniture <id> at <location>Stand a piece of furniture there

Events HyperModels

Guide and examples
on model block break "ruby_ore":
    give model "ruby" to player
    add 1 to {%player%.rubies_mined}

on model block place "ruby_ore":
    send "&7Ruby ore is for mines, not for walls."

on model block place:
    log "%player.name% placed %{_model}% at %{_location}%"

on model block click "crate":
    execute player command "crate open"

on model furniture click "chair":
    send "&7A comfortable chair."
SyntaxEffect
on model block break "<id>":Runs when a player breaks that custom block
on model block place "<id>":Runs when a player places it
on model block click "<id>":Runs when a player right-clicks it
on model item click "<id>":Runs when a player right-clicks while holding that custom item in their main hand, in the air or at a block. {_location} is the block that was clicked, or where they stand
on model furniture click "<id>":Runs when a player clicks a piece of furniture
  • Without an id, a block runs for every custom block or piece of furniture.
  • Inside the blocks player is the player, {_model} the id and {_location} where it is.
  • These run after the plugin has made up its mind: a break or place that it refused does not reach a script, and cancel event does not undo one.

Furniture put down, broken and taken away HyperModels

Guide and examples
on model furniture place "furniture:throne":
    broadcast "&6%player.name% has set up a throne."
    set {throne.place} to {_location}

on model furniture break "furniture:throne":
    broadcast "&7The throne is gone."
    delete {throne.place}

on model furniture place:
    add 1 to {%player%.furniture_placed}

command /clearthrone:
    permission: "models.admin"
    trigger:
        if {throne.place} is set:
            remove model furniture at {throne.place}
            delete {throne.place}
SyntaxEffect
on model furniture place "<id>":Runs when a player puts that piece of furniture down. {_model} is its id and {_location} where it stands. Without an id it runs for every piece
on model furniture break "<id>":Runs when a player breaks one, with the same values
remove model furniture at <location>Take away the piece of furniture that stands there, without dropping it. Nothing happens where there is none
  • These need a version of ItemsAdder, Oraxen or Nexo that says when furniture is put down and broken, and lets it be removed; with one that does not, the blocks never run and the line does nothing.

HyperPackets

An addon: a separate plugin whose words work once it is installed.

Fake players on the tab list HyperPackets

expression... named <text>HyperPackets

What the list shows, with colours: named "&c&lConsole". Without it, the name itself

expression... with skin of <name>HyperPackets

The head of that player. Somebody who is online is taken from the server; anybody else is asked of Mojang, which takes a moment, and the head changes when the answer is there

expression... with order <n>HyperPackets

Where on the list: the higher the number, the further up. Real players are at 0. Needs Minecraft 1.21.2 or newer

expression... for <who>HyperPackets

Only on that player's list

effectset tab name of fake player <name> to <text>HyperPackets

Changes what is shown

effectset tab ping of fake player <name> to <n>HyperPackets

Changes the bars

effectset tab order of fake player <name> to <n>HyperPackets

Moves it up or down the list

effectset tab skin of fake player <name> to <name>HyperPackets

Another head. to "" gives the plain one

effectremove fake tab player <name>HyperPackets

Takes it off everybody's list. With for <who>, off that player's only

Guide and examples

A fake tab player is a line on the list players see when they hold Tab. Nobody is on the server for it: it has a name, a skin for the little head, a ping for the bars, and a place.

SyntaxWhat it does
add fake tab player <name>Puts one on everybody's list. The name is what scripts call it by afterwards. Adding one that is there already changes it
... named <text>What the list shows, with colours: named "&c&lConsole". Without it, the name itself
... with skin of <name>The head of that player. Somebody who is online is taken from the server; anybody else is asked of Mojang, which takes a moment, and the head changes when the answer is there
... with ping <n>The bars: 0 is full, 1000 is one bar
... with order <n>Where on the list: the higher the number, the further up. Real players are at 0. Needs Minecraft 1.21.2 or newer
... for <who>Only on that player's list
set tab name of fake player <name> to <text>Changes what is shown
set tab ping of fake player <name> to <n>Changes the bars
set tab order of fake player <name> to <n>Moves it up or down the list
set tab skin of fake player <name> to <name>Another head. to "" gives the plain one
remove fake tab player <name>Takes it off everybody's list. With for <who>, off that player's only
remove all fake tab playersAll of them
fake tab playersThe names of those there are, as a list

What follows the name of add fake tab player can come in any order.

command /fakes <text>:
    permission: "fakes.use"
    trigger:
        if arg.1 is "clear":
            remove all fake tab players
            send "&7Gone."
            stop
        add fake tab player arg.1 with ping 40
        send "&a%arg.1% is on the list. There are now %size of fake tab players%."
  • A fake tab player is only on the list. It is not in the world, cannot be messaged, and does not count as online.
  • Players who join later get the ones that are for everybody. One that was for a single player goes when that player leaves.
  • They are gone after a restart or a reload of the plugin: add them from on load: to keep them.
  • On servers older than 1.21.2 the list has no order of its own and sorts by name; with order does nothing there.
  • At most 200 at a time.

To change the name a real player has on the list, HyperScript itself has set tab name of <who> to <text>; this addon is for entries that are nobody.

Sending any packet HyperPackets

expressionpacket namesHyperPackets

Every packet there is, as a list

Guide and examples
SyntaxWhat it does
send packet <name> to <who>Sends that packet to a player, or to all players
send packet <name> with <value>, <value> to <who>With the values the packet takes, in its order
packet namesEvery packet there is, as a list

The packets are PacketEvents' own, about 160 of them, and are named as it names them: "ChangeGameState", "EntityAnimation", "SetTitleText". Spaces and capitals do not matter, so "change game state" is the same.

/hyperpackets lists them all, and /hyperpackets <name> says what one takes:

/hyperpackets entity animation
EntityAnimation takes, in this order:
  whole number, one of swing_main_arm/hurt/wake_up/swing_off_hand/critical_hit/magic_critical_hit

What a script gives is turned into what the packet asks for:

The packet asks forGive it
a whole number, a numberA number. Where it is the number of an entity, a player or an entity can be given instead: player
true/falsetrue or false
textA text; colours with & work where the packet shows it
one of ...One of the words listed, as text: "swing main arm"
a placeA location, or three numbers as a list: [0, 1, 0]
UUIDA player or an entity
ItemStackThe name of an item: "diamond sword"
a list of somethingSeveral values of that kind, as a list or one after another
command /swing:
    trigger:
        send packet "entity animation" with player, "swing main arm" to all players

command /credits:
    trigger:
        send packet "change game state" with "win game", 1 to player
  • A packet changes only what that player sees. The server does not know about it: rain sent by a packet does not water crops, and a block shown by one is not there.
  • A packet that is given what it does not take is not sent, and the console says what it takes.
  • A few packets take things a script has no way to give, such as a whole chunk. They are listed but cannot be made.
  • Packets a client sends to the server are not part of this: only those the server sends.
  • Sending the wrong thing can throw a player off the server or leave their game showing something that is not so until they join again. Try a packet on yourself first.

HyperPerms

An addon: a separate plugin whose words work once it is installed.

Groups HyperPerms

Guide and examples
on player join:
    if group of player is "default":
        send "&7Type &f/rankup &7when you have 1000 coins."
    if groups of player contains "vip":
        send "&6Welcome back, VIP!"

on player chat:
    set {_before} to prefix of player
    set {_after} to suffix of player
    set chat format to "%{_before}%&f%player.name%%{_after}%&7: &f%event.message%"
SyntaxResult
group of <who>The player's primary group, e.g. default or vip
groups of <who>A list of every group the player is in
prefix of <who>The chat prefix LuckPerms gives the player; unset if none
suffix of <who>The chat suffix; unset if none
  • These are values like any other: if group of player is "vip":, if groups of arg.1 contains "staff":, send "Rank: " + group of player.
  • They are read for players who are online. For someone offline they are unset.
  • prefix of team "red" is still HyperScript's own, about scoreboard teams.

Changing groups HyperPerms

Guide and examples
command /givevip <target:player> <days:integer>:
    permission: "ranks.give"
    trigger:
        add arg.1 to group "vip" for arg.2 * 1 day
        send "&a%arg.1% is VIP for %arg.2% day(s)."

command /vipleft:
    trigger:
        set {_left} to time left in group "vip" of player
        if {_left} is not set:
            send "&7You are not VIP for a limited time."
            stop
        send "&6Your VIP lasts another %{_left}%."

command /demote <target:player>:
    permission: "ranks.give"
    trigger:
        set group of arg.1 to "default"

command /takevip <target:player>:
    permission: "ranks.give"
    trigger:
        remove arg.1 from group "vip"
        send "&e%arg.1% is no longer VIP."
SyntaxEffect
add <who> to group <name>Put a player in a group, keeping the ones they have
add <who> to group <name> for <duration>The same, for a limited time; LuckPerms takes it away again
time left in group <name> of <who>How long a time-limited membership still lasts, as a duration; unset if they are not in the group, or are in it for good
remove <who> from group <name>Take a player out of a group
set group of <who> to <name>Out of every other group and into this one
promote <who> on track <name>One group up a track made in LuckPerms (/lp createtrack staff). Somebody who is on none of its groups gets the first
demote <who> on track <name>One group down; from the first group, out of the track
  • <who> is player, all players, or a name. A named player may be offline: LuckPerms looks them up, makes the change and saves it.
  • The group has to exist in LuckPerms. A name it does not know is reported in the console and nothing changes.
  • Adding someone to a group they are already in replaces the old membership, so a new time limit takes the place of the old one.
  • Changes are saved by LuckPerms and, if it is set up for that, shared with your other servers.

Single permissions HyperPerms

Guide and examples
command /fly1h <target:player>:
    permission: "ranks.give"
    trigger:
        grant arg.1 permission "essentials.fly" for 1 hour
        send "&a%arg.1% can fly for an hour."

command /nofly <target:player>:
    permission: "ranks.give"
    trigger:
        revoke permission "essentials.fly" from arg.1
SyntaxEffect
grant <who> permission <node>Give a player one permission, for good
grant <who> permission <node> for <duration>The same for a limited time; LuckPerms takes it away again
revoke permission <node> from <who>Take a permission back
  • As with groups, <who> may be a player who is offline, and a new time limit replaces an old one.
  • These are saved by LuckPerms. HyperScript's own permission <who> add <node> is a different thing: it lasts until the player leaves and is not saved.

Lists and weights HyperPerms

Guide and examples
command /staff:
    trigger:
        send "&7Staff online: &f" + join players in group "staff" with ", "

command /ranks:
    trigger:
        for each {_group} in all groups:
            send "&7%{_group}% &8- &fweight " + weight of group {_group}
SyntaxResult
all groupsA list of every group LuckPerms has, in alphabetical order
rank of <who> on track <name>The group of that track the player is in, the highest if several; unset if none. For players who are online
groups of track <name>The groups of a track, from the lowest to the highest
players in group <name>The names of the online players in that group, directly or through another group
weight of group <name>The group's weight; unset if it has none

Meta HyperPerms

Guide and examples
command /sethomelimit <target:player> <amount:integer>:
    permission: "ranks.give"
    trigger:
        set meta "home-limit" of arg.1 to arg.2
        send "&a%arg.1% may now have %arg.2% homes."

command /homelimit:
    players only: true
    trigger:
        set {_limit} to meta "home-limit" of player
        if {_limit} is not set:
            set {_limit} to 1
        send "&7You may have &f%{_limit}% &7home(s)."

command /resethomelimit <target:player>:
    permission: "ranks.give"
    trigger:
        clear meta "home-limit" of arg.1
SyntaxEffect
meta <key> of <who>A meta value of the player, their own or from one of their groups; unset if there is none
set meta <key> of <who> to <value>Give the player a value of their own under that key
clear meta <key> of <who>Take the player's own value away again
  • Meta is how LuckPerms keeps values per rank: /lp group vip meta set home-limit 5 gives every VIP a limit of 5, and a script reads it with meta "home-limit" of player.
  • The value comes back as text. Use parsed as number to count with it.

Group events HyperPerms

Guide and examples
on group change:
    log "%{_player}% is now in %{_group}% (%{_groups}%)"
    if {_group} is "vip":
        send "&6Thank you for supporting the server!" to {_player}
SyntaxEffect
on group change:Runs when the groups of any player change, however it happened
  • Inside the block, {_player} is the player's name, {_group} their primary group after the change, and {_groups} the list of all their groups.
  • It runs for changes made by scripts, by /lp commands and by a time limit running out alike.
  • The block runs with no player, like a console command; use {_player} to say who it is about.

Making groups, prefixes and suffixes HyperPerms

Guide and examples
command /makerank <name> <prefix>:
    permission: "ranks.admin"
    trigger:
        create group arg.1
        wait 1 second
        set prefix of group arg.1 to "&7[%arg.2%&7] "
        send "&aThere is now a group called %arg.1%."

command /dropgroup <name>:
    permission: "ranks.admin"
    trigger:
        if group exists arg.1:
            delete group arg.1
        else:
            send "&cThere is no group called %arg.1%."

command /groupfly <name>:
    permission: "ranks.admin"
    trigger:
        grant group arg.1 permission "essentials.fly"
        set weight of group arg.1 to 50
        send "&7%arg.1% has %size of permissions of group arg.1% permissions."

command /groupnofly <name>:
    permission: "ranks.admin"
    trigger:
        revoke permission "essentials.fly" from group arg.1

command /title <text>:
    permission: "title.use"
    trigger:
        set prefix of player to "&d[%arg.1%&d] "
        set suffix of player to " &8*"

command /notitle:
    trigger:
        clear prefix of player
        clear suffix of player

command /myperms:
    trigger:
        set {_nodes} to permissions of player
        send "&7You have %size of {_nodes}% permissions."
        if {_nodes} contains "essentials.fly":
            send "&aFlying is one of them."
SyntaxEffect
create group <name>Make a LuckPerms group. Small letters, digits, _, - and . only; a group that is there already is left as it is
delete group <name>Delete one, for good. default is never deleted
set prefix of <who> to <text>Give a player a prefix of their own, in front of whatever their groups give. set suffix of <who> to <text> likewise
set prefix of group <name> to <text>The same for a group, and set suffix of group <name> to <text>
clear prefix of <who>Take away the prefix a player has of their own; the one of their group shows again. clear suffix of, and of group <name>, likewise
group exists <name>True if LuckPerms has a group of that name
grant group <name> permission <node>Give a group a permission, for everybody in it. revoke permission <node> from group <name> takes it back
set weight of group <name> to <n>Which group counts for more when a player is in several: the higher number wins
permissions of group <name>A list of every permission a group has, its own and those of the groups it inherits from
permissions of <who>A list of every permission a player who is online has, their own and those of their groups
  • A group is made in a moment, not at once: give LuckPerms a tick before using it, as the example does with wait.
  • A prefix set here replaces the one the player or the group had of its own, and is given a priority above the ones that come from elsewhere, so that it is the one that shows.
  • clear prefix of team ... and set prefix of team ... are HyperScript's own, for scoreboard teams, and are left to it.

More examples HyperPerms

Guide and examples
command /promote <target:player>:
    permission: "staff.promote"
    trigger:
        promote arg.1 on track "staff"
        set {_now} to rank of arg.1 on track "staff"
        send "&a%arg.1% is now %{_now}%"

command /demote <target:player>:
    permission: "staff.promote"
    trigger:
        demote arg.1 on track "staff"

command /ladder:
    trigger:
        set {_groups} to groups of track "staff"
        send "&7Staff ranks: &f%{_groups}%"

HyperPlots

An addon: a separate plugin whose words work once it is installed.

Coming and going HyperPlots

Guide and examples
on plot enter:
    if {_owner} is player.name:
        send "&aWelcome home."

on plot leave:
    send action bar "&7You left plot %{_plot}%" to player
SyntaxEffect
on plot enter:Runs when a player walks, or is taken, into a plot. player is who came
on plot leave:Runs when they go out of one: onto the road, into another plot, or to another world
  • Inside on plot enter: {_plot} is the plot's number as PlotSquared writes it (3;-2), {_owner} the name of its owner, unset for a plot nobody has claimed, and {_owners} all of them as a list. on plot leave: has {_plot}, the one that was left.
  • Walking from one plot straight into the next runs on plot leave: for the first and then on plot enter: for the second.
  • The blocks run after the step is taken, so a script cannot stop somebody from walking in; PlotSquared's own flags and deny are what keep players out.

Asking about plots HyperPlots

Guide and examples
command /whose:
    trigger:
        set {_plot} to plot of player
        if {_plot} is not set:
            send "&7You are not on a plot."
            stop
        set {_owner} to owner of plot at player's location
        send "&7Plot &f%{_plot}% &7belongs to &f%{_owner}%"
        set {_helpers} to trusted of plot at player's location
        send "&7Trusted: &f%{_helpers}%"
SyntaxMeaning
plot at <location>The number of the plot a place is in, as text such as 3;-2; unset on a road or outside a plot world
plot of <who>The plot that player stands in; unset if they stand in none
owner of plot at <location>The name of its owner; unset for a plot nobody has claimed
owners of plot at <location>All of them, as a list; a plot can have several
members of plot at <location>The players added as members
trusted of plot at <location>The players who are trusted there
denied of plot at <location>The players who are kept out
plots of <who>The numbers of the plots a player owns, as a list
plot count of <who>How many plots they own
  • plots of and plot count of are about players who are online; for somebody who is not, the list is empty and the count 0.
  • A player the server has never seen is left out of the lists.
  • In a sum, put the whole in brackets: (plot count of player) + 1.

Changing who a plot lists HyperPlots

Guide and examples
command /letin <target:offline player>:
    trigger:
        if owner of plot at player's location is not player.name:
            send "&cThis is not your plot."
            stop
        add arg.1 to plot at player's location
        send "&a%arg.1% may now build here while you are online."

command /trustin <target:offline player>:
    trigger:
        if owner of plot at player's location is player.name:
            add arg.1 to plot at player's location as trusted

command /keepout <target:offline player>:
    trigger:
        if owner of plot at player's location is player.name:
            deny arg.1 from plot at player's location

command /unlist <target:offline player>:
    trigger:
        if owner of plot at player's location is player.name:
            remove arg.1 from plot at player's location

command /free:
    trigger:
        if plot claimed at player's location:
            send "&7Somebody owns this plot."
        else:
            send "&aNobody owns this."
SyntaxEffect
add <who> to plot at <location>Put a player on the plot's list of members, who may build while an owner is online
add <who> to plot at <location> as trustedPut them on the list of trusted players, who may build at any time
deny <who> from plot at <location>Put them on the list of players who may not come in
remove <who> from plot at <location>Take them off all three lists
plot claimed at <location>True where there is a plot that somebody owns
  • The player need not be online, but must have played on the server before.
  • Somebody is on one list at a time: adding them as trusted takes them off the members and off the denied.
  • These change the plot the way PlotSquared's own /plot add, /plot trust, /plot deny and /plot remove do, without asking who runs the command: check the owner in the script, as the examples do.

More examples HyperPlots

Guide and examples
command /plotinfo:
    trigger:
        set {_owners} to owners of plot at player's location
        set {_members} to members of plot at player's location
        set {_denied} to denied of plot at player's location
        send "&7Owners: &f%{_owners}% &7Members: &f%{_members}% &7Kept out: &f%{_denied}%"

command /plotlist:
    trigger:
        set {_mine} to plots of player
        set {_count} to plot count of player
        send "&7Your %{_count}% plots: &f%{_mine}%"

HyperSkin

An addon: a separate plugin whose words work once it is installed.

Changing a skin HyperSkin

Guide and examples
on player join:
    if {%player%.team} is "red":
        set skin of player to "https://example.com/skins/red.png"

command /lookalike <target:player>:
    permission: "skin.others"
    trigger:
        set skin of player to arg.1
        send "&7You are wearing: &f%skin of player%"

command /unskin:
    trigger:
        reset skin of player
SyntaxEffect
set skin of <who> to <text>Give a player the skin of that name: the skin of the player called so, or one SkinsRestorer has under that name. The address of a skin image works too
reset skin of <who>Give them their own skin back
skin of <who>What the skin they were given is called; unset while they wear their own
  • The skin is looked up first, which asks Mojang or a website and takes a moment, so the lines after set skin of run before the player looks different. A skin that cannot be found is said in the console, with the script and line, and the player keeps the one they have.
  • It is for players who are online. SkinsRestorer remembers the skin, so it is still theirs when they join again.
  • set skin of npc ... belongs to HyperCitizens and is left to it.

A head with the skin somebody wears HyperSkin

Guide and examples
command /twin <target:player>:
    permission: "skin.others"
    trigger:
        copy skin of arg.1 to player
        send "&7You now look like %arg.1%."

command /myhead:
    trigger:
        set {_texture} to skin texture of player
        if {_texture} is not set:
            send "&cYour skin could not be read."
            stop
        give 1 player head textured {_texture} named "&f%player.name%" to player
SyntaxEffect
copy skin of <who> to <who>Give the second player the skin the first one wears: the one they were given, or their own
skin texture of <who>The skin a player who is online has on right now, as the text a head takes: 1 player head textured <value>. It is the skin they were given, or their own if they were given none. Unset if the server cannot tell
  • A head made with owned by shows the skin of that account, whatever the player is wearing; this is the one for the skin SkinsRestorer has put on them.
  • Heads with a texture need HyperScript 1.7.64 or newer, and Minecraft 1.18.1 or newer.

HyperVelocity

An addon: a separate plugin whose words work once it is installed.

Proxy players HyperVelocity

Guide and examples

Values about the whole network. They are what the proxy last reported, so they can be a few seconds behind.

command /glist:
    trigger:
        set {_players} to all proxy players
        set {_count} to proxy player count
        send "&6%{_count}% player(s) on the network:"
        for each {_server} in proxy servers:
            set {_names} to join players on server {_server} with ", "
            send "&e%{_server}%&7: &f%{_names}%"

command /here:
    trigger:
        set {_here} to join this server players with ", "
        set {_name} to this server name
        send "&7On &f%{_name}%&7: &f%{_here}%"
SyntaxResult
all proxy playersA list of the names of everyone on the proxy
this server playersA list of the names of everyone on this server
players on server <name>A list of the names on one server
proxy serversA list of the names of the servers behind the proxy
proxy player countHow many players are on the proxy
this server nameThe name the proxy knows this server by
  • These are lists and values like any other: size of all proxy players, if all proxy players contains arg.1:, for each {_name} in players on server "pvp":.
  • Until the proxy has answered for the first time, the lists are empty and this server name is unset. The first time a script asks for players on server "x", that server is added to the ones asked about, so the very first answer may be empty.
  • this server players never needs the proxy and is always current.

Proxy commands HyperVelocity

Guide and examples
command /pvp:
    trigger:
        send "&7Sending you to the PvP server..."
        send player to server "pvp"

command /sendall <server>:
    permission: op
    trigger:
        send all players to server arg.1
SyntaxEffect
send <who> to server <name>Move a player to another server
  • <who> is player, all players (everyone on this server), or a name. A named player may be on any server of the network: send "Alex" to server "lobby".
  • The server name is the one in the proxy's own configuration. A name the proxy does not know does nothing.
  • This is an ordinary send with a new ending. send "hello" to player still sends a message.

Proxy variables HyperVelocity

Guide and examples
command /setmotd <text>:
    permission: op
    trigger:
        set {shared.motd} to args
        send variable {shared.motd} to all servers
        send "&aThe message of the day was changed on every server."

command /sharecoins:
    trigger:
        send variable {%player%.coins} to server "pvp"
        send "&7Your coins were copied to the PvP server."
SyntaxEffect
send variable {<name>} to server <name>Copy a variable's value to the same variable on another server
send variable {<name>} to all serversThe same, to every other server
  • The other server gets the value under the same name. It works for every kind of value: numbers, text, lists, items, locations, durations.
  • A player's own variable arrives as that player's own: send variable {%player%.coins} to server "pvp" sets that player's {%player%.coins} there.
  • Sending a variable that is not set deletes it on the other server.
  • It is a copy made at that moment, not a link. Send it again when it changes.
  • to all servers does not include the server that is sending.
  • A server can refuse variables it should not be told: see accept-variables under Installation.

Proxy events HyperVelocity

Guide and examples

One server can make something happen on another. The sender names an event and may attach values; the receiver has a block for it.

On the sending server:

command /netban <player> <reason>:
    permission: "staff.ban"
    trigger:
        send event "ban" with variable "Target", arg.1 with variable "Reason", arg.2 to all servers
        ban arg.1 because arg.2

command /alert <server> <text>:
    permission: op
    trigger:
        send event "alert" with variable "Text", arg.2 to server arg.1

On every receiving server:

on receive event "ban":
    set {_p} to {_Target} parsed as offlineplayer
    ban {_p} because {_Reason}
    log "%{_p}% was banned from %{_sender_server}%"
SyntaxEffect
send event <name> to server <name>Run the on receive event blocks for that name on another server
send event <name> to all serversThe same, on every other server
with variable <name>, <value>Attach a value; write it once per value, before to
on receive event <name>:The block that runs when the event arrives
  • Each attached value is a local variable in the receiving block, under the name it was sent with: with variable "Target", arg.1 is read as {_Target}. Names ignore case.
  • {_sender_server} is always there too: the name of the server the event came from.
  • on receive event: without a name runs for every event that arrives.
  • The block runs with no player, like a console command, so send with no target goes to the console. Use the attached values to say who it is about.
  • An event is not saved or retried. If the other server cannot receive it at that moment (see below), it is lost.
  • on recieve event is accepted as well, for those of us who spell it that way.

Parties and groups HyperVelocity

Guide and examples

HyperScript's parties live on one server. These move a party, or any group of players, to another server together, and there they are one party again.

command /partywarp <server>:
    players only: true
    trigger:
        if party leader of player is not player:
            send "&cOnly the leader can move the party."
            stop
        send party of player to server arg.1

on queue "duels" of 2:
    send group {_players} to server "arena"
SyntaxEffect
send party of <who> to server <name>Move everyone in that player's party. Someone without a party goes alone
send group <list> to server <name>Move the players in a list together, such as those a queue hands over
  • For the players to be one party again where they arrive, both servers need HyperScript 1.7.19 or newer, and the server they go to needs somebody online at that moment (see below). Without that they still arrive, each for themselves.
  • The party is led there by whoever led it here; a group by the first name in the list.
  • Players arrive one by one. They are put together as they come in, for up to a minute.

Asking another server HyperVelocity

Guide and examples

send variable pushes a value to another server. This asks for one instead:

command /coins:
    players only: true
    trigger:
        request variable {%player%.coins} from server "survival"
        send "&7Asking the survival server..."

on receive variable "coins":
    send "&7Your coins on survival: &f%{_value}%" to {_owner}
SyntaxEffect
request variable {<name>} from server <name>Ask another server what it has in that variable. When the answer comes, the variable here is set to it
on receive variable <name>:Runs when such an answer has arrived. {_value} is what came, {_owner} the player it belongs to (empty for a variable that is nobody's), {_sender_server} who answered
  • Nothing waits for the answer: the lines after request variable run at once, and the answer comes a moment later, in on receive variable. Without that block the variable is still set.
  • The name in on receive variable "coins": is the variable's name without the player: {%player%.coins} arrives as coins.
  • The answer is taken in like any variable that is sent, so accept-variables here applies to it. What a server gives out is decided by its own share-variables.

Channels HyperVelocity

Guide and examples

A line of text for whoever is listening, on every server: staff chat, announcements, a shared death feed.

command /sc <message>:
    permission: "staff.chat"
    trigger:
        send "%player%: %args%" to network channel "staff"

on network message "staff":
    for each {_name} in this server players:
        if {_name} has permission "staff.chat":
            send "&c[Staff] &f%{_message}% &8(%{_sender_server}%)" to {_name}
SyntaxEffect
send <text> to network channel <name>Hand a line to every server, this one included
on network message <name>:Runs on each server when a line arrives on that channel. {_message} is the text, {_sender} the player whose trigger sent it (empty for the console), {_sender_server} where it came from
  • The block runs once on every server, as the console; it decides who gets to read the line.
  • on network message: without a name hears every channel.

Server status HyperVelocity

Guide and examples
on server offline "survival":
    broadcast "&cSurvival has gone down."

on server online "survival":
    broadcast "&aSurvival is back."

command /room <server>:
    trigger:
        set {_online} to size of players on server arg.1
        set {_room} to max players of server arg.1
        send "&7%arg.1%: &f%{_online}%&7/&f%{_room}%"
SyntaxEffect
max players of server <name>How many players that server has room for, as it says in the server list; unset while it has not answered
on server online <name>: / on server offline <name>:Runs when a server that was down can be reached again, or one that was up no longer can. {_server} is its name. Without a name, for any server
  • These come from asking each server directly, every fifth refresh (every 15 seconds with the settings above), so they can be that far behind.
  • The first time a server is looked at only sets what is known about it; the events are for changes after that.

Coming, going and changing server HyperVelocity

Guide and examples
on network join:
    broadcast "&a+ &f%{_player}% &7joined the network on &f%{_server}%"

on network leave:
    broadcast "&c- &f%{_player}% &7left the network"

on server switch:
    log "%{_player}% went from %{_from}% to %{_server}%"

on server switch "survival":
    broadcast "&f%{_player}% &7has arrived from &f%{_from}%"

command /find <name>:
    trigger:
        set {_server} to network server of arg.1
        if {_server} is set:
            send "&f%arg.1% &7is on &f%{_server}%&7."
        else:
            send "&7%arg.1% is not on the network."

command /lag <server>:
    trigger:
        set {_ms} to ping of server arg.1
        if {_ms} is set:
            send "&7%arg.1% answers in &f%{_ms}% ms"
        else:
            send "&c%arg.1% is not answering."
SyntaxEffect
on network join:Runs on this server when somebody joins the network, whichever server they arrive on. {_player} is their name and {_server} where they arrived. With a name, on network join "lobby":, only for that server
on network leave:Runs when somebody leaves the network. {_player} is their name and {_server} the server they were last seen on
on server switch:Runs when somebody goes from one server to another. {_player}, {_from} and {_server}, which is where they are now. With a name, only for arrivals on that server
network server of <who>Which server of the network a player is on, by its name on the proxy; unset if they are on none. As of the last refresh for a player on another server
ping of server <name>How long that server took to answer the last time it was tried, in milliseconds, measured from this server; unset if it did not answer
  • These are noticed by comparing the lists of players from one refresh to the next, so they run up to refresh-seconds after it happened, and somebody who joins and leaves between two refreshes is never seen.
  • The player is usually on another server, so there is no player in these blocks: the name is in {_player}. Every server that has HyperVelocity runs its own blocks, so a message to the whole network belongs on one of them only.
  • What a player was seen doing before this server started, or before its first refresh, sets what is known and runs nothing.

HyperVoice

An addon: a separate plugin whose words work once it is installed.

Groups HyperVoice

Guide and examples
on load:
    create voice group "Red"
    create voice group "Blue"
    create voice group "Staff" with password "letmein" hidden
    create voice group "Arena" isolated
    create voice group "Lobby" open

command /team <red|blue>:
    players only: true
    trigger:
        add player to voice group arg.1
        send "&aYou talk with team %arg.1% now."

command /leavevoice:
    players only: true
    trigger:
        remove player from voice group
        send "&7You talk to those near you again."

command /endgame:
    permission: "game.admin"
    trigger:
        for each {_name} in players in voice group "Red":
            remove {_name} from voice group
        delete voice group "Red"
        delete voice group "Blue"
SyntaxEffect
create voice group <name>Make a group. With a name that is taken, nothing happens
create voice group <name> with password <text>The same, with a password players have to type to join it themselves
create voice group <name> hiddenIt is not shown in the list of groups players can join
create voice group <name> openThose in the group also hear players near them who are not in it
create voice group <name> isolatedThose in the group hear only each other, and nobody outside hears them
delete voice group <name>Remove a group; whoever is in it is taken out first
add <who> to voice group <name>Put a player in a group, making an ordinary one if there is none of that name
remove <who> from voice groupTake a player out of the group they are in
  • with password, hidden and open or isolated can be combined on one line.
  • Without open or isolated, a group is an ordinary one: its members hear each other everywhere, and players near them hear them as well.
  • A group made by a script stays when it is empty, until it is deleted or the server restarts. Make the groups you need in on load:.
  • A player without the mod, or one who is offline, cannot be put in a group; the line does nothing.

Who is connected HyperVoice

Guide and examples
command /voice <player>:
    trigger:
        if voice connected arg.1:
            if voice group of arg.1 is set:
                send "&7%arg.1% is in the group &f%voice group of arg.1%&7."
            else:
                send "&7%arg.1% has voice chat and is in no group."
        else:
            send "&7%arg.1% does not have voice chat."
        if voice muted arg.1:
            send "&c%arg.1% is muted."

command /voicegroups:
    trigger:
        for each {_group} in voice groups:
            send "&e%{_group}%&7: " + join players in voice group {_group} with ", "
SyntaxResult
voice connected <who>Whether they have the mod and are connected to the voice chat
voice group of <who>The name of the group they are in; unset if none
voice groupsA list of the names of every group
players in voice group <name>A list of the names of the online players in that group
voice muted <who>Whether a script has muted them

Muting HyperVoice

Guide and examples
command /voicemute <player>:
    permission: "staff.mute"
    trigger:
        mute voice of arg.1
        send "&c%arg.1% can no longer be heard."

command /voiceunmute <player>:
    permission: "staff.mute"
    trigger:
        unmute voice of arg.1

on region enter:
    if "%event.region%" is "library":
        mute voice of player
        send "&7Quiet, please: you are muted in the library."

on region leave:
    if "%event.region%" is "library":
        unmute voice of player
SyntaxEffect
mute voice of <who>Nobody hears them any more, near them or in their group
unmute voice of <who>They are heard again
  • A mute holds until unmute voice, or until the server restarts. To keep one across restarts, save it in a variable and mute again in on voice connect:.
  • The player is not told by the mod that they are muted; say so in a message.

Hearing nothing, and how far a voice carries HyperVoice

Guide and examples
command /deafen <target:player>:
    permission: "voice.staff"
    trigger:
        if voice deafened arg.1:
            undeafen arg.1
            send "&a%arg.1% hears the others again."
        else:
            deafen arg.1
            send "&e%arg.1% no longer hears anybody."

command /shout:
    permission: "voice.shout"
    trigger:
        set voice distance of player to 96
        send "&6Your voice now carries 96 blocks, for a minute."
        wait 1 minute
        reset voice distance of player

command /canhear <target:player>:
    trigger:
        if voice disabled arg.1:
            send "&7%arg.1% has switched the voice chat off."
        else if voice connected arg.1:
            send "&a%arg.1% can hear you."
        else:
            send "&7%arg.1% does not have the voice chat."

command /whisper:
    trigger:
        set voice distance of player to 6
        send "&7Your voice carries &f%voice distance of player% &7blocks."
SyntaxEffect
deafen <who>That player is sent nobody's voice, until undeafen <who>. They can still speak
undeafen <who>They hear the others again
voice disabled <who>True if a player has the voice chat installed but switched off in their own game: they hear nothing and cannot speak, by their own choice
voice deafened <who>True while a player is deafened this way
set voice distance of <who> to <n>How many blocks that player's voice carries: less than the server's own distance, or more, up to 512
reset voice distance of <who>Their voice carries as far as everybody's again
voice distance of <who>How far their voice carries, in blocks: what was set, or the server's own distance
  • Both hold until the server stops, or until they are taken back; they are not kept across a restart.
  • A distance is for talking to those nearby. In a voice group it changes nothing: a group hears its members wherever they are.
  • A voice that carries further reaches the players the voice chat would have left out, with the sound still coming from where the speaker stands. A whisper is never carried further.

Events HyperVoice

Guide and examples
on voice connect:
    if {%player%.voicebanned} is true:
        mute voice of player

on voice disconnect:
    log "%player.name% left the voice chat"

on voice group join "Staff":
    send "&cStaff channel: keep it professional."

on voice group leave "Staff":
    send "&7You left the staff channel."

on voice group leave:
    log "%player.name% left the voice group %{_group}%"
SyntaxEffect
on voice connect:Runs when a player's voice chat connects, a moment after they join
on voice disconnect:Runs when it disconnects
on voice group join "<name>":Runs when a player joins that group, by a script or by themselves. Without a name: any group
on voice group leave "<name>":Runs when they leave it
  • Inside the blocks player is the player, and in the two group events {_group} is the group's name.

HyperVotes

An addon: a separate plugin whose words work once it is installed.

When somebody votes HyperVotes

Guide and examples
on vote:
    give 3 diamond to player
    add 50 to {%player%.coins}
    if {_late} is true:
        send "&7Thanks for voting while you were away!"
    else:
        broadcast "&a%player.name% &7voted on &f%{_service}%&7."

on vote "PlanetMinecraft":
    give 1 emerald to player

on offline vote:
    broadcast "&a%{_voter}% &7voted while offline. Vote too with &f/vote&7!"

on vote party:
    broadcast "&d&lVote party! &7%{_votes}% votes reached."
    loop all players:
        give 5 diamond to loop-player
SyntaxEffect
on vote:Runs when a player who is online votes, and for a kept vote when its player joins. player is the voter
on vote "<site>":The same for votes from one voting site only, by the name the site gives itself
on offline vote:Runs at once when a vote comes for someone who is not online. There is no player; {_voter} is the name
on vote reminder:Runs every remind-every minutes for each player who is on the server and has not voted yet today. player is who is reminded; {_votes} and {_streak} are theirs
on vote party:Runs every party-every votes. There is no player
  • Inside the blocks: {_voter} is the voter's name, {_service} the voting site, {_votes} how often they have voted, {_streak} their streak in days, and {_late} is true for a vote that waited for its player.
  • A reward belongs in on vote:. With keep-offline-votes on, every vote reaches it exactly once: at once, or when the player next joins.
  • A voting site sends the name the player typed. A vote for a name nobody has is counted under that name and waits for a player who never comes.

Counting votes HyperVotes

Guide and examples
command /votes:
    players only: true
    trigger:
        send "&7You have voted &f%votes of player% &7times, &f%vote streak of player% &7days in a row."
        if last vote of player is set:
            send "&7Your last vote was " + last vote of player formatted as "d MMMM, HH:mm"
        if votes until party > 0:
            send "&d%votes until party% &7more votes until the next party."

command /votetop:
    trigger:
        send "&6Top voters &7(%total votes% votes in all)"
        set {_place} to 0
        for each {_name} in top voters:
            add 1 to {_place}
            if {_place} > 10:
                stop
            send "&e%{_place}%. &f%{_name}% &7- %votes of {_name}%"
SyntaxResult
votes of <who>How often they have voted; works for someone offline
votes today of <who>How many times they have voted today, by the server's calendar; 0 for somebody who has not yet
vote streak of <who>How many days in a row they have voted. A day without a vote brings it back to 0
last vote of <who>When they last voted, as a date; unset if never
total votesEvery vote the server has counted
top votersA list of names, the most votes first, at most 100
votes until partyHow many votes are missing until the next party; 0 when parties are off

Testing and resetting HyperVotes

Guide and examples
command /testvote:
    permission: "votes.admin"
    players only: true
    trigger:
        add test vote for player from "TestSite"

command /resetvotes <player>:
    permission: "votes.admin"
    trigger:
        reset votes of arg.1
        send "&aThe votes of %arg.1% were reset."

command /newvoteseason:
    permission: "votes.admin"
    trigger:
        reset all votes
        broadcast "&eA new voting season has begun."
SyntaxEffect
add test vote for <who>A vote that did not come from a site, counted and rewarded like a real one. For trying a script out
add test vote for <who> from <site>The same, as if from that site
reset votes of <who>Forget one player's votes and streak
reset all votesForget everybody's, for a new season

This month, and round numbers HyperVotes

Guide and examples
on vote milestone 50:
    broadcast "&d%{_voter}% &7has voted &f50 &7times. Thank you!"
    give 1 diamond block to player

on vote milestone 100:
    execute console command "lp user %{_voter}% parent add supporter"

on vote streak 7:
    broadcast "&d%{_voter}% &7has voted seven days in a row!"

command /setvotes <target> <votes:number>:
    permission: "votes.admin"
    trigger:
        set votes of arg.1 to arg.2
        send "&a%arg.1% now has %arg.2% votes."

command /votemonth:
    trigger:
        set {_mine} to votes this month of player
        send "&7You have voted &f%{_mine}% &7times this month."
        set {_place} to 0
        for each {_name} in top voters this month:
            add 1 to {_place}
            if {_place} <= 5:
                send "&e#%{_place}% &f%{_name}% &7- %votes this month of {_name}%"
SyntaxEffect
on vote milestone <n>:Runs the one time a player's own votes get to that number: on vote milestone 50:. It needs a number. player is the voter if they are on the server; {_voter}, {_service}, {_votes} and {_streak} are as in on vote:
on vote streak <n>:Runs the one time a player's streak gets to that many days in a row: on vote streak 7:. The values are those of on vote:
set votes of <who> to <n>Make a player's votes that number, for carrying votes over from another plugin or putting a mistake right. Their streak stays as it is, and no event runs
votes this month of <who>How many times somebody has voted in this calendar month; 0 if not at all
top voters this monthThe names of those with the most votes this month, best first, up to 100
  • A milestone is reached when the vote comes in, also for a player who is not on the server then; there is no player in the block in that case, so reward them by name, or in on vote: when they are back.
  • Months are counted from this version on: votes that came in with an older version count for the total and the streak, but not for the month they were in.

More examples HyperVotes

Guide and examples
command /votedtoday:
    trigger:
        set {_today} to votes today of player
        if {_today} is 0:
            send "&eYou have not voted today."
        else:
            send "&aVotes today: &f%{_today}%"