package NET.worlds.scape; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class TCompressor { private static final int CMAP_MAXPOSCOMP = 128; private static final int CMAP_DEFAULTAXIS = 0; private static final int CMAP_XUNITARY = 32; private static final int CMAP_YUNITARY = 64; private static final int CMAP_ZUNITARY = 96; private static final int CMAP_ROTATION = 16; private static final int CMAP_ROTSIGN1 = 8; private static final int CMAP_ROTSIGN2 = 4; private static final int CMAP_SCALE = 2; private static final int CMAP_UNIFORMSCALE = 1; private static final int MODE_SENDCMAP = 8388608; private static final int MODE_SENDZ = 4194304; private static final int MODE_MAXPOSCOMP = 128; private static final int MODE_SENDROTAXIS = 96; private static final int MODE_SENDROTATION = 16; private static final int MODE_SENDSCALE = 2; public static final int USER_SEND_POSITION = 32768; public static final int USER_SEND_ROTATION = 16384; public static final int USER_SEND_SCALE = 8192; public static final int USER_SEND_ALL = 57344; private static final int LOW21BITSMASK = 2097151; private static final int LOW18BITSMASK = 262143; private static final int LOW12BITSMASK = 4095; private static final int LOW10BITSMASK = 1023; private static final int LOW8BITSMASK = 255; private static final int BIT20 = 1048576; private static final double SCFACT = 16.0; private static final double SCOFFSET = 121.6; static int wroteBytes = 0; public static boolean dontSend = false; public static void compress(WObject w, Point3Temp defPos, Point3Temp defRAxis, float defRotation, Point3Temp defScale, int inputModes, DataOutputStream ds) throws IOException { Point3Temp pos = w.getPosition(); Point3Temp rAxis = Point3Temp.make(); float rotation = w.getSpin(rAxis); Point3Temp scale = w.getScale(); if (dontSend) { System.err.println("DONTSEND is TRUE on COMPRESS CALL"); } else { int mode = inputModes; if ((inputModes & 32768) != 0) { if (pos.x >= 0.0F && pos.x <= 4095.0 && pos.y >= 0.0F && pos.y <= 4095.0 && (pos.z >= 0.0F && pos.z <= 255.0 || pos.z == defPos.z)) { mode = inputModes | 128; } if (pos.z != defPos.z) { mode |= 4194304; } } int outaxis1 = 0; int outaxis2 = 0; if ((mode & 16384) != 0 && !rAxis.sameValue(defRAxis)) { int axisFlag = 0; float maxAxis = rAxis.x; int var24 = 32; if (Math.abs(rAxis.y) > Math.abs(maxAxis)) { maxAxis = rAxis.y; var24 = 64; } if (Math.abs(rAxis.z) > Math.abs(maxAxis)) { maxAxis = rAxis.z; var24 = 96; } rAxis.x /= maxAxis; rAxis.y /= maxAxis; rAxis.z /= maxAxis; mode |= var24; if (maxAxis < 0.0F) { rotation *= -1.0F; } switch (var24) { case 32: if (rAxis.y < 0.0F) { mode |= 8; } if (rAxis.z < 0.0F) { mode |= 4; } outaxis1 = Math.round(Math.abs(255.0F * rAxis.y)); outaxis2 = Math.round(Math.abs(255.0F * rAxis.z)); break; case 64: if (rAxis.x < 0.0F) { mode |= 8; } if (rAxis.z < 0.0F) { mode |= 4; } outaxis1 = Math.round(Math.abs(255.0F * rAxis.x)); outaxis2 = Math.round(Math.abs(255.0F * rAxis.z)); break; case 96: if (rAxis.x < 0.0F) { mode |= 8; } if (rAxis.y < 0.0F) { mode |= 4; } outaxis1 = Math.round(Math.abs(255.0F * rAxis.x)); outaxis2 = Math.round(Math.abs(255.0F * rAxis.y)); } if (outaxis1 == 0 && outaxis2 == 0 && maxAxis < 0.0F) { mode |= 8; mode |= 4; } while (rotation >= 360.0F) { rotation -= 360.0F; } while (rotation < 0.0F) { rotation += 360.0F; } if (rotation != defRotation) { mode |= 8388608; mode |= 16; } } if ((mode & 8192) != 0 && !scale.sameValue(defScale)) { mode |= 8388608; mode |= 2; if (scale.x == scale.y && scale.x == scale.z) { mode |= 1; } } if ((mode & 8388608) != 0) { ds.writeByte(mode & 0xFF); wroteBytes++; } if ((mode & 32768) != 0) { if ((mode & 128) != 0) { maxCompressXY(pos.x, pos.y, ds); if ((mode & 4194304) != 0 || (mode & 8388608) != 0) { short iz = (short)Math.round(pos.z); int outbyte = iz & 255; ds.writeByte(outbyte); wroteBytes++; } } else { minCompressXYZ(pos.x, pos.y, pos.z, ds); } } if ((mode & 96) != 0) { ds.writeByte(outaxis1); ds.writeByte(outaxis2); wroteBytes += 2; } if ((mode & 16) != 0) { int outbyte = (int)Math.round(256.0 * (rotation / 360.0)); ds.writeByte(outbyte); wroteBytes++; } if ((mode & 2) != 0) { double y = 16.0 * Math.log(scale.x / defScale.x) + 121.6; if (y < 0.0) { y = 0.0; } if (y > 255.0) { y = 255.0; } int outbyte = (int)Math.round(y); ds.writeByte(outbyte); wroteBytes++; if ((mode & 1) == 0) { y = 16.0 * Math.log(scale.y / defScale.y) + 121.6; if (y < 0.0) { y = 0.0; } if (y > 255.0) { y = 255.0; } outbyte = (int)Math.round(y); ds.writeByte(outbyte); wroteBytes++; y = 16.0 * Math.log(scale.z / defScale.z) + 121.6; if (y < 0.0) { y = 0.0; } if (y > 255.0) { y = 255.0; } outbyte = (int)Math.round(y); ds.writeByte(outbyte); wroteBytes++; } } wroteBytes = 0; } } private static void maxCompressXY(float x, float y, DataOutputStream ds) throws IOException { short ix = (short)Math.round(x); short iy = (short)Math.round(y); ix = (short)(ix & 4095); iy = (short)(iy & 4095); int posbyte = ix >>> 4; ds.writeByte(posbyte); wroteBytes++; ix = (short)(ix << 4); ix = (short)(ix & 255); posbyte = ix | iy >>> 8; ds.writeByte(posbyte); wroteBytes++; posbyte = iy & 255; ds.writeByte(posbyte); wroteBytes++; } private static void minCompressXYZ(float x, float y, float z, DataOutputStream ds) throws IOException { int xval = floatTo21bits(x); int yval = floatTo21bits(y); int zval = floatTo21bits(z); int outbits = xval << 10 | yval >>> 11; ds.writeInt(outbits); wroteBytes += 4; outbits = yval << 21 | zval; ds.writeInt(outbits); wroteBytes += 4; } private static int floatTo21bits(float f) { for (int e = 0; e <= 3; e++) { double decimal = Math.pow(10.0, e - 2); float limit = (float)(262144.0 * decimal); float af = Math.abs(f); if (af < limit || e == 3) { int m = (int)Math.round(af / decimal); m &= 262143; m <<= 2; m |= e; if (f < 0.0F) { m |= 1048576; } return m; } } return 0; } public static void decompress( WObject w, Point3Temp defPos, Point3Temp defRAxis, float defRotation, Point3Temp defScale, int inputModes, int len, DataInputStream ds ) throws IOException { Point3Temp pos = w.getPosition(); Point3Temp rAxis = Point3Temp.make(); float rotation = w.getSpin(rAxis); Point3Temp scale = w.getScale(); dontSend = true; if (len == 0) { w.moveTo(defPos); scale.x = defScale.x / scale.x; scale.y = defScale.y / scale.y; scale.z = defScale.z / scale.z; w.scale(scale); dontSend = false; } else if (len == 24) { pos.x = ds.readFloat(); pos.y = ds.readFloat(); pos.z = ds.readFloat(); scale.x = ds.readFloat() / scale.x; scale.y = ds.readFloat() / scale.y; scale.z = ds.readFloat() / scale.z; w.moveTo(pos); w.scale(scale); dontSend = false; } else { int mode; if (len > 4) { mode = inputModes | 8388608; } else { mode = inputModes | 128; } if (len == 4) { mode |= 4194304; } if ((mode & 8388608) != 0) { int inbyte = ds.readUnsignedByte(); mode |= inbyte; mode |= 4194304; } if ((mode & 32768) != 0) { if ((mode & 128) != 0) { pos = maxDecompressXY(pos, ds); if ((mode & 4194304) != 0) { int iz = ds.readUnsignedByte(); pos.z = iz; } } else { pos = minDecompressXYZ(pos, ds); } w.moveTo(pos); } if ((mode & 8388608) == 0) { dontSend = false; } else { if ((mode & 16) != 0) { w.spin(rAxis.x, rAxis.y, rAxis.z, -rotation); } rAxis.x = defRAxis.x; rAxis.y = defRAxis.y; rAxis.z = defRAxis.z; if ((mode & 96) != 0) { int inaxis1 = ds.readUnsignedByte(); int inaxis2 = ds.readUnsignedByte(); switch (mode & 96) { case 0: default: break; case 32: rAxis.x = 1.0F; rAxis.y = (float)(inaxis1 / 255.0); rAxis.z = (float)(inaxis2 / 255.0); if ((mode & 8) != 0) { rAxis.y = (float)(rAxis.y * -1.0); } if ((mode & 4) != 0) { rAxis.z = (float)(rAxis.z * -1.0); } if (rAxis.y == 0.0F && rAxis.z == 0.0F && (mode & 8) != 0 && (mode & 4) != 0) { rAxis.x = -1.0F; } break; case 64: rAxis.y = 1.0F; rAxis.x = (float)(inaxis1 / 255.0); rAxis.z = (float)(inaxis2 / 255.0); if ((mode & 8) != 0) { rAxis.x = (float)(rAxis.x * -1.0); } if ((mode & 4) != 0) { rAxis.z = (float)(rAxis.z * -1.0); } if (rAxis.x == 0.0F && rAxis.z == 0.0F && (mode & 8) != 0 && (mode & 4) != 0) { rAxis.y = -1.0F; } break; case 96: rAxis.z = 1.0F; rAxis.x = (float)(inaxis1 / 255.0); rAxis.y = (float)(inaxis2 / 255.0); if ((mode & 8) != 0) { rAxis.x = (float)(rAxis.x * -1.0); } if ((mode & 4) != 0) { rAxis.y = (float)(rAxis.y * -1.0); } if (rAxis.x == 0.0F && rAxis.y == 0.0F && (mode & 8) != 0 && (mode & 4) != 0) { rAxis.z = -1.0F; } } } if ((mode & 16) != 0) { int inbyte = ds.readUnsignedByte(); rotation = (float)(360.0 * (inbyte / 256.0)); w.worldSpin(rAxis.x, rAxis.y, rAxis.z, rotation); } if ((mode & 2) != 0) { int inbyte = ds.readUnsignedByte(); double s = defScale.x * Math.exp((inbyte - 121.6) / 16.0); scale.x = (float)s; if ((mode & 1) != 0) { scale.y = scale.x; scale.z = scale.x; } else { inbyte = ds.readUnsignedByte(); s = defScale.y * Math.exp((inbyte - 121.6) / 16.0); scale.y = (float)s; inbyte = ds.readUnsignedByte(); s = defScale.z * Math.exp((inbyte - 121.6) / 16.0); scale.z = (float)s; } Point3Temp oldScale = w.getScale(); scale.x = scale.x / oldScale.x; scale.y = scale.y / oldScale.y; scale.z = scale.z / oldScale.z; w.scale(scale); } dontSend = false; } } } private static Point3Temp maxDecompressXY(Point3Temp pos, DataInputStream ds) throws IOException { int ix = ds.readUnsignedByte(); ix <<= 4; int iy = ds.readUnsignedByte(); ix |= iy >>> 4; iy &= 15; iy <<= 8; iy |= ds.readUnsignedByte(); pos.x = ix; pos.y = iy; return pos; } private static Point3Temp minDecompressXYZ(Point3Temp pos, DataInputStream ds) throws IOException { int i1 = ds.readInt(); int i2 = ds.readInt(); int tmp = i1 >>> 10; pos.x = floatFrom21bits(tmp); tmp = (i1 & 1023) << 11; tmp |= i2 >>> 21; pos.y = floatFrom21bits(tmp); tmp = i2 & 2097151; pos.z = floatFrom21bits(tmp); return pos; } private static float floatFrom21bits(int bits) { int e = bits & 3; int s = (bits & 1048576) << 11 | 1; int m = (bits & -1048577) >>> 2; double d = Math.pow(10.0, e - 2); return (float)(m * d * s); } }