Misc. Features & Guides - Membercat-Studios/Streamlabs-Integration GitHub Wiki

This page will go over some smaller but still important features that don't fit within any of the other pages.

Named Collections

A named collection is a collection of specific elements within the game that have an associated name and (in most cases), an associated ID. Named collections can be used in a few places through the plugin (e.g. the random_element and extract queries) to interact with certain game features.

The following types of collections are currently supported:

  • PLAYER: A collection of every online player on the server, with the ID being the player's name
  • ENTITY_TYPE: Every available entity type in the game (includes entities like boats and item frames)
  • LIVING_ENTITY_TYPE: Every available living entity type in the game (only includes living entities/mobs like pigs and zombies)
  • ENCHANTMENT: Every enchantment available in the game, this might work with some custom enchantment plugins (most likely paper plugins), depending on how they register their enchantments
  • ITEM: Every item available in the game
  • BLOCK: Every block in the game (includes blocks like air)
  • NON_AIR_BLOCK: Every block in the game that isn't any kind of air
  • BIOME: Every biome available in the game
  • STRUCTURE: Every structure available in the game

Most queries using named collections will return the ID of the selected collection item. For all collections except PLAYER, this will be their corresponding minecraft ID, meaning the output of those queries can directly be used in a related command. If a query requires the name of a named collection, most collections will use the English translation of the item in question.

When to use server_thread

server_thread is a property on certain logic steps (such as repeat) that allows control over where the step is executed.

Note

This section gets quite technical and detailed. Feel free to continue reading if you're interested on how exactly it works, but it essentially comes down to this:

server_thread will execute the entire loop in one server tick, which makes it run way faster, but using things like delay steps or command queries (not command steps) can freeze the entire server when used inside of that step!

Normally, all actions executed by streamlabs integration will be ran in a separate thread from the main server thread. You can imagine a separate thread as if the code was running at the same time as any other thread (this is technically not always the case, depending on the hardware, operating system and other running threads and processes). This means that, if an action takes a while to execute (e.g. if it uses a lot of delay steps), the entire server won't freeze until it's done.

While this behavior is usually good, it can cause a few issues when trying to execute a lot of steps quickly after each other. Bukkit, and by that extend Paper requires everything that interacts with the server in some way to run on the main thread (the thread the server is running on). Now, since all of our actions are running on a separate thread, every time the plugin has to interact with the server (e.g. by executing a command), it has to "return" to the main thread to do so. Seems fine, right? But we have a small problem: How do you "return" to a thread that is constantly looping?

The server thread will always be stuck in kind of an infinite loop, since it has to constantly tick the server at 20 ticks per second. Now say we want to execute some code on the server thread, we can't just "interrupt" the thread at any point, since we could be executing our commands at completely the wrong time. Luckily, Bukkit provides something called a scheduler for this exact use case. The scheduler will let us schedule events for execution in the next server tick, meaning at some (fixed) point while ticking the server, the scheduler will execute all scheduled events.

This is great, but now we run into a small issue due to how steps like command are executed. For every command step, the plugin will schedule the command execution on the server thread, wait for it to complete, and then execute the next step. This behavior is in place to ensure other logic doesn't start running on the separate thread while the command is not even executed yet. Now, let's imagine a scenario like this, where we want to instantly spawn 20 zombies on the player:

- repeat:
    - command: "execute at {player} run summon zombie"
  amount: 20

Can you see the problem here? Instead of spawning all of them at the same time, the plugin will wait about one tick until spawning the next zombie. Since we're waiting for the command to complete to continue execution, most of the time, we're also waiting for the current tick to finish, since the scheduler will only run on the next tick.

Obviously we don't want our loops to be that slow, but how can we prevent this from happening? We could just run every loop on the server thread directly, so we don't have to schedule a task for every single step inside of it. But this will cause other issues, since now, every delay step inside that loop will freeze the entire server until it's complete. This is where the server_thread property comes in place. It allows you to specify whether a loop should run entirely on the server thread (which is disabled by default).

Knowing all of this, here are some things to keep in mind when using server_thread:

  • Never use any step that will wait for something unrelated to the server thread, it will result in the server freezing for that time
  • Certain queries (like the command query) can freeze the server thread indefinitely in some cases, since they'll wait for the command to return an output. The command step in normal mode will only wait for the command to dispatch, rather than waiting for execution to complete. The command query will wait for an output from the command, which will never happen, since the query itself is preventing the command from running fully by waiting for an output on the main thread. (The query does have a timeout, but setting it too high will result in the server freezing)
  • server_thread should only really be used for cases like trying to instantly spawn 20 zombies, and it's usage should be tested properly, especially when running it on a public server!

Tip

If you want to run parts of your configuration that don't use loops on the server thread, simply wrap them within a repeat step with amount set to 1 and server_thread enabled!

Actions in detail

Actions have some additional properties that haven't been covered on other pages, which we'll go over now.

actions:
  my_action:
    enabled: <true/false> # true if left out
    instancing_behavior: <CANCEL_PREVIOUS/RUN_IN_PARALLEL> # Optional, CANCEL_PREVIOUS by default
    stop_on_failure: <true/false> # Optional, false by default
    ...
  • enabled: If disabled, the action won't be ran at all.
  • instancing_behavior: Determines how the action behaves when triggered again while a previous instance of the same action is still running. CANCEL_PREVIOUS will stop the previous instance, and RUN_IN_PARALLEL will start another instance and run both of them at the same time.
  • stop_on_failure: If a step fails because of an error, the entire action will be canceled. Note that this only applies to actual errors, not things like being unable to parse the amount of a repeat step.
⚠️ **GitHub.com Fallback** ⚠️