first commit
Build AsminVoicechat / prepare-release (push) Successful in 14s
Build AsminVoicechat / build-and-test (17) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (18) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (19) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (20) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (21) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (22) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (23) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (24) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (25) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (26) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (27-ea) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (16) (push) Canceled after 38s

This commit is contained in:
asminme committed 2026-10-24 15:18:03 +02:00
commit bbccd4a815
454 files changed
+45050

No files matched your search

@@ -0,0 +1,65 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
public class AudioUtils {
public static final int MAX_OPUS_PAYLOAD_SIZE = 1275;
public static short[] bytesToShorts(byte[] bytes) {
if (bytes.length % 2 != 0) {
throw new IllegalArgumentException("Input bytes need to be divisible by 2");
}
ShortBuffer sb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
short[] out = new short[sb.remaining()];
sb.get(out);
return out;
}
public static byte[] shortsToBytes(short[] shorts) {
ByteBuffer bb = ByteBuffer.allocate(shorts.length * 2).order(ByteOrder.LITTLE_ENDIAN);
for (short s : shorts) {
bb.putShort(s);
}
return bb.array();
}
public static short[] floatsToShorts(float[] floats) {
short[] shorts = new short[floats.length];
for (int i = 0; i < floats.length; ++i) {
shorts[i] = Float.valueOf(floats[i]).shortValue();
}
return shorts;
}
public static float[] shortsToFloats(short[] shorts) {
float[] floats = new float[shorts.length];
for (int i = 0; i < shorts.length; ++i) {
floats[i] = Short.valueOf(shorts[i]).floatValue();
}
return floats;
}
public static byte[] floatsToBytes(float[] floats) {
byte[] bytes = new byte[floats.length * 2];
for (int i = 0; i < floats.length; ++i) {
short x = Float.valueOf(floats[i]).shortValue();
bytes[i * 2] = (byte)(x & 0xFF);
bytes[i * 2 + 1] = (byte)((x & 0xFF00) >> 8);
}
return bytes;
}
public static float[] bytesToFloats(byte[] bytes) {
float[] floats = new float[bytes.length / 2];
for (int i = 0; i < bytes.length / 2; ++i) {
floats[i] = (bytes[i * 2 + 1] & 0x80) != 0 ? (float)(Short.MIN_VALUE + ((bytes[i * 2 + 1] & 0x7F) << 8) | bytes[i * 2] & 0xFF) : (float)(bytes[i * 2 + 1] << 8 & 0xFF00 | bytes[i * 2] & 0xFF);
}
return floats;
}
}
@@ -0,0 +1,20 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.Packet;
public class AuthenticateAckPacket
implements Packet<AuthenticateAckPacket> {
@Override
public AuthenticateAckPacket fromBytes(FriendlyByteBuf buf) {
return new AuthenticateAckPacket();
}
@Override
public void toBytes(FriendlyByteBuf buf) {
}
}
@@ -0,0 +1,46 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.Packet;
import de.maxhenkel.voicechat.voice.common.Secret;
import java.util.UUID;
public class AuthenticatePacket
implements Packet<AuthenticatePacket> {
private UUID playerUUID;
private Secret secret;
public AuthenticatePacket(UUID playerUUID, Secret secret) {
this.playerUUID = playerUUID;
this.secret = secret;
}
public AuthenticatePacket() {
}
public UUID getPlayerUUID() {
return this.playerUUID;
}
public Secret getSecret() {
return this.secret;
}
@Override
public AuthenticatePacket fromBytes(FriendlyByteBuf buf) {
AuthenticatePacket packet = new AuthenticatePacket();
packet.playerUUID = buf.readUUID();
packet.secret = Secret.fromBytes(buf);
return packet;
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeUUID(this.playerUUID);
this.secret.toBytes(buf);
}
}
@@ -0,0 +1,77 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.api.Group;
import de.maxhenkel.voicechat.plugins.impl.GroupImpl;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import java.util.Objects;
import java.util.UUID;
public class ClientGroup {
private final UUID id;
private final String name;
private final boolean hasPassword;
private final boolean persistent;
private final boolean hidden;
private final Group.Type type;
public ClientGroup(UUID id, String name, boolean hasPassword, boolean persistent, boolean hidden, Group.Type type) {
this.id = id;
this.name = name;
this.hasPassword = hasPassword;
this.persistent = persistent;
this.hidden = hidden;
this.type = type;
}
public UUID getId() {
return this.id;
}
public String getName() {
return this.name;
}
public boolean hasPassword() {
return this.hasPassword;
}
public boolean isPersistent() {
return this.persistent;
}
public boolean isHidden() {
return this.hidden;
}
public Group.Type getType() {
return this.type;
}
public static ClientGroup fromBytes(FriendlyByteBuf buf) {
return new ClientGroup(buf.readUUID(), buf.readUtf(512), buf.readBoolean(), buf.readBoolean(), buf.readBoolean(), GroupImpl.TypeImpl.fromInt(buf.readShort()));
}
public void toBytes(FriendlyByteBuf buf) {
buf.writeUUID(this.id);
buf.writeUtf(this.name, 512);
buf.writeBoolean(this.hasPassword);
buf.writeBoolean(this.persistent);
buf.writeBoolean(this.hidden);
buf.writeShort(GroupImpl.TypeImpl.toInt(this.type));
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass() != o.getClass()) {
return false;
}
ClientGroup group = (ClientGroup)o;
return Objects.equals(this.id, group.id);
}
}
@@ -0,0 +1,20 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.Packet;
public class ConnectionCheckAckPacket
implements Packet<ConnectionCheckAckPacket> {
@Override
public ConnectionCheckAckPacket fromBytes(FriendlyByteBuf buf) {
return new ConnectionCheckAckPacket();
}
@Override
public void toBytes(FriendlyByteBuf buf) {
}
}
@@ -0,0 +1,20 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.Packet;
public class ConnectionCheckPacket
implements Packet<ConnectionCheckPacket> {
@Override
public ConnectionCheckPacket fromBytes(FriendlyByteBuf buf) {
return new ConnectionCheckPacket();
}
@Override
public void toBytes(FriendlyByteBuf buf) {
}
}
@@ -0,0 +1,53 @@
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* javax.annotation.Nullable
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.SoundPacket;
import java.util.UUID;
import javax.annotation.Nullable;
public class GroupSoundPacket
extends SoundPacket<GroupSoundPacket> {
public GroupSoundPacket(UUID channelId, UUID sender, byte[] data, long sequenceNumber, @Nullable String category) {
super(channelId, sender, data, sequenceNumber, category);
}
public GroupSoundPacket() {
}
@Override
public GroupSoundPacket fromBytes(FriendlyByteBuf buf) {
GroupSoundPacket soundPacket = new GroupSoundPacket();
soundPacket.channelId = buf.readUUID();
soundPacket.sender = buf.readUUID();
soundPacket.data = buf.readByteArray(1275);
soundPacket.sequenceNumber = buf.readLong();
byte data = buf.readByte();
if (this.hasFlag(data, (byte)2)) {
soundPacket.category = buf.readUtf(16);
}
return soundPacket;
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeUUID(this.channelId);
buf.writeUUID(this.sender);
buf.writeByteArray(this.data);
buf.writeLong(this.sequenceNumber);
byte data = 0;
if (this.category != null) {
data = this.setFlag(data, (byte)2);
}
buf.writeByte(data);
if (this.category != null) {
buf.writeUtf(this.category, 16);
}
}
}
@@ -0,0 +1,20 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.Packet;
public class KeepAlivePacket
implements Packet<KeepAlivePacket> {
@Override
public KeepAlivePacket fromBytes(FriendlyByteBuf buf) {
return new KeepAlivePacket();
}
@Override
public void toBytes(FriendlyByteBuf buf) {
}
}
@@ -0,0 +1,74 @@
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* javax.annotation.Nullable
* org.bukkit.Location
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.SoundPacket;
import java.util.UUID;
import javax.annotation.Nullable;
import org.bukkit.Location;
public class LocationSoundPacket
extends SoundPacket<LocationSoundPacket> {
protected Location location;
protected float distance;
public LocationSoundPacket(UUID channelId, UUID sender, Location location, byte[] data, long sequenceNumber, float distance, @Nullable String category) {
super(channelId, sender, data, sequenceNumber, category);
this.location = location;
this.distance = distance;
}
public LocationSoundPacket() {
}
public Location getLocation() {
return this.location;
}
public float getDistance() {
return this.distance;
}
@Override
public LocationSoundPacket fromBytes(FriendlyByteBuf buf) {
LocationSoundPacket soundPacket = new LocationSoundPacket();
soundPacket.channelId = buf.readUUID();
soundPacket.sender = buf.readUUID();
soundPacket.location = new Location(null, buf.readDouble(), buf.readDouble(), buf.readDouble());
soundPacket.data = buf.readByteArray(1275);
soundPacket.sequenceNumber = buf.readLong();
soundPacket.distance = buf.readFloat();
byte data = buf.readByte();
if (this.hasFlag(data, (byte)2)) {
soundPacket.category = buf.readUtf(16);
}
return soundPacket;
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeUUID(this.channelId);
buf.writeUUID(this.sender);
buf.writeDouble(this.location.getX());
buf.writeDouble(this.location.getY());
buf.writeDouble(this.location.getZ());
buf.writeByteArray(this.data);
buf.writeLong(this.sequenceNumber);
buf.writeFloat(this.distance);
byte data = 0;
if (this.category != null) {
data = this.setFlag(data, (byte)2);
}
buf.writeByte(data);
if (this.category != null) {
buf.writeUtf(this.category, 16);
}
}
}
@@ -0,0 +1,61 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.Packet;
public class MicPacket
implements Packet<MicPacket> {
private byte[] data;
private boolean whispering;
private long sequenceNumber;
public MicPacket(byte[] data, boolean whispering, long sequenceNumber) {
this.data = data;
this.whispering = whispering;
this.sequenceNumber = sequenceNumber;
}
public MicPacket() {
}
@Override
public long getTTL() {
return 500L;
}
public byte[] getData() {
return this.data;
}
public void setData(byte[] data) {
this.data = data;
}
public long getSequenceNumber() {
return this.sequenceNumber;
}
public boolean isWhispering() {
return this.whispering;
}
@Override
public MicPacket fromBytes(FriendlyByteBuf buf) {
MicPacket soundPacket = new MicPacket();
soundPacket.data = buf.readByteArray(1275);
soundPacket.sequenceNumber = buf.readLong();
soundPacket.whispering = buf.readBoolean();
return soundPacket;
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeByteArray(this.data);
buf.writeLong(this.sequenceNumber);
buf.writeBoolean(this.whispering);
}
}
@@ -0,0 +1,175 @@
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* io.netty.buffer.Unpooled
* io.netty.handler.codec.DecoderException
* javax.annotation.Nonnull
* javax.annotation.Nullable
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.Voicechat;
import de.maxhenkel.voicechat.api.RawUdpPacket;
import de.maxhenkel.voicechat.debug.PingHandler;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.AuthenticateAckPacket;
import de.maxhenkel.voicechat.voice.common.AuthenticatePacket;
import de.maxhenkel.voicechat.voice.common.ConnectionCheckAckPacket;
import de.maxhenkel.voicechat.voice.common.ConnectionCheckPacket;
import de.maxhenkel.voicechat.voice.common.GroupSoundPacket;
import de.maxhenkel.voicechat.voice.common.KeepAlivePacket;
import de.maxhenkel.voicechat.voice.common.LocationSoundPacket;
import de.maxhenkel.voicechat.voice.common.MicPacket;
import de.maxhenkel.voicechat.voice.common.Packet;
import de.maxhenkel.voicechat.voice.common.PingPacket;
import de.maxhenkel.voicechat.voice.common.PlayerSoundPacket;
import de.maxhenkel.voicechat.voice.common.Secret;
import de.maxhenkel.voicechat.voice.server.ClientConnection;
import de.maxhenkel.voicechat.voice.server.Server;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.DecoderException;
import java.lang.reflect.InvocationTargetException;
import java.net.SocketAddress;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class NetworkMessage {
public static final byte MAGIC_BYTE = -1;
private final long timestamp;
private Packet<? extends Packet> packet;
private SocketAddress address;
private static final Map<Byte, Class<? extends Packet>> packetRegistry = new HashMap<Byte, Class<? extends Packet>>();
public NetworkMessage(long timestamp, Packet<?> packet) {
this(timestamp);
this.packet = packet;
}
public NetworkMessage(Packet<?> packet) {
this(System.currentTimeMillis());
this.packet = packet;
}
private NetworkMessage(long timestamp) {
this.timestamp = timestamp;
}
@Nonnull
public Packet<? extends Packet> getPacket() {
return this.packet;
}
public long getTimestamp() {
return this.timestamp;
}
public long getTTL() {
return this.packet.getTTL();
}
public SocketAddress getAddress() {
return this.address;
}
@Nullable
public static NetworkMessage readPacketServer(RawUdpPacket packet, Server server) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
try {
byte[] data = packet.getData();
FriendlyByteBuf b = new FriendlyByteBuf(Unpooled.wrappedBuffer((byte[])data));
if (b.readByte() != -1) {
Voicechat.LOGGER.debug("Received invalid packet from {}", packet.getSocketAddress());
return null;
}
UUID playerID = b.readUUID();
if (!server.hasSecret(playerID)) {
if (PingHandler.onPacket(server, packet.getSocketAddress(), playerID, b)) {
return null;
}
Voicechat.LOGGER.debug("Player {} does not have a secret", playerID);
return null;
}
return NetworkMessage.readFromBytes(packet.getSocketAddress(), server.getSecret(playerID), b.readByteArray(2048), packet.getTimestamp());
}
catch (DecoderException | IndexOutOfBoundsException e) {
Voicechat.LOGGER.debug("Received invalid packet from {}", packet.getSocketAddress());
return null;
}
}
@Nullable
private static NetworkMessage readFromBytes(SocketAddress socketAddress, Secret secret, byte[] encryptedPayload, long timestamp) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
byte[] decrypt;
try {
decrypt = secret.decrypt(encryptedPayload);
}
catch (Exception e) {
Voicechat.LOGGER.debug("Failed to decrypt packet from {}", socketAddress);
return null;
}
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.wrappedBuffer((byte[])decrypt));
byte packetType = buffer.readByte();
Class<? extends Packet> packetClass = packetRegistry.get(packetType);
if (packetClass == null) {
Voicechat.LOGGER.debug("Got invalid packet ID {}", packetType);
return null;
}
Packet p = packetClass.getDeclaredConstructor(new Class[0]).newInstance(new Object[0]);
NetworkMessage message = new NetworkMessage(timestamp);
message.address = socketAddress;
message.packet = p.fromBytes(buffer);
return message;
}
private static byte getPacketType(Packet<? extends Packet> packet) {
for (Map.Entry<Byte, Class<? extends Packet>> entry : packetRegistry.entrySet()) {
if (!packet.getClass().equals(entry.getValue())) continue;
return entry.getKey();
}
return -1;
}
public byte[] writeServer(Server server, ClientConnection connection) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
byte[] payload = this.write(server.getSecret(connection.getPlayerUUID()));
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer((int)(1 + payload.length)));
buffer.writeByte(-1);
buffer.writeByteArray(payload);
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
return bytes;
}
public byte[] write(Secret secret) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer());
byte type = NetworkMessage.getPacketType(this.packet);
if (type < 0) {
throw new IllegalArgumentException("Packet type not found");
}
buffer.writeByte(type);
this.packet.toBytes(buffer);
return secret.encrypt(buffer.array());
}
static {
packetRegistry.put((byte)1, MicPacket.class);
packetRegistry.put((byte)2, PlayerSoundPacket.class);
packetRegistry.put((byte)3, GroupSoundPacket.class);
packetRegistry.put((byte)4, LocationSoundPacket.class);
packetRegistry.put((byte)5, AuthenticatePacket.class);
packetRegistry.put((byte)6, AuthenticateAckPacket.class);
packetRegistry.put((byte)7, PingPacket.class);
packetRegistry.put((byte)8, KeepAlivePacket.class);
packetRegistry.put((byte)9, ConnectionCheckPacket.class);
packetRegistry.put((byte)10, ConnectionCheckAckPacket.class);
}
}
@@ -0,0 +1,17 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
public interface Packet<T extends Packet> {
public T fromBytes(FriendlyByteBuf var1);
public void toBytes(FriendlyByteBuf var1);
default public long getTTL() {
return 10000L;
}
}
@@ -0,0 +1,45 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.Packet;
import java.util.UUID;
public class PingPacket
implements Packet<PingPacket> {
private UUID id;
private long timestamp;
public PingPacket(UUID id, long timestamp) {
this.id = id;
this.timestamp = timestamp;
}
public PingPacket() {
}
public long getTimestamp() {
return this.timestamp;
}
public UUID getId() {
return this.id;
}
@Override
public PingPacket fromBytes(FriendlyByteBuf buf) {
PingPacket soundPacket = new PingPacket();
soundPacket.id = buf.readUUID();
soundPacket.timestamp = buf.readLong();
return soundPacket;
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeUUID(this.id);
buf.writeLong(this.timestamp);
}
}
@@ -0,0 +1,77 @@
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* javax.annotation.Nullable
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import de.maxhenkel.voicechat.voice.common.SoundPacket;
import java.util.UUID;
import javax.annotation.Nullable;
public class PlayerSoundPacket
extends SoundPacket<PlayerSoundPacket> {
protected boolean whispering;
protected float distance;
public PlayerSoundPacket(UUID channelId, UUID sender, byte[] data, long sequenceNumber, boolean whispering, float distance, @Nullable String category) {
super(channelId, sender, data, sequenceNumber, category);
this.whispering = whispering;
this.distance = distance;
}
public PlayerSoundPacket() {
}
@Override
public UUID getSender() {
return this.sender;
}
public boolean isWhispering() {
return this.whispering;
}
public float getDistance() {
return this.distance;
}
@Override
public PlayerSoundPacket fromBytes(FriendlyByteBuf buf) {
PlayerSoundPacket soundPacket = new PlayerSoundPacket();
soundPacket.channelId = buf.readUUID();
soundPacket.sender = buf.readUUID();
soundPacket.data = buf.readByteArray(1275);
soundPacket.sequenceNumber = buf.readLong();
soundPacket.distance = buf.readFloat();
byte data = buf.readByte();
soundPacket.whispering = this.hasFlag(data, (byte)1);
if (this.hasFlag(data, (byte)2)) {
soundPacket.category = buf.readUtf(16);
}
return soundPacket;
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeUUID(this.channelId);
buf.writeUUID(this.sender);
buf.writeByteArray(this.data);
buf.writeLong(this.sequenceNumber);
buf.writeFloat(this.distance);
byte data = 0;
if (this.whispering) {
data = this.setFlag(data, (byte)1);
}
if (this.category != null) {
data = this.setFlag(data, (byte)2);
}
buf.writeByte(data);
if (this.category != null) {
buf.writeUtf(this.category, 16);
}
}
}
@@ -0,0 +1,100 @@
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* javax.annotation.Nullable
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.util.FriendlyByteBuf;
import java.util.UUID;
import javax.annotation.Nullable;
public class PlayerState {
private UUID uuid;
private String name;
private boolean disabled;
private boolean disconnected;
@Nullable
private UUID group;
public PlayerState(UUID uuid, String name, boolean disabled, boolean disconnected) {
this.uuid = uuid;
this.name = name;
this.disabled = disabled;
this.disconnected = disconnected;
}
public UUID getUuid() {
return this.uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public boolean isDisabled() {
return this.disabled;
}
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
public boolean isDisconnected() {
return this.disconnected;
}
public void setDisconnected(boolean disconnected) {
this.disconnected = disconnected;
}
@Nullable
public UUID getGroup() {
return this.group;
}
public void setGroup(@Nullable UUID group) {
this.group = group;
}
public boolean hasGroup() {
return this.group != null;
}
public String toString() {
return "{disabled=" + this.disabled + ", disconnected=" + this.disconnected + ", uuid=" + this.uuid + ", name=" + this.name + ", group=" + this.group + '}';
}
public static PlayerState fromBytes(FriendlyByteBuf buf) {
boolean disabled = buf.readBoolean();
boolean disconnected = buf.readBoolean();
UUID uuid = buf.readUUID();
String name = buf.readUtf(Short.MAX_VALUE);
PlayerState state = new PlayerState(uuid, name, disabled, disconnected);
if (buf.readBoolean()) {
state.setGroup(buf.readUUID());
}
return state;
}
public void toBytes(FriendlyByteBuf buf) {
buf.writeBoolean(this.disabled);
buf.writeBoolean(this.disconnected);
buf.writeUUID(this.uuid);
buf.writeUtf(this.name);
buf.writeBoolean(this.hasGroup());
if (this.hasGroup()) {
buf.writeUUID(this.group);
}
}
}
@@ -0,0 +1,140 @@
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* io.netty.buffer.ByteBuf
*/
package de.maxhenkel.voicechat.voice.common;
import io.netty.buffer.ByteBuf;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Secret {
public static final int SECRET_SIZE_BYTES = 16;
public static final int IV_SIZE_BYTES = 12;
public static final int TAG_LEN_BITS = 128;
public static final String CIPHER = "AES/GCM/NoPadding";
private static final SecureRandom RANDOM = new SecureRandom();
private final byte[] secret;
private final SecretKeySpec keySpec;
private volatile boolean legacyProtocol;
protected Secret(byte[] byArray) {
if (byArray == null || byArray.length != 16) {
throw new IllegalArgumentException("Voice chat secret must contain exactly 16 bytes");
}
this.secret = (byte[])byArray.clone();
this.keySpec = new SecretKeySpec(this.secret, "AES");
}
public static Secret generateNewRandomSecret() {
byte[] byArray = new byte[16];
RANDOM.nextBytes(byArray);
return new Secret(byArray);
}
public static Secret fromBytes(byte[] byArray) {
return new Secret(byArray);
}
public static Secret fromBytes(ByteBuf byteBuf) {
byte[] byArray = new byte[16];
byteBuf.readBytes(byArray);
return Secret.fromBytes(byArray);
}
public void toBytes(ByteBuf byteBuf) {
byteBuf.writeBytes(this.secret);
}
public byte[] getSecret() {
return (byte[])this.secret.clone();
}
public SecretKeySpec getKeySpec() {
return this.keySpec;
}
public void setLegacyProtocol(boolean bl) {
this.legacyProtocol = bl;
}
public boolean isLegacyProtocol() {
return this.legacyProtocol;
}
public static byte[] generateIV() {
byte[] byArray = new byte[12];
RANDOM.nextBytes(byArray);
return byArray;
}
private static byte[] generateLegacyIV() {
byte[] byArray = new byte[16];
RANDOM.nextBytes(byArray);
return byArray;
}
public byte[] encrypt(byte[] byArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
if (this.legacyProtocol) {
byte[] byArray2 = Secret.generateLegacyIV();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(1, (Key)this.keySpec, new IvParameterSpec(byArray2));
byte[] byArray3 = cipher.doFinal(byArray);
byte[] byArray4 = new byte[byArray2.length + byArray3.length];
System.arraycopy(byArray2, 0, byArray4, 0, byArray2.length);
System.arraycopy(byArray3, 0, byArray4, byArray2.length, byArray3.length);
return byArray4;
}
byte[] byArray5 = Secret.generateIV();
Cipher cipher = Cipher.getInstance(CIPHER);
cipher.init(1, (Key)this.keySpec, new GCMParameterSpec(128, byArray5));
byte[] byArray6 = cipher.doFinal(byArray);
byte[] byArray7 = new byte[byArray5.length + byArray6.length];
System.arraycopy(byArray5, 0, byArray7, 0, byArray5.length);
System.arraycopy(byArray6, 0, byArray7, byArray5.length, byArray6.length);
return byArray7;
}
public byte[] decrypt(byte[] byArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
if (this.legacyProtocol) {
if (byArray.length < 32 || (byArray.length - 16) % 16 != 0) {
throw new IllegalBlockSizeException("Invalid legacy AES-CBC packet size");
}
byte[] byArray2 = Arrays.copyOfRange(byArray, 0, 16);
byte[] byArray3 = Arrays.copyOfRange(byArray, 16, byArray.length);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(2, (Key)this.keySpec, new IvParameterSpec(byArray2));
return cipher.doFinal(byArray3);
}
if (byArray.length < 28) {
throw new IllegalBlockSizeException("Invalid AES-GCM packet size");
}
byte[] byArray4 = Arrays.copyOfRange(byArray, 0, 12);
byte[] byArray5 = Arrays.copyOfRange(byArray, 12, byArray.length);
Cipher cipher = Cipher.getInstance(CIPHER);
cipher.init(2, (Key)this.keySpec, new GCMParameterSpec(128, byArray4));
return cipher.doFinal(byArray5);
}
public boolean equals(Object object) {
return object instanceof Secret && Arrays.equals(this.secret, ((Secret)object).secret);
}
public int hashCode() {
return Arrays.hashCode(this.secret);
}
}
@@ -0,0 +1,64 @@
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* javax.annotation.Nullable
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.voice.common.Packet;
import java.util.UUID;
import javax.annotation.Nullable;
public abstract class SoundPacket<T extends SoundPacket>
implements Packet<T> {
public static final byte WHISPER_MASK = 1;
public static final byte HAS_CATEGORY_MASK = 2;
protected UUID channelId;
protected UUID sender;
protected byte[] data;
protected long sequenceNumber;
@Nullable
protected String category;
public SoundPacket(UUID channelId, UUID sender, byte[] data, long sequenceNumber, @Nullable String category) {
this.channelId = channelId;
this.sender = sender;
this.data = data;
this.sequenceNumber = sequenceNumber;
this.category = category;
}
public SoundPacket() {
}
public UUID getChannelId() {
return this.channelId;
}
public UUID getSender() {
return this.sender;
}
public byte[] getData() {
return this.data;
}
public long getSequenceNumber() {
return this.sequenceNumber;
}
@Nullable
public String getCategory() {
return this.category;
}
protected boolean hasFlag(byte data, byte mask) {
return (data & mask) != 0;
}
protected byte setFlag(byte data, byte mask) {
return (byte)(data | mask);
}
}
@@ -0,0 +1,15 @@
/*
* Decompiled with CFR 0.152.
*/
package de.maxhenkel.voicechat.voice.common;
import de.maxhenkel.voicechat.Voicechat;
public class Utils {
public static final int MAX_VOICE_CHAT_PACKET_SIZE = 2048;
public static float getDefaultDistance() {
return Voicechat.SERVER_CONFIG.voiceChatDistance.get().floatValue();
}
}