public IndexedImage(Archive archive, String name, int id) { try { Default317Buffer imageBuffer = new Default317Buffer(archive.decompressFile(name + ".dat")); Default317Buffer metadataBuffer = new Default317Buffer(archive.decompressFile("index.dat")); metadataBuffer.position = imageBuffer.getUnsignedLEShort(); resizeWidth = metadataBuffer.getUnsignedLEShort(); resizeHeight = metadataBuffer.getUnsignedLEShort(); int colourCount = metadataBuffer.getUnsignedByte(); palette = new int[colourCount]; for (int c = 0; c < colourCount - 1; c++) { palette[c + 1] = metadataBuffer.get3Bytes(); } for (int i = 0; i < id; i++) { metadataBuffer.position += 2; imageBuffer.position += metadataBuffer.getUnsignedLEShort() * metadataBuffer.getUnsignedLEShort(); metadataBuffer.position++; } drawOffsetX = metadataBuffer.getUnsignedByte(); drawOffsetY = metadataBuffer.getUnsignedByte(); width = metadataBuffer.getUnsignedLEShort(); height = metadataBuffer.getUnsignedLEShort(); int type = metadataBuffer.getUnsignedByte(); int pixelCount = width * height; pixels = new byte[pixelCount]; if (type == 0) { for (int i = 0; i < pixelCount; i++) { pixels[i] = imageBuffer.get(); } return; } if (type == 1) { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = imageBuffer.get(); } } } } catch (Exception e) { throw new InvalidOperationException($"Failed to generate IndexedImage for: {name} id: {id}. Reason: {e.Message}\nStack: {e.StackTrace}", e); } }
private void loadDefinition(Default317Buffer stream) { do { int opcode = stream.getUnsignedByte(); if (opcode == 0) { return; } if (opcode == 1) { int modelCount = stream.getUnsignedByte(); modelIds = new int[modelCount]; for (int m = 0; m < modelCount; m++) { modelIds[m] = stream.getUnsignedLEShort(); } } else if (opcode == 2) { name = stream.getString(); } else if (opcode == 3) { description = stream.readBytes(); } else if (opcode == 12) { boundaryDimension = stream.get(); } else if (opcode == 13) { standAnimationId = stream.getUnsignedLEShort(); } else if (opcode == 14) { walkAnimationId = stream.getUnsignedLEShort(); } else if (opcode == 17) { walkAnimationId = stream.getUnsignedLEShort(); turnAboutAnimationId = stream.getUnsignedLEShort(); turnRightAnimationId = stream.getUnsignedLEShort(); turnLeftAnimationId = stream.getUnsignedLEShort(); } else if (opcode >= 30 && opcode < 40) { if (actions == null) { actions = new String[5]; } actions[opcode - 30] = stream.getString(); if (actions[opcode - 30].Equals("hidden", StringComparison.InvariantCultureIgnoreCase)) { actions[opcode - 30] = null; } } else if (opcode == 40) { int colourCount = stream.getUnsignedByte(); modifiedModelColours = new int[colourCount]; originalModelColours = new int[colourCount]; for (int c = 0; c < colourCount; c++) { modifiedModelColours[c] = stream.getUnsignedLEShort(); originalModelColours[c] = stream.getUnsignedLEShort(); } } else if (opcode == 60) { int additionalModelCount = stream.getUnsignedByte(); headModelIds = new int[additionalModelCount]; for (int m = 0; m < additionalModelCount; m++) { headModelIds[m] = stream.getUnsignedLEShort(); } } else if (opcode == 90) { stream.getUnsignedLEShort(); } else if (opcode == 91) { stream.getUnsignedLEShort(); } else if (opcode == 92) { stream.getUnsignedLEShort(); } else if (opcode == 93) { visibleMinimap = false; } else if (opcode == 95) { combatLevel = stream.getUnsignedLEShort(); } else if (opcode == 97) { scaleXY = stream.getUnsignedLEShort(); } else if (opcode == 98) { scaleZ = stream.getUnsignedLEShort(); } else if (opcode == 99) { visible = true; } else if (opcode == 100) { brightness = stream.get(); } else if (opcode == 101) { contrast = stream.get() * 5; } else if (opcode == 102) { headIcon = stream.getUnsignedLEShort(); } else if (opcode == 103) { degreesToTurn = stream.getUnsignedLEShort(); } else if (opcode == 106) { varBitId = stream.getUnsignedLEShort(); if (varBitId == 65535) { varBitId = -1; } settingId = stream.getUnsignedLEShort(); if (settingId == 65535) { settingId = -1; } int childCount = stream.getUnsignedByte(); childrenIDs = new int[childCount + 1]; for (int c = 0; c <= childCount; c++) { childrenIDs[c] = stream.getUnsignedLEShort(); if (childrenIDs[c] == 65535) { childrenIDs[c] = -1; } } } else if (opcode == 107) { clickable = false; } } while(true); }
private void readValues(Default317Buffer stream) { do { int opcode = stream.getUnsignedByte(); if (opcode == 0) { return; } if (opcode == 1) { modelId = stream.getUnsignedLEShort(); } else if (opcode == 2) { name = stream.getString(); } else if (opcode == 3) { description = stream.readBytes(); } else if (opcode == 4) { modelZoom = stream.getUnsignedLEShort(); } else if (opcode == 5) { modelRotationX = stream.getUnsignedLEShort(); } else if (opcode == 6) { modelRotationY = stream.getUnsignedLEShort(); } else if (opcode == 7) { modelOffset1 = stream.getUnsignedLEShort(); if (modelOffset1 > 32767) { modelOffset1 -= 0x10000; } } else if (opcode == 8) { modelOffset2 = stream.getUnsignedLEShort(); if (modelOffset2 > 32767) { modelOffset2 -= 0x10000; } } else if (opcode == 10) { stream.getUnsignedLEShort(); } else if (opcode == 11) { stackable = true; } else if (opcode == 12) { value = stream.getInt(); } else if (opcode == 16) { membersObject = true; } else if (opcode == 23) { maleEquipModelIdPrimary = stream.getUnsignedLEShort(); equipModelTranslationMale = stream.get(); } else if (opcode == 24) { maleEquipModelIdSecondary = stream.getUnsignedLEShort(); } else if (opcode == 25) { femaleEquipModelIdPrimary = stream.getUnsignedLEShort(); equipModelTranslationFemale = stream.get(); } else if (opcode == 26) { femaleEquipModelIdSecondary = stream.getUnsignedLEShort(); } else if (opcode >= 30 && opcode < 35) { if (groundActions == null) { groundActions = new String[5]; } groundActions[opcode - 30] = stream.getString(); if (groundActions[opcode - 30].Equals("hidden", StringComparison.InvariantCultureIgnoreCase)) { groundActions[opcode - 30] = null; } } else if (opcode >= 35 && opcode < 40) { if (actions == null) { actions = new String[5]; } actions[opcode - 35] = stream.getString(); } else if (opcode == 40) { int colourCount = stream.getUnsignedByte(); modifiedModelColors = new int[colourCount]; originalModelColors = new int[colourCount]; for (int c = 0; c < colourCount; c++) { modifiedModelColors[c] = stream.getUnsignedLEShort(); originalModelColors[c] = stream.getUnsignedLEShort(); } } else if (opcode == 78) { maleEquipModelIdEmblem = stream.getUnsignedLEShort(); } else if (opcode == 79) { femaleEquipModelIdEmblem = stream.getUnsignedLEShort(); } else if (opcode == 90) { maleDialogueModelId = stream.getUnsignedLEShort(); } else if (opcode == 91) { femaleDialogueModelId = stream.getUnsignedLEShort(); } else if (opcode == 92) { maleDialogueHatModelId = stream.getUnsignedLEShort(); } else if (opcode == 93) { femaleDialogueHatModelId = stream.getUnsignedLEShort(); } else if (opcode == 95) { modelRotationZ = stream.getUnsignedLEShort(); } else if (opcode == 97) { noteId = stream.getUnsignedLEShort(); } else if (opcode == 98) { noteTemplateId = stream.getUnsignedLEShort(); } else if (opcode >= 100 && opcode < 110) { if (stackableIds == null) { stackableIds = new int[10]; stackableAmounts = new int[10]; } stackableIds[opcode - 100] = stream.getUnsignedLEShort(); stackableAmounts[opcode - 100] = stream.getUnsignedLEShort(); } else if (opcode == 110) { modelScaleX = stream.getUnsignedLEShort(); } else if (opcode == 111) { modelScaleY = stream.getUnsignedLEShort(); } else if (opcode == 112) { modelScaleZ = stream.getUnsignedLEShort(); } else if (opcode == 113) { lightModifier = stream.get(); } else if (opcode == 114) { shadowModifier = stream.get() * 5; } else if (opcode == 115) { teamId = stream.getUnsignedByte(); } } while(true); }
private void loadDefinition(Default317Buffer stream) { int _actions = -1; do { int opcode; do { opcode = stream.getUnsignedByte(); if (opcode == 0) { goto label0; } if (opcode == 1) { int modelCount = stream.getUnsignedByte(); if (modelCount > 0) { if (modelIds == null || lowMemory) { modelTypes = new int[modelCount]; modelIds = new int[modelCount]; for (int m = 0; m < modelCount; m++) { modelIds[m] = stream.getUnsignedLEShort(); modelTypes[m] = stream.getUnsignedByte(); } } else { stream.position += modelCount * 3; } } } else if (opcode == 2) { name = stream.getString(); } else if (opcode == 3) { description = stream.readBytes(); } else if (opcode == 5) { int modelCount = stream.getUnsignedByte(); if (modelCount > 0) { if (modelIds == null || lowMemory) { modelTypes = null; modelIds = new int[modelCount]; for (int m = 0; m < modelCount; m++) { modelIds[m] = stream.getUnsignedLEShort(); } } else { stream.position += modelCount * 2; } } } else if (opcode == 14) { sizeX = stream.getUnsignedByte(); } else if (opcode == 15) { sizeY = stream.getUnsignedByte(); } else if (opcode == 17) { solid = false; } else if (opcode == 18) { walkable = false; } else if (opcode == 19) { _actions = stream.getUnsignedByte(); if (_actions == 1) { hasActions = true; } } else if (opcode == 21) { adjustToTerrain = true; } else if (opcode == 22) { delayShading = true; } else if (opcode == 23) { wall = true; } else if (opcode == 24) { animationId = stream.getUnsignedLEShort(); if (animationId == 65535) { animationId = -1; } } else if (opcode == 28) { offsetAmplifier = stream.getUnsignedByte(); } else if (opcode == 29) { ambient = stream.get(); } else if (opcode == 39) { diffuse = stream.get(); } else if (opcode >= 30 && opcode < 39) { if (actions == null) { actions = new String[5]; } actions[opcode - 30] = stream.getString(); if (actions[opcode - 30].Equals("hidden", StringComparison.InvariantCultureIgnoreCase)) { actions[opcode - 30] = null; } } else if (opcode == 40) { int colourCount = stream.getUnsignedByte(); modifiedModelColors = new int[colourCount]; originalModelColors = new int[colourCount]; for (int c = 0; c < colourCount; c++) { modifiedModelColors[c] = stream.getUnsignedLEShort(); originalModelColors[c] = stream.getUnsignedLEShort(); } } else if (opcode == 60) { icon = stream.getUnsignedLEShort(); } else if (opcode == 62) { rotated = true; } else if (opcode == 64) { castsShadow = false; } else if (opcode == 65) { scaleX = stream.getUnsignedLEShort(); } else if (opcode == 66) { scaleY = stream.getUnsignedLEShort(); } else if (opcode == 67) { scaleZ = stream.getUnsignedLEShort(); } else if (opcode == 68) { mapScene = stream.getUnsignedLEShort(); } else if (opcode == 69) { face = stream.getUnsignedByte(); } else if (opcode == 70) { translateX = stream.getShort(); } else if (opcode == 71) { translateY = stream.getShort(); } else if (opcode == 72) { translateZ = stream.getShort(); } else if (opcode == 73) { unknownAttribute = true; } else if (opcode == 74) { unwalkableSolid = true; } else { if (opcode != 75) { continue; } _solid = stream.getUnsignedByte(); } continue; } while(opcode != 77); varBitId = stream.getUnsignedLEShort(); if (varBitId == 65535) { varBitId = -1; } configIds = stream.getUnsignedLEShort(); if (configIds == 65535) { configIds = -1; } int childCount = stream.getUnsignedByte(); childIds = new int[childCount + 1]; for (int c = 0; c <= childCount; c++) { childIds[c] = stream.getUnsignedLEShort(); if (childIds[c] == 65535) { childIds[c] = -1; } } } while(true); label0: if (_actions == -1) { hasActions = modelIds != null && (modelTypes == null || modelTypes[0] == 10); if (actions != null) { hasActions = true; } } if (unwalkableSolid) { solid = false; walkable = false; } if (_solid == -1) { _solid = solid ? 1 : 0; } }
/** * Initialise a GameFont. * * @param name The name of the font. * * @param archive The archive containing the information about the font. * * @param monospace Is the font monospace? */ public GameFont(String name, Archive archive, bool monospace) { glyphPixels = new byte[256][]; glyphWidth = new int[256]; glyphHeight = new int[256]; horizontalKerning = new int[256]; verticalKerning = new int[256]; glyphDisplayWidth = new int[256]; random = new Random(); strikethrough = false; /* * The buffer containing data about this specific font. The position of the font * within the parent archive (index.dat) and the pixel data for the glyph. */ Default317Buffer glyphData = new Default317Buffer(archive.decompressFile(name + ".dat")); /* * Stores the information about the glyphs, such as the kerning and the * dimensons. */ Default317Buffer glyphInformation = new Default317Buffer(archive.decompressFile("index.dat")); /* * Find the glyph information within the parent archive. */ glyphInformation.position = glyphData.getUnsignedLEShort() + 4; /* * Find the glyph data for this font within the parent archive. */ int startPosition = glyphInformation.getUnsignedByte(); if (startPosition > 0) { glyphInformation.position += 3 * (startPosition - 1); } /* * Get the data for each glyph. */ for (int g = 0; g < 256; g++) { horizontalKerning[g] = glyphInformation.getUnsignedByte(); verticalKerning[g] = glyphInformation.getUnsignedByte(); int width = glyphWidth[g] = glyphInformation.getUnsignedLEShort(); int height = glyphHeight[g] = glyphInformation.getUnsignedLEShort(); /* * Is the glyph rectangular? */ int rectangular = glyphInformation.getUnsignedByte(); /* * Get the area of the glyph. */ int area = width * height; /* * Initialise the pixels for this glyph. */ glyphPixels[g] = new byte[area]; /* * Set the pixels for the glyph based on whether it is square or rectangular. */ if (rectangular == 0) { for (int p = 0; p < area; p++) { glyphPixels[g][p] = glyphData.get(); } } else if (rectangular == 1) { for (int w = 0; w < width; w++) { for (int h = 0; h < height; h++) { glyphPixels[g][w + h * width] = glyphData.get(); } } } /* * If the height of this glyph is higher than the highest glyph we've currently * processed for this font, store this glyph's height as the highest. * * 126 is the last visible character used in this client (~). No support for * accented characters! */ if (height > fontHeight && g < 128) { fontHeight = height; } horizontalKerning[g] = 1; glyphDisplayWidth[g] = width + 2; int activePixels = 0; for (int h = height / 7; h < height; h++) { activePixels += glyphPixels[g][h * width]; } if (activePixels <= height / 7) { glyphDisplayWidth[g]--; horizontalKerning[g] = 0; } activePixels = 0; for (int h = height / 7; h < height; h++) { activePixels += glyphPixels[g][(width - 1) + h * width]; } if (activePixels <= height / 7) { glyphDisplayWidth[g]--; } } /* * Character 32 is space, character 73 is uppercase I and character 105 is * lowercase i. */ if (monospace) { glyphDisplayWidth[32] = glyphDisplayWidth[73]; } else { glyphDisplayWidth[32] = glyphDisplayWidth[105]; } }
public IndexedImage(Archive archive, String name, int id, Default317Buffer optionalMetaDataBuffer = null) { try { Default317Buffer imageBuffer = new Default317Buffer(archive.decompressFile(name + ".dat")); Default317Buffer metadataBuffer = optionalMetaDataBuffer != null ? optionalMetaDataBuffer : new Default317Buffer(archive.decompressFile("index.dat")); metadataBuffer.position = imageBuffer.getUnsignedLEShort(); resizeWidth = metadataBuffer.getUnsignedLEShort(); resizeHeight = metadataBuffer.getUnsignedLEShort(); int colourCount = metadataBuffer.getUnsignedByte(); palette = new int[colourCount]; for (int c = 0; c < colourCount - 1; c++) { palette[c + 1] = metadataBuffer.get3Bytes(); } for (int i = 0; i < id; i++) { metadataBuffer.position += 2; imageBuffer.position += metadataBuffer.getUnsignedLEShort() * metadataBuffer.getUnsignedLEShort(); metadataBuffer.position++; } drawOffsetX = metadataBuffer.getUnsignedByte(); drawOffsetY = metadataBuffer.getUnsignedByte(); width = metadataBuffer.getUnsignedLEShort(); height = metadataBuffer.getUnsignedLEShort(); int type = metadataBuffer.getUnsignedByte(); int pixelCount = width * height; //Custom: Below are some sanity checks that are custom but help guard against known clean cache data issues. bool isEnoughDataAvailable = pixelCount <= (imageBuffer.buffer.Length - imageBuffer.position); //Don't let corrupt image data, in default cache, cause BIG allocation (bad for WebGL) //or allocate/read for empty images. if (pixelCount <= 0 || pixelCount > int.MaxValue / 100 || !isEnoughDataAvailable || imageBuffer.position < 0) //sometimes happens!! { width = 0; height = 0; this.pixels = Array.Empty <byte>(); return; } pixels = new byte[pixelCount]; if (type == 0) { for (int i = 0; i < pixelCount; i++) { pixels[i] = imageBuffer.get(); } return; } if (type == 1) { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = imageBuffer.get(); } } } } catch (Exception e) { isValid = false; //Don't throw, this is just a data error. Not an engine fault. throw new InvalidOperationException($"Failed to generate IndexedImage for: {name} id: {id}. Reason: {e.Message}\nStack: {e.StackTrace}", e); } }