Skip to content
On this page

Activations

Activations allow capturing client's voice on separate hotkey.

Registering an activation

To register an activation, you need to create addon first, how to do it see Creating an addon.

Activations are dynamically synced with players, allowing you to register or unregister activations at any time. The sync also operates with permissions. Consequently, when a player loses or gains their activation permission, the activation will be removed or added to the client, respectively.

java
PlasmoVoiceServer voiceServer = /* */;
Object addon = /* */;

ServerActivation activation = voiceServer.getActivationManager().createBuilder(
    addon,
    "priority", // name
    "pv.activation.priority", // translation key
    "plasmovoice:textures/icons/microphone_priority.png", // icon resource location
    "pv.activation.priority", // permission
    10 // weight
).build();
kotlin
val voiceServer: PlasmoVoiceServer
val addon: Any

val activation = voiceServer.activationManager.createBuilder(
    addon,
    "priority", // name
    "pv.activation.priority", // translation key
    "plasmovoice:textures/icons/microphone_priority.png", // icon resource location
    "pv.activation.priority", // permission
    10 // weight
).build()

Icon

You can also use InputStream as an icon.

java
PlasmoVoiceServer voiceServer = /* */;
Object addon = /* */;

try (InputStream is = Files.newInputStream(new File("icon.png").toPath())) {
    ServerActivation activation = voiceServer.getActivationManager().createBuilder(
        addon,
        "priority", // name
        "pv.activation.priority", // translation key
        is, // icon
        "pv.activation.priority", // permission
        10 // weight
    ).build();
} catch (IOException e) {
    e.printStackTrace();
}
kotlin
val voiceServer: PlasmoVoiceServer
val addon: Any

val activation = Files.newInputStream(File("icon.png").toPath()).use { icon ->
    voiceServer.activationManager.createBuilder(
        this,
        "priority", // name
        "pv.activation.priority", // translation key
        icon, // icon
        "pv.activation.priority", // permission
        10 // weight
    ).build()
}

Weight

Activation weight is determined how high it will be in the list. Lower weight means higher place, if activations have the same weight, then they would be sorted alphabetically.

Distances

You can set a list of available distances using ServerActivation.Builder#setDistances.

An empty list indicates that the activation doesn't have player-controlled distances.

To set a dynamic range of distances, set the first element to -1:
(ImmutableList.of(-1, 64)). This will define a range from 1 to 64.

Other options

See ServerActivation.Builder for all available builder options.

Obtaining an existing activation

If you don't want to create your own activation, you can obtain an existing one:

java
PlasmoVoiceServer voiceServer = /* */;

ServerActivation activation = voiceServer.getActivationManager()
        .getActivationByName("proximity")
        .orElseThrow(() -> new IllegalStateException("Proximity activation not found"));
kotlin
val voiceServer: PlasmoVoiceServer

val activation = voiceServer.activationManager
    .getActivationByName("proximity")
    .orElseThrow { IllegalStateException("Proximity activation not found") }

Activation listeners

There are three type of listeners:

  • onPlayerActivationStart — invoked when a player starts to speak.
  • onPlayerActivation — invoked when a player is speaking.
  • onPlayerActivationEnd — invoked when a player has finished speaking.
java
ServerActivation activation = /* */;

activation.onPlayerActivationStart(player -> {
    System.out.println(player + " start speaking to activation");
});

activation.onPlayerActivation((player, packet) -> {
    System.out.println(player + " is speaking to activation");

    // you need to return "HANDLED" if activation was handled successfully.
    // this will cancel PlayerSpeakEvent
    return ServerActivation.Result.HANDLED;
});

activation.onPlayerActivationEnd((player, packet) -> {
    System.out.println(player + " has finished speaking to activation");

    // you need to return "HANDLED" if activation was handled successfully.
    // this will cancel PlayerSpeakEndEvent
    return ServerActivation.Result.HANDLED;
});
kotlin
val activation: ServerActivation = /* */;

activation.onPlayerActivationStart { player ->
    println("$player start speaking to activation")
}

activation.onPlayerActivation { player, packet ->
    println("$player is speaking to activation")

    ServerActivation.Result.HANDLED
}

activation.onPlayerActivationEnd { player, packet ->
    println("$player has finished speaking to activation")

    ServerActivation.Result.HANDLED
}

Proximity activation helper

If you want to create a simple proximity activation, you can use built-in ProximityServerActivationHelper class. This class will automatically create player sources using provided source line and send packets from activation to the created sources.

To create a proximity activation helper, you first need to register the Activation and the Source Line.

java
package com.plasmovoice.testaddon;

import su.plo.voice.api.addon.AddonInitializer;
import su.plo.voice.api.addon.InjectPlasmoVoice;
import su.plo.voice.api.addon.annotation.Addon;
import su.plo.voice.api.server.PlasmoVoiceServer;
import su.plo.voice.api.server.audio.capture.ProximityServerActivationHelper;
import su.plo.voice.api.server.audio.capture.ServerActivation;
import su.plo.voice.api.server.audio.line.ServerSourceLine;

@Addon(
        id = "pv-addon-test",
        name = "Test Addon",
        version = "1.0.0",
        authors = {"Plasmo"}
)
public final class TestAddon implements AddonInitializer {

    @InjectPlasmoVoice
    private PlasmoVoiceServer voiceServer;

    private ProximityServerActivationHelper proximityHelper;

    @Override
    public void onAddonInitialize() {
        ServerActivation activation = /* register or get activation */;
        ServerSourceLine sourceLine = /* register or get source line */;

        this.proximityHelper = new ProximityServerActivationHelper(voiceServer, activation, sourceLine);
        proximityHelper.registerListeners(this);
    }

    @Override
    public void onAddonShutdown() {
        if (proximityHelper != null) {
            proximityHelper.unregisterListeners(this);
        }
    }
}
kotlin
package com.plasmovoice.testaddon

import su.plo.voice.api.addon.AddonInitializer
import su.plo.voice.api.addon.annotation.Addon
import su.plo.voice.api.addon.injectPlasmoVoice
import su.plo.voice.api.server.PlasmoVoiceServer
import su.plo.voice.api.server.audio.capture.ProximityServerActivationHelper
import su.plo.voice.api.server.audio.capture.ServerActivation
import su.plo.voice.api.server.audio.line.ServerSourceLine

@Addon(
    id = "pv-addon-test",
    name = "Test Addon",
    version = "1.0.0",
    authors = ["Plasmo"]
)
class TestAddon : AddonInitializer {

    private val voiceServer: PlasmoVoiceServer by injectPlasmoVoice()

    private var proximityHelper: ProximityServerActivationHelper? = null

    override fun onAddonInitialize() {
        val activation: ServerActivation = /* register or get activation */
        val sourceLine: ServerSourceLine = /* register or get source line */

        proximityHelper = ProximityServerActivationHelper(voiceServer, activation, sourceLine)
            .also { it.registerListeners(this) }
    }

    override fun onAddonShutdown() {
        proximityHelper?.unregisterListeners(this)
    }
}

Controlling the distance

By default, the activation helper will use the distance provided by the player. You can override this using DistanceSupplier

java
package com.plasmovoice.testaddon;

import su.plo.voice.api.addon.AddonInitializer;
import su.plo.voice.api.addon.InjectPlasmoVoice;
import su.plo.voice.api.addon.annotation.Addon;
import su.plo.voice.api.server.PlasmoVoiceServer;
import su.plo.voice.api.server.audio.capture.ProximityServerActivationHelper;
import su.plo.voice.api.server.audio.capture.ServerActivation;
import su.plo.voice.api.server.audio.line.ServerSourceLine;
import su.plo.voice.api.server.player.VoiceServerPlayer;
import su.plo.voice.proto.packets.tcp.serverbound.PlayerAudioEndPacket;
import su.plo.voice.proto.packets.udp.serverbound.PlayerAudioPacket;

@Addon(
        id = "pv-addon-test",
        name = "Test Addon",
        version = "1.0.0",
        authors = {"Plasmo"}
)
public final class TestAddon implements AddonInitializer {

    @InjectPlasmoVoice
    private PlasmoVoiceServer voiceServer;

    private ProximityServerActivationHelper proximityHelper;

    @Override
    public void onAddonInitialize() {
        ServerActivation activation = /* register or get activation */;
        ServerSourceLine sourceLine = /* register or get source line */;

        this.proximityHelper = new ProximityServerActivationHelper(
                voiceServer,
                activation,
                sourceLine,
                new TestDistanceSupplier()
        );
        proximityHelper.registerListeners(this);
    }

    @Override
    public void onAddonShutdown() {
        if (proximityHelper != null) {
            proximityHelper.unregisterListeners(this);
        }
    }

    private static class TestDistanceSupplier implements ProximityServerActivationHelper.DistanceSupplier {

        @Override
        public short getDistance(VoiceServerPlayer player, PlayerAudioEndPacket packet) {
            return 12;
        }

        @Override
        public short getDistance(VoiceServerPlayer player, PlayerAudioPacket packet) {
            return 12;
        }
    }
}
kotlin
package com.plasmovoice.testaddon

import su.plo.voice.api.addon.AddonInitializer
import su.plo.voice.api.addon.annotation.Addon
import su.plo.voice.api.addon.injectPlasmoVoice
import su.plo.voice.api.server.PlasmoVoiceServer
import su.plo.voice.api.server.audio.capture.ProximityServerActivationHelper
import su.plo.voice.api.server.audio.capture.ProximityServerActivationHelper.DistanceSupplier
import su.plo.voice.api.server.audio.capture.ServerActivation
import su.plo.voice.api.server.audio.line.ServerSourceLine
import su.plo.voice.api.server.player.VoiceServerPlayer
import su.plo.voice.proto.packets.tcp.serverbound.PlayerAudioEndPacket
import su.plo.voice.proto.packets.udp.serverbound.PlayerAudioPacket

@Addon(
    id = "pv-addon-test",
    name = "Test Addon",
    version = "1.0.0",
    authors = ["Plasmo"]
)
class TestAddon : AddonInitializer {

    private val voiceServer: PlasmoVoiceServer by injectPlasmoVoice()

    private var proximityHelper: ProximityServerActivationHelper? = null

    override fun onAddonInitialize() {
        val activation: ServerActivation /* register or get activation */
        val sourceLine: ServerSourceLine /* register or get source line */

        proximityHelper = ProximityServerActivationHelper(
            voiceServer,
            activation,
            sourceLine,
            TestDistanceSupplier()
        )
        proximityHelper!!.registerListeners(this)
    }

    override fun onAddonShutdown() {
        if (proximityHelper != null) {
            proximityHelper!!.unregisterListeners(this)
        }
    }

    private class TestDistanceSupplier : DistanceSupplier {

        override fun getDistance(player: VoiceServerPlayer, packet: PlayerAudioEndPacket): Short {
            return 12
        }

        override fun getDistance(player: VoiceServerPlayer, packet: PlayerAudioPacket): Short {
            return 12
        }
    }
}