ADD FULL SKIN PASSTHROUGH

This commit is contained in:
ayunami2000 2023-10-06 17:44:04 -04:00
parent 1dc04f3927
commit f2a6185e2b
3 changed files with 144 additions and 75 deletions

View File

@ -1,4 +1,4 @@
# 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)
note: skin files from 1.5.2 are excluded
note: skin files are excluded

View File

@ -9,6 +9,7 @@ import com.viaversion.viaversion.util.ChatColorUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
@ -35,6 +36,7 @@ import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*;
@ -153,10 +155,38 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
}
if (in.readableBytes() >= 2 && in.getUnsignedByte(0) == 2) {
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) {
return;
}
if (proxyConnection instanceof ProxyConnection) {
if (in.readableBytes() >= 3 && in.getUnsignedByte(0) == 250) {
in.skipBytes(1);
String tag;
@ -207,6 +237,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
}
in.resetReaderIndex();
}
}
out.add(new BinaryWebSocketFrame(in.retain()));
}
@ -438,6 +469,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
}
}
public void decodeOld(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
if (proxyConnection instanceof ProxyConnection) {
if (in.getUnsignedByte(0) == 0x14) {
try {
in.skipBytes(1);
@ -468,6 +500,7 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
eidUuidMap.clear();
uuidStringMap.clear();
}
}
if (in.getUnsignedByte(0) == 0xFD) {
in.writerIndex(0);
in.writeByte((byte) 0xCD);
@ -481,16 +514,32 @@ public class EaglerServerHandler extends MessageToMessageCodec<WebSocketFrame, B
byte[] msg;
try {
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()];
in.readBytes(msg);
short id = (short) ((msg[0] << 8) + msg[1]);
if (!skinsBeingFetched.containsKey(id)) {
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);
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[] tmp2 = new int[4096];
for (int i = 0; i < tmp1.length; ++i) {

View File

@ -39,6 +39,22 @@ public class SkinService {
final byte[] src = EaglerSkinHandler.skinCollection.get(searchUUID);
byte[] res = new byte[src.length - 1];
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) {
final int[] tmp1 = new int[2048];
final int[] tmp2 = new int[4096];
@ -122,10 +138,12 @@ public class SkinService {
final byte type = packet[0];
byte[] res;
switch (type) {
case 1:
case 4: {
res = new byte[16385];
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");
if (stream == null) {
throw new IOException("Invalid skin preset: " + presetId);
@ -140,10 +158,12 @@ public class SkinService {
}
break;
}
case 2:
case 5: {
res = new byte[16385];
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) {
final byte tmp = res[i];
res[i] = res[i + 1];