github SkriptLang/Skript 2.17.0-pre1
Pre-Release 2.17.0-pre1

pre-release4 hours ago

Skript 2.17.0-pre1

Supports: Paper 1.21.5 - 26.3

Today, we're excited to be releasing Skript 2.17.0-pre1! While this release may seem small, includes a handful of exciting changes that address some gaps in Skript's content coverage. From sign-side support to a full-blown command overhaul, there is still a lot to check out! This release also includes support for Minecraft 26.3.

In accordance with supporting the last 18 months of Minecraft updates, Skript 2.17.0 supports Minecraft 1.21.5 to 26.3. Newer versions may also work but were not tested at time of release. Paper is required.

Below, you can familiarize yourself with the changes. Additionally, by clicking here, you can view the list of new syntax on our documentation site. As always, but especially with this release, please report any issues or unexpected behavior to our issues page!

Per our release model, we plan to release 2.17.0 on October 15th. We may release additional pre-releases before then should the need arise.

Happy Skripting!

Release Highlights

Command Overhaul

Our biggest feature for this release is a complete overhaul of Skript's existing system for creating custom commands. Most importantly, we expect that nearly all existing commands will continue to work. Custom commands now make use of Brigadier, Minecraft's command processing system, enabling scripters to create vanilla-like commands. This comes with numerous new features which we will briefly cover below.

Expanded executable by Entry

The executable by entry now supports two new types: operators and blocks (e.g., command blocks). As with permissions, players not covered under the executable by entry of a command will no longer be aware of that command.

Improved Arguments

Many supported argument types are now able to make use of their vanilla equivalents, which enables real-time validation. For example, <player> and <entity> arguments now support selectors. <integer> and <number> arguments can now be ranged: <integer between 5 and 10>.

Important

By default, real-time command validation will not function.
This is a trade-off to preserve compatibility with the suggestion (tab completion) features offered by some addons.
You can disable this legacy compatibility feature, thus enabling real-time validation, by changing the enable legacy tab completion event compatibility configuration option to false.

Choice Arguments

Command arguments provided as choices can now be identified. For example, consider the following command:

command /alert (restart|giveaway):

It can be useful to restrict the possible options at the first argument position rather than accept a text argument (any input).
This behavior is still supported, and it is now also possible to determine what value was used using the new choice argument expression:

command /alert (restart|giveaway):
    trigger:
        if the choice argument is "restart":
            broadcast "<red>The server is restarting in 5 minutes!"
        else: # must be giveaway
            broadcast "<aqua>A giveaway is starting soon at spawn!"

Just like the regular argument expression, if multiple choices are present in the command tree, they can be differentiated by using a number: choice argument 1, choice argument 2, etc.

Subcommands

It is now possible to build entire command trees using subcommand entries:

command /home:
    subcommand set <name: text>:
        trigger:
            set {homes::%player%::%{_name}%} to the player's location
    subcommand <name: text>:
        trigger:
            teleport the player to {homes::%player%::%{_name}%}

This allows executing /home set main base and /home main base - no need for two text arguments!

Subcommands allow many of the entries currently supported by commands, such as permission, executable by, and cooldown.

At each level, up to one subcommand may be optional, assuming a trigger entry is not present. This allows treating one option as the default option, reducing code duplication. For example:

command /command:
    subcommand [help]:
        trigger:
            send "Help Information"

In this case, /command behaves the exact same as executing /command help.

It is also possible to use a subcommands entry to bulk define permissions, cooldowns, and other restrictions for a group of subcommands. For example:

command /command:
  subcommands:
    permission: command.admin
    subcommand "admin1":
      trigger:
        send "Admin 1"
    subcommand "admin2":
      trigger:
        send "Admin 2"
  subcommand [help]:
    trigger:
      send "Help Information"

Custom Suggestions

You can now also define custom suggestions (tab completions). For example, expanding the home command example from above:

command /home:
    subcommand set <name: text>:
        trigger:
            set {homes::%player%::%{_name}%} to the player's location
    subcommand <name: text>:
        suggestions:
            set the suggestions for the text argument to the indices of {homes::%player%::*}
        trigger:
            teleport the player to {homes::%player%::%{_name}%}

By default, Skript will automatically filter down the suggestions based on the current input. The default mode is a starts with mode, meaning if a player has two homes, base and temple, and they are typing /home b, only base will be shown. This can be customized using the filtering mode effect:

use starts with filtering for the text argument # default behavior
use contains filtering for the text argument # matches any suggestion that contains the current input
disable filtering for the text argument # always shows all suggestions

Further, suggestions support hover messages (text that appears when you hover/mouse over the suggestion). This is supported through text components. Consider amending the home example from above to show the location of the home as a hover message:

command /home2:
	subcommand set <name: text>:
		trigger:
			set {homes::%player%::%{_name}%} to the player's location
	subcommand <name: text>:
		suggestions:
			loop {homes::%player%::*}:
				add "<ttp:'Location: %loop-value%'>%loop-index%" to the suggestions for the text argument
		trigger:
			teleport the player to {homes::%player%::%{_name}%}

Another important thing to note is that it is possible to obtain the values of arguments that have already been finished. For example, consider a message command that uses custom suggestions to give real time feedback:

command /message <player> <text>:
    suggestions:
        player argument is set # they are writing the text argument
        if the current input contains "frick":
            set the text argument's suggestions to "Keep your messages nice please!"
            disable filtering for the text argument's suggestions
    trigger:
        send "<grey><italic>%player% -> You: %text argument%" to player argument
        send "<grey><italic>You -> %player argument%: %text argument%" to player

Failures and Return Values

Commands can now report explicit failures and return an integer value.
These are the success and result values of the command execution, respectively. This is mainly useful for commands like /execute that can function off of these values.

Here's an example of both in action:

command /filter-number <number>:
    trigger:
        if the argument is 67:
            fail the command execution with the error "Forbidden Input: %argument%"
        return the argument

Changeable Conditions

Many of the existing conditions have associated effects for changing the value. This approach was chosen because expressions returning booleans often require odd syntax and checks (e.g., player's flight mode is true). However, there is still value in boolean expressions: changing their value dynamically in a single line. We are introducing a new approach to address this problem: changeable conditions. Most conditions now support being changed through the whether expression.

For example:

set whether the last spawned piglin is dancing to true

# also supports the toggle effect
toggle whether the player can fly

Sign Sides

At long last, Skript now has proper support for sign sides! All existing sign syntax will continue to work. By default, the front side of a sign is used.

set the 1st line of the back side of {_sign} to "The back side can now be changed!"

Additionally, all lines of a sign can now be obtained:

on sign change:
    any of the lines contain "bad word"
    cancel the event
    send "<red>You may not write profanity on signs!" to the player

Finally, it is also possible to check what side of a sign was changed in a 'sign change' event. For example, if you wanted to restrict back side editing:

on sign change:
  the back side was changed
  cancel the event
  send "<red>It is not possible to change the back side of a sign!" to the player

Improved Warning Suppression

We have made some changes to improve the warning suppression experience.

First, it is now possible to unsuppress warnings. Consider the following example:

suppress starting with expression warnings
set {%the script%::info} to ...
unsuppress starting with expression warnings

Now, the constant condition warning will only be suppressed for the true is true statement.

Further, it is also now possible to suppress warnings generated by code within a section:

suppress starting with expression warnings:
  set {%the script%::info} to ...

Please note that these sections make no changes to the flow of code. The code after the section will not execute until the code within the section runs.

Text Formatting Tweaks

We have relaxed the requirements around the usage of formatted for processing more advanced tags. Now, formatted is no longer required for literal strings (i.e., those without any expressions), and all tags will be processed.

To provide an example:

# before 2.17
send formatted "<click:run_command:/seed>Click</click> to show the world seed!" to the player

# after 2.17
# since this string contains no expressions, 'formatted' is not needed!
send "<click:run_command:/seed>Click</click> to show the world seed!" to the player

⚠ Breaking Changes

The following breaking changes are related to commands:

  • Given the differences between the two systems, it was not possible to fully retain all existing features of Skript's existing command system. However, we expect that nearly all commands should work without issue in this version. If an existing feature is not mentioned below, we are expecting it to function as it currently does. If you find that something not listed below is not working as expected, please let us know! We of course welcome any concern about the changes listed below.
  • The permission message command entry has been deprecated and no longer has functionality. If a player does not have permission to execute a command, their client will no longer be aware of it, meaning they will instead receive an "unknown command" error - the same message that players who attempt to execute regular vanilla commands without permission receive. If you wish to retain a permission message, simply manually check the permission and send an error message at the start of command execution.
  • There are new restrictions on how a command can be defined. It is no longer possible to place literal content next to an argument. For example, the following is no longer valid (a space would be needed between to and <number>):
command /test hello to<number>:
  • Some plural arguments will now need quoted. Consider the following command:
command /plural <numbers> <player>:
  • It is no longer possible to execute this command like /plural 5 and 10 APickledWalrus. It must be wrapped in quotes: /plural "5 and 10" APickledWalrus. Of course, it is still possible to pass a single argument as normal: /plural 5 APickledWalrus. The quotes are only needed as the argument contains whitespace.
  • The last usage date expression has been removed. It was not properly implemented, and the configuration option to have it work somewhat well was only enabled by one server. If this behavior is necessary, it can be easily implemented using native syntax and variables.
  • The the executor expression, which previously was synonymous with the sender, now has a different functionality. It now returns the executor of a command, which is not necessarily the same as the sender. While the sender and executor are typically the same, it is possible to change them. For example, if using the /execute command, it is possible to change the executor: /execute as <player>. Consider this command for how this might work:
command /balance:
    # This works if you do "/execute as <player> run balance"
    # It will send the output to the command sender, but it will be as if "<player>" was the thing executing it.
    send "Your balance is %{balance::%uuid of the executor%}%" to the sender
  • The event-strings event value in a command execution now has different behavior. Rather than returning the result of splitting the raw input at every whitespace character, it now returns a string representation of every available argument.
  • The configuration option keep command last usage dates has been removed.
  • This value can be determined by using the available cooldown expressions. For example, the elapsed time of the cooldown before now.
  • The configuration option case-insensitive commands has been removed. The client will treat improperly typed commands as unknown.

The following changes are related to Skript's API:

  • Due to internal changes to EntityData, any field access (i.e., via reflection) will now fail due to class migrations.

Changelog

Additions

  • #8050 Adds support for loading/reloading scripts from symlinked directories.
  • #8050 Adds a new /skript recover subcommand that dumps all loaded scripts back into files.
  • #8050 Adds a new /skript reload last reload option for reloading the last reloaded script.
  • #8707 Adds support for changing most existing conditions through the whether expression.
  • #8745 Completely overhauls Skript's existing command system. See above for more information.
  • #8745 Adds support for the unknown command event, including the ability to change the unknown command message.
  • #8779 Adds an expression for obtaining and changing the item model of an item.
  • #8809 Adds support for obtaining the x and z coordinates of a chunk.
  • #8811 Adds support for sign sides. It is now possible to explicitly specify changing the front or back side in sign-related syntaxes. By default, the front side is used. It is also now possible to obtain all lines of a sign.
  • #8832 Overhauls warning suppression. It is now possible to unsuppress warnings. It is also possible to suppress warnings within a section. See the section 'Improved Warning Suppression' from the release highlights.
  • #8883 Adds an expression for obtaining and changing the rarity of an item.
  • #8884 Adds support for Minecraft 26.3.
  • #8884 Adds support for spawning colored shulkers (e.g., spawn a red shulker).

Changes

  • #8410 Overhauled internal handling of entity data.
  • #8882 Relaxes requirements around the usage of formatted for processing more advanced tags. Now, when advanced tags are used in literal strings (i.e., the string has no expressions), all formatting is processed.

Bug Fixes

  • #8050 Fixes an issue where reported a missing language entry skript command.help.show.
  • #8050 Improves the script suggestion behavior in the skript command.
  • #8050 Fixes an error where the Skript prefix was missing in some errors.
  • #8875 Fixes an issue where some scripts could be lost when loading through parallel loading.
  • #8876 Fixes an issue where script loader threads were not removed after being shutdown when changing the thread count.
  • #8878 Fixes an error where using a function without a return type as an expression could cause an error.

API Changes

  • #8755 Adds an alternative Patterns constructor to simplify usage.
  • #8759 Deprecates multiple RegistryClassInfo constructors in favor of one that accepts a RegistryKey. For setting the default expression, it is now permitted to simply call .defaultExpression after ClassInfo creation.
  • #8830 Converts the ExperimentRegistry into a modern registry accessible through a modern addon instance. Experiment registration now also supports modern addon instances.
  • #8831 Some registry constructors asked for a ch.njol.Skript instance as opposed to an org.skriptlang.skript.Skript instance. This has been corrected (with compatibility for existing constructors).
  • #8833 Adds support for obtaining all registries accessible through an addon instance.

Click here to view the full list of commits made since 2.16.2

Notices

Experimental Features

Experimental features can be used to enable syntax and other behavior on a per-script basis. Some of these features are new proposals that we are testing while others may have unsafe or complex elements that regular users may not need.

While we have tested the available experiments to the best of our ability, they are they are still in development. As a result, they are subject to change and may contain bugs. Experiments should be used at your own discretion.

Additionally, example scripts demonstrating usage of the available experiments can be found here.

Click to reveal the experiments available in this release

Queue

Enable by adding using queues to your script.

A collection that removes elements whenever they are requested.

This is useful for processing tasks or keeping track of things that need to happen only once.

set {queue} to a new queue of "hello" and "world"

broadcast the first element of {queue}
# "hello" is now removed

broadcast the first element of {queue}
# "world" is now removed

# queue is empty
set {queue} to a new queue of all players

set {player 1} to a random element out of {queue} 
set {player 2} to a random element out of {queue}
# players 1 and 2 are guaranteed to be distinct

Queues can be looped over like a regular list.

Script Reflection

Enable by adding using script reflection to your script.

This feature includes:

  • The ability to reference a script in code.
  • Finding and running functions by name.
  • Reading configuration files and values.

Local Variable Type Hints

Enable by adding using type hints to your script.

Local variable type hints enable Skript to understand what kind of values your local variables will hold at parse time. Consider the following example:

set {_a} to 5
set {_b} to "some string"
... do stuff ...
set {_c} to {_a} in lowercase # oops i used the wrong variable

Previously, the code above would parse without issue. However, Skript now understands that when it is used, {_a} could only be a number (and not a text). Thus, the code above would now error with a message about mismatched types.

Please note that this feature is currently only supported by simple local variables. A simple local variable is one whose name does not contain any expressions:

{_var} # can use type hints
{_var::%player's name%} # can't use type hints

Runtime Error Catching

Enable by adding using error catching to your script.

A new catch [run[ ]time] error[s] section allows you to catch and suppress runtime errors within it and access them later with [the] last caught [run[ ]time] errors.

catch runtime errors:
    ...
    set worldborder center of {_border} to {_my unsafe location}
    ...
if last caught runtime errors contains "Your location can't have a NaN value as one of its components":
    set worldborder center of {_border} to location(0, 0, 0)

Equippable Components

Enable by adding using equippable components to your script.

Equippable components allows retrieving and changing the data of an item in the usage as equipment/armor.

Below is an example of creating a blank equippable component, modifying it, and applying it to an item:

set {_component} to a blank equippable component:
	set the camera overlay to "custom_overlay"
	set the allowed entities to a zombie and a skeleton
	set the equip sound to "block.note_block.pling"
	set the equipped model id to "custom_model"
	set the shear sound to "ui.toast.in"
	set the equipment slot to chest slot
	allow event-equippable component to be damage when hurt
	allow event-equippable component to be dispensed
	allow event-equippable component to be equipped onto entities
	allow event-equippable component to be sheared off
	allow event-equippable component to swap equipment
set the equippable component of {_item} to {_component}

Changes can be made directly on to the existing equippable component of an item whether using the item itself or the retrieved equippable component

set the equipment slot of {_item} to helmet slot
    
set {_component} to the equippable component of {_item}
allow {_component} to swap equipment

For more details about the syntax, visit equippable component on our documentation website.

Help Us Test

We have an official Discord community for beta testing Skript's new features and releases.

Thank You

Special thanks to the contributors whose work was included in this version:

As always, if you encounter any issues or have some minor suggestions, please report them at https://github.com/SkriptLang/Skript/issues.
If you have any bigger ideas or input for the future of Skript, you can share those too at https://github.com/SkriptLang/Skript/discussions.

Don't miss a new Skript release

NewReleases is sending notifications on new releases.