-
Notifications
You must be signed in to change notification settings - Fork 3
API
Playing audio clips is simple. All you need is your own AudioHandler instance.
using LabExtended.API.Audio;
public void CreateHandler()
{
// Retrieves our AudioHandler (if we've already created one)
// OR creates a new one (in which case the delegate in the second parameter is called)
AudioHandler handler = AudioManager.GetOrAddHandler("ExampleHandler", handler =>
{
// Adds an AudioPlayer instance to your AudioHandler instance.
handler.AddPlayer();
// Adds a SpeakerToy instance to your AudioHandler instance.
// The first parameter is the name of the SpeakerToy, used only in the AudioHandler.
// The second parameter is the controller ID of the SpeakerToy, which is used when sending audio to players.
// - Assigning the same ID to multiple speakers results in the same audio playing from all speakers with this ID.
handler.EnsureSpeaker("ExampleSpeaker", 1);
});
// Lets also load the clip that we want to play.
// It's important to use the same name as the file in the method's first argument (this includes any extensions).
KeyValuePair<string, byte[]> clip = AudioManager.GetClip("ExampleClip");
}// This is called every time a player sends a voice chat packet to the server.
public void OnSpeaking(PlayerSendingVoiceChatMessageEventArgs args)
{
// You should save your AudioHandler instance as a field or a property, this event is called A LOT
if (!AudioManager.TryGetHandler("ExampleHandler", out var handler))
return;
// Since this is a LabAPI events and not a custom LabExtended event, we need to cast the LabAPI player instance
// into our custom subtype ExPlayer instance.
if (args.Speaker is not ExPlayer speaker)
return;
// This will send the voice chat message through each speaker you defined in your AudioHandler.
handler.Transmit(args.Messsage.Data, args.Message.DataLength);
// This will send the voice chat message through each speaker to players that are within 20 meters of the speaking player.
handler.Transmit(args.Messsage.Data, args.Message.DataLength, player => player.Position.DistanceTo(speaker) <= 20f);
}public void PlayClip()
{
// Will return false if no AudioHandler with name "ExampleHandler" is found.
if (!AudioManager.TryGetHandler("ExampleHandler", out var handler))
return;
// Will return false if no audio clip file with name "ExampleClip" is found.
if (!AudioManager.TryGetClip("ExampleClip", out var clip))
return;
// Will start playing the audio clip (or put it into the queue if something is playing)
// Audio of the clip will be sent through each speaker ID defined in your AudioHandler.
handler.Player.Play(clip, false);
// You can also start playback of an audio clip at a specific location.
handler.PlayAt(clip, Vector3.zero);
// OR you can start playback of an audio clip with a specific Transform!
handler.PlayOn(clip, ExPlayer.Players.RandomItem().CameraTransform);
}You can keep track of your playback using events defined in the AudioPlayer class.
LabExtended adds some custom collections, mostly for the purpose of optimization and convenience.
This is just a normal List<T> from System.Collections.Generic, the only difference is that ALL "safety" mechanisms have been removed, which means
- If you remove an item while enumerating the list, no exceptions will be thrown BUT you may skip some items.
This collection (a subtype of UnsafeList<T>) calls an update method on each element every frame with a configurable delay.
Each element must be a subtype of the IUpdateableElement interface.
LabExtended provides developers with classes meant to "contain" properties specific to a function in order to reduce clutter in the main ExPlayer class.
Provides helper methods meant to check and modify ammo count.
Provides helper methods used to check effect properties (also provides a property for every in-game effect so you don't have to look it up in a dictionary every time you need to access it).
- Also provides methods for managing Custom Effects.
Provides a lot of helper methods and properties used to keep track and manage inventory items.
Provides position-related methods.
Provides role-related methods.
Provides a property for every player stat
- Also provides properties to directly set the values of these stats (like
MaxHealth,CurStamina, etc.)
Provides a property for every role subroutine the game contains
- These properties are not cached but rather looked up every time it's getter is called.
The SwitchContainer class is used to configure custom player functions, which range from changing Remote Admin visibility to to the ability to configure position synchronization.
- Commands can be used to change values of these switches.
- Custom Ammo is stored in a very simple way, as a developer you only need to respect ammo IDs of other plugins (ammo ID is stored as a 16-bit unsigned integer!)
- Commands can also be used to list and manage custom ammo.
public void AddAmmo(ExPlayer player)
{
// This will add 500 bullets of ammo with the ID 10
player.Inventory.CustomAmmo.Add(10, 500);
}LabExtended provides a very basic API for Custom Effects.
- Custom Effects do not have a name nor an ID
- Instead, they are listed by their type name.
- Custom Effects are stored in the
EffectContainerclass. - Custom Effects are automatically registered by the loader (unless you specify a
LoaderIgnoreattribute).- To manually register a Custom Effect, just add the effect's type to the
CustomPlayerEffect.Effectslist.
- To manually register a Custom Effect, just add the effect's type to the
- Custom Effects have a separate instance for every player, hence why registration uses only the type.
- Custom Effects can also be managed by commands.
The structure of a Custom Effect class shoud look like this:
public class BoostEffect : CustomPlayerEffect
{
// You can also override methods like Start() to initialize your Custom Effect, but for the sake of simplicity we'll just apply it.
// This method is called once something calls the effect's Enable() method.
public override void ApplyEffects()
{
// This will set the intensity of the MovementBoost effect to 255.
Player.Effects.MovementBoost.Intensity = 255;
}
// This method is called once something calls the effect's Disable() method.
public override void RemoveEffects()
{
// This will set the intensity of the MovementBoost effect to 0.
Player.Effects.MovementBoost.Intensity = 0;
}
}public void ActivateBoost(ExPlayer player)
{
// Attempts to find a previously registered Custom Effect by it's type, in this case BoostEffect.
if (player.Effects.TryGetCustomEffect<BoostEffect>(out var boostEffect))
{
// Enables our custom effect by calling it's ApplyEffects() method.
boostEffect.Enable();
}
}
// You can disable the effect in the same way.
public void DisableBoost(ExPlayer player)
{
// Attempts to find a previously registered Custom Effect by it's type, in this case BoostEffect.
if (player.Effects.TryGetCustomEffect<BoostEffect>(out var boostEffect))
{
// Disables our custom effect by calling it's RemoveEffects() method.
boostEffect.Disable();
}
}If you need your Custom Effect to update every frame, you can use the CustomTickingEffect subtype.
- This class provides an overridable
Tick()method - You can also set a custom delay (in seconds) between each
Tick()method call by overriding theDelayproperty.
If you want a duration for your Custom Effect, you can use the CustomDurationEffect subtype.
- This class provides an overridable
GetDuration()method, in which you should calculate the effect's duration in seconds. -
CheckDuration()method is called every time before the effect ends in case you need to add duration. -
RemainingDurationcan be used to check the effect's remaining duration (in seconds).
This wiki may be incomplete or outdated! Sorry for that, but this project is mostly a one-man show.