VoiceRouter class
Пакет: com.hypixel.hytale.server.core.modules.voice
Файл: com/hypixel/hytale/server/core/modules/voice/VoiceRouter.java
Поля (42)
| Модификаторы | Тип | Имя |
|---|---|---|
final |
int |
VERBOSE_LOG_PACKET_FREQUENCY |
|
|
break |
|
|
break |
|
|
return |
|
double |
var11 |
|
VoiceModule.PositionSnapshot |
var11 |
|
double |
var12 |
|
PacketHandler |
var14 |
|
ChannelConnection |
var15 |
|
VoiceConfig |
var2 |
|
Vector3dc |
var2 |
|
PlayerRef |
var2 |
|
Set |
var3 |
|
VoicePlayerState |
var3 |
|
UUID |
var3 |
|
int |
var3 |
|
boolean |
var4 |
|
VoiceRouter.SpeakerDescriptor |
var4 |
|
Vector3dc |
var4 |
|
VoiceModule.PositionSnapshot |
var5 |
|
VoiceRouter.SpeakerDescriptor |
var5 |
|
|
var5 |
|
RelayedVoiceData |
var5 |
|
List |
var5 |
|
UUID |
var5 |
|
VoiceRouter.SpeakerDescriptor |
var6 |
|
RelayedVoiceData |
var6 |
|
Vector3dc |
var6 |
|
int |
var6 |
|
PacketHandler |
var6 |
|
Set |
var6 |
|
PlayerVoiceFrame |
var7 |
|
RelayedVoiceData |
var7 |
|
double |
var7 |
|
ChannelConnection |
var7 |
|
float |
var7 |
|
UUID |
var8 |
|
List |
var8 |
|
|
var8 |
|
|
var8 |
|
VoiceModule.PositionSnapshot |
var9 |
|
double |
var9 |
Методы (30)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
private |
record |
ListenerCandidaterecord ListenerCandidate(double distSq, ChannelConnection voiceChannel) |
|
record |
SpeakerDescriptorrecord SpeakerDescriptor(@Nonnull UUID speakerId, @Nullable Vector3dc position, boolean isUnderwater, @Nonnull UUID worldId, int entityId) |
private |
RelayedVoiceData |
buildRelayRelayedVoiceData buildRelay(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4) |
private |
void |
dispatchInterceptedFramevoid dispatchInterceptedFrame(@Nonnull PlayerVoiceFrame var1) |
|
|
for for(VoiceRouter.ListenerCandidate var8 : var5) |
|
|
for for(UUID var5 : var1) |
|
|
for for(UUID var10 : var6) |
private |
PacketHandler |
getPlayerHandlerPacketHandler getPlayerHandler(UUID var1) |
|
|
if if(var2 == null || var3 == null) |
|
|
if if(var6 != null) |
|
|
if if(!this.loggedFirstCacheRoute && var3 > 0) |
|
|
if if(var2 % 50 == 0) |
|
|
if if(var5 == null) |
|
|
if if(var5 != null) |
|
|
if if(var6 != null) |
|
|
if if(var4 == null) |
|
|
if if(var14 != null) |
|
|
if if(var8 == null) |
private |
void |
logRoutevoid logRoute(@Nonnull VoiceRouter.SpeakerDescriptor var1, short var2, int var3) |
|
void |
removePlayerFromWorldSetvoid removePlayerFromWorldSet(@Nonnull UUID var1, @Nonnull UUID var2) |
public |
void |
removePlayerFromWorldSetsvoid removePlayerFromWorldSets(@Nonnull UUID var1) |
private |
int |
routeByProximityint routeByProximity(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull RelayedVoiceData var2, @Nullable Set<UUID> var3, @Nullable Set<UUID> var4) |
|
void |
routeExplicitFramevoid routeExplicitFrame(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4, @Nonnull Collection<UUID> var5) |
|
void |
routeProximityFramevoid routeProximityFrame(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4) |
|
void |
routeProximityFramevoid routeProximityFrame(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4, @Nullable Set<UUID> var5, @Nullable Set<UUID> var6) |
private |
int |
routeToExplicitint routeToExplicit(@Nonnull Collection<UUID> var1, @Nonnull RelayedVoiceData var2) |
public |
void |
routeVoiceFromCachevoid routeVoiceFromCache(@Nonnull PlayerRef var1, @Nonnull VoiceData var2) |
private |
boolean |
sendRelayboolean sendRelay(@Nonnull ChannelConnection var1, @Nonnull RelayedVoiceData var2) |
public |
void |
sendVoiceConfigvoid sendVoiceConfig(@Nonnull PlayerRef var1) |
public |
void |
updateSpeakerPositionCachevoid updateSpeakerPositionCache(@Nonnull PlayerRef var1, @Nonnull Vector3d var2, float var3, boolean var4, @Nonnull UUID var5, int var6, boolean var7) |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.modules.voice;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.protocol.Position;
class="kw">import com.hypixel.hytale.protocol.io.ChannelConnection;
class="kw">import com.hypixel.hytale.protocol.packets.stream.StreamType;
class="kw">import com.hypixel.hytale.protocol.packets.voice.RelayedVoiceData;
class="kw">import com.hypixel.hytale.protocol.packets.voice.VoiceCodec;
class="kw">import com.hypixel.hytale.protocol.packets.voice.VoiceConfig;
class="kw">import com.hypixel.hytale.protocol.packets.voice.VoiceData;
class="kw">import com.hypixel.hytale.server.core.io.PacketHandler;
class="kw">import com.hypixel.hytale.server.core.universe.PlayerRef;
class="kw">import com.hypixel.hytale.server.core.universe.Universe;
class="kw">import com.hypixel.hytale.server.core.util.UUIDUtil;
class="kw">import java.util.ArrayList;
class="kw">import java.util.Collection;
class="kw">import java.util.List;
class="kw">import java.util.Set;
class="kw">import java.util.UUID;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector3d;
class="kw">import org.joml.Vector3dc;
class="kw">public class VoiceRouter {
class="kw">private class="kw">static class="kw">final int VERBOSE_LOG_PACKET_FREQUENCY = 50;
class="kw">private class="kw">static class="kw">final int MAX_LISTENERS_PER_SPEAKER = 12;
class="kw">private class="kw">final VoiceModule voiceModule;
class="kw">private class="kw">final HytaleLogger logger;
class="kw">private class="kw">final ConcurrentHashMap<UUID, Set<UUID>> worldPlayerSets = new ConcurrentHashMap<>();
class="kw">private class="kw">volatile boolean loggedFirstCacheRoute = false;
class="kw">public VoiceRouter(@Nonnull VoiceModule var1) {
this.voiceModule = var1;
this.logger = var1.getLogger();
}
class="kw">public void updateSpeakerPositionCache(@Nonnull PlayerRef var1, @Nonnull Vector3d var2, float var3, boolean var4, @Nonnull UUID var5, int var6, boolean var7) {
UUID var8 = var1.getUuid();
VoiceModule.PositionSnapshot var9 = this.voiceModule.getCachedPosition(var8);
if (var9 != null && !var9.worldId().equals(var5)) {
this.removePlayerFromWorldSet(var8, var9.worldId());
}
this.worldPlayerSets.compute(var5, (var1x, var2x) -> {
Set var3 = var2x != null ? var2x : ConcurrentHashMap.newKeySet();
var3.add(var8);
class="kw">return var3;
});
this.voiceModule.updatePositionCache(var8, VoiceModule.PositionSnapshot.atEyeHeight(var2, var3, var4, var5, var6, var7));
}
class="kw">public void removePlayerFromWorldSets(@Nonnull UUID var1) {
for (UUID var3 : this.worldPlayerSets.keySet()) {
this.removePlayerFromWorldSet(var1, var3);
}
}
void removePlayerFromWorldSet(@Nonnull UUID var1, @Nonnull UUID var2) {
this.worldPlayerSets.computeIfPresent(var2, (var1x, var2x) -> {
var2x.remove(var1);
class="kw">return var2x.isEmpty() ? null : var2x;
});
}
class="kw">public void sendVoiceConfig(@Nonnull PlayerRef var1) {
VoiceConfig var2 = new VoiceConfig();
var2.voiceEnabled = this.voiceModule.isVoiceEnabled();
var2.codec = VoiceCodec.Opus;
var2.sampleRate = 48000;
var2.channels = 1;
var2.maxHearingDistance = this.voiceModule.getMaxHearingDistance();
var2.referenceDistance = this.voiceModule.getReferenceDistance();
var2.supportsVoiceStream = true;
var2.maxPacketsPerSecond = (byte)this.voiceModule.getMaxPacketsPerSecond();
var1.getPacketHandler().writeNoCache(var2);
this.logger
.at(Level.FINE)
.log(
"[VoiceConfig] Sent to %s: enabled=%s, codec=%s, sampleRate=%d, maxDistance=%.1f, refDistance=%.1f, supportsVoiceStream=true, maxPacketsPerSecond=%d",
var1.getUsername(),
var2.voiceEnabled,
var2.codec,
var2.sampleRate,
var2.maxHearingDistance,
var2.referenceDistance,
var2.maxPacketsPerSecond
);
}
class="kw">public void routeVoiceFromCache(@Nonnull PlayerRef var1, @Nonnull VoiceData var2) {
if (!this.voiceModule.isShutdown()) {
if (this.voiceModule.isVoiceEnabled()) {
if (!this.voiceModule.isPlayerMuted(var1.getUuid())) {
if (var2.opusData != null && var2.opusData.length <= this.voiceModule.getMaxPacketSize()) {
VoicePlayerState var3 = this.voiceModule.getPlayerState(var1.getUuid());
boolean var4 = var3 != null && var3.isSilenced();
VoiceModule.PositionSnapshot var5 = this.voiceModule.getCachedPosition(var1.getUuid());
if (this.voiceModule.hasPlayerVoiceInterceptors()) {
PlayerVoiceFrame var7 = new PlayerVoiceFrame(var1, var5, var4, var2.opusData, var2.sequenceNumber, var2.timestamp);
this.voiceModule.runPlayerVoiceInterceptors(var7);
this.dispatchInterceptedFrame(var7);
} else if (!var4 && var5 != null) {
VoiceRouter.SpeakerDescriptor var6 = new VoiceRouter.SpeakerDescriptor(
var1.getUuid(), var5.position(), var5.isUnderwater(), var5.worldId(), var5.networkId()
);
this.routeProximityFrame(var6, var2.opusData, var2.sequenceNumber, var2.timestamp);
}
}
}
}
}
}
class="kw">private void dispatchInterceptedFrame(@Nonnull PlayerVoiceFrame var1) {
class="kw">switch (var1.delivery()) {
case NONE:
class="kw">default:
break;
case EXPLICIT: {
VoiceRouter.SpeakerDescriptor var5 = new VoiceRouter.SpeakerDescriptor(var1.speakerId(), null, false, UUIDUtil.EMPTY_UUID, var1.entityNetworkId());
this.routeExplicitFrame(var5, var1.opus(), var1.sequenceNumber(), var1.timestamp(), var1.explicitListeners());
break;
}
case PROXIMITY: {
Vector3dc var2 = var1.position();
UUID var3 = var1.worldId();
if (var2 == null || var3 == null) {
class="kw">return;
}
VoiceRouter.SpeakerDescriptor var4 = new VoiceRouter.SpeakerDescriptor(var1.speakerId(), var2, var1.underwater(), var3, var1.entityNetworkId());
this.routeProximityFrame(var4, var1.opus(), var1.sequenceNumber(), var1.timestamp(), var1.allowedListeners(), var1.excludedListeners());
}
}
}
void routeProximityFrame(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4) {
this.routeProximityFrame(var1, var2, var3, var4, null, null);
}
void routeProximityFrame(
@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4, @Nullable Set<UUID> var5, @Nullable Set<UUID> var6
) {
var5 = this.voiceModule.getVoiceChannels().restrictAllowed(var1.speakerId(), var5);
if (var5 == null || !var5.isEmpty()) {
RelayedVoiceData var7 = this.buildRelay(var1, var2, var3, var4);
this.logRoute(var1, var3, this.routeByProximity(var1, var7, var5, var6));
}
}
void routeExplicitFrame(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4, @Nonnull Collection<UUID> var5) {
RelayedVoiceData var6 = this.buildRelay(var1, var2, var3, var4);
this.logRoute(var1, var3, this.routeToExplicit(var5, var6));
}
class="kw">private RelayedVoiceData buildRelay(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull byte[] var2, short var3, int var4) {
RelayedVoiceData var5 = new RelayedVoiceData();
var5.speakerId = var1.speakerId();
var5.entityId = var1.entityId();
var5.sequenceNumber = var3;
var5.timestamp = var4;
var5.speakerIsUnderwater = var1.isUnderwater();
var5.opusData = var2;
Vector3dc var6 = var1.position();
if (var6 != null) {
double var7 = Math.round(var6.x() * 2.0) / 2.0;
double var9 = Math.round(var6.y() * 2.0) / 2.0;
double var11 = Math.round(var6.z() * 2.0) / 2.0;
var5.speakerPosition = new Position(var7, var9, var11);
}
class="kw">return var5;
}
class="kw">private void logRoute(@Nonnull VoiceRouter.SpeakerDescriptor var1, short var2, int var3) {
if (!this.loggedFirstCacheRoute && var3 > 0) {
this.loggedFirstCacheRoute = true;
this.logger.at(Level.INFO).log("[VoiceRouter] First voice packet routed: speaker=%s, seq=%d, recipientCount=%d", var1.speakerId(), var2, var3);
}
if (var2 % 50 == 0) {
this.logger.at(Level.FINE).log("[VoiceRouter] Route seq=%d, recipients=%d", var2, var3);
}
}
class="kw">private int routeByProximity(@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nonnull RelayedVoiceData var2, @Nullable Set<UUID> var3, @Nullable Set<UUID> var4) {
List var5 = this.selectNearbyListeners(var1, var3, var4);
if (var5 == null) {
class="kw">return 0;
}
int var6 = 0;
for (VoiceRouter.ListenerCandidate var8 : var5) {
if (this.sendRelay(var8.voiceChannel(), var2)) {
var6++;
}
}
class="kw">return var6;
}
class="kw">private int routeToExplicit(@Nonnull Collection<UUID> var1, @Nonnull RelayedVoiceData var2) {
int var3 = 0;
for (UUID var5 : var1) {
if (var5 != null) {
PacketHandler var6 = this.getPlayerHandler(var5);
if (var6 != null) {
ChannelConnection var7 = var6.getChannel(StreamType.Voice);
if (var7 != null && this.sendRelay(var7, var2)) {
var3++;
}
}
}
}
class="kw">return var3;
}
class="kw">private boolean sendRelay(@Nonnull ChannelConnection var1, @Nonnull RelayedVoiceData var2) {
if (!var1.isActive()) {
class="kw">return false;
}
var1.writeAndFlush(var2);
class="kw">return true;
}
@Nullable
class="kw">private List<VoiceRouter.ListenerCandidate> selectNearbyListeners(
@Nonnull VoiceRouter.SpeakerDescriptor var1, @Nullable Set<UUID> var2, @Nullable Set<UUID> var3
) {
Vector3dc var4 = var1.position();
if (var4 == null) {
class="kw">return null;
}
UUID var5 = var1.worldId();
Set var6 = this.worldPlayerSets.get(var5);
if (var6 != null && !var6.isEmpty()) {
float var7 = this.voiceModule.getMaxHearingDistance() * this.voiceModule.getMaxHearingDistance();
List var8 = null;
for (UUID var10 : var6) {
if (!var10.equals(var1.speakerId()) && (var2 == null || var2.contains(var10)) && (var3 == null || !var3.contains(var10))) {
VoiceModule.PositionSnapshot var11 = this.voiceModule.getCachedPosition(var10);
if (var11 != null && var11.worldId().equals(var5) && (this.voiceModule.isDeadPlayersCanHear() || !var11.isDead())) {
double var12 = var4.distanceSquared(var11.position());
if (Double.isFinite(var12) && !(var12 > var7)) {
PacketHandler var14 = this.getPlayerHandler(var10);
if (var14 != null) {
ChannelConnection var15 = var14.getChannel(StreamType.Voice);
if (var15 != null && var15.isActive()) {
if (var8 == null) {
var8 = new ArrayList<>();
}
var8.add(new VoiceRouter.ListenerCandidate(var12, var15));
}
}
}
}
}
}
if (var8 != null && var8.size() > 12) {
var8.sort((var0, var1x) -> Double.compare(var0.distSq(), var1x.distSq()));
var8 = var8.subList(0, 12);
}
class="kw">return var8;
} else {
class="kw">return null;
}
}
class="kw">private PacketHandler getPlayerHandler(UUID var1) {
PlayerRef var2 = Universe.get().getPlayer(var1);
class="kw">return var2 != null ? var2.getPacketHandler() : null;
}
class="kw">private record ListenerCandidate(double distSq, ChannelConnection voiceChannel) {
class="kw">private ListenerCandidate {
}
}
record SpeakerDescriptor(@Nonnull UUID speakerId, @Nullable Vector3dc position, boolean isUnderwater, @Nonnull UUID worldId, int entityId) {
SpeakerDescriptor {
}
}
}