mirror of
https://github.com/ayunami2000/ayunViaProxyEagUtils.git
synced 2024-11-22 04:16:04 -08:00
update a LOT
todo: 1.8 capes and fnaw skins
This commit is contained in:
parent
6cc8a79c8b
commit
790b33ad68
|
@ -10,5 +10,5 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation files("libs/ViaProxy-3.0.22-SNAPSHOT+java8.jar")
|
||||
implementation files("libs/ViaProxy-3.2.0-SNAPSHOT+java8.jar")
|
||||
}
|
|
@ -5,6 +5,7 @@ import com.google.gson.JsonArray;
|
|||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.util.ChatColorUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
|
@ -24,7 +25,6 @@ import net.raphimc.vialegacy.api.LegacyProtocolVersion;
|
|||
import net.raphimc.vialegacy.protocols.release.protocol1_6_1to1_5_2.ClientboundPackets1_5_2;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_6_1to1_5_2.ServerboundPackets1_5_2;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.types.Types1_6_4;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
import net.raphimc.viaproxy.proxy.session.LegacyProxyConnection;
|
||||
import net.raphimc.viaproxy.proxy.session.ProxyConnection;
|
||||
import net.raphimc.viaproxy.proxy.util.ExceptionUtil;
|
||||
|
@ -43,7 +43,7 @@ import java.util.*;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, ByteBuf> {
|
||||
private final VersionEnum version;
|
||||
private final ProtocolVersion version;
|
||||
private final String password;
|
||||
private final NetClient proxyConnection;
|
||||
private final Map<UUID, String> uuidStringMap = new HashMap<>();
|
||||
|
@ -53,7 +53,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
|||
private ByteBuf serverBoundPartialPacket = Unpooled.EMPTY_BUFFER;
|
||||
private ByteBuf clientBoundPartialPacket = Unpooled.EMPTY_BUFFER;
|
||||
public EaglerServerHandler(NetClient proxyConnection, String password) {
|
||||
this.version = proxyConnection instanceof ProxyConnection ? ((ProxyConnection) proxyConnection).getServerVersion() : VersionEnum.r1_5_2;
|
||||
this.version = proxyConnection instanceof ProxyConnection ? ((ProxyConnection) proxyConnection).getServerVersion() : LegacyProtocolVersion.r1_5_2;
|
||||
this.password = password;
|
||||
this.proxyConnection = proxyConnection;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
|||
out.add(Unpooled.EMPTY_BUFFER);
|
||||
return;
|
||||
}
|
||||
if (version.isNewerThan(VersionEnum.r1_6_4)) {
|
||||
if (version.newerThanOrEqualTo(ProtocolVersion.v1_7_2)) {
|
||||
if (in.readableBytes() >= 2 && in.getUnsignedByte(0) == 0xFE && in.getUnsignedByte(1) == 0x01) {
|
||||
handshakeState = -1;
|
||||
out.add(new TextWebSocketFrame("Accept: MOTD"));
|
||||
|
@ -282,7 +282,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
|||
ByteBuf bb = ctx.alloc().buffer();
|
||||
bb.writeByte((byte) 0xFF);
|
||||
StringBuilder sb = new StringBuilder("\u00A71\0");
|
||||
sb.append(LegacyProtocolVersion.getRealProtocolVersion(version.getVersion())).append("\0");
|
||||
sb.append(version.getVersion()).append("\0");
|
||||
sb.append(version.getName()).append("\0");
|
||||
sb.append(motdSb).append("\0");
|
||||
sb.append(online).append("\0");
|
||||
|
@ -307,7 +307,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
|||
JsonObject resp = new JsonObject();
|
||||
JsonObject versionObj = new JsonObject();
|
||||
versionObj.addProperty("name", version.getName());
|
||||
versionObj.addProperty("protocol", LegacyProtocolVersion.getRealProtocolVersion(version.getVersion()));
|
||||
versionObj.addProperty("protocol", version.getVersion());
|
||||
resp.add("version", versionObj);
|
||||
JsonObject playersObj = new JsonObject();
|
||||
playersObj.addProperty("max", max);
|
||||
|
@ -358,7 +358,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
|||
JsonObject resp = new JsonObject();
|
||||
JsonObject versionObj = new JsonObject();
|
||||
versionObj.addProperty("name", version.getName());
|
||||
versionObj.addProperty("protocol", LegacyProtocolVersion.getRealProtocolVersion(version.getVersion()));
|
||||
versionObj.addProperty("protocol", version.getVersion());
|
||||
resp.add("version", versionObj);
|
||||
JsonObject playersObj = new JsonObject();
|
||||
playersObj.addProperty("max", serverInfo.max);
|
||||
|
@ -401,7 +401,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
|||
handshakeState = -1;
|
||||
return;
|
||||
}
|
||||
if (version.isNewerThan(VersionEnum.r1_6_4)) {
|
||||
if (version.newerThanOrEqualTo(ProtocolVersion.v1_7_2)) {
|
||||
if (handshakeState == 0) {
|
||||
out.add(Unpooled.EMPTY_BUFFER);
|
||||
} else if (handshakeState == 1) {
|
||||
|
@ -440,7 +440,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
|||
bb.writeBytes(clientBoundPartialPacket);
|
||||
clientBoundPartialPacket.release();
|
||||
clientBoundPartialPacket = Unpooled.EMPTY_BUFFER;
|
||||
bb.writeBytes(in.content());
|
||||
bb.writeBytes(in.content()); // todo: do i need to reset this??????
|
||||
int readerIndex = 0;
|
||||
try {
|
||||
while (bb.isReadable()) {
|
||||
|
|
|
@ -4,38 +4,32 @@ import io.netty.buffer.ByteBuf;
|
|||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import io.netty.util.AttributeKey;
|
||||
import net.raphimc.netminecraft.packet.PacketTypes;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.types.Types1_6_4;
|
||||
import net.raphimc.viaproxy.proxy.util.ExceptionUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class EaglerVoiceHandler extends ChannelInboundHandlerAdapter {
|
||||
private static final ConcurrentHashMap<String, ChannelHandlerContext> voicePlayers;
|
||||
private static final ConcurrentHashMap<String, ExpiringSet<String>> voiceRequests;
|
||||
private static final CopyOnWriteArraySet<String[]> voicePairs;
|
||||
private final String user;
|
||||
private static final Collection<String> iceServers;
|
||||
private static final AttributeKey<Boolean> VOICE_ENABLED;
|
||||
|
||||
private static void sendData(final ChannelHandlerContext ctx, final byte[] data) throws IOException {
|
||||
final ByteBuf bb = ctx.alloc().buffer();
|
||||
bb.writeByte(250);
|
||||
try {
|
||||
Types1_6_4.STRING.write(bb, "EAG|Voice");
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
bb.writeShort(data.length);
|
||||
bb.writeBytes(data);
|
||||
ctx.writeAndFlush(new BinaryWebSocketFrame(bb));
|
||||
}
|
||||
public static final VoiceServerImpl voiceService = new VoiceServerImpl();
|
||||
|
||||
public String user;
|
||||
public UUID uuid;
|
||||
public final boolean old;
|
||||
private int pluginMessageId = -1;
|
||||
|
||||
public EaglerVoiceHandler(final String username) {
|
||||
this.user = username;
|
||||
if (this.user == null) {
|
||||
this.uuid = null;
|
||||
old = false;
|
||||
} else {
|
||||
old = true;
|
||||
this.uuid = nameToUUID(this.user);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,23 +37,29 @@ public class EaglerVoiceHandler extends ChannelInboundHandlerAdapter {
|
|||
ExceptionUtil.handleNettyException(ctx, cause, null);
|
||||
}
|
||||
|
||||
private static UUID nameToUUID(String name) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
private boolean sent = false;
|
||||
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object obj) throws Exception {
|
||||
if (((EaglercraftHandler) ctx.pipeline().get("eaglercraft-handler")).state == EaglercraftHandler.State.LOGIN_COMPLETE && !ctx.channel().hasAttr(EaglerVoiceHandler.VOICE_ENABLED)) {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final DataOutputStream dos = new DataOutputStream(baos);
|
||||
dos.write(0);
|
||||
dos.writeBoolean(true);
|
||||
dos.write(EaglerVoiceHandler.iceServers.size());
|
||||
for (final String str : EaglerVoiceHandler.iceServers) {
|
||||
dos.writeUTF(str);
|
||||
if (!FunnyConfig.eaglerVoice) {
|
||||
super.channelRead(ctx, obj);
|
||||
return;
|
||||
}
|
||||
sendData(ctx, baos.toByteArray());
|
||||
this.sendVoicePlayers(this.user);
|
||||
ctx.channel().attr(EaglerVoiceHandler.VOICE_ENABLED).set(true);
|
||||
if (((EaglercraftHandler) ctx.pipeline().get("eaglercraft-handler")).state == EaglercraftHandler.State.LOGIN_COMPLETE && !sent) {
|
||||
if (this.user == null) {
|
||||
this.user = ((EaglercraftHandler) ctx.pipeline().get("eaglercraft-handler")).username;
|
||||
this.uuid = nameToUUID(this.user);
|
||||
}
|
||||
sent = true;
|
||||
voiceService.handlePlayerLoggedIn(ctx);
|
||||
}
|
||||
if (obj instanceof BinaryWebSocketFrame) {
|
||||
final ByteBuf bb = ((BinaryWebSocketFrame) obj).content();
|
||||
if (old) {
|
||||
if (bb.readableBytes() >= 3 && bb.readByte() == -6) {
|
||||
String tag;
|
||||
byte[] msg;
|
||||
|
@ -78,135 +78,35 @@ public class EaglerVoiceHandler extends ChannelInboundHandlerAdapter {
|
|||
super.channelRead(ctx, obj);
|
||||
return;
|
||||
}
|
||||
if (!FunnyConfig.eaglerVoice) {
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
final DataInputStream streamIn = new DataInputStream(new ByteArrayInputStream(msg));
|
||||
final int sig = streamIn.read();
|
||||
switch (sig) {
|
||||
case 0: {
|
||||
if (!EaglerVoiceHandler.voicePlayers.containsKey(this.user)) {
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
final String targetUser = streamIn.readUTF();
|
||||
if (this.user.equals(targetUser)) {
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
if (this.checkVoicePair(this.user, targetUser)) {
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
if (!EaglerVoiceHandler.voicePlayers.containsKey(targetUser)) {
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
if (!EaglerVoiceHandler.voiceRequests.containsKey(this.user)) {
|
||||
EaglerVoiceHandler.voiceRequests.put(this.user, new ExpiringSet<>(2000L));
|
||||
}
|
||||
if (!EaglerVoiceHandler.voiceRequests.get(this.user).contains(targetUser)) {
|
||||
EaglerVoiceHandler.voiceRequests.get(this.user).add(targetUser);
|
||||
if (EaglerVoiceHandler.voiceRequests.containsKey(targetUser) && EaglerVoiceHandler.voiceRequests.get(targetUser).contains(this.user)) {
|
||||
if (EaglerVoiceHandler.voiceRequests.containsKey(targetUser)) {
|
||||
EaglerVoiceHandler.voiceRequests.get(targetUser).remove(this.user);
|
||||
if (EaglerVoiceHandler.voiceRequests.get(targetUser).isEmpty()) {
|
||||
EaglerVoiceHandler.voiceRequests.remove(targetUser);
|
||||
}
|
||||
}
|
||||
if (EaglerVoiceHandler.voiceRequests.containsKey(this.user)) {
|
||||
EaglerVoiceHandler.voiceRequests.get(this.user).remove(targetUser);
|
||||
if (EaglerVoiceHandler.voiceRequests.get(this.user).isEmpty()) {
|
||||
EaglerVoiceHandler.voiceRequests.remove(this.user);
|
||||
}
|
||||
}
|
||||
EaglerVoiceHandler.voicePairs.add(new String[]{this.user, targetUser});
|
||||
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
|
||||
DataOutputStream dos2 = new DataOutputStream(baos2);
|
||||
dos2.write(1);
|
||||
dos2.writeUTF(this.user);
|
||||
dos2.writeBoolean(false);
|
||||
sendData(EaglerVoiceHandler.voicePlayers.get(targetUser), baos2.toByteArray());
|
||||
baos2 = new ByteArrayOutputStream();
|
||||
dos2 = new DataOutputStream(baos2);
|
||||
dos2.write(1);
|
||||
dos2.writeUTF(targetUser);
|
||||
dos2.writeBoolean(true);
|
||||
sendData(ctx, baos2.toByteArray());
|
||||
}
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
voiceService.handleVoiceSignalPacketTypeRequest(nameToUUID(streamIn.readUTF()), ctx);
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
case 1: {
|
||||
if (!EaglerVoiceHandler.voicePlayers.containsKey(this.user)) {
|
||||
final ByteArrayOutputStream baos3 = new ByteArrayOutputStream();
|
||||
final DataOutputStream dos3 = new DataOutputStream(baos3);
|
||||
dos3.write(1);
|
||||
dos3.writeUTF(this.user);
|
||||
final byte[] out = baos3.toByteArray();
|
||||
for (final ChannelHandlerContext conn : EaglerVoiceHandler.voicePlayers.values()) {
|
||||
sendData(conn, out);
|
||||
}
|
||||
EaglerVoiceHandler.voicePlayers.put(this.user, ctx);
|
||||
for (final String username : EaglerVoiceHandler.voicePlayers.keySet()) {
|
||||
this.sendVoicePlayers(username);
|
||||
}
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
voiceService.handleVoiceSignalPacketTypeConnect(ctx);
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
case 2: {
|
||||
if (!EaglerVoiceHandler.voicePlayers.containsKey(this.user)) {
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final String targetUser = streamIn.readUTF();
|
||||
if (!EaglerVoiceHandler.voicePlayers.containsKey(targetUser)) {
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
if (EaglerVoiceHandler.voicePairs.removeIf(pair -> (pair[0].equals(this.user) && pair[1].equals(targetUser)) || (pair[0].equals(targetUser) && pair[1].equals(this.user)))) {
|
||||
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
|
||||
DataOutputStream dos2 = new DataOutputStream(baos2);
|
||||
dos2.write(2);
|
||||
dos2.writeUTF(this.user);
|
||||
sendData(EaglerVoiceHandler.voicePlayers.get(targetUser), baos2.toByteArray());
|
||||
baos2 = new ByteArrayOutputStream();
|
||||
dos2 = new DataOutputStream(baos2);
|
||||
dos2.write(2);
|
||||
dos2.writeUTF(targetUser);
|
||||
sendData(ctx, baos2.toByteArray());
|
||||
break;
|
||||
}
|
||||
} catch (EOFException var7) {
|
||||
this.removeUser(this.user);
|
||||
voiceService.handleVoiceSignalPacketTypeDisconnect(nameToUUID(streamIn.readUTF()), ctx);
|
||||
} catch (EOFException e) {
|
||||
voiceService.handleVoiceSignalPacketTypeDisconnect(null, ctx);
|
||||
}
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
case 3:
|
||||
case 3: {
|
||||
voiceService.handleVoiceSignalPacketTypeICE(nameToUUID(streamIn.readUTF()), streamIn.readUTF(), ctx);
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
case 4: {
|
||||
if (EaglerVoiceHandler.voicePlayers.containsKey(this.user)) {
|
||||
final String username = streamIn.readUTF();
|
||||
if (this.checkVoicePair(this.user, username)) {
|
||||
final String data = streamIn.readUTF();
|
||||
final ByteArrayOutputStream baos4 = new ByteArrayOutputStream();
|
||||
final DataOutputStream dos4 = new DataOutputStream(baos4);
|
||||
dos4.write(sig);
|
||||
dos4.writeUTF(this.user);
|
||||
dos4.writeUTF(data);
|
||||
sendData(EaglerVoiceHandler.voicePlayers.get(username), baos4.toByteArray());
|
||||
}
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
voiceService.handleVoiceSignalPacketTypeDesc(nameToUUID(streamIn.readUTF()), streamIn.readUTF(), ctx);
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
|
@ -216,14 +116,28 @@ public class EaglerVoiceHandler extends ChannelInboundHandlerAdapter {
|
|||
}
|
||||
}
|
||||
} catch (Throwable var8) {
|
||||
this.removeUser(this.user);
|
||||
voiceService.handlePlayerLoggedOut(uuid);
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
bb.resetReaderIndex();
|
||||
} else {
|
||||
if (this.pluginMessageId <= 0) {
|
||||
this.pluginMessageId = ((EaglercraftHandler) ctx.pipeline().get("eaglercraft-handler")).pluginMessageId;
|
||||
}
|
||||
try {
|
||||
if (PacketTypes.readVarInt(bb) == this.pluginMessageId && PacketTypes.readString(bb, 32767).equals("EAG|Voice-1.8")) {
|
||||
final byte[] data = new byte[bb.readableBytes()];
|
||||
bb.readBytes(data);
|
||||
VoiceSignalPackets.processPacket(data, ctx);
|
||||
bb.release();
|
||||
return;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
bb.resetReaderIndex();
|
||||
}
|
||||
}
|
||||
super.channelRead(ctx, obj);
|
||||
}
|
||||
|
@ -231,95 +145,6 @@ public class EaglerVoiceHandler extends ChannelInboundHandlerAdapter {
|
|||
@Override
|
||||
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
|
||||
super.channelInactive(ctx);
|
||||
this.removeUser(this.user);
|
||||
}
|
||||
|
||||
public void sendVoicePlayers(final String name) {
|
||||
if (EaglerVoiceHandler.voicePlayers.containsKey(name)) {
|
||||
try {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final DataOutputStream dos = new DataOutputStream(baos);
|
||||
dos.write(5);
|
||||
final Set<String> mostlyGlobalPlayers = ConcurrentHashMap.newKeySet();
|
||||
for (final String username : EaglerVoiceHandler.voicePlayers.keySet()) {
|
||||
if (!username.equals(name) && EaglerVoiceHandler.voicePairs.stream().noneMatch(pair -> (pair[0].equals(name) && pair[1].equals(username)) || (pair[0].equals(username) && pair[1].equals(name)))) {
|
||||
mostlyGlobalPlayers.add(username);
|
||||
}
|
||||
}
|
||||
if (!mostlyGlobalPlayers.isEmpty()) {
|
||||
dos.writeInt(mostlyGlobalPlayers.size());
|
||||
for (final String username : mostlyGlobalPlayers) {
|
||||
dos.writeUTF(username);
|
||||
}
|
||||
sendData(EaglerVoiceHandler.voicePlayers.get(name), baos.toByteArray());
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeUser(final String name) {
|
||||
EaglerVoiceHandler.voicePlayers.remove(name);
|
||||
for (final String username : EaglerVoiceHandler.voicePlayers.keySet()) {
|
||||
if (!name.equals(username)) {
|
||||
this.sendVoicePlayers(username);
|
||||
}
|
||||
}
|
||||
for (final String[] voicePair : EaglerVoiceHandler.voicePairs) {
|
||||
String target = null;
|
||||
if (voicePair[0].equals(name)) {
|
||||
target = voicePair[1];
|
||||
} else if (voicePair[1].equals(name)) {
|
||||
target = voicePair[0];
|
||||
}
|
||||
if (target != null && EaglerVoiceHandler.voicePlayers.containsKey(target)) {
|
||||
try {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final DataOutputStream dos = new DataOutputStream(baos);
|
||||
dos.write(2);
|
||||
dos.writeUTF(name);
|
||||
sendData(EaglerVoiceHandler.voicePlayers.get(target), baos.toByteArray());
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
EaglerVoiceHandler.voicePairs.removeIf(pair -> pair[0].equals(name) || pair[1].equals(name));
|
||||
}
|
||||
|
||||
private boolean checkVoicePair(final String user1, final String user2) {
|
||||
return EaglerVoiceHandler.voicePairs.stream().anyMatch(pair -> (pair[0].equals(user1) && pair[1].equals(user2)) || (pair[0].equals(user2) && pair[1].equals(user1)));
|
||||
}
|
||||
|
||||
static {
|
||||
voicePlayers = new ConcurrentHashMap<>();
|
||||
voiceRequests = new ConcurrentHashMap<>();
|
||||
voicePairs = new CopyOnWriteArraySet<>();
|
||||
(iceServers = new ArrayList<>()).add("stun:stun.l.google.com:19302");
|
||||
EaglerVoiceHandler.iceServers.add("stun:stun1.l.google.com:19302");
|
||||
EaglerVoiceHandler.iceServers.add("stun:stun2.l.google.com:19302");
|
||||
EaglerVoiceHandler.iceServers.add("stun:stun3.l.google.com:19302");
|
||||
EaglerVoiceHandler.iceServers.add("stun:stun4.l.google.com:19302");
|
||||
EaglerVoiceHandler.iceServers.add("stun:openrelay.metered.ca:80");
|
||||
final Map<String, Map<String, String>> turnServerList = new HashMap<>();
|
||||
HashMap<String, String> n = new HashMap<>();
|
||||
n.put("url", "turn:openrelay.metered.ca:80");
|
||||
n.put("username", "openrelayproject");
|
||||
n.put("password", "openrelayproject");
|
||||
turnServerList.put("openrelay1", n);
|
||||
n = new HashMap<>();
|
||||
n.put("url", "turn:openrelay.metered.ca:443");
|
||||
n.put("username", "openrelayproject");
|
||||
n.put("password", "openrelayproject");
|
||||
turnServerList.put("openrelay2", n);
|
||||
n = new HashMap<>();
|
||||
n.put("url", "turn:openrelay.metered.ca:443?transport=tcp");
|
||||
n.put("username", "openrelayproject");
|
||||
n.put("password", "openrelayproject");
|
||||
turnServerList.put("openrelay3", n);
|
||||
for (final Map.Entry<String, Map<String, String>> trn : turnServerList.entrySet()) {
|
||||
final Map<String, String> o = trn.getValue();
|
||||
EaglerVoiceHandler.iceServers.add(o.get("url") + ";" + o.get("username") + ";" + o.get("password"));
|
||||
}
|
||||
VOICE_ENABLED = AttributeKey.valueOf("ayun-voice-enabled");
|
||||
voiceService.handlePlayerLoggedOut(uuid);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package me.ayunami2000.ayunViaProxyEagUtils;
|
||||
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.libs.gson.JsonArray;
|
||||
import com.viaversion.viaversion.libs.gson.JsonObject;
|
||||
import com.viaversion.viaversion.libs.gson.JsonParser;
|
||||
|
@ -22,9 +23,9 @@ import net.raphimc.netminecraft.constants.ConnectionState;
|
|||
import net.raphimc.netminecraft.constants.MCPackets;
|
||||
import net.raphimc.netminecraft.constants.MCPipeline;
|
||||
import net.raphimc.netminecraft.packet.PacketTypes;
|
||||
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_6_1to1_5_2.ServerboundPackets1_5_2;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.types.Types1_6_4;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
import net.raphimc.viaproxy.ViaProxy;
|
||||
import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyChannelInitializer;
|
||||
import net.raphimc.viaproxy.proxy.util.ExceptionUtil;
|
||||
|
@ -53,7 +54,7 @@ public class EaglercraftHandler extends MessageToMessageCodec<WebSocketFrame, By
|
|||
public static final AttributeKey<HttpHeaders> httpHeadersKey = AttributeKey.newInstance("eag-http-headers");
|
||||
private HostAndPort host;
|
||||
public State state;
|
||||
public VersionEnum version;
|
||||
public ProtocolVersion version;
|
||||
public int pluginMessageId;
|
||||
public String username;
|
||||
|
||||
|
@ -143,7 +144,7 @@ public class EaglercraftHandler extends MessageToMessageCodec<WebSocketFrame, By
|
|||
if (data.readableBytes() >= 2 && data.getByte(0) == 2 && data.getByte(1) == 69) {
|
||||
data.setByte(1, 61);
|
||||
this.state = State.LOGIN_COMPLETE;
|
||||
this.version = VersionEnum.r1_5_2;
|
||||
this.version = LegacyProtocolVersion.r1_5_2;
|
||||
out.add(data.retain());
|
||||
break;
|
||||
}
|
||||
|
@ -197,8 +198,8 @@ public class EaglercraftHandler extends MessageToMessageCodec<WebSocketFrame, By
|
|||
}
|
||||
Logger.LOGGER.info("Eaglercraft client connected: " + clientBrand + " " + clientVersionString);
|
||||
this.state = State.HANDSHAKE_COMPLETE;
|
||||
this.version = VersionEnum.fromProtocolId(minecraftVersion);
|
||||
if (this.version.equals(VersionEnum.UNKNOWN)) {
|
||||
this.version = ProtocolVersion.getProtocol(minecraftVersion);
|
||||
if (this.version.equals(ProtocolVersion.unknown)) {
|
||||
Logger.LOGGER.error("Unsupported protocol version: " + minecraftVersion);
|
||||
ctx.close();
|
||||
return;
|
||||
|
@ -278,7 +279,7 @@ public class EaglercraftHandler extends MessageToMessageCodec<WebSocketFrame, By
|
|||
break;
|
||||
}
|
||||
case LOGIN_COMPLETE: {
|
||||
if (this.version.equals(VersionEnum.r1_5_2)) {
|
||||
if (this.version.equals(LegacyProtocolVersion.r1_5_2)) {
|
||||
final int packetId = data.readUnsignedByte();
|
||||
if (packetId == ServerboundPackets1_5_2.SHARED_KEY.getId()) {
|
||||
ctx.channel().writeAndFlush(new BinaryWebSocketFrame(data.readerIndex(0).retain()));
|
||||
|
@ -289,7 +290,7 @@ public class EaglercraftHandler extends MessageToMessageCodec<WebSocketFrame, By
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (this.version.isNewerThanOrEqualTo(VersionEnum.r1_7_2tor1_7_5) && (!ctx.channel().hasAttr(Main.secureWs) || ctx.channel().attr(Main.secureWs) == null)) {
|
||||
} else if (this.version.newerThanOrEqualTo(ProtocolVersion.v1_7_2) && (!ctx.channel().hasAttr(Main.secureWs) || ctx.channel().attr(Main.secureWs) == null)) {
|
||||
final int packetId = PacketTypes.readVarInt(data);
|
||||
if (packetId == this.pluginMessageId && PacketTypes.readString(data, 32767).startsWith("EAG|")) {
|
||||
break;
|
||||
|
@ -315,7 +316,7 @@ public class EaglercraftHandler extends MessageToMessageCodec<WebSocketFrame, By
|
|||
return;
|
||||
}
|
||||
this.state = State.STATUS;
|
||||
this.version = VersionEnum.r1_8;
|
||||
this.version = ProtocolVersion.v1_8;
|
||||
if (ctx.pipeline().get(Client2ProxyChannelInitializer.LEGACY_PASSTHROUGH_INITIAL_HANDLER_NAME) != null) {
|
||||
ctx.pipeline().remove(Client2ProxyChannelInitializer.LEGACY_PASSTHROUGH_INITIAL_HANDLER_NAME);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
|||
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import net.raphimc.viaproxy.plugins.PluginManager;
|
||||
import net.raphimc.viaproxy.ViaProxy;
|
||||
import net.raphimc.viaproxy.plugins.events.Client2ProxyHandlerCreationEvent;
|
||||
import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyChannelInitializer;
|
||||
import net.raphimc.viaproxy.proxy.client2proxy.passthrough.LegacyPassthroughInitialHandler;
|
||||
|
@ -40,8 +40,9 @@ public class EaglercraftInitialHandler extends ByteToMessageDecoder {
|
|||
return;
|
||||
}
|
||||
if (in.readableBytes() >= 3 || in.getByte(0) != 71) {
|
||||
if ((in.readableBytes() >= 3 && in.getCharSequence(0, 3, StandardCharsets.UTF_8).equals("GET")) || (in.readableBytes() >= 4 && in.getCharSequence(0, 4, StandardCharsets.UTF_8).equals("POST"))) {
|
||||
if (EaglercraftInitialHandler.sslContext != null) {
|
||||
boolean ssl = EaglercraftInitialHandler.sslContext != null && in.readableBytes() >= 3 && in.getByte(0) == 22;
|
||||
if (ssl || (in.readableBytes() >= 3 && in.getCharSequence(0, 3, StandardCharsets.UTF_8).equals("GET")) || (in.readableBytes() >= 4 && in.getCharSequence(0, 4, StandardCharsets.UTF_8).equals("POST"))) {
|
||||
if (ssl) {
|
||||
ctx.pipeline().addBefore("eaglercraft-initial-handler", "ws-ssl-handler", EaglercraftInitialHandler.sslContext.newHandler(ctx.alloc()));
|
||||
}
|
||||
ctx.pipeline().addBefore("eaglercraft-initial-handler", "ws-http-codec", new HttpServerCodec());
|
||||
|
@ -69,7 +70,7 @@ public class EaglercraftInitialHandler extends ByteToMessageDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
Supplier<ChannelHandler> handlerSupplier = () -> PluginManager.EVENT_MANAGER.call(new Client2ProxyHandlerCreationEvent(new PassthroughClient2ProxyHandler(), true)).getHandler();
|
||||
Supplier<ChannelHandler> handlerSupplier = () -> ViaProxy.EVENT_MANAGER.call(new Client2ProxyHandlerCreationEvent(new PassthroughClient2ProxyHandler(), true)).getHandler();
|
||||
PassthroughClient2ProxyChannelInitializer channelInitializer = new PassthroughClient2ProxyChannelInitializer(handlerSupplier);
|
||||
try {
|
||||
initChannelMethod.invoke(channelInitializer, ctx.channel());
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
package me.ayunami2000.ayunViaProxyEagUtils;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.handler.codec.compression.ZlibCodecFactory;
|
||||
import io.netty.handler.codec.http.*;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.WebSocketClientExtensionHandler;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.compression.DeflateFrameClientExtensionHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.compression.PerMessageDeflateClientExtensionHandshaker;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.util.AsciiString;
|
||||
import io.netty.util.AttributeKey;
|
||||
import net.lenni0451.lambdaevents.EventHandler;
|
||||
import net.raphimc.netminecraft.constants.MCPipeline;
|
||||
import net.raphimc.netminecraft.netty.connection.NetClient;
|
||||
import net.raphimc.netminecraft.util.ServerAddress;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.types.Types1_6_4;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
import net.raphimc.viaproxy.plugins.PluginManager;
|
||||
import net.raphimc.viaproxy.ViaProxy;
|
||||
import net.raphimc.viaproxy.plugins.ViaProxyPlugin;
|
||||
import net.raphimc.viaproxy.plugins.events.Client2ProxyChannelInitializeEvent;
|
||||
import net.raphimc.viaproxy.plugins.events.Proxy2ServerChannelInitializeEvent;
|
||||
|
@ -31,6 +33,8 @@ import javax.net.ssl.*;
|
|||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.KeyManagementException;
|
||||
|
@ -70,8 +74,8 @@ public class Main extends ViaProxyPlugin {
|
|||
}
|
||||
|
||||
public void onEnable() {
|
||||
PluginManager.EVENT_MANAGER.register(this);
|
||||
(new FunnyConfig(new File("ViaLoader", "vpeagutils.yml"))).reloadConfig();
|
||||
ViaProxy.EVENT_MANAGER.register(this);
|
||||
(new FunnyConfig(new File("ViaLoader", "vpeagutils.yml"))).reload();
|
||||
EaglerXSkinHandler.skinService = new SkinService();
|
||||
}
|
||||
|
||||
|
@ -82,7 +86,7 @@ public class Main extends ViaProxyPlugin {
|
|||
|
||||
NetClient proxyConnection;
|
||||
Channel c2p;
|
||||
ServerAddress addr;
|
||||
SocketAddress addr;
|
||||
if (event.isLegacyPassthrough()) {
|
||||
proxyConnection = LegacyProxyConnection.fromChannel(ch);
|
||||
c2p = ((LegacyProxyConnection) proxyConnection).getC2P();
|
||||
|
@ -99,8 +103,8 @@ public class Main extends ViaProxyPlugin {
|
|||
c2p.attr(secureWs).set(true);
|
||||
}
|
||||
|
||||
if (c2p.hasAttr(secureWs) && c2p.attr(secureWs).get() != null) {
|
||||
doWsServerStuff(ch, proxyConnection, c2p, addr);
|
||||
if (c2p.hasAttr(secureWs) && c2p.attr(secureWs).get() != null && addr instanceof InetSocketAddress) {
|
||||
doWsServerStuff(ch, proxyConnection, c2p, (InetSocketAddress) addr);
|
||||
if (!event.isLegacyPassthrough()) {
|
||||
ch.pipeline().addFirst("handshake-waiter", new ChannelOutboundHandlerAdapter() {
|
||||
private boolean hasHandshake = false;
|
||||
|
@ -142,9 +146,9 @@ public class Main extends ViaProxyPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
private static void doWsServerStuff(Channel ch, NetClient proxyConnection, Channel c2p, ServerAddress addr) throws URISyntaxException {
|
||||
private static void doWsServerStuff(Channel ch, NetClient proxyConnection, Channel c2p, InetSocketAddress addr) throws URISyntaxException {
|
||||
ch.attr(MCPipeline.COMPRESSION_THRESHOLD_ATTRIBUTE_KEY).set(-2);
|
||||
if (proxyConnection instanceof ProxyConnection && ((ProxyConnection) proxyConnection).getServerVersion().isNewerThan(VersionEnum.r1_6_4)) {
|
||||
if (proxyConnection instanceof ProxyConnection && ((ProxyConnection) proxyConnection).getServerVersion().newerThanOrEqualTo(ProtocolVersion.v1_7_2)) {
|
||||
ch.pipeline().remove(MCPipeline.SIZER_HANDLER_NAME);
|
||||
} else if (ch.pipeline().get(MCPipeline.ENCRYPTION_HANDLER_NAME) != null) {
|
||||
ch.pipeline().remove(MCPipeline.ENCRYPTION_HANDLER_NAME);
|
||||
|
@ -164,7 +168,7 @@ public class Main extends ViaProxyPlugin {
|
|||
StringBuilder url = new StringBuilder("ws");
|
||||
boolean secure = c2p.attr(secureWs).get();
|
||||
if (secure) {
|
||||
final SSLEngine sslEngine = sc.createSSLEngine(addr.getAddress(), addr.getPort());
|
||||
final SSLEngine sslEngine = sc.createSSLEngine(addr.getHostString(), addr.getPort());
|
||||
sslEngine.setUseClientMode(true);
|
||||
sslEngine.setNeedClientAuth(false);
|
||||
ch.pipeline().addFirst("eag-server-ssl", new SslHandler(sslEngine) {
|
||||
|
@ -181,7 +185,7 @@ public class Main extends ViaProxyPlugin {
|
|||
} else {
|
||||
ch.pipeline().addFirst("eag-server-http-codec", new HttpClientCodec());
|
||||
}
|
||||
url.append("://").append(addr.getAddress());
|
||||
url.append("://").append(addr.getHostString());
|
||||
if ((secure && addr.getPort() != 443) || (!secure && addr.getPort() != 80)) {
|
||||
url.append(":").append(addr.getPort());
|
||||
}
|
||||
|
@ -193,7 +197,7 @@ public class Main extends ViaProxyPlugin {
|
|||
URI uri = new URI(url.toString());
|
||||
HttpHeaders headers = c2p.hasAttr(EaglercraftHandler.httpHeadersKey) ? c2p.attr(EaglercraftHandler.httpHeadersKey).get() : new DefaultHttpHeaders().clear().set(HttpHeaderNames.ORIGIN, "https://via.shhnowisnottheti.me");
|
||||
ch.pipeline().addAfter("eag-server-http-codec", "eag-server-http-aggregator", new HttpObjectAggregator(2097152, true));
|
||||
ch.pipeline().addAfter("eag-server-http-aggregator", "eag-server-ws-compression", WebSocketClientCompressionHandler.INSTANCE);
|
||||
ch.pipeline().addAfter("eag-server-http-aggregator", "eag-server-ws-compression", new WebSocketClientExtensionHandler(new PerMessageDeflateClientExtensionHandshaker(1, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), 15, false, false), new DeflateFrameClientExtensionHandshaker(1, false), new DeflateFrameClientExtensionHandshaker(1, true)));
|
||||
ch.pipeline().addAfter("eag-server-ws-compression", "eag-server-ws-handshaker", new WebSocketClientProtocolHandler(WebSocketClientHandshakerFactory.newHandshaker(uri, WebSocketVersion.V13, null, true, headers, 2097152)));
|
||||
ch.pipeline().addAfter("eag-server-ws-handshaker", "eag-server-ws-ready", new WebSocketConnectedNotifier());
|
||||
ch.pipeline().addAfter("eag-server-ws-ready", "eag-server-handler", new EaglerServerHandler(proxyConnection, c2p.attr(eagxPass).get()));
|
||||
|
@ -239,6 +243,7 @@ public class Main extends ViaProxyPlugin {
|
|||
} else {
|
||||
ctx.pipeline().addBefore("eaglercraft-handler", "ayun-eag-x-login", new EaglerXLoginHandler());
|
||||
ctx.pipeline().addBefore("eaglercraft-handler", "ayun-eag-skin-x", new EaglerXSkinHandler());
|
||||
ctx.pipeline().addBefore("eaglercraft-handler", "ayun-eag-voice", new EaglerVoiceHandler(null));
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,400 @@
|
|||
package me.ayunami2000.ayunViaProxyEagUtils;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import net.raphimc.netminecraft.constants.MCPackets;
|
||||
import net.raphimc.netminecraft.packet.PacketTypes;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.types.Types1_6_4;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class VoiceServerImpl {
|
||||
|
||||
public static final Map<UUID, String> uuidToUsernameMap = new HashMap<>();
|
||||
|
||||
private static void fuckFuckFuck(ByteBuf out, String str) {
|
||||
int strlen = str.length();
|
||||
int utflen = 0;
|
||||
int c, count = 0;
|
||||
|
||||
/* use charAt instead of copying String to char array */
|
||||
for (int i = 0; i < strlen; i++) {
|
||||
c = str.charAt(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
utflen++;
|
||||
} else if (c > 0x07FF) {
|
||||
utflen += 3;
|
||||
} else {
|
||||
utflen += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (utflen > 65535)
|
||||
throw new RuntimeException(
|
||||
"encoded string too long: " + utflen + " bytes");
|
||||
|
||||
byte[] bytearr = new byte[utflen+2];
|
||||
|
||||
bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
|
||||
bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
|
||||
|
||||
int i=0;
|
||||
for (i=0; i<strlen; i++) {
|
||||
c = str.charAt(i);
|
||||
if (!((c >= 0x0001) && (c <= 0x007F))) break;
|
||||
bytearr[count++] = (byte) c;
|
||||
}
|
||||
|
||||
for (;i < strlen; i++){
|
||||
c = str.charAt(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
bytearr[count++] = (byte) c;
|
||||
|
||||
} else if (c > 0x07FF) {
|
||||
bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
|
||||
bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
|
||||
bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
|
||||
} else {
|
||||
bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
|
||||
bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
|
||||
}
|
||||
}
|
||||
out.writeBytes(bytearr, 0, utflen+2);
|
||||
}
|
||||
|
||||
private int pluginMessageId = -1;
|
||||
private void sendData(final ChannelHandlerContext ctx, final byte[] data) {
|
||||
final ByteBuf bb = ctx.alloc().buffer();
|
||||
if (((EaglerVoiceHandler) ctx.pipeline().get("ayun-eag-voice")).old) {
|
||||
bb.writeByte(250);
|
||||
try {
|
||||
Types1_6_4.STRING.write(bb, "EAG|Voice");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
bb.writeShort(data.length);
|
||||
bb.writeBytes(data);
|
||||
bb.readerIndex(23);
|
||||
switch (bb.readByte()) {
|
||||
case 0:
|
||||
if (bb.readableBytes() == 1) break;
|
||||
bb.skipBytes(1);
|
||||
int vi = PacketTypes.readVarInt(bb);
|
||||
String[] fard = new String[vi];
|
||||
for (int i = 0; i < vi; i++) {
|
||||
int xd = PacketTypes.readVarInt(bb);
|
||||
byte[] arr = new byte[xd];
|
||||
bb.readBytes(arr);
|
||||
fard[i] = new String(arr, StandardCharsets.UTF_8);
|
||||
}
|
||||
bb.readerIndex(0);
|
||||
bb.writerIndex(25);
|
||||
bb.writeByte(vi);
|
||||
for (String s : fard) {
|
||||
fuckFuckFuck(bb, s);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
UUID uuid = PacketTypes.readUuid(bb);
|
||||
boolean o = bb.readBoolean();
|
||||
bb.readerIndex(0);
|
||||
bb.writerIndex(24);
|
||||
fuckFuckFuck(bb, uuidToUsernameMap.get(uuid));
|
||||
bb.writeBoolean(o);
|
||||
break;
|
||||
case 2:
|
||||
if (bb.readableBytes() == 0) break;
|
||||
uuid = PacketTypes.readUuid(bb);
|
||||
bb.readerIndex(0);
|
||||
bb.writerIndex(24);
|
||||
fuckFuckFuck(bb, uuidToUsernameMap.get(uuid));
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
uuid = PacketTypes.readUuid(bb);
|
||||
vi = PacketTypes.readVarInt(bb);
|
||||
byte[] arr = new byte[vi];
|
||||
bb.readBytes(arr);
|
||||
bb.readerIndex(0);
|
||||
bb.writerIndex(24);
|
||||
fuckFuckFuck(bb, uuidToUsernameMap.get(uuid));
|
||||
fuckFuckFuck(bb, new String(arr, StandardCharsets.UTF_8));
|
||||
break;
|
||||
case 5:
|
||||
vi = PacketTypes.readVarInt(bb);
|
||||
bb.skipBytes(vi * 16);
|
||||
fard = new String[vi];
|
||||
for (int i = 0; i < vi; i++) {
|
||||
int xd = PacketTypes.readVarInt(bb);
|
||||
arr = new byte[xd];
|
||||
bb.readBytes(arr);
|
||||
fard[i] = new String(arr, StandardCharsets.UTF_8);
|
||||
}
|
||||
bb.readerIndex(0);
|
||||
bb.writerIndex(24);
|
||||
bb.writeInt(vi);
|
||||
for (String s : fard) {
|
||||
fuckFuckFuck(bb, s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
bb.readerIndex(0);
|
||||
bb.setShort(21, bb.writerIndex() - 23);
|
||||
} else {
|
||||
if (pluginMessageId <= 0) {
|
||||
pluginMessageId = MCPackets.S2C_PLUGIN_MESSAGE.getId((((EaglercraftHandler) ctx.pipeline().get("eaglercraft-handler")).version).getVersion());
|
||||
}
|
||||
PacketTypes.writeVarInt(bb, pluginMessageId);
|
||||
PacketTypes.writeString(bb, "EAG|Voice-1.8");
|
||||
bb.writeBytes(data);
|
||||
}
|
||||
ctx.writeAndFlush(new BinaryWebSocketFrame(bb));
|
||||
}
|
||||
|
||||
private final byte[] iceServersPacket;
|
||||
|
||||
private final Map<UUID, ChannelHandlerContext> voicePlayers = new HashMap<>();
|
||||
private final Map<UUID, ExpiringSet<UUID>> voiceRequests = new HashMap<>();
|
||||
private final Set<VoicePair> voicePairs = new HashSet<>();
|
||||
|
||||
private static class VoicePair {
|
||||
|
||||
private final UUID uuid1;
|
||||
private final UUID uuid2;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return uuid1.hashCode() ^ uuid2.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
VoicePair other = (VoicePair) obj;
|
||||
return (uuid1.equals(other.uuid1) && uuid2.equals(other.uuid2))
|
||||
|| (uuid1.equals(other.uuid2) && uuid2.equals(other.uuid1));
|
||||
}
|
||||
|
||||
private VoicePair(UUID uuid1, UUID uuid2) {
|
||||
this.uuid1 = uuid1;
|
||||
this.uuid2 = uuid2;
|
||||
}
|
||||
|
||||
private boolean anyEquals(UUID uuid) {
|
||||
return uuid1.equals(uuid) || uuid2.equals(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
VoiceServerImpl() {
|
||||
if (FunnyConfig.eaglerVoice) {
|
||||
Set<String> list = new HashSet<>();
|
||||
list.add("stun:stun.l.google.com:19302");
|
||||
list.add("stun:stun1.l.google.com:19302");
|
||||
list.add("stun:stun2.l.google.com:19302");
|
||||
list.add("stun:stun3.l.google.com:19302");
|
||||
list.add("stun:stun4.l.google.com:19302");
|
||||
list.add("turn:relay1.expressturn.com:3478;ef2KWF55ZPQWCLBMIG;MGn8T66L0GhgDodf");
|
||||
this.iceServersPacket = VoiceSignalPackets.makeVoiceSignalPacketAllowed(true, list.toArray(new String[0]));
|
||||
} else {
|
||||
this.iceServersPacket = VoiceSignalPackets.makeVoiceSignalPacketAllowed(false, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void handlePlayerLoggedIn(ChannelHandlerContext player) {
|
||||
EaglerVoiceHandler evh = (EaglerVoiceHandler) player.pipeline().get("ayun-eag-voice");
|
||||
uuidToUsernameMap.put(evh.uuid, evh.user);
|
||||
sendData(player, iceServersPacket);
|
||||
}
|
||||
|
||||
public void handlePlayerLoggedOut(UUID playerUUID) {
|
||||
removeUser(playerUUID);
|
||||
uuidToUsernameMap.remove(playerUUID);
|
||||
}
|
||||
|
||||
void handleVoiceSignalPacketTypeRequest(UUID player, ChannelHandlerContext sender) {
|
||||
UUID senderUUID = ((EaglerVoiceHandler) sender.pipeline().get("ayun-eag-voice")).uuid;
|
||||
synchronized (voicePlayers) {
|
||||
if (senderUUID.equals(player))
|
||||
return; // prevent duplicates
|
||||
if (!voicePlayers.containsKey(senderUUID))
|
||||
return;
|
||||
ChannelHandlerContext targetPlayerCon = voicePlayers.get(player);
|
||||
if (targetPlayerCon == null)
|
||||
return;
|
||||
VoicePair newPair = new VoicePair(player, senderUUID);
|
||||
if (voicePairs.contains(newPair))
|
||||
return; // already paired
|
||||
ExpiringSet<UUID> senderRequestSet = voiceRequests.get(senderUUID);
|
||||
if (senderRequestSet == null) {
|
||||
voiceRequests.put(senderUUID, senderRequestSet = new ExpiringSet<>(2000));
|
||||
}
|
||||
if (!senderRequestSet.add(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if other has requested earlier
|
||||
ExpiringSet<UUID> theSet;
|
||||
if ((theSet = voiceRequests.get(player)) != null && theSet.contains(senderUUID)) {
|
||||
theSet.remove(senderUUID);
|
||||
if (theSet.isEmpty())
|
||||
voiceRequests.remove(player);
|
||||
senderRequestSet.remove(player);
|
||||
if (senderRequestSet.isEmpty())
|
||||
voiceRequests.remove(senderUUID);
|
||||
// send each other add data
|
||||
voicePairs.add(newPair);
|
||||
sendData(targetPlayerCon,
|
||||
VoiceSignalPackets.makeVoiceSignalPacketConnect(senderUUID, false));
|
||||
sendData(sender, VoiceSignalPackets.makeVoiceSignalPacketConnect(player, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleVoiceSignalPacketTypeConnect(ChannelHandlerContext sender) {
|
||||
UUID senderUUID = ((EaglerVoiceHandler) sender.pipeline().get("ayun-eag-voice")).uuid;
|
||||
synchronized (voicePlayers) {
|
||||
if (voicePlayers.containsKey(senderUUID)) {
|
||||
return;
|
||||
}
|
||||
boolean hasNoOtherPlayers = voicePlayers.isEmpty();
|
||||
voicePlayers.put(senderUUID, sender);
|
||||
if (hasNoOtherPlayers) {
|
||||
return;
|
||||
}
|
||||
byte[] packetToBroadcast = VoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values());
|
||||
for (ChannelHandlerContext userCon : voicePlayers.values()) {
|
||||
sendData(userCon, packetToBroadcast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleVoiceSignalPacketTypeICE(UUID player, String str, ChannelHandlerContext sender) {
|
||||
UUID senderUUID = ((EaglerVoiceHandler) sender.pipeline().get("ayun-eag-voice")).uuid;
|
||||
ChannelHandlerContext pass;
|
||||
VoicePair pair = new VoicePair(player, senderUUID);
|
||||
synchronized (voicePlayers) {
|
||||
pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null;
|
||||
}
|
||||
if (pass != null) {
|
||||
sendData(pass, VoiceSignalPackets.makeVoiceSignalPacketICE(senderUUID, str));
|
||||
}
|
||||
}
|
||||
|
||||
void handleVoiceSignalPacketTypeDesc(UUID player, String str, ChannelHandlerContext sender) {
|
||||
UUID senderUUID = ((EaglerVoiceHandler) sender.pipeline().get("ayun-eag-voice")).uuid;
|
||||
ChannelHandlerContext pass;
|
||||
VoicePair pair = new VoicePair(player, senderUUID);
|
||||
synchronized (voicePlayers) {
|
||||
pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null;
|
||||
}
|
||||
if (pass != null) {
|
||||
sendData(pass,
|
||||
VoiceSignalPackets.makeVoiceSignalPacketDesc(senderUUID, str));
|
||||
}
|
||||
}
|
||||
|
||||
void handleVoiceSignalPacketTypeDisconnect(UUID player, ChannelHandlerContext sender) {
|
||||
UUID senderUUID = ((EaglerVoiceHandler) sender.pipeline().get("ayun-eag-voice")).uuid;
|
||||
if (player != null) {
|
||||
synchronized (voicePlayers) {
|
||||
if (!voicePlayers.containsKey(player)) {
|
||||
return;
|
||||
}
|
||||
byte[] userDisconnectPacket = null;
|
||||
Iterator<VoicePair> pairsItr = voicePairs.iterator();
|
||||
while (pairsItr.hasNext()) {
|
||||
VoicePair voicePair = pairsItr.next();
|
||||
UUID target = null;
|
||||
if (voicePair.uuid1.equals(player)) {
|
||||
target = voicePair.uuid2;
|
||||
} else if (voicePair.uuid2.equals(player)) {
|
||||
target = voicePair.uuid1;
|
||||
}
|
||||
if (target != null) {
|
||||
pairsItr.remove();
|
||||
ChannelHandlerContext conn = voicePlayers.get(target);
|
||||
if (conn != null) {
|
||||
if (userDisconnectPacket == null) {
|
||||
userDisconnectPacket = VoiceSignalPackets.makeVoiceSignalPacketDisconnect(player);
|
||||
}
|
||||
sendData(conn, userDisconnectPacket);
|
||||
}
|
||||
sendData(sender,
|
||||
VoiceSignalPackets.makeVoiceSignalPacketDisconnect(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removeUser(senderUUID);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeUser(UUID user) {
|
||||
synchronized (voicePlayers) {
|
||||
if (voicePlayers.remove(user) == null) {
|
||||
return;
|
||||
}
|
||||
voiceRequests.remove(user);
|
||||
if (voicePlayers.size() > 0) {
|
||||
byte[] voicePlayersPkt = VoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values());
|
||||
for (Map.Entry<UUID, ChannelHandlerContext> userCon : voicePlayers.entrySet()) {
|
||||
if (!user.equals(userCon.getKey())) {
|
||||
sendData(userCon.getValue(), voicePlayersPkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] userDisconnectPacket = null;
|
||||
Iterator<VoicePair> pairsItr = voicePairs.iterator();
|
||||
while (pairsItr.hasNext()) {
|
||||
VoicePair voicePair = pairsItr.next();
|
||||
UUID target = null;
|
||||
if (voicePair.uuid1.equals(user)) {
|
||||
target = voicePair.uuid2;
|
||||
} else if (voicePair.uuid2.equals(user)) {
|
||||
target = voicePair.uuid1;
|
||||
}
|
||||
if (target != null) {
|
||||
pairsItr.remove();
|
||||
if (voicePlayers.size() > 0) {
|
||||
ChannelHandlerContext conn = voicePlayers.get(target);
|
||||
if (conn != null) {
|
||||
if (userDisconnectPacket == null) {
|
||||
userDisconnectPacket = VoiceSignalPackets.makeVoiceSignalPacketDisconnect(user);
|
||||
}
|
||||
sendData(conn, userDisconnectPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
package me.ayunami2000.ayunViaProxyEagUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import net.raphimc.netminecraft.packet.PacketTypes;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class VoiceSignalPackets {
|
||||
|
||||
static final int VOICE_SIGNAL_ALLOWED = 0;
|
||||
static final int VOICE_SIGNAL_REQUEST = 0;
|
||||
static final int VOICE_SIGNAL_CONNECT = 1;
|
||||
static final int VOICE_SIGNAL_DISCONNECT = 2;
|
||||
static final int VOICE_SIGNAL_ICE = 3;
|
||||
static final int VOICE_SIGNAL_DESC = 4;
|
||||
static final int VOICE_SIGNAL_GLOBAL = 5;
|
||||
|
||||
public static void processPacket(byte[] data, ChannelHandlerContext sender) throws IOException {
|
||||
int packetId = -1;
|
||||
if(data.length == 0) {
|
||||
throw new IOException("Zero-length packet recieved");
|
||||
}
|
||||
try {
|
||||
ByteBuf buffer = Unpooled.wrappedBuffer(data).writerIndex(data.length);
|
||||
packetId = buffer.readUnsignedByte();
|
||||
switch(packetId) {
|
||||
case VOICE_SIGNAL_REQUEST: {
|
||||
EaglerVoiceHandler.voiceService.handleVoiceSignalPacketTypeRequest(PacketTypes.readUuid(buffer), sender);
|
||||
break;
|
||||
}
|
||||
case VOICE_SIGNAL_CONNECT: {
|
||||
EaglerVoiceHandler.voiceService.handleVoiceSignalPacketTypeConnect(sender);
|
||||
break;
|
||||
}
|
||||
case VOICE_SIGNAL_ICE: {
|
||||
EaglerVoiceHandler.voiceService.handleVoiceSignalPacketTypeICE(PacketTypes.readUuid(buffer), PacketTypes.readString(buffer, 32767), sender);
|
||||
break;
|
||||
}
|
||||
case VOICE_SIGNAL_DESC: {
|
||||
EaglerVoiceHandler.voiceService.handleVoiceSignalPacketTypeDesc(PacketTypes.readUuid(buffer), PacketTypes.readString(buffer, 32767), sender);
|
||||
break;
|
||||
}
|
||||
case VOICE_SIGNAL_DISCONNECT: {
|
||||
EaglerVoiceHandler.voiceService.handleVoiceSignalPacketTypeDisconnect(buffer.readableBytes() > 0 ? PacketTypes.readUuid(buffer) : null, sender);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IOException("Unknown packet type " + packetId);
|
||||
}
|
||||
}
|
||||
if(buffer.readableBytes() > 0) {
|
||||
throw new IOException("Voice packet is too long!");
|
||||
}
|
||||
}catch(IOException ex) {
|
||||
throw ex;
|
||||
}catch(Throwable t) {
|
||||
throw new IOException("Unhandled exception handling voice packet type " + packetId, t);
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] makeVoiceSignalPacketAllowed(boolean allowed, String[] iceServers) {
|
||||
if (iceServers == null) {
|
||||
byte[] ret = new byte[2];
|
||||
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0);
|
||||
wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED);
|
||||
wrappedBuffer.writeBoolean(allowed);
|
||||
return ret;
|
||||
}
|
||||
byte[][] iceServersBytes = new byte[iceServers.length][];
|
||||
int totalLen = 2 + getVarIntSize(iceServers.length);
|
||||
for(int i = 0; i < iceServers.length; ++i) {
|
||||
byte[] b = iceServersBytes[i] = iceServers[i].getBytes(StandardCharsets.UTF_8);
|
||||
totalLen += getVarIntSize(b.length) + b.length;
|
||||
}
|
||||
byte[] ret = new byte[totalLen];
|
||||
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0);
|
||||
wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED);
|
||||
wrappedBuffer.writeBoolean(allowed);
|
||||
PacketTypes.writeVarInt(wrappedBuffer, iceServersBytes.length);
|
||||
for(int i = 0; i < iceServersBytes.length; ++i) {
|
||||
byte[] b = iceServersBytes[i];
|
||||
PacketTypes.writeVarInt(wrappedBuffer, b.length);
|
||||
wrappedBuffer.writeBytes(b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static byte[] makeVoiceSignalPacketGlobal(Collection<ChannelHandlerContext> users) {
|
||||
int cnt = users.size();
|
||||
byte[][] displayNames = new byte[cnt][];
|
||||
int i = 0;
|
||||
for(ChannelHandlerContext user : users) {
|
||||
String name = ((EaglerVoiceHandler) user.pipeline().get("ayun-eag-voice")).user;
|
||||
if(name.length() > 16) name = name.substring(0, 16);
|
||||
displayNames[i++] = name.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
int totalLength = 1 + getVarIntSize(cnt) + (cnt << 4);
|
||||
for(i = 0; i < cnt; ++i) {
|
||||
totalLength += getVarIntSize(displayNames[i].length) + displayNames[i].length;
|
||||
}
|
||||
byte[] ret = new byte[totalLength];
|
||||
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0);
|
||||
wrappedBuffer.writeByte(VOICE_SIGNAL_GLOBAL);
|
||||
PacketTypes.writeVarInt(wrappedBuffer, cnt);
|
||||
for(ChannelHandlerContext user : users) {
|
||||
PacketTypes.writeUuid(wrappedBuffer, ((EaglerVoiceHandler) user.pipeline().get("ayun-eag-voice")).uuid);
|
||||
}
|
||||
for(i = 0; i < cnt; ++i) {
|
||||
PacketTypes.writeVarInt(wrappedBuffer, displayNames[i].length);
|
||||
wrappedBuffer.writeBytes(displayNames[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static byte[] makeVoiceSignalPacketConnect(UUID player, boolean offer) {
|
||||
byte[] ret = new byte[18];
|
||||
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0);
|
||||
wrappedBuffer.writeByte(VOICE_SIGNAL_CONNECT);
|
||||
PacketTypes.writeUuid(wrappedBuffer, player);
|
||||
wrappedBuffer.writeBoolean(offer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static byte[] makeVoiceSignalPacketDisconnect(UUID player) {
|
||||
if(player == null) {
|
||||
return new byte[] { (byte)VOICE_SIGNAL_DISCONNECT };
|
||||
}
|
||||
byte[] ret = new byte[17];
|
||||
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0);
|
||||
wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT);
|
||||
PacketTypes.writeUuid(wrappedBuffer, player);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static byte[] makeVoiceSignalPacketICE(UUID player, String str) {
|
||||
byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] ret = new byte[17 + getVarIntSize(strBytes.length) + strBytes.length];
|
||||
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0);
|
||||
wrappedBuffer.writeByte(VOICE_SIGNAL_ICE);
|
||||
PacketTypes.writeUuid(wrappedBuffer, player);
|
||||
PacketTypes.writeVarInt(wrappedBuffer, strBytes.length);
|
||||
wrappedBuffer.writeBytes(strBytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static byte[] makeVoiceSignalPacketDesc(UUID player, String str) {
|
||||
byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] ret = new byte[17 + getVarIntSize(strBytes.length) + strBytes.length];
|
||||
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0);
|
||||
wrappedBuffer.writeByte(VOICE_SIGNAL_DESC);
|
||||
PacketTypes.writeUuid(wrappedBuffer, player);
|
||||
PacketTypes.writeVarInt(wrappedBuffer, strBytes.length);
|
||||
wrappedBuffer.writeBytes(strBytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int getVarIntSize(int input) {
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
if ((input & -1 << i * 7) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user