Skip to content
Open
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,6 @@ gradle-app.setting
# JDT-specific (Eclipse Java Development Tools)
.classpath
.gitsync.json

# NixOS flake.nix
flake.*
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,22 @@ private static void processServerData(ByteBuffer data) {
}

private static void handlePacket01(byte[] decryptedBuffer) throws Exception {
// Plaintext shape (server nativeSyncModels + encrypt appendNextKey):
// [garbageLen|0x80] [0x00] [garbage] [0x01] [56-byte nextKey]
// garbageLen fits in 7 bits, so total = 2 + garbageLen + 1 + 56 ∈ [59, 186].
// A late packet 05 chunk decrypted with the wrong key shows up here as
// kilobytes of structurally-invalid bytes — drop it instead of accepting
// it as a key exchange, which would corrupt lastKey and cascade into a
// handlePacket03 crash on the next inbound chunk.
if (decryptedBuffer == null || decryptedBuffer.length < 59 || decryptedBuffer.length > 186) {
return;
}
int rxGarbageLen = decryptedBuffer[0] & 0x7F;
if (decryptedBuffer.length != 2 + rxGarbageLen + 1 + 56
|| decryptedBuffer[2 + rxGarbageLen] != 0x01) {
return;
}

key1 = new byte[56];
System.arraycopy(decryptedBuffer, decryptedBuffer.length - 56, key1, 0, 56);
syncStep = 2;
Expand Down Expand Up @@ -223,7 +239,11 @@ private record ModelHash(long hash1, long hash2) {

private static void handlePacket03(YSMByteBuf buf) throws Exception {
buf.skipGarbageHeader();
int type = buf.readVarInt(); // expect 3
int type = buf.readVarInt();
// Defense in depth: a wrong-key decryption here would have lastKey pointing
// at junk and `type` reading as anything. handlePacket05 already does the
// same guard with `if (type != 5) return`.
if (type != 3) return;
long folderHash = buf.readVarLong();
currentCacheFolderName = Long.toHexString(folderHash);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@

public class OuterFileTexture extends AbstractTexture implements ITextureMap {
private final byte[] data;
private final int rawRgbaWidth;
private final int rawRgbaHeight;

private Map<ShadersTextureType, OuterFileTexture> suffixTextures = Reference2ReferenceMaps.emptyMap();

public OuterFileTexture(byte[] data) {
this.data = data;
this.rawRgbaWidth = 0;
this.rawRgbaHeight = 0;
}

public OuterFileTexture(byte[] rawRgbaData, int width, int height) {
this.data = rawRgbaData;
this.rawRgbaWidth = width;
this.rawRgbaHeight = height;
}

@Override
Expand All @@ -34,7 +44,7 @@ public void load(@NotNull ResourceManager resourceManager) {

public void doLoad() {
try {
NativeImage imageIn = NativeImage.read(new ByteArrayInputStream(data));
NativeImage imageIn = isRawRgba() ? readRawRgba() : NativeImage.read(new ByteArrayInputStream(data));
int width = imageIn.getWidth();
int height = imageIn.getHeight();
TextureUtil.prepareImage(this.getId(), 0, width, height);
Expand All @@ -44,11 +54,36 @@ public void doLoad() {
}
}

private boolean isRawRgba() {
return rawRgbaWidth > 0 && rawRgbaHeight > 0;
}

private NativeImage readRawRgba() throws IOException {
long expectedLength = (long) rawRgbaWidth * (long) rawRgbaHeight * 4L;
if (data == null || data.length < expectedLength) {
throw new IOException("Invalid raw RGBA texture data");
}

NativeImage image = new NativeImage(rawRgbaWidth, rawRgbaHeight, false);
for (int y = 0; y < rawRgbaHeight; y++) {
int row = y * rawRgbaWidth * 4;
for (int x = 0; x < rawRgbaWidth; x++) {
int offset = row + x * 4;
int r = data[offset] & 0xFF;
int g = data[offset + 1] & 0xFF;
int b = data[offset + 2] & 0xFF;
int a = data[offset + 3] & 0xFF;
image.setPixelRGBA(x, y, (a << 24) | (b << 16) | (g << 8) | r);
}
}
return image;
}

public void setSuffixTextures(Map<ShadersTextureType, OuterFileTexture> map) {
this.suffixTextures = Reference2ReferenceMaps.unmodifiable(new Reference2ReferenceOpenHashMap<>(map));
}

public Map<ShadersTextureType, ? extends AbstractTexture> getSuffixTextures() {
return this.suffixTextures;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.elfmcys.yesstevemodel.resource;

import com.elfmcys.yesstevemodel.YesSteveModel;
import com.elfmcys.yesstevemodel.resource.pojo.RawYsmModel;
import io.netty.buffer.Unpooled;
import rip.ysm.security.YSMByteBuf;
Expand Down Expand Up @@ -28,7 +29,7 @@ public YSMBinaryDeserializer(byte[] decompressedData, int format) {


private RawYsmModel deserializeInternal(boolean closeOnExit) {
System.out.println("deserializing format " + format + " file...");
YesSteveModel.LOGGER.debug("deserializing format {} file...", format);
if (format < 4) {
deserializeLegacyV1();
} else if (format <= 15) {
Expand All @@ -46,7 +47,7 @@ private RawYsmModel deserializeInternal(boolean closeOnExit) {
if (closeOnExit) {
this.reader.close();
}
System.out.println("end offset: 0x" + Integer.toHexString(offset));
YesSteveModel.LOGGER.debug("end offset: 0x{}", Integer.toHexString(offset));
return model;
}

Expand Down Expand Up @@ -82,8 +83,8 @@ public void parseYSMFooter(RawYsmModel footer) {
}

} catch (Throwable t) {
System.out.println("ERROR");
t.printStackTrace(System.out);
YesSteveModel.LOGGER.debug("Failed to parse YSM footer (format={}, offset=0x{})",
format, Integer.toHexString(reader.getOffset()), t);
}
}

Expand Down Expand Up @@ -400,7 +401,7 @@ private void deserializeModern() {
geoRef.sha256 = hash;
geoRef.modelType = modelType;
tempMainModels.add(geoRef);
System.out.println("Model Table Entry: ID=" + modelType + ", Hash=" + hash);
YesSteveModel.LOGGER.debug("Model Table Entry: ID={}, Hash={}", modelType, hash);
}
assignMainModels(tempMainModels);

Expand Down
Loading