mirror of
https://github.com/ayunami2000/ayunViaProxyEagUtils.git
synced 2024-12-21 14:24:10 -08:00
ADD FULL SKIN PASSTHROUGH
This commit is contained in:
parent
1dc04f3927
commit
f2a6185e2b
|
@ -1,4 +1,4 @@
|
||||||
# ayunViaProxyEagUtils
|
# ayunViaProxyEagUtils
|
||||||
eaglercraft support for viaproxy. ws:// on same port as java. supports both 1.5.2 and 1.8.8 eaglercraft depending on the configuration (e.g. use legacy passthrough & protocolsupport if the backend server doesn't support 1.5.2)
|
eaglercraft support for viaproxy. ws:// on same port as java. supports both 1.5.2 and 1.8.8 eaglercraft depending on the configuration (e.g. use legacy passthrough & protocolsupport if the backend server doesn't support 1.5.2)
|
||||||
|
|
||||||
note: skin files from 1.5.2 are excluded
|
note: skin files are excluded
|
|
@ -9,6 +9,7 @@ import com.viaversion.viaversion.util.ChatColorUtil;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.MessageToMessageCodec;
|
import io.netty.handler.codec.MessageToMessageCodec;
|
||||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||||
|
@ -35,6 +36,7 @@ import java.awt.image.DataBufferByte;
|
||||||
import java.awt.image.Raster;
|
import java.awt.image.Raster;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -153,59 +155,88 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
||||||
}
|
}
|
||||||
if (in.readableBytes() >= 2 && in.getUnsignedByte(0) == 2) {
|
if (in.readableBytes() >= 2 && in.getUnsignedByte(0) == 2) {
|
||||||
in.setByte(1, in.getUnsignedByte(1) + 8);
|
in.setByte(1, in.getUnsignedByte(1) + 8);
|
||||||
|
out.add(new BinaryWebSocketFrame(in.retain()));
|
||||||
|
|
||||||
|
Channel c2p;
|
||||||
|
if (proxyConnection instanceof ProxyConnection) {
|
||||||
|
c2p = ((ProxyConnection) proxyConnection).getC2P();
|
||||||
|
} else {
|
||||||
|
c2p = ((LegacyProxyConnection) proxyConnection).getC2P();
|
||||||
|
}
|
||||||
|
if (c2p.hasAttr(EaglercraftHandler.profileDataKey)) {
|
||||||
|
EaglercraftHandler.ProfileData profileData = c2p.attr(EaglercraftHandler.profileDataKey).get();
|
||||||
|
if (profileData.type.equals("skin_v1")) {
|
||||||
|
int packetType = profileData.data[0] & 0xFF;
|
||||||
|
if (packetType == 1 || packetType == 2) {
|
||||||
|
try {
|
||||||
|
byte[] res = SkinService.newToOldSkin(profileData.data);
|
||||||
|
ByteBuf bb = ctx.alloc().buffer();
|
||||||
|
bb.writeByte((byte) 250);
|
||||||
|
Types1_6_4.STRING.write(bb, "EAG|MySkin");
|
||||||
|
bb.writeShort(res.length);
|
||||||
|
bb.writeBytes(res);
|
||||||
|
out.add(new BinaryWebSocketFrame(bb));
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (in.getUnsignedByte(0) == 0xFD) {
|
if (in.getUnsignedByte(0) == 0xFD) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (in.readableBytes() >= 3 && in.getUnsignedByte(0) == 250) {
|
if (proxyConnection instanceof ProxyConnection) {
|
||||||
in.skipBytes(1);
|
if (in.readableBytes() >= 3 && in.getUnsignedByte(0) == 250) {
|
||||||
String tag;
|
in.skipBytes(1);
|
||||||
byte[] msg;
|
String tag;
|
||||||
try {
|
byte[] msg;
|
||||||
tag = Types1_6_4.STRING.read(in);
|
try {
|
||||||
if (tag.equals("EAG|Skins-1.8")) {
|
tag = Types1_6_4.STRING.read(in);
|
||||||
msg = new byte[in.readShort()];
|
if (tag.equals("EAG|Skins-1.8")) {
|
||||||
in.readBytes(msg);
|
msg = new byte[in.readShort()];
|
||||||
if (msg.length == 0) {
|
in.readBytes(msg);
|
||||||
throw new IOException("Zero-length packet recieved");
|
if (msg.length == 0) {
|
||||||
}
|
throw new IOException("Zero-length packet recieved");
|
||||||
final int packetId = msg[0] & 0xFF;
|
}
|
||||||
switch (packetId) {
|
final int packetId = msg[0] & 0xFF;
|
||||||
case 3: {
|
switch (packetId) {
|
||||||
if (msg.length != 17) {
|
case 3: {
|
||||||
throw new IOException("Invalid length " + msg.length + " for skin request packet");
|
if (msg.length != 17) {
|
||||||
|
throw new IOException("Invalid length " + msg.length + " for skin request packet");
|
||||||
|
}
|
||||||
|
final UUID searchUUID = SkinPackets.bytesToUUID(msg, 1);
|
||||||
|
if (uuidStringMap.containsKey(searchUUID)) {
|
||||||
|
short id = skinFetchCounter++;
|
||||||
|
skinsBeingFetched.put(id, searchUUID);
|
||||||
|
String name = uuidStringMap.get(searchUUID);
|
||||||
|
ByteBuf bb = ctx.alloc().buffer();
|
||||||
|
bb.writeByte((byte) 250);
|
||||||
|
Types1_6_4.STRING.write(bb, "EAG|FetchSkin");
|
||||||
|
ByteBuf bbb = ctx.alloc().buffer();
|
||||||
|
bbb.writeByte((byte) ((id >> 8) & 0xFF));
|
||||||
|
bbb.writeByte((byte) (id & 0xFF));
|
||||||
|
bbb.writeBytes(name.getBytes(StandardCharsets.UTF_8));
|
||||||
|
bb.writeShort(bbb.readableBytes());
|
||||||
|
bb.writeBytes(bbb);
|
||||||
|
bbb.release();
|
||||||
|
out.add(new BinaryWebSocketFrame(bb));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
final UUID searchUUID = SkinPackets.bytesToUUID(msg, 1);
|
case 6: {
|
||||||
if (uuidStringMap.containsKey(searchUUID)) {
|
break;
|
||||||
short id = skinFetchCounter++;
|
}
|
||||||
skinsBeingFetched.put(id, searchUUID);
|
default: {
|
||||||
String name = uuidStringMap.get(searchUUID);
|
throw new IOException("Unknown packet type " + packetId);
|
||||||
ByteBuf bb = ctx.alloc().buffer();
|
|
||||||
bb.writeByte((byte) 250);
|
|
||||||
Types1_6_4.STRING.write(bb, "EAG|FetchSkin");
|
|
||||||
ByteBuf bbb = ctx.alloc().buffer();
|
|
||||||
bbb.writeByte((byte) ((id >> 8) & 0xFF));
|
|
||||||
bbb.writeByte((byte) (id & 0xFF));
|
|
||||||
bbb.writeBytes(name.getBytes(StandardCharsets.UTF_8));
|
|
||||||
bb.writeShort(bbb.readableBytes());
|
|
||||||
bb.writeBytes(bbb);
|
|
||||||
bbb.release();
|
|
||||||
out.add(new BinaryWebSocketFrame(bb));
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 6: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
throw new IOException("Unknown packet type " + packetId);
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
in.resetReaderIndex();
|
||||||
}
|
}
|
||||||
in.resetReaderIndex();
|
|
||||||
}
|
}
|
||||||
out.add(new BinaryWebSocketFrame(in.retain()));
|
out.add(new BinaryWebSocketFrame(in.retain()));
|
||||||
}
|
}
|
||||||
|
@ -438,35 +469,37 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void decodeOld(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
public void decodeOld(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||||
if (in.getUnsignedByte(0) == 0x14) {
|
if (proxyConnection instanceof ProxyConnection) {
|
||||||
try {
|
if (in.getUnsignedByte(0) == 0x14) {
|
||||||
in.skipBytes(1);
|
try {
|
||||||
int eid = in.readInt();
|
in.skipBytes(1);
|
||||||
String name = Types1_6_4.STRING.read(in);
|
|
||||||
UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
|
|
||||||
eidUuidMap.put(eid, uuid);
|
|
||||||
uuidStringMap.put(uuid, name);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
in.resetReaderIndex();
|
|
||||||
}
|
|
||||||
if (in.getUnsignedByte(0) == 0x1D) {
|
|
||||||
try {
|
|
||||||
in.skipBytes(1);
|
|
||||||
short count = in.readUnsignedByte();
|
|
||||||
for (short i = 0; i < count; i++) {
|
|
||||||
int eid = in.readInt();
|
int eid = in.readInt();
|
||||||
if (eidUuidMap.containsKey(eid)) {
|
String name = Types1_6_4.STRING.read(in);
|
||||||
uuidStringMap.remove(eidUuidMap.remove(eid));
|
UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
eidUuidMap.put(eid, uuid);
|
||||||
|
uuidStringMap.put(uuid, name);
|
||||||
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
in.resetReaderIndex();
|
||||||
|
}
|
||||||
|
if (in.getUnsignedByte(0) == 0x1D) {
|
||||||
|
try {
|
||||||
|
in.skipBytes(1);
|
||||||
|
short count = in.readUnsignedByte();
|
||||||
|
for (short i = 0; i < count; i++) {
|
||||||
|
int eid = in.readInt();
|
||||||
|
if (eidUuidMap.containsKey(eid)) {
|
||||||
|
uuidStringMap.remove(eidUuidMap.remove(eid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
in.resetReaderIndex();
|
||||||
|
}
|
||||||
|
if (in.getUnsignedByte(0) == 0x09) {
|
||||||
|
eidUuidMap.clear();
|
||||||
|
uuidStringMap.clear();
|
||||||
}
|
}
|
||||||
in.resetReaderIndex();
|
|
||||||
}
|
|
||||||
if (in.getUnsignedByte(0) == 0x09) {
|
|
||||||
eidUuidMap.clear();
|
|
||||||
uuidStringMap.clear();
|
|
||||||
}
|
}
|
||||||
if (in.getUnsignedByte(0) == 0xFD) {
|
if (in.getUnsignedByte(0) == 0xFD) {
|
||||||
in.writerIndex(0);
|
in.writerIndex(0);
|
||||||
|
@ -481,16 +514,32 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
|
||||||
byte[] msg;
|
byte[] msg;
|
||||||
try {
|
try {
|
||||||
tag = Types1_6_4.STRING.read(in);
|
tag = Types1_6_4.STRING.read(in);
|
||||||
if (tag.equals("EAG|UserSkin")) {
|
if (proxyConnection instanceof ProxyConnection && tag.equals("EAG|UserSkin")) {
|
||||||
msg = new byte[in.readShort()];
|
msg = new byte[in.readShort()];
|
||||||
in.readBytes(msg);
|
in.readBytes(msg);
|
||||||
short id = (short) ((msg[0] << 8) + msg[1]);
|
short id = (short) ((msg[0] << 8) + msg[1]);
|
||||||
if (!skinsBeingFetched.containsKey(id)) {
|
if (!skinsBeingFetched.containsKey(id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
byte[] res = new byte[msg.length - 3];
|
byte[] res = new byte[Math.min(16384, msg.length - 3)];
|
||||||
System.arraycopy(msg, 3, res, 0, res.length);
|
System.arraycopy(msg, 3, res, 0, res.length);
|
||||||
if (res.length == 8192) {
|
if (res.length <= 16) {
|
||||||
|
int presetId = res[0] & 0xFF;
|
||||||
|
InputStream stream = Main.class.getResourceAsStream("/n" + presetId + ".png");
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
res = ((DataBufferByte) ImageIO.read(stream).getRaster().getDataBuffer()).getData();
|
||||||
|
for (int i = 0; i < res.length; i += 4) {
|
||||||
|
final byte tmp = res[i];
|
||||||
|
res[i] = res[i + 1];
|
||||||
|
res[i + 1] = res[i + 2];
|
||||||
|
res[i + 2] = res[i + 3];
|
||||||
|
res[i + 3] = tmp;
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res.length >= 8192 && res.length < 16384) {
|
||||||
final int[] tmp1 = new int[2048];
|
final int[] tmp1 = new int[2048];
|
||||||
final int[] tmp2 = new int[4096];
|
final int[] tmp2 = new int[4096];
|
||||||
for (int i = 0; i < tmp1.length; ++i) {
|
for (int i = 0; i < tmp1.length; ++i) {
|
||||||
|
|
|
@ -39,6 +39,22 @@ public class SkinService {
|
||||||
final byte[] src = EaglerSkinHandler.skinCollection.get(searchUUID);
|
final byte[] src = EaglerSkinHandler.skinCollection.get(searchUUID);
|
||||||
byte[] res = new byte[src.length - 1];
|
byte[] res = new byte[src.length - 1];
|
||||||
System.arraycopy(src, 1, res, 0, res.length);
|
System.arraycopy(src, 1, res, 0, res.length);
|
||||||
|
if (res.length <= 16) {
|
||||||
|
int presetId = res[0] & 0xFF;
|
||||||
|
InputStream stream = Main.class.getResourceAsStream("/n" + presetId + ".png");
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
res = ((DataBufferByte) ImageIO.read(stream).getRaster().getDataBuffer()).getData();
|
||||||
|
for (int i = 0; i < res.length; i += 4) {
|
||||||
|
final byte tmp = res[i];
|
||||||
|
res[i] = res[i + 1];
|
||||||
|
res[i + 1] = res[i + 2];
|
||||||
|
res[i + 2] = res[i + 3];
|
||||||
|
res[i + 3] = tmp;
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (res.length == 8192) {
|
if (res.length == 8192) {
|
||||||
final int[] tmp1 = new int[2048];
|
final int[] tmp1 = new int[2048];
|
||||||
final int[] tmp2 = new int[4096];
|
final int[] tmp2 = new int[4096];
|
||||||
|
@ -122,10 +138,12 @@ public class SkinService {
|
||||||
final byte type = packet[0];
|
final byte type = packet[0];
|
||||||
byte[] res;
|
byte[] res;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case 1:
|
||||||
case 4: {
|
case 4: {
|
||||||
res = new byte[16385];
|
res = new byte[16385];
|
||||||
res[0] = 1;
|
res[0] = 1;
|
||||||
final int presetId = packet[17] << 24 | packet[18] << 16 | packet[19] << 8 | packet[20];
|
final int o = type == 1 ? 16 : 0;
|
||||||
|
final int presetId = packet[17 - o] << 24 | packet[18 - o] << 16 | packet[19 - o] << 8 | packet[20 - o];
|
||||||
final InputStream stream = Main.class.getResourceAsStream("/" + presetId + ".png");
|
final InputStream stream = Main.class.getResourceAsStream("/" + presetId + ".png");
|
||||||
if (stream == null) {
|
if (stream == null) {
|
||||||
throw new IOException("Invalid skin preset: " + presetId);
|
throw new IOException("Invalid skin preset: " + presetId);
|
||||||
|
@ -140,10 +158,12 @@ public class SkinService {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 2:
|
||||||
case 5: {
|
case 5: {
|
||||||
res = new byte[16385];
|
res = new byte[16385];
|
||||||
res[0] = 1;
|
res[0] = 1;
|
||||||
System.arraycopy(packet, 18, res, 1, 16384);
|
final int o = type == 2 ? 16 : 0;
|
||||||
|
System.arraycopy(packet, 18 - o, res, 1, 16384);
|
||||||
for (int i = 1; i < 16385; i += 4) {
|
for (int i = 1; i < 16385; i += 4) {
|
||||||
final byte tmp = res[i];
|
final byte tmp = res[i];
|
||||||
res[i] = res[i + 1];
|
res[i] = res[i + 1];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user