Your First World Script ----------------------- ```eval_rst .. contents:: Table of Contents :local: ``` ### It Runs On Its Own! So, you've learned [how to use '/ex' to run a single Denizen command](/guides/first-steps/ex-command) and [how to make a 'task' script to run a series of commands together](/guides/first-steps/task-script). Those are pretty useful tools, but they require you sit there and type commands in to make it happen. Isn't the point of a script engine supposed to be that it automatically triggers when needed, to make custom stuff on your server? It would be ridiculous to just sit on a server typing `/ex` commands whenever a player needs something! ### Introducing: The World Script Let's take a look at the primary way we make automatically triggered scripts: `world` script containers! A world script contains `events`. An event is basically: a thing that happens in the world. For example, when a player breaks a block, there's an event for that. Most events are named pretty clearly and simply - for example, the previously mentioned event would be `player breaks block`. Note that all events start with either the word `on` or `after`, and what follows is usually English phrasing of the event based on that. Some more examples of event names: `on player places block`, `after entity dies`, `on creeper powered`, `after lightning strikes`, ... (the distinction between `on` and `after` is explained farther down this page). ### Let's See A Real World Script! ```dscript_green my_world_script: type: world events: after player breaks block: - narrate "Whoa , you broke a block!" ``` Go ahead and put that into a script file, use `/ex reload` to load it in, then break any block. You'll see the message appear in chat when you do so. ![](images/brokeablock.png) Some things to note in this example: - The `type` for these scripts is now `world`. - Instead of `script:` from before, we now have `events:`, which contains within it the actual event name. - The event itself (`after player breaks block`) is indented another 4 spaces past where `events:` is, which makes the event part of the `events` block rather than part of the script's base level keys. - The player that broke the block is automatically the contextually linked player. So, the narrate shows to that player, and `` will be that players name. An event will run every time the thing happens in the world. Every single time any player breaks any block, that script will run. If 5 players all break a block at the same time, that script will run 5 times - once for each player, each time linking to the specific player that broke the block that the script is reacting to. If one player gets an efficiency 5 shovel and destroys 10 dirt blocks in under a second... yep, the event will run 10 times, with that one player linked each time. ### Okay, But What Block Did They Break? So, you know that they broke a block when that script runs, but you're of course wondering how you know what type of block was broken (after all, breaking a block of dirt and breaking a block of diamond ore probably shouldn't be handled the exact same way). There are two ways of doing this. #### Context Tags The first way to know what type of block was broken is `context` tags. Context tags are tags that, as the name implies, give the details about the context of when/where/why a script is running. In an event, context tags contain everything you need to know about the event that happened. `` is available in the `on player breaks block` event as a way to get a material. This returns a MaterialTag, and the tag `` gets the name of a material, so let's stick these tags together to form ``. Try putting that tag into the narrate line, like `- narrate "Whoa , you broke a !"`, and then reloading and breaking a few blocks. You should see the name of each block type you broke, as you break them. ![](images/brokeastone.png) Note that context tags are always base tags, and are never sub-tags (though, of course, you can tack a sub-tag onto the end of a context tag whenever needed). Note also that context tags, naturally, only exist within their relevant context. The `on entity dies` event doesn't have ``, as that's not part of that event. Similarly, a task script or an `/ex` command won't have any contexts at all, as they're not part of any event. #### More Specific Event Lines Event names allow extra specification to be added, as either an input filling or an event switch. The breaks block event is documented as: `player breaks block` or `player breaks `. The second version here gives us a `` input option. In this context, the `<>` means "fill in your specific value here". So, try changing your script's event line to be `after player breaks stone:`, then reload and try breaking a few different block types, including stone. You will see that the narrate only happens when you break stone. If you break dirt or anything else, nothing will happen. Event switches are additional options on an event aside from just the basic name input. The breaks block event has a few switches available, including one documented as `with: to only process the event when the player is breaking the block with a specified item`. To put this to use, you can do, for example: `after player breaks stone with:diamond_pickaxe:` to make the script only run when the player specifically uses a diamond pickaxe while breaking the stone - if you try it with an iron pickaxe or anything else instead, the script simply won't run. #### Event Lines Are Static Note that event lines can never contain tags - they must always be valid plain text. In a [later section](/guides/basics/if-command) you will learn how to change whether the script runs based on more dynamic tag-based checks. There is, however, a bit of limited dynamicness available. For example, consider the `with:diamond_pickaxe` switch we used above. What if we want *any* pickaxe to count? We can use `with:*_pickaxe` for this. The `*` symbol means "anything here". Similarly, if we want only diamond or iron, we can use `with:diamond_pickaxe|iron_pickaxe`. The `|` symbol means "either one of these counts". You can also apply this to the input portions of an event line. For example, if you want to react to players breaking wood logs, but don't want to have a different event for each and every type of log, you can simply use `after player breaks *_log:`. ### Okay But Stop Breaking My Blocks Please So, you can make a script run when an event happens. You can also check the specific details of the event when it happens. But how do you *do anything* about the event? What, do we have to just `- narrate "*shakes fist* stop breaking my blocks!"`? Enter the `determine` command. The determine command is how you *determine the outcome* of an event. When not put to use, the event simply happens however it normally would. When you use determine, you can change anything about the event (within the reasonable limits of being an alteration to the event - if you want an unrelated change to the world to take place in response to the event, use the applicable command that produces that change). The most commonly available determination, that almost all events support, is `- determine cancelled`. This *cancels* the event - that is, the event will either not take place at all, or immediately undo itself. In the case of the `breaks block` event, this will make it so the block never breaks (players watching will see nothing happen, however, the player that attempted to break a block will see it flash broken and then pop right back in - this is a consequence of clientside prediction and is unfortunately unavoidable without a client mod). So, let's try it! After the narrate line in our test script, add the determine. If you've applied all the suggested changes thus far, your script should now look like this: ```dscript_red my_world_script: type: world events: after player breaks stone with:diamond_pickaxe: - narrate "Whoa , you broke a !" - determine cancelled ``` Wait... that didn't work. What went wrong? #### We Have Events Now And Then This is where the difference between `after` and `on` comes into play. `after` means to run the script *after* the event happens and is already done. `on` means to run the script *before* the event happens and can be changed. Effectively, when `after` is used, the event is a *past* event, and when `on` is used, the event is a *future* event. You can only use `determine` within `on`, not `after`, for a pretty simple reason: You can't change the past! So, change the `after` in our example script to `on`. ```dscript_green my_world_script: type: world events: on player breaks stone with:diamond_pickaxe: - narrate "Whoa , you broke a !" - determine cancelled ``` This script theoretically means if you break a stone with a diamond pickaxe, you will be stopped. If you break a different block, or don't use a diamond pick, things will work normally. ![](images/breakingthemstones.gif) Note that a determine command is considered by default the end of a script. if you want to use a determine command but then continue running commands in the script (for example, to apply multiple different determinations to change multiple parts of an event), you must use the `passively` argument, like `- determine passively cancelled`. #### Making A Difference In This World If you want to change an event, rather than simply cancelling it outright, most events have specific determination options available. The breaks block has the determination option `nothing` to make no items drop when the block is broken in survival mode, and the option of inputting an item or list of items to make the block instead drop those listed items when broken. As an example of how you might use this, you can use the tag `` to get an item from any material, and combined with the `` context tag available, get the resulting line: `- determine `. You now have free silk touch powers! Every block now drops its exact raw form - so if you mine a diamond ore block for example, you'll receive the diamond ore block, instead of diamonds (note that you will have to change the event line back to `block` instead of `stone`, or specify `diamond_ore` or anything like that). ### A Whole Big Bunch of Events As an additional note to be aware of: any one world script can contain several events. That might look something like this: ```dscript_green my_world_script: type: world events: after player breaks block: - narrate "Whoa , you broke a !" on player breaks stone with:diamond_pickaxe: - determine cancelled after player places stone: - narrate "Why are you putting that stone there? Better not break it with a diamond pickaxe!" ``` ### Related Technical Docs If you want to read a lot more about world events, here are a few technical guides you might consider... Note: most users, especially those learning from the Denizen for the first time, should just continue on to the next guides page. These references might be of interest to later come back to after you've learned Denizen as far as this guide teaches. - [Switches language doc](https://meta.denizenscript.com/Docs/Languages/script%20event%20switches) - [Player switches language doc](https://meta.denizenscript.com/Docs/Languages/player%20event%20switches) - [Advanced matching language doc](https://meta.denizenscript.com/Docs/Languages/advanced%20script%20event%20matching) - [Cancellation language doc](https://meta.denizenscript.com/Docs/Languages/script%20event%20cancellation) - [Special contexts language doc](https://meta.denizenscript.com/Docs/Languages/script%20event%20special%20contexts) - [After vs On language doc](https://meta.denizenscript.com/Docs/Languages/script%20event%20after%20vs%20on) - [Safety in events language doc](https://meta.denizenscript.com/Docs/Languages/safety%20in%20events) - [Priority language doc](https://meta.denizenscript.com/Docs/Languages/script%20event%20priority) - [Bukkit priority language doc](https://meta.denizenscript.com/Docs/Languages/bukkit%20event%20priority) - [World script containers doc](https://meta.denizenscript.com/Docs/Languages/world%20script%20containers) - [List of all world events](https://meta.denizenscript.com/Docs/Events/)