Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

ParticleTasks

ByteZ edited this page Jun 5, 2021 · 11 revisions

! This is not implemented in the current version (1.5.1) !

It will be added with the next update (1.17)


Quick Explanation With Example

ParticleTasks are the most efficient and elegant way to repeatingly display particles. As an example, let's look at a very inefficient method which even lags the server when used excessively:

public void displayCube(World world, Vector start, Vector end) {
  for (int x = start.getBlockX(); x <= end.getBlockX(); ++x) {
    for (int y = start.getBlockY(); y <= end.getBlockY(); ++y) {
      for (int z = start.getBlockZ(); z <= end.getBlockZ(); ++z) {
        new ParticleBuilder(ParticleEffect.FLAME, new Location(world, x, y, z)).display();
      }
    }
  }
}

To progressively display this cube, this method has to be called every few ticks. This will lead to high CPU time and lag because the packets are rebuilt for every run. Also, the PlayerConnection has to be retrieved for every particle which also causes delay (Even with the ConnectionCache).

Instead of the above code, we can start a new GlobalTask. A GlobalTask is a repeating task that sends the given particles to every player.

public void startCubeTask(World world, Vector start, Vector end) {
  List<Object> packets = new ArrayList<>();
  ParticleBuilder particle = new ParticleBuilder(ParticleEffect.FLAME);
  for (int x = start.getBlockX(); x <= end.getBlockX(); ++x) {
    for (int y = start.getBlockY(); y <= end.getBlockY(); ++y) {
      for (int z = start.getBlockZ(); z <= end.getBlockZ(); ++z) {
        packets.add(particle.setLocation(new Location(world, x, y, z)).toPacket());
      }
    }
  }
  ParticleTask task = new GlobalTask(packets, 5); // Create a new GlobalTask with a tick delay of 5
  return TaskManager.getTaskManager().startTask(task); // Start the new task and return the id
}

This method will start a new ParticleTask that displays a cube of flame particles every 5 ticks. The return value is the id of the task, which can be used to cancel the timer at any time (see TaskManager#stopTask).

Currently built-in ParticleTask implementations

Class name Short explanation
GlobalTask Displays the particle to every player that is currently online.
TargetedTask Displays the particle to the provided list of players.
SingularTask Only displays the particles to one specific player.
FilteredTask Only displays the particles to players that match the given filter.
SuppliedTask Uses a Supplier to evaluate which players should see particles.

If you have any suggestions for more task implementations, please open an issue with a detailed explanation.

GlobalTask

A GlobalTask is the simplest implementation of the ParticleTask class. It displays the particles to every player that is currently online. The constructor only needs the packets and the tick delay.

TargetedTask

TargetedTasks are tasks that only target a predefined list of players. Please note that this implementation currently saves a collection of players, not UUIDS! So if a player rejoins, he won't be able to see the particles. However, because of the JVMs reference implementation, this can be used to directly link to the reference of an object.

SingularTask

A SingularTask only sends the particles to one specific player. But unlike TargetedTasks, the UUID of the player is saved instead of the player object. Because of this, the targeted player will still see the particle, even after rejoining.

FilteredTask

A FilteredTask applies a given Filter to all online players and only displays the particle to matches.

As an example, let's create a task that only sends the particles to server operators every 10 ticks: Lambda:

ParticleTask task = new FilteredTask(packets, 10, player -> player.isOp());

or by using a method reference:

ParticleTask task = new FilteredTask(packets, 10, Player::isOp);

SuppliedTask

SuppliedTasks use a Supplier to retrieve the list of targeted players. The supplier is called every time the task is called.

e.g. with a TeamManager that has getters for each team.

ParticleTask task = new SuppliedTask(packets, 5, () -> teamManager.getRedPlayers());
Clone this wiki locally