public static DesignBlock fromDesignString( boolean isStarbase, int designNumber, boolean isRs, String designString, String name) throws Exception { DesignBlock designBlock = new DesignBlock(); designBlock.isFullDesign = true; String[] parts = designString.split(","); byte hull = Items.getHullIdOfUserString(parts[0]); designBlock.isStarbase = isStarbase; designBlock.designNumber = designNumber; designBlock.hullId = hull; designBlock.pic = 4 * hull; if (hull == 29) designBlock.pic = 4 * 31; // No idea why these pics are swapped else if (hull == 31) designBlock.pic = 4 * 29; designBlock.armor = Items.ships[hull].armor; designBlock.slotCount = Items.ships[hull].slotCount; designBlock.slots = new ArrayList<DesignBlock.Slot>(); for (int slot = 0; slot < designBlock.slotCount; slot++) { if (parts.length <= slot + 1) { designBlock.slots.add(new Slot()); continue; } int slotSize = Items.ships[hull].slotSizes[slot]; Slot slotInfo = Items.getSlotOfUserString(parts[slot + 1]); if (slotInfo.count < 0 || slotInfo.count > slotSize) slotInfo.count = slotSize; Integer armor = Items.itemArmors.get((slotInfo.category << 8) | slotInfo.itemId); if (armor != null) { if (isRs && slotInfo.category == Items.TechCategory.Armor.getMask()) { designBlock.armor += slotInfo.count * (armor / 2); } else { designBlock.armor += slotInfo.count * armor; } } designBlock.slots.add(slotInfo); } designBlock.nameBytes = Util.encodeStringForStarsFile(name); designBlock.encode(); return designBlock; }
@Override public void encode() { calculateMassAndFuelCapacity(); byte[] data; if (isFullDesign) { data = new byte[4 + 13 + 4 * slotCount + nameBytes.length]; } else { data = new byte[6 + nameBytes.length]; } if (isFullDesign) data[0] = 7; else data[0] = 3; data[1] = 1; data[1] |= designNumber << 2; if (isTransferred) data[1] |= 0x80; if (isStarbase) data[1] |= 0x40; data[2] = (byte) hullId; data[3] = (byte) pic; int index; if (isFullDesign) { Util.write16(data, 4, armor); data[6] = (byte) slotCount; Util.write16(data, 7, turnDesigned); Util.write32(data, 9, totalBuilt); Util.write32(data, 13, totalRemaining); index = 17; for (Slot slot : slots) { Util.write16(data, index, slot.category); index += 2; data[index++] = (byte) slot.itemId; data[index++] = (byte) slot.count; } } else { Util.write16(data, 4, mass); index = 6; } System.arraycopy(nameBytes, 0, data, index, nameBytes.length); setDecryptedData(data, data.length); setData(data, data.length); encrypted = false; }
@Override public void decode() throws Exception { if ((decryptedData[0] & 3) != 3) { throw new Exception("Unexpected design first byte: " + this); } if ((decryptedData[0] & 0xF8) != 0) { throw new Exception("Unexpected design first byte: " + this); } isFullDesign = (decryptedData[0] & 0x04) == 0x04; if ((decryptedData[1] & 0x02) != 0) { throw new Exception("Unexpected design second byte: " + this); } if ((decryptedData[1] & 0x01) != 0x01) { throw new Exception("Unexpected design second byte: " + this); } isTransferred = (decryptedData[1] & 0x80) == 0x80; isStarbase = (decryptedData[1] & 0x40) == 0x40; designNumber = (decryptedData[1] & 0x3C) >> 2; hullId = decryptedData[2] & 0xFF; fuelCapacity = Items.ships[hullId].fuel; pic = decryptedData[3] & 0xFF; int index; if (isFullDesign) { if (isStarbase) mass = 0; else mass = Items.ships[hullId].mass; armor = Util.read16(decryptedData, 4); slotCount = decryptedData[6] & 0xFF; turnDesigned = Util.read16(decryptedData, 7); totalBuilt = Util.read32(decryptedData, 9); totalRemaining = Util.read32(decryptedData, 13); index = 17; slots.clear(); for (int i = 0; i < slotCount; i++) { Slot slot = new Slot(); slot.category = Util.read16(decryptedData, index); index += 2; slot.itemId = Util.read8(decryptedData[index++]); slot.count = Util.read8(decryptedData[index++]); slots.add(slot); if (slot.count > 0) { int key = (slot.category << 8) | (slot.itemId & 0xFF); mass += slot.count * Items.itemMasses.get(key); if (slot.category == Items.TechCategory.Mechanical.getMask()) { if (slot.itemId == 5) fuelCapacity += slot.count * 250; if (slot.itemId == 6) fuelCapacity += slot.count * 500; } if (slot.category == Items.TechCategory.Electrical.getMask()) { if (slot.itemId == 16) fuelCapacity += slot.count * 200; } } } } else { mass = Util.read16(decryptedData, 4); index = 6; } int nameLen = decryptedData[index]; nameBytes = new byte[1 + nameLen]; System.arraycopy(decryptedData, index, nameBytes, 0, 1 + nameLen); index += 1 + nameLen; if (index != size) { throw new Exception("Unexpected design size: " + this); } }