← All of the Docs The basics
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%"