diff --git a/api/src/main/java/com/craftmend/openaudiomc/api/VoiceApi.java b/api/src/main/java/com/craftmend/openaudiomc/api/VoiceApi.java index c41787d5c0..2ea551b409 100644 --- a/api/src/main/java/com/craftmend/openaudiomc/api/VoiceApi.java +++ b/api/src/main/java/com/craftmend/openaudiomc/api/VoiceApi.java @@ -3,6 +3,7 @@ import com.craftmend.openaudiomc.api.channels.VoiceChannel; import com.craftmend.openaudiomc.api.clients.Client; import com.craftmend.openaudiomc.api.voice.CustomPlayerFilter; +import com.craftmend.openaudiomc.api.voice.DisplayOverride; import com.craftmend.openaudiomc.api.voice.VoicePeerOptions; import org.jetbrains.annotations.Nullable; @@ -67,6 +68,19 @@ static VoiceApi getInstance() { */ void addStaticPeer(Client client, Client peerToAdd, boolean visible, boolean mutual); + /** + * Add a peer (partner) to someone's voice chat. + * This would let the client hear the peerToAdd as a global voice (without spatial audio/distance) until it's removed. + * + * @param client The web client that should receive this update + * @param peerToAdd The peer that should be added + * @param visible Whether the peer should be visible in the client + * @param mutual Whether the peer should also hear the client (repeat the call for mutual) + * @param displayOverride A display override, which can be used to change the display name and skin of a player in the voice chat system. + * @since 6.10.2 + */ + void addStaticPeer(Client client, Client peerToAdd, boolean visible, boolean mutual, DisplayOverride displayOverride); + /** * Remove a global peer from someone's voice chat. * This would remove a static peer if they have been added through addStaticPeer, but not diff --git a/api/src/main/java/com/craftmend/openaudiomc/api/voice/DisplayOverride.java b/api/src/main/java/com/craftmend/openaudiomc/api/voice/DisplayOverride.java new file mode 100644 index 0000000000..0219407392 --- /dev/null +++ b/api/src/main/java/com/craftmend/openaudiomc/api/voice/DisplayOverride.java @@ -0,0 +1,30 @@ +package com.craftmend.openaudiomc.api.voice; + +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +/** + * This class is used to override the display name of a player in the voice chat system. + * This is useful for when you want to display a different name than the player's actual name, + * to add compatibility for bedrock players or display game ranks. + * @since 6.10.2 + */ +@Data +public class DisplayOverride { + + /** + * The name that should be displayed in the voice chat system. + * MUST be 32 characters or less. + */ + @Nullable + private String name; + + /** + * The new UUID that should be used to obtain skin data. + */ + @Nullable + private UUID displayUuid; + +} diff --git a/api/src/main/java/com/craftmend/openaudiomc/api/voice/VoicePeerOptions.java b/api/src/main/java/com/craftmend/openaudiomc/api/voice/VoicePeerOptions.java index 3c81e12c52..1ebf9bb1f6 100644 --- a/api/src/main/java/com/craftmend/openaudiomc/api/voice/VoicePeerOptions.java +++ b/api/src/main/java/com/craftmend/openaudiomc/api/voice/VoicePeerOptions.java @@ -3,6 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.jetbrains.annotations.Nullable; @Data @NoArgsConstructor @@ -36,13 +37,21 @@ public class VoicePeerOptions implements Cloneable { */ private boolean spatialAudio = true; + /** + * An optional display override, which can be used to change the display name and skin of a player in the voice chat system. + * This can be left null if no override is needed. + * @since 6.10.2 + */ + @Nullable + private DisplayOverride displayOverride; + /** * Clone the object * @return a clone of the object */ @Override public VoicePeerOptions clone() { - return new VoicePeerOptions(visible, spatialAudio); + return new VoicePeerOptions(visible, spatialAudio, null); } } diff --git a/client/public/metadata.json b/client/public/metadata.json index 2b5cc42d91..f7a2c2da08 100644 --- a/client/public/metadata.json +++ b/client/public/metadata.json @@ -1 +1 @@ -{"buildMajor":1,"buildMinor":125,"buildRevision":244,"buildTag":"dev","buildDate":"Tue Jun 11 2024","build":"1.125.244 dev"} \ No newline at end of file +{"buildMajor":1,"buildMinor":125,"buildRevision":250,"buildTag":"dev","buildDate":"Thu Jun 13 2024","build":"1.125.250 dev"} \ No newline at end of file diff --git a/client/src/client/services/voice/peers/VoicePeer.jsx b/client/src/client/services/voice/peers/VoicePeer.jsx index 4c19b6ea6e..6741ed86d0 100644 --- a/client/src/client/services/voice/peers/VoicePeer.jsx +++ b/client/src/client/services/voice/peers/VoicePeer.jsx @@ -9,6 +9,15 @@ export class VoicePeer { constructor(peerName, peerUuid, peerStreamKey, location, options) { this.options = options; + let displayName = peerName; + let displayUuid = peerUuid; + + if (options.displayOverride) { + // override display name and uuid + displayName = options.displayOverride.name || peerName; + displayUuid = options.displayOverride.displayUuid || peerUuid; + } + // register in global state setGlobalState({ voiceState: { @@ -21,6 +30,8 @@ export class VoicePeer { muted: false, loading: true, options: this.options, + displayName, + displayUuid, }, }, }, @@ -28,6 +39,8 @@ export class VoicePeer { this.peerName = peerName; this.peerUuid = peerUuid; + this.displayName = displayName; + this.displayUuid = displayUuid; this.peerStreamKey = peerStreamKey; this.location = location; this.killed = false; @@ -62,9 +75,17 @@ export class VoicePeer { } } + let { displayUuid, displayName } = this; + + if (changedOptions.displayOverride) { + // override display name and uuid + displayName = changedOptions.displayOverride.name || this.peerName; + displayUuid = changedOptions.displayOverride.displayUuid || this.peerUuid; + } + this.options = changedOptions; // update global state - setGlobalState({ voiceState: { peers: { [this.peerStreamKey]: { options: this.options } } } }); + setGlobalState({ voiceState: { peers: { [this.peerStreamKey]: { options: this.options, displayName, displayUuid } } } }); } updateLocation(x, y, z) { diff --git a/client/src/client/services/voice/peers/VoicePeerOptions.jsx b/client/src/client/services/voice/peers/VoicePeerOptions.jsx index 9b2720ccd0..e4d96d8a33 100644 --- a/client/src/client/services/voice/peers/VoicePeerOptions.jsx +++ b/client/src/client/services/voice/peers/VoicePeerOptions.jsx @@ -5,9 +5,11 @@ export class VoicePeerOptions { constructor( visible = true, spatialAudio = getGlobalState().settings.voicechatSurroundSound, + displayOverride = null, ) { this.visible = visible; this.spatialAudio = spatialAudio; + this.displayOverride = displayOverride; } } @@ -16,5 +18,6 @@ export function peerOptionsFromObj(obj) { return new VoicePeerOptions( (obj.visible !== undefined) ? obj.visible : true, (obj.spatialAudio !== undefined) ? obj.spatialAudio : getGlobalState().settings.voicechatSurroundSound, + (obj.displayOverride !== undefined) ? obj.displayOverride : null, ); } diff --git a/client/src/components/voice/VoicePeerBox.jsx b/client/src/components/voice/VoicePeerBox.jsx index b6840aec87..57aac3a383 100644 --- a/client/src/components/voice/VoicePeerBox.jsx +++ b/client/src/components/voice/VoicePeerBox.jsx @@ -17,7 +17,8 @@ function VoicePeerBox(props) { return ( +
  • {loading ? (
    ) : null} -
    +
    {`Avatar
    -
    -
    -

    +
    +
    +

    {muted ? () : null} {this.props.spatialAudio ? () : } {name} diff --git a/client/src/metadata.json b/client/src/metadata.json index 2b5cc42d91..f7a2c2da08 100644 --- a/client/src/metadata.json +++ b/client/src/metadata.json @@ -1 +1 @@ -{"buildMajor":1,"buildMinor":125,"buildRevision":244,"buildTag":"dev","buildDate":"Tue Jun 11 2024","build":"1.125.244 dev"} \ No newline at end of file +{"buildMajor":1,"buildMinor":125,"buildRevision":250,"buildTag":"dev","buildDate":"Thu Jun 13 2024","build":"1.125.250 dev"} \ No newline at end of file diff --git a/plugin/src/main/java/com/craftmend/openaudiomc/generic/api/implementaions/VoiceApiImpl.java b/plugin/src/main/java/com/craftmend/openaudiomc/generic/api/implementaions/VoiceApiImpl.java index 9fb48f29e6..75c2cc3b15 100644 --- a/plugin/src/main/java/com/craftmend/openaudiomc/generic/api/implementaions/VoiceApiImpl.java +++ b/plugin/src/main/java/com/craftmend/openaudiomc/generic/api/implementaions/VoiceApiImpl.java @@ -9,6 +9,7 @@ import com.craftmend.openaudiomc.api.events.client.ClientPeerRemovedEvent; import com.craftmend.openaudiomc.api.interfaces.AudioApi; import com.craftmend.openaudiomc.api.voice.CustomPlayerFilter; +import com.craftmend.openaudiomc.api.voice.DisplayOverride; import com.craftmend.openaudiomc.api.voice.VoicePeerOptions; import com.craftmend.openaudiomc.generic.client.objects.ClientConnection; import com.craftmend.openaudiomc.generic.networking.interfaces.NetworkingService; @@ -83,13 +84,24 @@ public boolean isGlobalPeer(Client haystack, Client needle) { @Override public void addStaticPeer(Client client, Client peerToAdd, boolean visible, boolean mutual) { + addStaticPeer(client, peerToAdd, visible, mutual, null); + } + + @Override + public void addStaticPeer(Client client, Client peerToAdd, boolean visible, boolean mutual, DisplayOverride displayOverride) { if (OpenAudioMc.getInstance().getPlatform() != Platform.SPIGOT) { throw new IllegalStateException("This method is only available on the spigot platform"); } + if (displayOverride != null && displayOverride.getName() != null && displayOverride.getName().length() > 32) { + throw new IllegalArgumentException("Display name cannot be longer than 32 characters"); + } + VoicePeerOptions options = new VoicePeerOptions(); options.setSpatialAudio(false); options.setVisible(visible); + // may put in null, that's fine. + options.setDisplayOverride(displayOverride); ClientConnection clientConnection = (ClientConnection) client; ClientConnection peerConnection = (ClientConnection) peerToAdd;