almost working but still not... :(
the issue is in the VoiceChatPlugin at line 146 BTW also ignore the sussy debug lines
This commit is contained in:
parent
ca830ed9bf
commit
5c53842157
10 changed files with 400 additions and 34 deletions
|
@ -0,0 +1,7 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.data.voiceChat;
|
||||
|
||||
public enum Codec {
|
||||
VOIP,
|
||||
AUDIO,
|
||||
RESTRICTED_LOWDELAY;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.data.voiceChat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class RawUdpPacket {
|
||||
@Getter private final byte[] data;
|
||||
@Getter private final SocketAddress socketAddress;
|
||||
@Getter private final long timestamp;
|
||||
}
|
|
@ -7,36 +7,31 @@ import com.github.steveice10.packetlib.Session;
|
|||
import com.github.steveice10.packetlib.packet.Packet;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import land.chipmunk.chayapak.chomens_bot.Bot;
|
||||
import land.chipmunk.chayapak.chomens_bot.util.AES;
|
||||
import land.chipmunk.chayapak.chomens_bot.data.voiceChat.RawUdpPacket;
|
||||
import land.chipmunk.chayapak.chomens_bot.util.FriendlyByteBuf;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.InitializationData;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.NetworkMessage;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.packets.KeepAlivePacket;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.packets.PingPacket;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.packets.SecretPacket;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.packets.AuthenticatePacket;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.util.Arrays;
|
||||
import java.net.*;
|
||||
|
||||
// exists for some reason, still wip and will be finished in the next 69 years
|
||||
// and i prob implemented it in a wrong way lol
|
||||
// at least when you do `/voicechat test (bot username)` it will show `Client not connected`
|
||||
// instead of `(bot username) does not have Simple Voice Chat installed`
|
||||
public class VoiceChatPlugin extends Bot.Listener {
|
||||
public static final byte MAGIC_BYTE = (byte) 0b11111111;
|
||||
|
||||
private final Bot bot;
|
||||
|
||||
private final ClientVoiceChatSocket socket;
|
||||
private InitializationData initializationData;
|
||||
private ClientVoiceChatSocket socket;
|
||||
private InetAddress address;
|
||||
private InetSocketAddress socketAddress;
|
||||
|
||||
public VoiceChatPlugin(Bot bot) {
|
||||
this.bot = bot;
|
||||
this.socket = new ClientVoiceChatSocket();
|
||||
try {
|
||||
socket.open();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
bot.addListener(this);
|
||||
}
|
||||
|
@ -56,43 +51,102 @@ public class VoiceChatPlugin extends Bot.Listener {
|
|||
|
||||
bot.session().send(new ServerboundCustomPayloadPacket(
|
||||
"voicechat:request_secret",
|
||||
new byte[] { 0, 0, 0, 17 } // what are these bytes?
|
||||
new FriendlyByteBuf(Unpooled.buffer()).writeInt(17).array()
|
||||
));
|
||||
|
||||
bot.session().send(new ServerboundCustomPayloadPacket(
|
||||
"voicechat:update_state",
|
||||
new FriendlyByteBuf(Unpooled.buffer()).writeBoolean(false).array()
|
||||
));
|
||||
}
|
||||
|
||||
public void packetReceived(ClientboundCustomPayloadPacket _packet) {
|
||||
// sus
|
||||
/*
|
||||
System.out.println(_packet.getChannel());
|
||||
System.out.println("\"" + _packet.getChannel() + "\"");
|
||||
System.out.println(Arrays.toString(_packet.getData()));
|
||||
System.out.println(new String(_packet.getData()));
|
||||
*/
|
||||
// for some reason this entire part is not running
|
||||
if (_packet.getChannel().equals("voicechat:secret")) {
|
||||
System.out.println("got the secret packet");
|
||||
|
||||
final byte[] bytes = _packet.getData();
|
||||
final FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(bytes));
|
||||
|
||||
final SecretPacket secretPacket = new SecretPacket().fromBytes(buf);
|
||||
|
||||
System.out.println(secretPacket.secret());
|
||||
System.out.println(secretPacket.serverPort());
|
||||
|
||||
initializationData = new InitializationData(bot.options().host(), secretPacket);
|
||||
|
||||
try {
|
||||
address = InetAddress.getByName(bot.options().host());
|
||||
socketAddress = new InetSocketAddress(address, initializationData.serverPort());
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
System.out.println("address " + address.getHostName());
|
||||
|
||||
socket = new ClientVoiceChatSocket();
|
||||
try {
|
||||
socket.open();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
bot.executorService().submit(() -> {
|
||||
while (true) {
|
||||
final RawUdpPacket packet = socket.read();
|
||||
try {
|
||||
if (socket.isClosed()) continue;
|
||||
|
||||
if (packet == null) return;
|
||||
System.out.println("reading packet");
|
||||
final NetworkMessage message = NetworkMessage.readPacket(socket.read(), initializationData);
|
||||
System.out.println("DONE reading packet, this message will; prob nto woshow");
|
||||
|
||||
byte[] data = packet.data();
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(data));
|
||||
if (message == null) continue;
|
||||
|
||||
if (buf.readByte() != MAGIC_BYTE) return;
|
||||
|
||||
// AES.decrypt(secret, payload) ?
|
||||
if (message.packet() instanceof AuthenticatePacket) {
|
||||
System.out.println("SERVER AUTHENTICATED FINALLYYYYYYYYYYYYYYYY");
|
||||
} else if (message.packet() instanceof PingPacket pingPacket) {
|
||||
System.out.println("got ping packet");
|
||||
sendToServer(new NetworkMessage(pingPacket));
|
||||
} else if (message.packet() instanceof KeepAlivePacket) {
|
||||
System.out.println("got keep alive packet");
|
||||
sendToServer(new NetworkMessage(new KeepAlivePacket()));
|
||||
} else {
|
||||
System.out.println("got " + message.packet().getClass().getName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToServer (NetworkMessage message) throws Exception {
|
||||
socket.send(
|
||||
message.writeClient(initializationData),
|
||||
socketAddress
|
||||
);
|
||||
}
|
||||
|
||||
private static class VoiceChatSocketBase {
|
||||
private final byte[] BUFFER = new byte[4096];
|
||||
|
||||
public RawUdpPacket read (DatagramSocket socket) {
|
||||
try {
|
||||
DatagramPacket packet = new DatagramPacket(BUFFER, BUFFER.length);
|
||||
|
||||
System.out.println("receiving packet");
|
||||
|
||||
// the problem is this next line, just this 1 line. it makes the entire thing froze
|
||||
socket.receive(packet);
|
||||
|
||||
System.out.println("FINALLY DONE RECEIVING AAAAHHHHHHHHHHHHHHHHHHH");
|
||||
|
||||
// Setting the timestamp after receiving the packet
|
||||
long timestamp = System.currentTimeMillis();
|
||||
byte[] data = new byte[packet.getLength()];
|
||||
|
@ -138,11 +192,4 @@ public class VoiceChatPlugin extends Bot.Listener {
|
|||
return socket == null;
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class RawUdpPacket {
|
||||
@Getter private final byte[] data;
|
||||
@Getter private final SocketAddress socketAddress;
|
||||
@Getter private final long timestamp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.voiceChat;
|
||||
|
||||
import land.chipmunk.chayapak.chomens_bot.data.voiceChat.Codec;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.packets.SecretPacket;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class InitializationData {
|
||||
@Getter private final String serverIP;
|
||||
@Getter private final int serverPort;
|
||||
@Getter private final UUID playerUUID;
|
||||
@Getter private final UUID secret;
|
||||
@Getter private final Codec codec;
|
||||
@Getter private final int mtuSize;
|
||||
@Getter private final double voiceChatDistance;
|
||||
@Getter private final int keepAlive;
|
||||
@Getter private final boolean groupsEnabled;
|
||||
@Getter private final boolean allowRecording;
|
||||
|
||||
public InitializationData(String serverIP, SecretPacket secretPacket) {
|
||||
this.serverIP = serverIP;
|
||||
this.serverPort = secretPacket.serverPort();
|
||||
this.playerUUID = secretPacket.playerUUID();
|
||||
this.secret = secretPacket.secret();
|
||||
this.codec = secretPacket.codec();
|
||||
this.mtuSize = secretPacket.mtuSize();
|
||||
this.voiceChatDistance = secretPacket.voiceChatDistance();
|
||||
this.keepAlive = secretPacket.keepAlive();
|
||||
this.groupsEnabled = secretPacket.groupsEnabled();
|
||||
this.allowRecording = secretPacket.allowRecording();
|
||||
}
|
||||
|
||||
private static class HostData {
|
||||
private final String ip;
|
||||
private final int port;
|
||||
|
||||
public HostData(String ip, int port) {
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.voiceChat;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import land.chipmunk.chayapak.chomens_bot.data.voiceChat.RawUdpPacket;
|
||||
import land.chipmunk.chayapak.chomens_bot.util.AES;
|
||||
import land.chipmunk.chayapak.chomens_bot.util.FriendlyByteBuf;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.packets.AuthenticatePacket;
|
||||
import lombok.Getter;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
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;
|
||||
|
||||
public class NetworkMessage {
|
||||
public static final byte MAGIC_BYTE = (byte) 0b11111111;
|
||||
|
||||
@Getter private final long timestamp;
|
||||
@Getter private Packet<? extends Packet<?>> packet;
|
||||
@Getter private SocketAddress address;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private static final Map<Byte, Class<? extends Packet<?>>> packetRegistry;
|
||||
|
||||
static {
|
||||
packetRegistry = new HashMap<>();
|
||||
// packetRegistry.put((byte) 0x1, MicPacket.class);
|
||||
// packetRegistry.put((byte) 0x2, PlayerSoundPacket.class);
|
||||
// packetRegistry.put((byte) 0x3, GroupSoundPacket.class);
|
||||
// packetRegistry.put((byte) 0x4, LocationSoundPacket.class);
|
||||
packetRegistry.put((byte) 0x5, AuthenticatePacket.class);
|
||||
// packetRegistry.put((byte) 0x6, AuthenticateAckPacket.class);
|
||||
// packetRegistry.put((byte) 0x7, PingPacket.class);
|
||||
// packetRegistry.put((byte) 0x8, KeepAlivePacket.class);
|
||||
// packetRegistry.put((byte) 0x9, ConnectionCheckPacket.class);
|
||||
// packetRegistry.put((byte) 0xA, ConnectionCheckAckPacket.class);
|
||||
}
|
||||
|
||||
public static NetworkMessage readPacket (RawUdpPacket packet, InitializationData initializationData) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
|
||||
final byte[] data = packet.data();
|
||||
final FriendlyByteBuf b = new FriendlyByteBuf(Unpooled.wrappedBuffer(data));
|
||||
|
||||
if (b.readByte() != MAGIC_BYTE) return null;
|
||||
|
||||
return readFromBytes(packet.socketAddress(), initializationData.secret(), b.readByteArray(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private static NetworkMessage readFromBytes(SocketAddress socketAddress, UUID secret, byte[] encryptedPayload, long timestamp) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
|
||||
byte[] decrypt;
|
||||
try {
|
||||
decrypt = AES.decrypt(secret, encryptedPayload);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.wrappedBuffer(decrypt));
|
||||
byte packetType = buffer.readByte();
|
||||
final Class<? extends Packet<?>> packetClass = packetRegistry.get(packetType);
|
||||
if (packetClass == null) {
|
||||
System.out.println("packet type is null " + packetType);
|
||||
return null;
|
||||
}
|
||||
Packet<?> p = packetClass.getDeclaredConstructor().newInstance();
|
||||
|
||||
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())) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public byte[] writeClient(InitializationData data) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
byte[] payload = write(data.secret());
|
||||
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer(1 + 16 + payload.length));
|
||||
buffer.writeByte(MAGIC_BYTE);
|
||||
buffer.writeUUID(data.playerUUID());
|
||||
buffer.writeByteArray(payload);
|
||||
|
||||
byte[] bytes = new byte[buffer.readableBytes()];
|
||||
buffer.readBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public byte[] write(UUID secret) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||
|
||||
byte type = getPacketType(packet);
|
||||
if (type < 0) {
|
||||
throw new IllegalArgumentException("Packet type not found");
|
||||
}
|
||||
|
||||
buffer.writeByte(type);
|
||||
packet.toBytes(buffer);
|
||||
|
||||
byte[] bytes = new byte[buffer.readableBytes()];
|
||||
buffer.readBytes(bytes);
|
||||
return AES.encrypt(secret, bytes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.voiceChat;
|
||||
|
||||
import land.chipmunk.chayapak.chomens_bot.util.FriendlyByteBuf;
|
||||
|
||||
public interface Packet<T extends Packet<T>> {
|
||||
T fromBytes (FriendlyByteBuf buf);
|
||||
|
||||
void toBytes (FriendlyByteBuf buf);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.voiceChat.packets;
|
||||
|
||||
import land.chipmunk.chayapak.chomens_bot.util.FriendlyByteBuf;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.Packet;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AuthenticatePacket implements Packet<AuthenticatePacket> {
|
||||
@Getter private UUID playerUUID;
|
||||
@Getter private UUID secret;
|
||||
|
||||
@Override
|
||||
public AuthenticatePacket fromBytes (FriendlyByteBuf buf) {
|
||||
AuthenticatePacket packet = new AuthenticatePacket();
|
||||
packet.playerUUID = buf.readUUID();
|
||||
packet.secret = buf.readUUID();
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes (FriendlyByteBuf buf) {
|
||||
buf.writeUUID(playerUUID);
|
||||
buf.writeUUID(secret);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.voiceChat.packets;
|
||||
|
||||
import land.chipmunk.chayapak.chomens_bot.util.FriendlyByteBuf;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.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,26 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.voiceChat.packets;
|
||||
|
||||
import land.chipmunk.chayapak.chomens_bot.util.FriendlyByteBuf;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.Packet;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PingPacket implements Packet<PingPacket> {
|
||||
@Getter private UUID id;
|
||||
@Getter private long timestamp;
|
||||
|
||||
@Override
|
||||
public PingPacket fromBytes(FriendlyByteBuf buf) {
|
||||
final PingPacket pingPacket = new PingPacket();
|
||||
pingPacket.id = buf.readUUID();
|
||||
pingPacket.timestamp = buf.readLong();
|
||||
return pingPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(FriendlyByteBuf buf) {
|
||||
buf.writeUUID(id);
|
||||
buf.writeLong(timestamp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.voiceChat.packets;
|
||||
|
||||
import land.chipmunk.chayapak.chomens_bot.data.voiceChat.Codec;
|
||||
import land.chipmunk.chayapak.chomens_bot.util.FriendlyByteBuf;
|
||||
import land.chipmunk.chayapak.chomens_bot.voiceChat.Packet;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SecretPacket implements Packet<SecretPacket> {
|
||||
@Getter private UUID secret;
|
||||
@Getter private int serverPort;
|
||||
@Getter private UUID playerUUID;
|
||||
@Getter private Codec codec;
|
||||
@Getter private int mtuSize;
|
||||
@Getter private double voiceChatDistance;
|
||||
@Getter private int keepAlive;
|
||||
@Getter private boolean groupsEnabled;
|
||||
@Getter private String voiceHost;
|
||||
@Getter private boolean allowRecording;
|
||||
|
||||
@Override
|
||||
public SecretPacket fromBytes(FriendlyByteBuf buf) {
|
||||
secret = buf.readUUID();
|
||||
serverPort = buf.readInt();
|
||||
playerUUID = buf.readUUID();
|
||||
codec = Codec.values()[buf.readByte()];
|
||||
mtuSize = buf.readInt();
|
||||
voiceChatDistance = buf.readDouble();
|
||||
keepAlive = buf.readInt();
|
||||
groupsEnabled = buf.readBoolean();
|
||||
voiceHost = buf.readUtf();
|
||||
allowRecording = buf.readBoolean();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes (FriendlyByteBuf buf) {
|
||||
buf.writeUUID(secret);
|
||||
buf.writeInt(serverPort);
|
||||
buf.writeUUID(playerUUID);
|
||||
buf.writeByte(codec.ordinal());
|
||||
buf.writeInt(mtuSize);
|
||||
buf.writeDouble(voiceChatDistance);
|
||||
buf.writeInt(keepAlive);
|
||||
buf.writeBoolean(groupsEnabled);
|
||||
buf.writeUtf(voiceHost);
|
||||
buf.writeBoolean(allowRecording);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue