This commit is contained in:
1 parent
bbccd4a815
commit
71396a86a0
581 files changed
+9084
-38713
No files matched your search
@@ -0,0 +1,12 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
public interface BukkitVoicechatService {
|
||||
|
||||
/**
|
||||
* Registers the voice chat plugin on bukkit based servers.
|
||||
*
|
||||
* @param plugin the voicechat plugin
|
||||
*/
|
||||
void registerPlugin(VoicechatPlugin plugin);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* A socket used for client side voice chat traffic.
|
||||
* Can be set using {@link de.maxhenkel.voicechat.api.events.ClientVoicechatInitializationEvent#setSocketImplementation(ClientVoicechatSocket)}.
|
||||
*/
|
||||
public interface ClientVoicechatSocket {
|
||||
|
||||
void open() throws Exception;
|
||||
|
||||
RawUdpPacket read() throws Exception;
|
||||
|
||||
void send(byte[] data, SocketAddress address) throws Exception;
|
||||
|
||||
void close();
|
||||
|
||||
boolean isClosed();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Entity {
|
||||
|
||||
/**
|
||||
* @return the UUID of the entity
|
||||
*/
|
||||
UUID getUuid();
|
||||
|
||||
/**
|
||||
* @return the actual entity object
|
||||
*/
|
||||
Object getEntity();
|
||||
|
||||
/**
|
||||
* @return the current position of the entity
|
||||
*/
|
||||
Position getPosition();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ForgeVoicechatPlugin {
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Groups can be created using {@link VoicechatServerApi#groupBuilder()}.
|
||||
*/
|
||||
public interface Group {
|
||||
|
||||
/**
|
||||
* @return the visual name of the group
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @return if the group has a password
|
||||
*/
|
||||
boolean hasPassword();
|
||||
|
||||
/**
|
||||
* @return the ID of the group
|
||||
*/
|
||||
UUID getId();
|
||||
|
||||
/**
|
||||
* @return if the group is persistent
|
||||
*/
|
||||
boolean isPersistent();
|
||||
|
||||
/**
|
||||
* @return if the group is hidden in the group list UI
|
||||
*/
|
||||
boolean isHidden();
|
||||
|
||||
/**
|
||||
* @return the group type
|
||||
*/
|
||||
Type getType();
|
||||
|
||||
public interface Type {
|
||||
|
||||
/**
|
||||
* Players in a group can hear nearby players that are not in a group
|
||||
*/
|
||||
public static final Type NORMAL = new Type() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Players in a group can hear nearby players and nearby players can hear players in the group
|
||||
*/
|
||||
public static final Type OPEN = new Type() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Players in a group can only hear other players in the group
|
||||
*/
|
||||
public static final Type ISOLATED = new Type() {
|
||||
};
|
||||
}
|
||||
|
||||
public interface Builder {
|
||||
|
||||
/**
|
||||
* Sets the ID of the group.
|
||||
* If this is not set, the ID will be randomly generated.
|
||||
* <br/>
|
||||
* <b>NOTE</b>: If there is already a group with the same ID, the group will be overwritten.
|
||||
*
|
||||
* @param id the group ID or <code>null</code> if the ID should be randomly generated
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setId(@Nullable UUID id);
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: The name might be stripped of special characters and whitespace.
|
||||
*
|
||||
* @param name the name of the group
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setName(String name);
|
||||
|
||||
/**
|
||||
* @param password the group password
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setPassword(@Nullable String password);
|
||||
|
||||
/**
|
||||
* @param persistent if the group should be persistent
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setPersistent(boolean persistent);
|
||||
|
||||
/**
|
||||
* @param hidden if the group should be hidden in the group list UI
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setHidden(boolean hidden);
|
||||
|
||||
/**
|
||||
* @param type the group type
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setType(Type type);
|
||||
|
||||
/**
|
||||
* @return the built group
|
||||
* @throws IllegalStateException if the name is not set or invalid
|
||||
*/
|
||||
Group build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
public interface Player extends Entity {
|
||||
|
||||
/**
|
||||
* @return the actual player object
|
||||
*/
|
||||
Object getPlayer();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
public interface Position {
|
||||
|
||||
/**
|
||||
* @return the X position
|
||||
*/
|
||||
double getX();
|
||||
|
||||
/**
|
||||
* @return the Y position
|
||||
*/
|
||||
double getY();
|
||||
|
||||
/**
|
||||
* @return the Z position
|
||||
*/
|
||||
double getZ();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
public interface RawUdpPacket {
|
||||
|
||||
byte[] getData();
|
||||
|
||||
long getTimestamp();
|
||||
|
||||
SocketAddress getSocketAddress();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
public interface ServerLevel {
|
||||
|
||||
/**
|
||||
* @return the actual level object
|
||||
*/
|
||||
Object getServerLevel();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
public interface ServerPlayer extends Player {
|
||||
|
||||
/**
|
||||
* @return the level of the player
|
||||
*/
|
||||
ServerLevel getServerLevel();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import de.maxhenkel.voicechat.api.audio.AudioConverter;
|
||||
import de.maxhenkel.voicechat.api.mp3.Mp3Decoder;
|
||||
import de.maxhenkel.voicechat.api.mp3.Mp3Encoder;
|
||||
import de.maxhenkel.voicechat.api.opus.OpusDecoder;
|
||||
import de.maxhenkel.voicechat.api.opus.OpusEncoder;
|
||||
import de.maxhenkel.voicechat.api.opus.OpusEncoderMode;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface VoicechatApi {
|
||||
|
||||
/**
|
||||
* Creates a new opus encoder.
|
||||
* Note that the encoder needs to be closed after you are finished using it.
|
||||
*/
|
||||
OpusEncoder createEncoder();
|
||||
|
||||
/**
|
||||
* Creates a new opus encoder.
|
||||
* Note that the encoder needs to be closed after you are finished using it.
|
||||
*
|
||||
* @param mode the opus encoder mode
|
||||
* @return the opus encoder
|
||||
*/
|
||||
OpusEncoder createEncoder(OpusEncoderMode mode);
|
||||
|
||||
/**
|
||||
* Creates a new opus decoder.
|
||||
* Note that the decoder needs to be closed after you are finished using it.
|
||||
*
|
||||
* @return the opus decoder
|
||||
*/
|
||||
OpusDecoder createDecoder();
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: This is not available for Bukkit! It will always return null.
|
||||
*
|
||||
* @param audioFormat the audio format
|
||||
* @param bitrate the bitrate in kbps
|
||||
* @param quality the quality from 0 (highest) to 9 (lowest)
|
||||
* @param outputStream the output stream to write the mp3 to
|
||||
* @return the mp3 encoder or null if the encoder could not be initialized or is not available
|
||||
*/
|
||||
@Nullable
|
||||
Mp3Encoder createMp3Encoder(AudioFormat audioFormat, int bitrate, int quality, OutputStream outputStream);
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: This is not available for Bukkit! It will always return null.
|
||||
*
|
||||
* @param inputStream the input stream to read the mp3 from
|
||||
* @return the mp3 decoder or null if the decoder could not be initialized or is not available
|
||||
*/
|
||||
@Nullable
|
||||
Mp3Decoder createMp3Decoder(InputStream inputStream);
|
||||
|
||||
/**
|
||||
* @return the audio converter
|
||||
*/
|
||||
AudioConverter getAudioConverter();
|
||||
|
||||
/**
|
||||
* Creates an entity object from an actual entity.
|
||||
*
|
||||
* @param entity the entity implementation of your mod/plugin loader
|
||||
* @return the entity object
|
||||
*/
|
||||
Entity fromEntity(Object entity);
|
||||
|
||||
/**
|
||||
* Creates a level object from an actual level.
|
||||
*
|
||||
* @param serverLevel the level implementation of your mod/plugin loader
|
||||
* @return the level
|
||||
*/
|
||||
ServerLevel fromServerLevel(Object serverLevel);
|
||||
|
||||
/**
|
||||
* Creates a player object from an actual player.
|
||||
*
|
||||
* @param serverPlayer the player implementation of your mod/plugin loader
|
||||
* @return the player
|
||||
*/
|
||||
ServerPlayer fromServerPlayer(Object serverPlayer);
|
||||
|
||||
/**
|
||||
* Creates a new position object.
|
||||
*
|
||||
* @param x the X position
|
||||
* @param y the Y position
|
||||
* @param z the Z position
|
||||
* @return the position with the provided coordinates
|
||||
*/
|
||||
Position createPosition(double x, double y, double z);
|
||||
|
||||
/**
|
||||
* Don't forget to register your category with {@link VoicechatServerApi#registerVolumeCategory(VolumeCategory)} or {@link VoicechatClientApi#registerClientVolumeCategory(VolumeCategory)}
|
||||
*
|
||||
* @return a builder to build a category
|
||||
*/
|
||||
VolumeCategory.Builder volumeCategoryBuilder();
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: Voice chat plugins can change this.
|
||||
* This is only the default value.
|
||||
* This value might not be correct if you are not connected to a server.
|
||||
*
|
||||
* @return the default distance, audio from voice chat is heard from
|
||||
*/
|
||||
double getVoiceChatDistance();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import de.maxhenkel.voicechat.api.audiochannel.ClientEntityAudioChannel;
|
||||
import de.maxhenkel.voicechat.api.audiochannel.ClientLocationalAudioChannel;
|
||||
import de.maxhenkel.voicechat.api.audiochannel.ClientStaticAudioChannel;
|
||||
import de.maxhenkel.voicechat.api.config.ConfigAccessor;
|
||||
import de.maxhenkel.voicechat.api.config.VolumeConfigAccessor;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface VoicechatClientApi extends VoicechatApi {
|
||||
|
||||
/**
|
||||
* @return if the local voice chat is muted
|
||||
*/
|
||||
boolean isMuted();
|
||||
|
||||
/**
|
||||
* Does the same as {@link #isDisabled(UUID)} with <code>null</code> as the player UUID.
|
||||
*
|
||||
* @return if the local voice chat is disabled
|
||||
*/
|
||||
default boolean isDisabled() {
|
||||
return isDisabled(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId the UUID of the player or <code>null</code> for the local player
|
||||
* @return if the player with the provided UUID has the voice chat disabled
|
||||
*/
|
||||
boolean isDisabled(@Nullable UUID playerId);
|
||||
|
||||
/**
|
||||
* Does the same as {@link #isDisconnected(UUID)} with <code>null</code> as the player UUID.
|
||||
*
|
||||
* @return if the voice chat is disconnected from the server
|
||||
*/
|
||||
default boolean isDisconnected() {
|
||||
return isDisconnected(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId the UUID of the player or <code>null</code> for the local player
|
||||
* @return if the player with the provided UUID is disconnected from voice chat
|
||||
*/
|
||||
boolean isDisconnected(@Nullable UUID playerId);
|
||||
|
||||
/**
|
||||
* Does the same as {@link #isTalking(UUID)} with <code>null</code> as the player UUID.
|
||||
*
|
||||
* @return if the local player is talking
|
||||
*/
|
||||
default boolean isTalking() {
|
||||
return isTalking(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId the UUID of the player or <code>null</code> for the local player
|
||||
* @return if the player with the provided UUID is currently talking
|
||||
*/
|
||||
boolean isTalking(@Nullable UUID playerId);
|
||||
|
||||
/**
|
||||
* Does the same as {@link #isWhispering(UUID)} with <code>null</code> as the player UUID.
|
||||
*
|
||||
* @return if the local player is whispering
|
||||
*/
|
||||
default boolean isWhispering() {
|
||||
return isWhispering(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerId the UUID of the player or <code>null</code> for the local player
|
||||
* @return if the player with the provided UUID is currently whispering
|
||||
*/
|
||||
boolean isWhispering(@Nullable UUID playerId);
|
||||
|
||||
/**
|
||||
* This method returns if the push to talk key is pressed, even when using voice activation.
|
||||
*
|
||||
* @return if the push to talk key is pressed
|
||||
*/
|
||||
boolean isPushToTalkKeyPressed();
|
||||
|
||||
/**
|
||||
* @return if the whisper key is pressed
|
||||
*/
|
||||
boolean isWhisperKeyPressed();
|
||||
|
||||
@Nullable
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* Creates a client side entity audio channel.
|
||||
*
|
||||
* @param uuid the UUID of the entity
|
||||
* @return the audio channel
|
||||
* @deprecated use {@link #createEntityAudioChannel(UUID, Entity)}
|
||||
*/
|
||||
@Deprecated
|
||||
ClientEntityAudioChannel createEntityAudioChannel(UUID uuid);
|
||||
|
||||
/**
|
||||
* Creates a client side entity audio channel.
|
||||
*
|
||||
* @param uuid the ID of the channel
|
||||
* @param entity the entity to attach the channel to
|
||||
* @return the audio channel
|
||||
*/
|
||||
ClientEntityAudioChannel createEntityAudioChannel(UUID uuid, Entity entity);
|
||||
|
||||
/**
|
||||
* Creates a client side locational audio channel.
|
||||
*
|
||||
* @param uuid the ID of the channel
|
||||
* @return the audio channel
|
||||
*/
|
||||
ClientLocationalAudioChannel createLocationalAudioChannel(UUID uuid, Position position);
|
||||
|
||||
/**
|
||||
* Creates a client side static audio channel.
|
||||
*
|
||||
* @param uuid the ID of the channel
|
||||
* @return the audio channel
|
||||
*/
|
||||
ClientStaticAudioChannel createStaticAudioChannel(UUID uuid);
|
||||
|
||||
/**
|
||||
* Registers a volume category just for this client.
|
||||
* A category can be created with {@link VoicechatApi#volumeCategoryBuilder()}.
|
||||
* The category can be unregistered with {@link #unregisterClientVolumeCategory}.
|
||||
*
|
||||
* @param category the category to register
|
||||
*/
|
||||
void registerClientVolumeCategory(VolumeCategory category);
|
||||
|
||||
/**
|
||||
* Unregisters a category on this client.
|
||||
* This will release the texture ID for the icon if one exists.
|
||||
*
|
||||
* @param category the category to remove
|
||||
*/
|
||||
default void unregisterClientVolumeCategory(VolumeCategory category) {
|
||||
unregisterClientVolumeCategory(category.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a category on this client.
|
||||
* This will release the texture ID for the icon if one exists.
|
||||
*
|
||||
* @param categoryId the category ID to remove
|
||||
*/
|
||||
void unregisterClientVolumeCategory(String categoryId);
|
||||
|
||||
/**
|
||||
* @return a read-only config accessor for the mods client config
|
||||
*/
|
||||
ConfigAccessor getClientConfig();
|
||||
|
||||
/**
|
||||
* @return a read-only accessor for player and category volumes
|
||||
*/
|
||||
VolumeConfigAccessor getVolumeConfig();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* <b>Note</b>: It is not guaranteed that the state of this connection object is up to date.
|
||||
* Please re-fetch the connection object to get the latest state.
|
||||
*/
|
||||
public interface VoicechatConnection {
|
||||
|
||||
/**
|
||||
* <b>Note</b>: This only returns the group the player was in when fetching this connection object.
|
||||
* Calling {@link #setGroup(Group)} won't update the return value of this method.
|
||||
*
|
||||
* @return the group of the player - <code>null</code> if the player is not in a group
|
||||
*/
|
||||
@Nullable
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* <b>Note</b>: This only returns if the player was in a group when fetching this connection object.
|
||||
* Calling {@link #setGroup(Group)} won't update the return value of this method.
|
||||
*
|
||||
* @return if the player is in a group
|
||||
*/
|
||||
boolean isInGroup();
|
||||
|
||||
/**
|
||||
* Joins this player to the provided group.
|
||||
*
|
||||
* @param group the group to join or <code>null</code> to leave the current group
|
||||
*/
|
||||
void setGroup(@Nullable Group group);
|
||||
|
||||
/**
|
||||
* This might not represent the actual state of the voice chat connection, since other voice chat plugins can fake having a player connected.
|
||||
* <br/>
|
||||
* <b>Note</b>: This only returns if the player was connected fetching this connection object.
|
||||
* Calling {@link #setConnected(boolean)} won't update the return value of this method.
|
||||
*
|
||||
* @return if the player is connected to voice chat
|
||||
*/
|
||||
boolean isConnected();
|
||||
|
||||
/**
|
||||
* The players disconnected state will reset if its actual disconnected state changes or if the player reconnects.
|
||||
* <br/>
|
||||
* <b>NOTE</b>: This method will only work for players that don't have the mod installed. See {@link #isInstalled()}.
|
||||
*
|
||||
* @param connected if the player should be shown as connected to voice chat
|
||||
*/
|
||||
void setConnected(boolean connected);
|
||||
|
||||
/**
|
||||
* <b>Note</b>: This only returns if the player has the voice chat disabled when fetching this connection object.
|
||||
* Calling {@link #setDisabled(boolean)} won't update the return value of this method.
|
||||
*
|
||||
* @return If the player muted the sound
|
||||
*/
|
||||
boolean isDisabled();
|
||||
|
||||
/**
|
||||
* Sets the players disabled state.
|
||||
* <b>NOTE</b>: This method will only work for players that don't have the mod installed. See {@link #isInstalled()}.
|
||||
*
|
||||
* @param disabled if the player should have the voice chat disabled icon
|
||||
*/
|
||||
void setDisabled(boolean disabled);
|
||||
|
||||
/**
|
||||
* @return if the player has a version of voice chat installed that is compatible with the server
|
||||
*/
|
||||
boolean isInstalled();
|
||||
|
||||
/**
|
||||
* @return the player
|
||||
*/
|
||||
ServerPlayer getPlayer();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import de.maxhenkel.voicechat.api.events.EventRegistration;
|
||||
|
||||
public interface VoicechatPlugin {
|
||||
|
||||
/**
|
||||
* @return the ID of this plugin - Has to be unique
|
||||
*/
|
||||
String getPluginId();
|
||||
|
||||
/**
|
||||
* Called after loading the plugin.
|
||||
*/
|
||||
default void initialize(VoicechatApi api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register your events here - Only here!
|
||||
*
|
||||
* @param registration the event registration object, used to register events
|
||||
*/
|
||||
default void registerEvents(EventRegistration registration) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import de.maxhenkel.voicechat.api.audiochannel.*;
|
||||
import de.maxhenkel.voicechat.api.audiolistener.AudioListener;
|
||||
import de.maxhenkel.voicechat.api.audiolistener.PlayerAudioListener;
|
||||
import de.maxhenkel.voicechat.api.audiosender.AudioSender;
|
||||
import de.maxhenkel.voicechat.api.config.ConfigAccessor;
|
||||
import de.maxhenkel.voicechat.api.opus.OpusEncoder;
|
||||
import de.maxhenkel.voicechat.api.packets.ConvertablePacket;
|
||||
import de.maxhenkel.voicechat.api.packets.EntitySoundPacket;
|
||||
import de.maxhenkel.voicechat.api.packets.LocationalSoundPacket;
|
||||
import de.maxhenkel.voicechat.api.packets.StaticSoundPacket;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface VoicechatServerApi extends VoicechatApi {
|
||||
|
||||
/**
|
||||
* Sends the sound packet to the provided connection.
|
||||
*
|
||||
* @param connection the connection to send the packet to
|
||||
* @param packet the packet to send
|
||||
*/
|
||||
void sendEntitySoundPacketTo(VoicechatConnection connection, EntitySoundPacket packet);
|
||||
|
||||
/**
|
||||
* Sends the sound packet to the provided connection.
|
||||
*
|
||||
* @param connection the connection to send the packet to
|
||||
* @param packet the packet to send
|
||||
*/
|
||||
void sendLocationalSoundPacketTo(VoicechatConnection connection, LocationalSoundPacket packet);
|
||||
|
||||
/**
|
||||
* Sends the sound packet to the provided connection.
|
||||
*
|
||||
* @param connection the connection to send the packet to
|
||||
* @param packet the packet to send
|
||||
*/
|
||||
void sendStaticSoundPacketTo(VoicechatConnection connection, StaticSoundPacket packet);
|
||||
|
||||
/**
|
||||
* Creates a sound packet that can be converted to any type.
|
||||
* <b>NOTE</b>: When creating a packet using this method, the sequence number must be set manually using {@link de.maxhenkel.voicechat.api.packets.SoundPacket.Builder#sequenceNumber(long)}.
|
||||
*
|
||||
* @return a convertable packet without any data
|
||||
*/
|
||||
ConvertablePacket createPacket();
|
||||
|
||||
/**
|
||||
* Creates a sound channel for the specified entity.
|
||||
*
|
||||
* @param channelId the ID of the channel - Has to be unique
|
||||
* @param entity the entity to attach the channel to
|
||||
* @return the channel
|
||||
*/
|
||||
@Nullable
|
||||
EntityAudioChannel createEntityAudioChannel(UUID channelId, Entity entity);
|
||||
|
||||
/**
|
||||
* Creates a sound channel at the provided location.
|
||||
*
|
||||
* @param channelId the ID of the channel - Has to be unique
|
||||
* @param level the world
|
||||
* @param initialPosition the position where the sound should be played
|
||||
* @return the channel
|
||||
*/
|
||||
@Nullable
|
||||
LocationalAudioChannel createLocationalAudioChannel(UUID channelId, ServerLevel level, Position initialPosition);
|
||||
|
||||
/**
|
||||
* Creates a static audio channel.
|
||||
*
|
||||
* @param channelId the ID of the channel - Has to be unique
|
||||
* @param level the level
|
||||
* @param connection the connection that should hear the audio
|
||||
* @return the channel
|
||||
* @deprecated use {@link #createStaticAudioChannel(UUID)} and add a target using {@link StaticAudioChannel#addTarget(VoicechatConnection)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
StaticAudioChannel createStaticAudioChannel(UUID channelId, ServerLevel level, VoicechatConnection connection);
|
||||
|
||||
/**
|
||||
* Creates a static audio channel.
|
||||
*
|
||||
* @param channelId the ID of the channel - Has to be unique
|
||||
* @return the channel
|
||||
*/
|
||||
@Nullable
|
||||
StaticAudioChannel createStaticAudioChannel(UUID channelId);
|
||||
|
||||
/**
|
||||
* Creates a new audio player.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* <b>NOTE</b>: Never use more than one audio player for every audio channel.
|
||||
*
|
||||
* @param audioChannel the channel where the audio player should send the audio to
|
||||
* @param encoder the opus encoder used to encode the audio data
|
||||
* @param audioSupplier this gets called whenever a new audio frame needs to be sent. The size of the array always needs to be 960. To end the playback, return <code>null</code>
|
||||
* @return the audio player
|
||||
*/
|
||||
AudioPlayer createAudioPlayer(AudioChannel audioChannel, OpusEncoder encoder, Supplier<short[]> audioSupplier);
|
||||
|
||||
/**
|
||||
* Creates a new audio player.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* <b>NOTE</b>: Never use more than one audio player for every audio channel.
|
||||
*
|
||||
* @param audioChannel the channel where the audio player should send the audio to
|
||||
* @param encoder the opus encoder used to encode the audio data
|
||||
* @param audio the audio data
|
||||
* @return the audio player
|
||||
*/
|
||||
AudioPlayer createAudioPlayer(AudioChannel audioChannel, OpusEncoder encoder, short[] audio);
|
||||
|
||||
/**
|
||||
* Creates a new audio sender.
|
||||
* <br/>
|
||||
* This can be used to simulate a player sending microphone packets.
|
||||
* This needs to be registered using {@link #registerAudioSender(AudioSender)} and unregistered using {@link #unregisterAudioSender(AudioSender)}.
|
||||
*
|
||||
* @param connection the connection of the player
|
||||
* @return the audio sender
|
||||
*/
|
||||
AudioSender createAudioSender(VoicechatConnection connection);
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: Only one instance of this can exist per player. This will return <code>false</code> if an audio sender for this player already exists.
|
||||
* <br/>
|
||||
* <b>NOTE</b>: The audio sender will only work for players that are connected to the server and don't have the mod installed. Otherwise, it will return <code>false</code>.
|
||||
*
|
||||
* @param sender the sender to register
|
||||
* @return if the sender was registered
|
||||
*/
|
||||
boolean registerAudioSender(AudioSender sender);
|
||||
|
||||
/**
|
||||
* Unregisters an audio sender.
|
||||
*
|
||||
* @param sender the sender to unregister
|
||||
* @return <code>false</code> if the audio sender was not registered.
|
||||
*/
|
||||
boolean unregisterAudioSender(AudioSender sender);
|
||||
|
||||
/**
|
||||
* @return a {@link PlayerAudioListener} builder
|
||||
*/
|
||||
PlayerAudioListener.Builder playerAudioListenerBuilder();
|
||||
|
||||
/**
|
||||
* Registers a new {@link AudioListener}.
|
||||
* <br/>
|
||||
* Returns false if the listener is already registered.
|
||||
*
|
||||
* @param listener the listener to register
|
||||
* @return if the listener was registered
|
||||
*/
|
||||
boolean registerAudioListener(AudioListener listener);
|
||||
|
||||
/**
|
||||
* Unregisters an {@link AudioListener}.
|
||||
* <br/>
|
||||
* Returns false if the listener is already unregistered.
|
||||
*
|
||||
* @param listener the listener to unregister
|
||||
* @return if the listener was unregistered
|
||||
*/
|
||||
boolean unregisterAudioListener(AudioListener listener);
|
||||
|
||||
/**
|
||||
* Unregisters an {@link AudioListener}.
|
||||
* <br/>
|
||||
* Returns false if the listener is already unregistered.
|
||||
*
|
||||
* @param listenerId the {@link AudioListener#getListenerId()} of the listener to unregister
|
||||
* @return if the listener was unregistered
|
||||
*/
|
||||
boolean unregisterAudioListener(UUID listenerId);
|
||||
|
||||
/**
|
||||
* Gets the connection of the player with this UUID.
|
||||
*
|
||||
* @param playerUuid the players UUID
|
||||
* @return the connection or <code>null</code> if the player is not connected
|
||||
*/
|
||||
@Nullable
|
||||
VoicechatConnection getConnectionOf(UUID playerUuid);
|
||||
|
||||
/**
|
||||
* Gets the connection of the player.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the connection or <code>null</code> if the player is not connected
|
||||
*/
|
||||
@Nullable
|
||||
default VoicechatConnection getConnectionOf(ServerPlayer player) {
|
||||
return getConnectionOf(player.getUuid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new group.
|
||||
*
|
||||
* @param name the name of the group
|
||||
* @param password the password of the group - <code>null</code> for no password
|
||||
* @return the group
|
||||
* @deprecated use {@link #groupBuilder()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
Group createGroup(String name, @Nullable String password);
|
||||
|
||||
/**
|
||||
* Creates a new group.
|
||||
*
|
||||
* @param name the name of the group
|
||||
* @param password the password of the group - <code>null</code> for no password
|
||||
* @param persistent if the group should be persistent
|
||||
* @return the group
|
||||
* @deprecated use {@link #groupBuilder()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
Group createGroup(String name, @Nullable String password, boolean persistent);
|
||||
|
||||
/**
|
||||
* @return a new group builder
|
||||
*/
|
||||
Group.Builder groupBuilder();
|
||||
|
||||
/**
|
||||
* Removes a persistent group.
|
||||
*
|
||||
* <b>NOTE</b>: You can't remove a group that is not persistent or has players in it.
|
||||
*
|
||||
* @param groupId the ID of the group
|
||||
* @return if the group was removed
|
||||
*/
|
||||
boolean removeGroup(UUID groupId);
|
||||
|
||||
/**
|
||||
* Gets a group by its ID.
|
||||
*
|
||||
* @param groupId the ID of the group
|
||||
* @return the group or <code>null</code> if the group doesn't exist
|
||||
*/
|
||||
@Nullable
|
||||
Group getGroup(UUID groupId);
|
||||
|
||||
/**
|
||||
* @return all groups
|
||||
*/
|
||||
Collection<Group> getGroups();
|
||||
|
||||
/**
|
||||
* Gets the secret for the user with this <code>userId</code>.
|
||||
* Calling this function with a players UUID, that is already connected, this will return the secret of that player.
|
||||
* Calling it with a new random UUID this will return a new secret.
|
||||
* Use this with caution - Keep this secret confidential, as this allows connecting to the voice chat as this person.
|
||||
* Note that if this <code>userId</code> is a players UUID and this player disconnects, the secret will get removed and thus is no longer valid to connect with.
|
||||
*
|
||||
* @param userId the user ID
|
||||
* @return the secret or <code>null</code> if no server is running
|
||||
* @deprecated this will just return <code>null</code>
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
UUID getSecret(UUID userId);
|
||||
|
||||
/**
|
||||
* A convenience method to get all players in the range of a specific location.
|
||||
*
|
||||
* @param level the world
|
||||
* @param pos the location
|
||||
* @param range the range
|
||||
* @param filter the filter to exclude specific players
|
||||
* @return all players in the provided location
|
||||
*/
|
||||
Collection<ServerPlayer> getPlayersInRange(ServerLevel level, Position pos, double range, Predicate<ServerPlayer> filter);
|
||||
|
||||
/**
|
||||
* The distance at which audio packets are broadcast.
|
||||
* <b>NOTE</b>: This is not the distance it can be heard.
|
||||
*
|
||||
* @return the maximum distance, voice chat audio packets can be received
|
||||
*/
|
||||
double getBroadcastRange();
|
||||
|
||||
/**
|
||||
* A convenience method to get all players in the range of a specific location.
|
||||
*
|
||||
* @param level the world
|
||||
* @param pos the location
|
||||
* @param range the range
|
||||
* @return all players in the provided location
|
||||
*/
|
||||
default Collection<ServerPlayer> getPlayersInRange(ServerLevel level, Position pos, double range) {
|
||||
return getPlayersInRange(level, pos, range, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a volume category.
|
||||
* This will get synchronized to all connected clients and all future clients that will connect.
|
||||
* A category can be created with {@link VoicechatApi#volumeCategoryBuilder()}.
|
||||
* The category can be unregistered with {@link #unregisterVolumeCategory}.
|
||||
*
|
||||
* @param category the category to register
|
||||
*/
|
||||
void registerVolumeCategory(VolumeCategory category);
|
||||
|
||||
/**
|
||||
* Unregisters a category for all connected players.
|
||||
* This will release the texture ID for the icon if one exists on all clients.
|
||||
*
|
||||
* @param category the category to remove
|
||||
*/
|
||||
default void unregisterVolumeCategory(VolumeCategory category) {
|
||||
unregisterVolumeCategory(category.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a category for all connected players.
|
||||
* This will release the texture ID for the icon if one exists on all clients.
|
||||
*
|
||||
* @param categoryId the category ID to remove
|
||||
*/
|
||||
void unregisterVolumeCategory(String categoryId);
|
||||
|
||||
/**
|
||||
* @return all registered volume categories
|
||||
*/
|
||||
Collection<VolumeCategory> getVolumeCategories();
|
||||
|
||||
/**
|
||||
* @return a read-only config accessor for the mods server config
|
||||
*/
|
||||
ConfigAccessor getServerConfig();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* A socket used for server side voice chat traffic.
|
||||
* Can be set using {@link de.maxhenkel.voicechat.api.events.VoicechatServerStartingEvent#setSocketImplementation(VoicechatSocket)}.
|
||||
*/
|
||||
public interface VoicechatSocket {
|
||||
|
||||
void open(int port, String bindAddress) throws Exception;
|
||||
|
||||
RawUdpPacket read() throws Exception;
|
||||
|
||||
void send(byte[] data, SocketAddress address) throws Exception;
|
||||
|
||||
int getLocalPort();
|
||||
|
||||
void close();
|
||||
|
||||
boolean isClosed();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package de.maxhenkel.voicechat.api;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A custom volume category for the "adjust volumes screen".
|
||||
* Create it with {@link VoicechatApi#volumeCategoryBuilder()}.
|
||||
* Register it with {@link VoicechatServerApi#registerVolumeCategory(VolumeCategory)} or {@link VoicechatClientApi#registerClientVolumeCategory(VolumeCategory)}.
|
||||
* Unregister it with {@link VoicechatServerApi#unregisterVolumeCategory} or {@link VoicechatClientApi#unregisterClientVolumeCategory}.
|
||||
*/
|
||||
public interface VolumeCategory {
|
||||
|
||||
/**
|
||||
* @return the unique ID of the category
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* @return the full name of the category, that is displayed for the end user
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @return the translation key for the full name of the category
|
||||
*/
|
||||
@Nullable
|
||||
String getNameTranslationKey();
|
||||
|
||||
/**
|
||||
* @return the hover tooltip that is shown for this category
|
||||
*/
|
||||
@Nullable
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* @return the translation key for the hover tooltip of the category
|
||||
*/
|
||||
@Nullable
|
||||
String getDescriptionTranslationKey();
|
||||
|
||||
/**
|
||||
* @return the icon that is shown for this category
|
||||
*/
|
||||
@Nullable
|
||||
int[][] getIcon();
|
||||
|
||||
public interface Builder {
|
||||
|
||||
/**
|
||||
* This ID has to be between 1 and 16 characters and can only contain lowercase <code>a-z</code> and <code>_</code>.
|
||||
*
|
||||
* @param id the unique ID of the category
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setId(String id);
|
||||
|
||||
/**
|
||||
* @param name the full name of the category, that is displayed for the end user if no translation is present
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setName(String name);
|
||||
|
||||
/**
|
||||
* @param translationKey the translation key for the full name of the category
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setNameTranslationKey(@Nullable String translationKey);
|
||||
|
||||
/**
|
||||
* @param description the hover tooltip that is shown for this category if no translation is present
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setDescription(@Nullable String description);
|
||||
|
||||
/**
|
||||
* @param translationKey the translation key for the hover tooltip
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setDescriptionTranslationKey(@Nullable String translationKey);
|
||||
|
||||
/**
|
||||
* The array has to be 16x16.
|
||||
* Each integer represents a pixel in the RGBA format.
|
||||
*
|
||||
* @param icon the icon that is shown for this category
|
||||
* @return the builder
|
||||
*/
|
||||
Builder setIcon(@Nullable int[][] icon);
|
||||
|
||||
/**
|
||||
* @return the built category
|
||||
*/
|
||||
VolumeCategory build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.maxhenkel.voicechat.api.audio;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatApi;
|
||||
|
||||
/**
|
||||
* A utility class to convert audio between different representations.
|
||||
* <br/>
|
||||
* Can be obtained by calling {@link VoicechatApi#getAudioConverter()}.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* <b>NOTE</b>: Everything is assumed to be 16 bit PCM audio.
|
||||
*/
|
||||
public interface AudioConverter {
|
||||
|
||||
short[] bytesToShorts(byte[] bytes);
|
||||
|
||||
byte[] shortsToBytes(short[] shorts);
|
||||
|
||||
short[] floatsToShorts(float[] floats);
|
||||
|
||||
float[] shortsToFloats(short[] shorts);
|
||||
|
||||
byte[] floatsToBytes(float[] floats);
|
||||
|
||||
float[] bytesToFloats(byte[] bytes);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Everything related to audio conversion and manipulation.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.audio;
|
||||
@@ -0,0 +1,65 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
import de.maxhenkel.voicechat.api.ServerPlayer;
|
||||
import de.maxhenkel.voicechat.api.VolumeCategory;
|
||||
import de.maxhenkel.voicechat.api.packets.MicrophonePacket;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface AudioChannel {
|
||||
|
||||
/**
|
||||
* Sends the audio data to this audio channel.
|
||||
*
|
||||
* @param opusData Opus encoded audio data
|
||||
*/
|
||||
void send(byte[] opusData);
|
||||
|
||||
/**
|
||||
* Forwards the provided microphone packet to this audio channel.
|
||||
*
|
||||
* @param packet the microphone packet containing the audio data
|
||||
*/
|
||||
void send(MicrophonePacket packet);
|
||||
|
||||
/**
|
||||
* Applies a filter to the audio channel.
|
||||
*
|
||||
* @param filter only sends the data to players where the filter applies
|
||||
*/
|
||||
void setFilter(Predicate<ServerPlayer> filter);
|
||||
|
||||
/**
|
||||
* Call this if you are finished sending data.
|
||||
* You can still use this audio channel after calling this function,
|
||||
* just don't call it after every packet, only after you are finished sending data.
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* @return if the audio channel is closed
|
||||
*/
|
||||
boolean isClosed();
|
||||
|
||||
/**
|
||||
* @return the ID of the audio channel
|
||||
*/
|
||||
UUID getId();
|
||||
|
||||
/**
|
||||
* @return the category ID of the audio channel
|
||||
*/
|
||||
@Nullable
|
||||
String getCategory();
|
||||
|
||||
/**
|
||||
* Make sure you registered your category before using it.
|
||||
* See {@link de.maxhenkel.voicechat.api.VoicechatServerApi#registerVolumeCategory(VolumeCategory)}.
|
||||
*
|
||||
* @param category the category ID of the audio channel
|
||||
*/
|
||||
void setCategory(@Nullable String category);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
/**
|
||||
* Streams audio data from the server to clients.
|
||||
* A player instance can be obtained by calling {@link de.maxhenkel.voicechat.api.VoicechatServerApi#createAudioPlayer}.
|
||||
*/
|
||||
public interface AudioPlayer {
|
||||
|
||||
/**
|
||||
* Starts playing/streaming the audio.
|
||||
*/
|
||||
void startPlaying();
|
||||
|
||||
/**
|
||||
* Stops playing/streaming the audio.
|
||||
*/
|
||||
void stopPlaying();
|
||||
|
||||
/**
|
||||
* @return if the player has been started
|
||||
*/
|
||||
boolean isStarted();
|
||||
|
||||
/**
|
||||
* @return if the audio is still playing
|
||||
*/
|
||||
boolean isPlaying();
|
||||
|
||||
/**
|
||||
* @return if the player stopped playing
|
||||
*/
|
||||
boolean isStopped();
|
||||
|
||||
/**
|
||||
* @param onStopped a runnable that's called when the player is finished playing
|
||||
*/
|
||||
void setOnStopped(Runnable onStopped);
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VolumeCategory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ClientAudioChannel {
|
||||
|
||||
/**
|
||||
* @return the ID of the channel
|
||||
*/
|
||||
UUID getId();
|
||||
|
||||
/**
|
||||
* Plays this audio data on this audio channel.
|
||||
* <br>
|
||||
* Providing audio that's not 960 samples will be ignored.
|
||||
*
|
||||
* @param rawAudio the raw 16 bit PCM audio frame
|
||||
*/
|
||||
void play(short[] rawAudio);
|
||||
|
||||
/**
|
||||
* @return the category ID of the audio channel
|
||||
*/
|
||||
@Nullable
|
||||
String getCategory();
|
||||
|
||||
/**
|
||||
* Make sure you registered your category before using it.
|
||||
* See {@link de.maxhenkel.voicechat.api.VoicechatServerApi#registerVolumeCategory(VolumeCategory)}.
|
||||
*
|
||||
* @param category the category of the audio channel
|
||||
*/
|
||||
void setCategory(@Nullable String category);
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ClientEntityAudioChannel extends ClientAudioChannel {
|
||||
|
||||
/**
|
||||
* @return the UUID of the entity
|
||||
*/
|
||||
UUID getEntityId();
|
||||
|
||||
/**
|
||||
* @param whispering if the entity should whisper
|
||||
*/
|
||||
void setWhispering(boolean whispering);
|
||||
|
||||
/**
|
||||
* @return if the entity is whispering
|
||||
*/
|
||||
boolean isWhispering();
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
|
||||
/**
|
||||
* @param distance the distance, the audio can be heard
|
||||
*/
|
||||
void setDistance(float distance);
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Position;
|
||||
|
||||
public interface ClientLocationalAudioChannel extends ClientAudioChannel {
|
||||
|
||||
/**
|
||||
* @return the current location of the audio channel
|
||||
*/
|
||||
Position getLocation();
|
||||
|
||||
/**
|
||||
* Updates the location of the audio channel.
|
||||
*
|
||||
* @param position the location of the audio channel
|
||||
*/
|
||||
void setLocation(Position position);
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
|
||||
/**
|
||||
* @param distance the distance, the audio can be heard
|
||||
*/
|
||||
void setDistance(float distance);
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
public interface ClientStaticAudioChannel extends ClientAudioChannel {
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Entity;
|
||||
|
||||
/**
|
||||
* An audio channel that is bound to an entity.
|
||||
* <b>NOTE</b>: If you are using this for a player, you need to use {@link #updateEntity(Entity)} to update the player after it died.
|
||||
*/
|
||||
public interface EntityAudioChannel extends AudioChannel {
|
||||
|
||||
/**
|
||||
* @return if the entity is whispering
|
||||
*/
|
||||
boolean isWhispering();
|
||||
|
||||
/**
|
||||
* @param whispering if the entity should whisper
|
||||
*/
|
||||
void setWhispering(boolean whispering);
|
||||
|
||||
/**
|
||||
* Sets a new entity where this channel is attached to.
|
||||
*
|
||||
* @param entity the entity to attach the channel to
|
||||
*/
|
||||
void updateEntity(Entity entity);
|
||||
|
||||
/**
|
||||
* @return the entity where the channel is attached to
|
||||
*/
|
||||
Entity getEntity();
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
|
||||
/**
|
||||
* @param distance the distance, the audio can be heard
|
||||
*/
|
||||
void setDistance(float distance);
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Position;
|
||||
|
||||
public interface LocationalAudioChannel extends AudioChannel {
|
||||
|
||||
/**
|
||||
* Updates the location of the audio.
|
||||
*
|
||||
* @param position the audio location
|
||||
*/
|
||||
void updateLocation(Position position);
|
||||
|
||||
/**
|
||||
* @return the current location of this channel
|
||||
*/
|
||||
Position getLocation();
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
|
||||
/**
|
||||
* @param distance the distance, the audio can be heard
|
||||
*/
|
||||
void setDistance(float distance);
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
public interface StaticAudioChannel extends AudioChannel {
|
||||
|
||||
/**
|
||||
* Sets whether this audio channel should be received by targets in isolated groups.
|
||||
*
|
||||
* @param bypassGroupIsolation if group isolation should be bypassed
|
||||
*/
|
||||
void setBypassGroupIsolation(boolean bypassGroupIsolation);
|
||||
|
||||
/**
|
||||
* @return if this audio channel is received by targets in isolated groups
|
||||
*/
|
||||
boolean bypassesGroupIsolation();
|
||||
|
||||
/**
|
||||
* Adds a target to the audio channel.
|
||||
*
|
||||
* @param target the target to add
|
||||
*/
|
||||
void addTarget(VoicechatConnection target);
|
||||
|
||||
/**
|
||||
* Removes a target from the audio channel.
|
||||
*
|
||||
* @param target the target to remove
|
||||
*/
|
||||
void removeTarget(VoicechatConnection target);
|
||||
|
||||
/**
|
||||
* Removes all targets from the audio channel.
|
||||
*/
|
||||
void clearTargets();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Everything related to audio channels and serverside audio.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.audiochannel;
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.maxhenkel.voicechat.api.audiolistener;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AudioListener {
|
||||
|
||||
/**
|
||||
* @return the ID of the listener
|
||||
*/
|
||||
UUID getListenerId();
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package de.maxhenkel.voicechat.api.audiolistener;
|
||||
|
||||
import de.maxhenkel.voicechat.api.ServerPlayer;
|
||||
import de.maxhenkel.voicechat.api.packets.SoundPacket;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface PlayerAudioListener extends AudioListener {
|
||||
|
||||
/**
|
||||
* @return the {@link UUID} of the player that is listened to
|
||||
*/
|
||||
UUID getPlayerUuid();
|
||||
|
||||
public interface Builder {
|
||||
|
||||
/**
|
||||
* <b>Note</b>: It is required to either set a player with this method or with {@link #setPlayer(UUID)}
|
||||
*
|
||||
* @param player the player that should be listened to
|
||||
*/
|
||||
Builder setPlayer(ServerPlayer player);
|
||||
|
||||
/**
|
||||
* <b>Note</b>: It is required to either set a player with this method or with {@link #setPlayer(ServerPlayer)}
|
||||
*
|
||||
* @param playerUuid the player UUID that should be listened to
|
||||
*/
|
||||
Builder setPlayer(UUID playerUuid);
|
||||
|
||||
/**
|
||||
* <b>Note</b>: It is required to set a listener
|
||||
*
|
||||
* @param listener the listener
|
||||
*/
|
||||
Builder setPacketListener(Consumer<SoundPacket> listener);
|
||||
|
||||
/**
|
||||
* @return the built listener
|
||||
* @throws IllegalStateException if the player or the listener is not set
|
||||
*/
|
||||
PlayerAudioListener build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Utilities for listening to all audio a player would theoretically receive.
|
||||
* <p>
|
||||
* Can be obtained by calling {@link de.maxhenkel.voicechat.api.VoicechatServerApi#playerAudioListenerBuilder()}.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.audiolistener;
|
||||
@@ -0,0 +1,52 @@
|
||||
package de.maxhenkel.voicechat.api.audiosender;
|
||||
|
||||
public interface AudioSender {
|
||||
|
||||
/**
|
||||
* @param whispering if the player should whisper
|
||||
* @return the audio sender itself
|
||||
*/
|
||||
AudioSender whispering(boolean whispering);
|
||||
|
||||
/**
|
||||
* @return if the player is whispering
|
||||
*/
|
||||
boolean isWhispering();
|
||||
|
||||
/**
|
||||
* Sets the sequence number of the packet.
|
||||
* <br/>
|
||||
* Setting this will override the automatic sequence numbering.
|
||||
* <br/>
|
||||
* If you set this value, consequent calls to {@link AudioSender#send(byte[])} will increase this number by 1.
|
||||
* If you don't intend this, you need to set the sequence number every time before calling {@link AudioSender#send(byte[])}.
|
||||
* <br/>
|
||||
* Calling {@link AudioSender#reset()} will also reset the sequence number to start with <code>0</code> again.
|
||||
*
|
||||
* @param sequenceNumber the sequence number (Must be >= 0)
|
||||
* @return the audio sender itself
|
||||
*/
|
||||
AudioSender sequenceNumber(long sequenceNumber);
|
||||
|
||||
/**
|
||||
* @return if a microphone packet can be sent. This will return false if the player has the mod installed or the {@link AudioSender} is not registered.
|
||||
*/
|
||||
boolean canSend();
|
||||
|
||||
/**
|
||||
* Acts as if the player has sent a microphone packet.
|
||||
*
|
||||
* @param opusEncodedAudioData the opus encoded audio data
|
||||
* @return <code>true</code> if the packet was sent, <code>false</code> if the sender does have the mod installed or the {@link AudioSender} is not registered
|
||||
*/
|
||||
boolean send(byte[] opusEncodedAudioData);
|
||||
|
||||
/**
|
||||
* Resets the sequence number and indicates to clients that the current audio stream is paused/stopped.
|
||||
* <br/>
|
||||
* This method should be called when the sending of audio is paused or stopped.
|
||||
* You can still send audio after this method is called.
|
||||
*/
|
||||
boolean reset();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Utilities for simulating players sending audio without the mod.
|
||||
* <p>
|
||||
* Can be obtained by calling {@link de.maxhenkel.voicechat.api.VoicechatServerApi#createAudioSender(de.maxhenkel.voicechat.api.VoicechatConnection)}.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.audiosender;
|
||||
@@ -0,0 +1,100 @@
|
||||
package de.maxhenkel.voicechat.api.config;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatClientApi;
|
||||
import de.maxhenkel.voicechat.api.VoicechatServerApi;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* An interface to access a config.
|
||||
* This is kept very generic, so it can be used for any config type.
|
||||
* <br/>
|
||||
* This contains a few default methods to get primitive values from the config.
|
||||
* <br/>
|
||||
* <b>NOTE</b>: You need to implement more complex values yourself (e.g. enums).
|
||||
* <br/>
|
||||
* Can be obtained by calling {@link VoicechatServerApi#getServerConfig()} or {@link VoicechatClientApi#getClientConfig()}.
|
||||
*/
|
||||
public interface ConfigAccessor {
|
||||
|
||||
/**
|
||||
* Checks if the config has the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @return <code>true</code> if the config has the key, <code>false</code> otherwise
|
||||
*/
|
||||
boolean hasKey(String key);
|
||||
|
||||
/**
|
||||
* Gets the raw value of the given key.
|
||||
* <b>NOTE</b>: This gets the <i>raw</i> value from the config, so it will be a {@link String} even if the value is a number, a boolean or an enum.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value or <code>null</code> if the key doesn't exist
|
||||
*/
|
||||
@Nullable
|
||||
String getValue(String key);
|
||||
|
||||
/**
|
||||
* Gets the string value of the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @param def the default value
|
||||
* @return the value or the default value if the key doesn't exist
|
||||
*/
|
||||
default String getString(String key, String def) {
|
||||
String value = getValue(key);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the boolean value of the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @param def the default value
|
||||
* @return the boolean value, <code>false</code> if the value is not <code>"true"</code> or the default value if the key doesn't exist
|
||||
*/
|
||||
default boolean getBoolean(String key, boolean def) {
|
||||
String value = getValue(key);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the integer value of the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @param def the default value
|
||||
* @return the value or the default value if the key doesn't exist
|
||||
* @throws NumberFormatException if the value is not an integer
|
||||
*/
|
||||
default int getInt(String key, int def) {
|
||||
String value = getValue(key);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the double value of the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @param def the default value
|
||||
* @return the value or the default value if the key doesn't exist
|
||||
* @throws NumberFormatException if the value is not a double
|
||||
*/
|
||||
default double getDouble(String key, double def) {
|
||||
String value = getValue(key);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package de.maxhenkel.voicechat.api.config;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatClientApi;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* An interface to access client side adjusted volumes.
|
||||
* <br/>
|
||||
* Can be obtained by calling {@link VoicechatClientApi#getVolumeConfig()}.
|
||||
*/
|
||||
public interface VolumeConfigAccessor {
|
||||
|
||||
/**
|
||||
* Gets the volume of a player by its UUID.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* This will always return a value, even if the player is not in the volume config.
|
||||
* <br/>
|
||||
* By default, the volume will be <code>1.0</code>.
|
||||
* A volume of <code>0.0</code> means this player is muted.
|
||||
* Can be larger than <code>1.0</code>.
|
||||
* Also works for players that are not online.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* If you want the <code>Other</code> volume (All volumes that are not covered by categories or players), use the UUID <code>00000000-0000-0000-0000-000000000000</code>.
|
||||
*
|
||||
* @param uuid the UUID of the player
|
||||
* @return the volume of the player
|
||||
* @throws NullPointerException if the UUID is null
|
||||
*/
|
||||
double getVolume(UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets the volume of a category by its UUID.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* This will always return a value, even if the category doesn't exist.
|
||||
* <br/>
|
||||
* By default, the volume will be <code>1.0</code>.
|
||||
* A volume of <code>0.0</code> means this category is muted.
|
||||
* Can be larger than <code>1.0</code>.
|
||||
* Also works for categories that are currently not registered.
|
||||
*
|
||||
* @param category the category
|
||||
* @return the volume of the category
|
||||
* @throws NullPointerException if the category is null
|
||||
*/
|
||||
double getCategoryVolume(String category);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Everything configuration related.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.config;
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatClientApi;
|
||||
|
||||
public interface ClientEvent extends Event {
|
||||
|
||||
/**
|
||||
* @return the voice chat client API
|
||||
*/
|
||||
VoicechatClientApi getVoicechat();
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Position;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This event is emitted before the sound is played on the client.
|
||||
*/
|
||||
public interface ClientReceiveSoundEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* @return the ID of the channel
|
||||
*/
|
||||
UUID getId();
|
||||
|
||||
/**
|
||||
* The unencoded audio data.
|
||||
* <br/>
|
||||
* Returns an empty array in case of the end of transmission
|
||||
*
|
||||
* @return the raw 16 bit PCM audio frame
|
||||
*/
|
||||
short[] getRawAudio();
|
||||
|
||||
/**
|
||||
* Overrides the actual audio data that is played.
|
||||
* <p>
|
||||
* This is ignored, if the {@link #getRawAudio} array is empty
|
||||
* <br>
|
||||
* Providing audio that's not 960 samples will be ignored.
|
||||
* An empty array skips this frame, which adds latency. To mute the audio, use an array filled with zeros instead.
|
||||
*
|
||||
* @param rawAudio the raw 16 bit PCM audio frame
|
||||
*/
|
||||
void setRawAudio(@Nullable short[] rawAudio);
|
||||
|
||||
public static interface EntitySound extends ClientReceiveSoundEvent {
|
||||
|
||||
/**
|
||||
* @return the UUID of the entity
|
||||
*/
|
||||
UUID getEntityId();
|
||||
|
||||
/**
|
||||
* @return if the player is whispering
|
||||
*/
|
||||
boolean isWhispering();
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
}
|
||||
|
||||
public static interface LocationalSound extends ClientReceiveSoundEvent {
|
||||
/**
|
||||
* @return the position of the sound
|
||||
*/
|
||||
Position getPosition();
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
}
|
||||
|
||||
public static interface StaticSound extends ClientReceiveSoundEvent {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
/**
|
||||
* This event is emitted before the client encodes the audio and sends it to the server.
|
||||
*/
|
||||
public interface ClientSoundEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* The unencoded audio data.
|
||||
* <br/>
|
||||
* <s>Returns an empty array in case of the end of transmission</s>
|
||||
*
|
||||
* @return the raw 16 bit PCM audio frame
|
||||
*/
|
||||
short[] getRawAudio();
|
||||
|
||||
/**
|
||||
* Overrides the actual audio data that's sent to the server.
|
||||
*
|
||||
* @param rawAudio the raw 16 bit PCM audio frame
|
||||
*/
|
||||
void setRawAudio(short[] rawAudio);
|
||||
|
||||
/**
|
||||
* @return if the player is whispering
|
||||
*/
|
||||
boolean isWhispering();
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
/**
|
||||
* This event is emitted on the client when the voice chat connects/disconnects.
|
||||
*/
|
||||
public interface ClientVoicechatConnectionEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* @return if the voice chat is connected to the server
|
||||
*/
|
||||
boolean isConnected();
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.ClientVoicechatSocket;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface ClientVoicechatInitializationEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* Sets a custom implementation of the socket used for client side voice chat traffic.
|
||||
*
|
||||
* @param socket the custom socket implementation
|
||||
*/
|
||||
void setSocketImplementation(ClientVoicechatSocket socket);
|
||||
|
||||
/**
|
||||
* @return the custom socket implementation or <code>null</code> to use voice chats default one
|
||||
*/
|
||||
@Nullable
|
||||
ClientVoicechatSocket getSocketImplementation();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Group;
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface CreateGroupEvent extends GroupEvent {
|
||||
|
||||
/**
|
||||
* @return the group that was created
|
||||
*/
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* @return the connection of the player that created the group or <code>null</code> if the group was not created by a player
|
||||
*/
|
||||
@Nullable
|
||||
VoicechatConnection getConnection();
|
||||
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
/**
|
||||
* This event is emitted when the voice chats OpenAL context is created.
|
||||
*/
|
||||
public interface CreateOpenALContextEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* @return the OpenAL context
|
||||
*/
|
||||
long getContext();
|
||||
|
||||
/**
|
||||
* @return the OpenAL device
|
||||
*/
|
||||
long getDevice();
|
||||
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
/**
|
||||
* This event is emitted when the voice chats OpenAL context is destroyed.
|
||||
*/
|
||||
public interface DestroyOpenALContextEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* @return the OpenAL context - Might be <code>0L</code> in some cases
|
||||
*/
|
||||
long getContext();
|
||||
|
||||
/**
|
||||
* @return the OpenAL device - Might be <code>0L</code> in some cases
|
||||
*/
|
||||
long getDevice();
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.packets.EntitySoundPacket;
|
||||
|
||||
/**
|
||||
* This event is emitted when an entity sound packet is about to get sent to a client.
|
||||
*/
|
||||
public interface EntitySoundPacketEvent extends SoundPacketEvent<EntitySoundPacket> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
public interface Event {
|
||||
|
||||
/**
|
||||
* @return if this event can be cancelled
|
||||
*/
|
||||
boolean isCancellable();
|
||||
|
||||
/**
|
||||
* Cancels this event.
|
||||
* Does nothing if the event isn't cancellable.
|
||||
*
|
||||
* @return if the event was actually cancelled
|
||||
*/
|
||||
boolean cancel();
|
||||
|
||||
/**
|
||||
* @return if the event was cancelled
|
||||
*/
|
||||
boolean isCancelled();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface EventRegistration {
|
||||
|
||||
/**
|
||||
* Registers an event.
|
||||
*
|
||||
* @param eventClass the class of the event you want to receive
|
||||
* @param onPacket the consumer that is called when the event was dispatched
|
||||
* @param priority the event priority - Higher values mean a higher priority
|
||||
* @param <T> the event type
|
||||
*/
|
||||
<T extends Event> void registerEvent(Class<T> eventClass, Consumer<T> onPacket, int priority);
|
||||
|
||||
/**
|
||||
* Registers an event.
|
||||
*
|
||||
* @param eventClass the class of the event you want to receive
|
||||
* @param onPacket the consumer that is called when the event was dispatched
|
||||
* @param <T> the event type
|
||||
*/
|
||||
default <T extends Event> void registerEvent(Class<T> eventClass, Consumer<T> onPacket) {
|
||||
registerEvent(eventClass, onPacket, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Group;
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface GroupEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return the group - <code>null</code> if there is no group
|
||||
*/
|
||||
@Nullable
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* @return the connection of the player
|
||||
*/
|
||||
@Nullable
|
||||
VoicechatConnection getConnection();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Group;
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
public interface JoinGroupEvent extends GroupEvent {
|
||||
|
||||
/**
|
||||
* @return the group that was joined
|
||||
*/
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* @return the connection of the player
|
||||
*/
|
||||
VoicechatConnection getConnection();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Group;
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface LeaveGroupEvent extends GroupEvent {
|
||||
|
||||
/**
|
||||
* @return the group that was left or <code>null</code> if the player was not in a group
|
||||
*/
|
||||
@Nullable
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* @return the connection of the player
|
||||
*/
|
||||
VoicechatConnection getConnection();
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.packets.LocationalSoundPacket;
|
||||
|
||||
/**
|
||||
* This event is emitted when a locational sound packet is about to get sent to a client.
|
||||
*/
|
||||
public interface LocationalSoundPacketEvent extends SoundPacketEvent<LocationalSoundPacket> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
/**
|
||||
* This event is emitted before the {@link ClientSoundEvent} is getting called.
|
||||
* It allows you to merge audio into the audio that is captured from the microphone.
|
||||
* <br/>
|
||||
* This is called even when the player is muted or not talking.
|
||||
* <br/>
|
||||
* When the voice chat it disabled, this event is not called.
|
||||
*/
|
||||
public interface MergeClientSoundEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* Merges the audio into the audio that is captured from the microphone.
|
||||
* <br/>
|
||||
* Calling this multiple times will merge the audio multiple times into the same audio frame.
|
||||
*
|
||||
* @param audio the audio that should get merged
|
||||
*/
|
||||
void mergeAudio(short[] audio);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
/**
|
||||
* This event is emitted on the client when the state of the microphone changes.
|
||||
*/
|
||||
public interface MicrophoneMuteEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* @return if the microphone is muted
|
||||
*/
|
||||
boolean isDisabled();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.packets.MicrophonePacket;
|
||||
|
||||
/**
|
||||
* This event is emitted when a microphone packet arrives at the server.
|
||||
*/
|
||||
public interface MicrophonePacketEvent extends PacketEvent<MicrophonePacket> {
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatClientApi;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This event is emitted when an icon is getting rendered.
|
||||
* <br/>
|
||||
* This event should not be used to do any actual rendering.
|
||||
* Just use this event to cancel the rendering of the icon.
|
||||
* <br/>
|
||||
* <b>Warning: </b> Don't do heavy operations in this event, as it will block the render thread!
|
||||
* <br/>
|
||||
* <br/>
|
||||
* <b>Note: </b> Don't keep references to this event. It will be reused for every icon render to avoid allocations.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* Use {@link VoicechatClientApi#isTalking(UUID)}, {@link VoicechatClientApi#isWhispering(UUID)},
|
||||
* {@link VoicechatClientApi#isDisabled(UUID)} and {@link VoicechatClientApi#isDisconnected(UUID)}
|
||||
* to get the status of the player and render it using your mod loaders render event system.
|
||||
*/
|
||||
public interface NameTagIconRenderEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* @return the UUID of the entity the icon is being rendered for
|
||||
*/
|
||||
UUID getEntityId();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Position;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This event is emitted for every audio chunk for every audio channel.
|
||||
* These events are meant to be used to modify OpenAL effects.
|
||||
* <br/>
|
||||
* This specific event is emitted after the position of the sound is set, but before the any other OpenAL calls.
|
||||
* Use {@link Pre} or {@link Post} get earlier or later events respectively.
|
||||
*/
|
||||
public interface OpenALSoundEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* Returns the position of the sound.
|
||||
* This returns <code>null</code> for static sounds.
|
||||
*
|
||||
* @return the position of the sound
|
||||
*/
|
||||
@Nullable
|
||||
Position getPosition();
|
||||
|
||||
/**
|
||||
* This returns <code>null</code> for non audio channel sounds, like microphone testing.
|
||||
*
|
||||
* @return the unique ID of the audio channel
|
||||
*/
|
||||
@Nullable
|
||||
UUID getChannelId();
|
||||
|
||||
/**
|
||||
* @return the OpenAL source
|
||||
*/
|
||||
int getSource();
|
||||
|
||||
/**
|
||||
* @return the category of the sound
|
||||
*/
|
||||
@Nullable
|
||||
String getCategory();
|
||||
|
||||
/**
|
||||
* This event is emitted before any OpenAL calls were made by the voice chat.
|
||||
*/
|
||||
public interface Pre extends OpenALSoundEvent {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is emitted after all OpenAL calls by the voice chat and the audio is added to the buffer queue.
|
||||
*/
|
||||
public interface Post extends OpenALSoundEvent {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
import de.maxhenkel.voicechat.api.packets.Packet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface PacketEvent<T extends Packet> extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return the packet
|
||||
*/
|
||||
T getPacket();
|
||||
|
||||
/**
|
||||
* @return the connection of the player that should receive this packet
|
||||
*/
|
||||
@Nullable
|
||||
VoicechatConnection getReceiverConnection();
|
||||
|
||||
/**
|
||||
* @return the connection of the player that sent this packet or <code>null</code> if it wasn't sent by a player
|
||||
*/
|
||||
@Nullable
|
||||
VoicechatConnection getSenderConnection();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
public interface PlayerConnectedEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return the connection of the player
|
||||
*/
|
||||
VoicechatConnection getConnection();
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface PlayerDisconnectedEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return the UUID of the player
|
||||
*/
|
||||
UUID getPlayerUuid();
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Called when a player changes its state.
|
||||
* For example if voice chat connects/disconnects, the player joins/leaves a group or disables voice chat.
|
||||
*/
|
||||
public interface PlayerStateChangedEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return if the player disabled voice chat
|
||||
*/
|
||||
boolean isDisabled();
|
||||
|
||||
/**
|
||||
* @return if the player is disconnected from voice chat
|
||||
*/
|
||||
boolean isDisconnected();
|
||||
|
||||
/**
|
||||
* @return the uuid of the player
|
||||
*/
|
||||
UUID getPlayerUuid();
|
||||
|
||||
/**
|
||||
* @return the connection of the player
|
||||
*/
|
||||
@Nullable
|
||||
VoicechatConnection getConnection();
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
public interface RegisterVolumeCategoryEvent extends VolumeCategoryEvent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Group;
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This event is only cancellable if the group is persistent
|
||||
*/
|
||||
public interface RemoveGroupEvent extends GroupEvent {
|
||||
|
||||
/**
|
||||
* @return the group that was removed
|
||||
*/
|
||||
Group getGroup();
|
||||
|
||||
/**
|
||||
* @return <code>null</code>
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
VoicechatConnection getConnection();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatServerApi;
|
||||
|
||||
public interface ServerEvent extends Event {
|
||||
|
||||
/**
|
||||
* @return the voice chat server API
|
||||
*/
|
||||
VoicechatServerApi getVoicechat();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.packets.Packet;
|
||||
|
||||
public interface SoundPacketEvent<T extends Packet> extends PacketEvent<T> {
|
||||
|
||||
String SOURCE_GROUP = "group";
|
||||
String SOURCE_PROXIMITY = "proximity";
|
||||
String SOURCE_SPECTATOR = "spectator";
|
||||
String SOURCE_PLUGIN = "plugin";
|
||||
|
||||
/**
|
||||
* Where the packet originated from.
|
||||
* It can be either {@value SOURCE_GROUP} for group chats,
|
||||
* {@value SOURCE_PROXIMITY} for proximity sound,
|
||||
* {@value SOURCE_SPECTATOR} for spectator sound
|
||||
* or {@value SOURCE_PLUGIN} if the packet was sent from a plugin.
|
||||
*
|
||||
* @return the source of the packet
|
||||
*/
|
||||
String getSource();
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.packets.StaticSoundPacket;
|
||||
|
||||
/**
|
||||
* This event is emitted when a static sound packet is about to get sent to a client.
|
||||
*/
|
||||
public interface StaticSoundPacketEvent extends SoundPacketEvent<StaticSoundPacket> {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
public interface UnregisterVolumeCategoryEvent extends VolumeCategoryEvent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatConnection;
|
||||
import de.maxhenkel.voicechat.api.packets.MicrophonePacket;
|
||||
|
||||
/**
|
||||
* This event is emitted after a microphone packet arrives at the server and the distance is processed.
|
||||
* This can be used to modify the distance at which other players can hear this packet.
|
||||
*/
|
||||
public interface VoiceDistanceEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return the microphone packet
|
||||
*/
|
||||
MicrophonePacket getPacket();
|
||||
|
||||
/**
|
||||
* @return the connection of the player
|
||||
*/
|
||||
VoicechatConnection getSenderConnection();
|
||||
|
||||
/**
|
||||
* This returns either the default distance that's set on the server or the modified distance if another subscriber changed it already.
|
||||
* In case a player is whispering, this will return the whisper distance.
|
||||
* The whisper state can be obtained by calling {@link #getPacket()} and getting {@link MicrophonePacket#isWhispering()}.
|
||||
*
|
||||
* @return the distance in blocks
|
||||
*/
|
||||
float getDistance();
|
||||
|
||||
/**
|
||||
* Sets the distance this player sends audio at.
|
||||
* Note that this also includes the whisper distance, if the player is whispering.
|
||||
*
|
||||
* @param distance the distance in blocks
|
||||
*/
|
||||
void setDistance(float distance);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.ServerPlayer;
|
||||
|
||||
public interface VoiceHostEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return the voice host string
|
||||
*/
|
||||
String getVoiceHost();
|
||||
|
||||
/**
|
||||
* Overwrites voice chats voice host - This is sent to the client and used by it to connect to the server.
|
||||
*
|
||||
* @param voiceHost the voice host string
|
||||
*/
|
||||
void setVoiceHost(String voiceHost);
|
||||
|
||||
/**
|
||||
* @return the player that is connecting
|
||||
*/
|
||||
ServerPlayer getPlayer();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
/**
|
||||
* This event is emitted on the client when the voice chat is getting enabled/disabled.
|
||||
*/
|
||||
public interface VoicechatDisableEvent extends ClientEvent {
|
||||
|
||||
/**
|
||||
* @return if the voice chat is disabled
|
||||
*/
|
||||
boolean isDisabled();
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
public interface VoicechatServerStartedEvent extends ServerEvent {
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatSocket;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface VoicechatServerStartingEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* Sets a custom implementation of the socket used for voice chat traffic.
|
||||
*
|
||||
* @param socket the custom socket implementation
|
||||
*/
|
||||
void setSocketImplementation(VoicechatSocket socket);
|
||||
|
||||
/**
|
||||
* @return the custom socket implementation or <code>null</code> to use voice chats default one
|
||||
*/
|
||||
@Nullable
|
||||
VoicechatSocket getSocketImplementation();
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
public interface VoicechatServerStoppedEvent extends ServerEvent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VolumeCategory;
|
||||
|
||||
public interface VolumeCategoryEvent extends ServerEvent {
|
||||
|
||||
/**
|
||||
* @return the volume category
|
||||
*/
|
||||
VolumeCategory getVolumeCategory();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* All registerable events.
|
||||
* <p>
|
||||
* Events can be registered by calling {@link de.maxhenkel.voicechat.api.events.EventRegistration#registerEvent}.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.events;
|
||||
@@ -0,0 +1,37 @@
|
||||
package de.maxhenkel.voicechat.api.mp3;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatApi;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* You can obtain an instance of this class by calling {@link VoicechatApi#createMp3Decoder}.
|
||||
*/
|
||||
public interface Mp3Decoder {
|
||||
|
||||
/**
|
||||
* Decodes the MP3 file and returns the decoded audio data as PCM samples.
|
||||
*
|
||||
* @return the decoded audio data as PCM samples
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
short[] decode() throws IOException;
|
||||
|
||||
/**
|
||||
* Decodes the MP3 file if {@link #decode()} has not been called before.
|
||||
*
|
||||
* @return the audio format of the decoded audio data
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
AudioFormat getAudioFormat() throws IOException;
|
||||
|
||||
/**
|
||||
* Decodes the MP3 file if {@link #decode()} has not been called before.
|
||||
*
|
||||
* @return the bitrate of the mp3 file
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
int getBitrate() throws IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.maxhenkel.voicechat.api.mp3;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatApi;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* You can obtain an instance of this class by calling {@link VoicechatApi#createMp3Encoder}.
|
||||
*/
|
||||
public interface Mp3Encoder {
|
||||
|
||||
/**
|
||||
* Encodes the given PCM samples and writes it to the provided output stream.
|
||||
*
|
||||
* @param samples the PCM samples to encode
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
void encode(short[] samples) throws IOException;
|
||||
|
||||
/**
|
||||
* Closes the encoder and flushes the output stream.
|
||||
* Also writes leftover mp3 data to the output stream.
|
||||
*
|
||||
* <b>NOTE</b>: Not closing encoders will cause a memory leak in voice chat versions <code><2.6.3</code>!
|
||||
*
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
void close() throws IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Wrappers for mp3 encoding and decoding.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.mp3;
|
||||
@@ -0,0 +1,45 @@
|
||||
package de.maxhenkel.voicechat.api.opus;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatApi;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Instances can be obtained by calling {@link VoicechatApi#createDecoder()}.
|
||||
*/
|
||||
public interface OpusDecoder {
|
||||
|
||||
/**
|
||||
* Decodes opus encoded audio data to 16 bit PCM audio.
|
||||
*
|
||||
* @param data the opus encoded data or <code>null</code> to do PLC
|
||||
* @return the 16 bit PCM audio data
|
||||
*/
|
||||
short[] decode(@Nullable byte[] data);
|
||||
|
||||
/**
|
||||
* Decodes the provided packet and recovers previous lost frames using FEC.
|
||||
*
|
||||
* @param input the input packet
|
||||
* @param frames the number of frames to return (min 1 for just the current frame)
|
||||
* @return an array containing the decoded frames - the length of the array is equal to {@param frames}
|
||||
*/
|
||||
short[][] decode(byte[] input, int frames);
|
||||
|
||||
/**
|
||||
* Resets the decoders state.
|
||||
*/
|
||||
void resetState();
|
||||
|
||||
/**
|
||||
* @return if the decoder is closed
|
||||
*/
|
||||
boolean isClosed();
|
||||
|
||||
/**
|
||||
* Closes the decoder.
|
||||
* <b>NOTE</b>: Not closing encoders will cause a memory leak in voice chat versions <code><2.6.3</code>!
|
||||
*/
|
||||
void close();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package de.maxhenkel.voicechat.api.opus;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatApi;
|
||||
|
||||
/**
|
||||
* Instances can be obtained by calling {@link VoicechatApi#createEncoder()}.
|
||||
*/
|
||||
public interface OpusEncoder {
|
||||
|
||||
/**
|
||||
* Encodes 16 bit PCM audio with opus.
|
||||
*
|
||||
* @param rawAudio the raw 16 bit PCM audio
|
||||
* @return the opus encoded data
|
||||
*/
|
||||
byte[] encode(short[] rawAudio);
|
||||
|
||||
/**
|
||||
* Resets the encoders state.
|
||||
*/
|
||||
void resetState();
|
||||
|
||||
/**
|
||||
* @return if the encoder is closed
|
||||
*/
|
||||
boolean isClosed();
|
||||
|
||||
/**
|
||||
* Closes the encoder.
|
||||
* <b>NOTE</b>: Not closing encoders will cause a memory leak in voice chat versions <code><2.6.3</code>!
|
||||
*/
|
||||
void close();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.maxhenkel.voicechat.api.opus;
|
||||
|
||||
/**
|
||||
* The different Opus encoder modes
|
||||
*/
|
||||
public enum OpusEncoderMode {
|
||||
VOIP, AUDIO, RESTRICTED_LOWDELAY;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Wrappers for the Opus codec.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.opus;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The main Simple Voice Chat API package.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api;
|
||||
@@ -0,0 +1,64 @@
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Position;
|
||||
import de.maxhenkel.voicechat.api.VoicechatServerApi;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ConvertablePacket {
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: Make sure to set {@link SoundPacket.Builder#channelId(UUID)} to avoid conflicts with other channels.
|
||||
*
|
||||
* @return a builder to build an entity sound packet based on this packet
|
||||
*/
|
||||
EntitySoundPacket.Builder<?> entitySoundPacketBuilder();
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: Make sure to set {@link SoundPacket.Builder#channelId(UUID)} to avoid conflicts with other channels.
|
||||
*
|
||||
* @return a builder to build a locational sound packet based on this packet
|
||||
*/
|
||||
LocationalSoundPacket.Builder<?> locationalSoundPacketBuilder();
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: Make sure to set {@link SoundPacket.Builder#channelId(UUID)} to avoid conflicts with other channels.
|
||||
*
|
||||
* @return a builder to build a static sound packet based on this packet
|
||||
*/
|
||||
StaticSoundPacket.Builder<?> staticSoundPacketBuilder();
|
||||
|
||||
/**
|
||||
* Converts this packet to an entity sound packet.
|
||||
*
|
||||
* @param entityUuid the UUID of the entity
|
||||
* @param whispering if the entity is whispering
|
||||
* @return the entity sound packet
|
||||
* @throws UnsupportedOperationException if this is called on a packet created by {@link VoicechatServerApi#createPacket()}
|
||||
* @deprecated use {@link #entitySoundPacketBuilder()}
|
||||
*/
|
||||
@Deprecated
|
||||
EntitySoundPacket toEntitySoundPacket(UUID entityUuid, boolean whispering);
|
||||
|
||||
/**
|
||||
* Converts this packet to a locational sound packet.
|
||||
*
|
||||
* @param position the position of the audio
|
||||
* @return the locational sound packet
|
||||
* @throws UnsupportedOperationException if this is called on a packet created by {@link VoicechatServerApi#createPacket()}
|
||||
* @deprecated use {@link #locationalSoundPacketBuilder()}
|
||||
*/
|
||||
@Deprecated
|
||||
LocationalSoundPacket toLocationalSoundPacket(Position position);
|
||||
|
||||
/**
|
||||
* Converts this packet to a static sound packet.
|
||||
*
|
||||
* @return the static sound packet
|
||||
* @throws UnsupportedOperationException if this is called on a packet created by {@link VoicechatServerApi#createPacket()}
|
||||
* @deprecated use {@link #staticSoundPacketBuilder()}
|
||||
*/
|
||||
@Deprecated
|
||||
StaticSoundPacket toStaticSoundPacket();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* The receiver of this event will hear the sound from the specified entity.
|
||||
* This can be done for all entities, but only players will show the speaker icon.
|
||||
* If the entity is further away than the maximum voice distance, the receiving player won't actually hear the sound.
|
||||
*/
|
||||
public interface EntitySoundPacket extends SoundPacket {
|
||||
|
||||
/**
|
||||
* @return the UUID of the entity
|
||||
*/
|
||||
UUID getEntityUuid();
|
||||
|
||||
/**
|
||||
* @return if the entity is whispering
|
||||
*/
|
||||
boolean isWhispering();
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
|
||||
/**
|
||||
* A builder to build an entity sound packet.
|
||||
*
|
||||
* <b>NOTE</b>: Some values are required to be set.
|
||||
*
|
||||
* @param <T> the builder itself
|
||||
*/
|
||||
public interface Builder<T extends Builder<T>> extends SoundPacket.Builder<T, EntitySoundPacket> {
|
||||
|
||||
/**
|
||||
* This is required to be set!
|
||||
* <br>
|
||||
* The entity UUID is also used as the sender of the packet.
|
||||
*
|
||||
* @param entityUuid the UUID of the entity
|
||||
* @return the builder
|
||||
*/
|
||||
T entityUuid(UUID entityUuid);
|
||||
|
||||
/**
|
||||
* @param whispering if the entity should be whispering
|
||||
* @return the builder
|
||||
*/
|
||||
T whispering(boolean whispering);
|
||||
|
||||
/**
|
||||
* @param distance the distance, this packet can be heard
|
||||
* @return the builder
|
||||
*/
|
||||
T distance(float distance);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
|
||||
import de.maxhenkel.voicechat.api.Position;
|
||||
|
||||
/**
|
||||
* The receiver of this event will hear the sound from the specified location.
|
||||
* If the location is further away than the maximum voice distance, the receiving player won't actually hear the sound.
|
||||
*/
|
||||
public interface LocationalSoundPacket extends SoundPacket {
|
||||
|
||||
/**
|
||||
* @return the audio location
|
||||
*/
|
||||
Position getPosition();
|
||||
|
||||
/**
|
||||
* @return the distance, the audio can be heard
|
||||
*/
|
||||
float getDistance();
|
||||
|
||||
/**
|
||||
* A builder to build a locational sound packet.
|
||||
*
|
||||
* <b>NOTE</b>: Some values are required to be set.
|
||||
*
|
||||
* @param <T> the builder itself
|
||||
*/
|
||||
public interface Builder<T extends Builder<T>> extends SoundPacket.Builder<T, LocationalSoundPacket> {
|
||||
|
||||
/**
|
||||
* This is required to be set!
|
||||
*
|
||||
* @param position the position of the sound
|
||||
* @return the builder
|
||||
*/
|
||||
T position(Position position);
|
||||
|
||||
/**
|
||||
* @param distance the distance, this packet can be heard
|
||||
* @return the builder
|
||||
*/
|
||||
T distance(float distance);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
|
||||
public interface MicrophonePacket extends Packet, ConvertablePacket {
|
||||
|
||||
/**
|
||||
* @return if the player is whispering
|
||||
*/
|
||||
boolean isWhispering();
|
||||
|
||||
/**
|
||||
* @return the opus encoded audio data from the player
|
||||
*/
|
||||
byte[] getOpusEncodedData();
|
||||
|
||||
/**
|
||||
* Allows you to modify or replace the opus encoded audio data.
|
||||
*
|
||||
* @param data the opus encoded audio data to replace
|
||||
*/
|
||||
void setOpusEncodedData(byte[] data);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
|
||||
public interface Packet {
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatServerApi;
|
||||
import de.maxhenkel.voicechat.api.VolumeCategory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface SoundPacket extends Packet, ConvertablePacket {
|
||||
|
||||
/**
|
||||
* @return the channel ID of the sound packet
|
||||
*/
|
||||
UUID getChannelId();
|
||||
|
||||
/**
|
||||
* @return the sender of this packet - doesn't necessarily need to be a player's UUID
|
||||
*/
|
||||
UUID getSender();
|
||||
|
||||
/**
|
||||
* @return the opus encoded audio data
|
||||
*/
|
||||
byte[] getOpusEncodedData();
|
||||
|
||||
/**
|
||||
* @return the sequence number of the packet
|
||||
*/
|
||||
long getSequenceNumber();
|
||||
|
||||
/**
|
||||
* @return the category ID of the sound packet
|
||||
*/
|
||||
@Nullable
|
||||
String getCategory();
|
||||
|
||||
/**
|
||||
* A builder to build a sound packet.
|
||||
*
|
||||
* @param <T> the builder itself
|
||||
* @param <P> the packet, the builder builds
|
||||
*/
|
||||
public interface Builder<T extends Builder<T, P>, P extends SoundPacket> {
|
||||
|
||||
/**
|
||||
* <b>NOTE</b>: Make sure to set this to a unique value to avoid conflicts with other channels.
|
||||
* This value needs to be the same when sending multiple packets of the same channel.
|
||||
*
|
||||
* @param channelId the channel ID of the sound packet
|
||||
* @return the builder
|
||||
*/
|
||||
T channelId(UUID channelId);
|
||||
|
||||
/**
|
||||
* Sets the sender of the sound packet.
|
||||
* This must be set if this is created using {@link VoicechatServerApi#createPacket()}.
|
||||
*
|
||||
* @param sender the sender of the sound packet
|
||||
* @return the builder
|
||||
*/
|
||||
T sender(UUID sender);
|
||||
|
||||
/**
|
||||
* @param data the opus encoded audio data
|
||||
* @return the builder
|
||||
*/
|
||||
T opusEncodedData(byte[] data);
|
||||
|
||||
/**
|
||||
* Sets the sequence number of the sound packet.
|
||||
* The sequence number is set automatically for everything except when using {@link VoicechatServerApi#createPacket()}.
|
||||
* <br/>
|
||||
* <br/>
|
||||
* <b>NOTE</b>: You should only change this when using {@link VoicechatServerApi#createPacket()}.
|
||||
*
|
||||
* @param sequenceNumber the sequence number of the sound packet
|
||||
* @return the builder
|
||||
*/
|
||||
T sequenceNumber(long sequenceNumber);
|
||||
|
||||
/**
|
||||
* Make sure you registered your category before using it.
|
||||
* See {@link de.maxhenkel.voicechat.api.VoicechatServerApi#registerVolumeCategory(VolumeCategory)}.
|
||||
*
|
||||
* @param category the category ID of the sound packet
|
||||
* @return the builder
|
||||
*/
|
||||
T category(@Nullable String category);
|
||||
|
||||
/**
|
||||
* Builds the packet.
|
||||
* <b>NOTE</b>: If you are missing required values, this will throw an {@link IllegalStateException}.
|
||||
*
|
||||
* @return the packet
|
||||
*/
|
||||
P build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
|
||||
/**
|
||||
* The receiver of this event will hear the sound non-directional.
|
||||
* This is what is basically used for group chats.
|
||||
*/
|
||||
public interface StaticSoundPacket extends SoundPacket {
|
||||
|
||||
/**
|
||||
* A builder to build a static sound packet.
|
||||
*
|
||||
* @param <T> the builder itself
|
||||
*/
|
||||
public interface Builder<T extends StaticSoundPacket.Builder<T>> extends SoundPacket.Builder<T, StaticSoundPacket> {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* All voice chat UDP packets.
|
||||
*/
|
||||
package de.maxhenkel.voicechat.api.packets;
|
||||
Reference in new issue
Block a user