|
| 1 | +package net.ddns.endercypt.cs2dmap.library.file.read; |
| 2 | + |
| 3 | +import java.io.File; |
| 4 | +import java.io.FileNotFoundException; |
| 5 | +import java.io.IOException; |
| 6 | +import java.util.ArrayList; |
| 7 | +import java.util.List; |
| 8 | + |
| 9 | +import net.ddns.endercypt.cs2dmap.library.file.read.stream.Cs2dByteReader; |
| 10 | +import net.ddns.endercypt.cs2dmap.library.file.read.stream.Cs2dMapReadException; |
| 11 | +import net.ddns.endercypt.cs2dmap.library.file.stream.assist.Cs2dByteInfo; |
| 12 | +import net.ddns.endercypt.cs2dmap.library.file.stream.exception.Cs2dUnexpectedEOFException; |
| 13 | +import net.ddns.endercypt.cs2dmap.library.map.Cs2dMap; |
| 14 | +import net.ddns.endercypt.cs2dmap.library.raw.RawCs2dEntity; |
| 15 | +import net.ddns.endercypt.cs2dmap.library.raw.RawCs2dMap; |
| 16 | +import net.ddns.endercypt.cs2dmap.library.raw.RawCs2dTile; |
| 17 | +import net.ddns.endercypt.cs2dmap.library.raw.rawbyte.RawByte; |
| 18 | +import net.ddns.endercypt.cs2dmap.library.raw.rawbyte.RawByteFlags; |
| 19 | + |
| 20 | +public class Cs2dMapReader |
| 21 | +{ |
| 22 | + public static Cs2dMap read(File file) throws FileNotFoundException, IOException |
| 23 | + { |
| 24 | + RawCs2dMap rawCs2dMap = new RawCs2dMap(); |
| 25 | + |
| 26 | + try (Cs2dByteReader reader = new Cs2dByteReader(file)) |
| 27 | + { |
| 28 | + // (1) HEADER |
| 29 | + rawCs2dMap.header = reader.readString(); |
| 30 | + |
| 31 | + // ----- 10 bytes for map settings / info |
| 32 | + rawCs2dMap.scroll_map_like_tiles = reader.readBooleanByte(); |
| 33 | + boolean use_modifiers_in_this_map = reader.readBooleanByte().value; |
| 34 | + rawCs2dMap.save_tile_heights_with_map = reader.readByte(); |
| 35 | + rawCs2dMap.use_64x64_pixel_tiles = reader.readBooleanByte(); |
| 36 | + reader.skip(Cs2dByteInfo.BYTE, 6); |
| 37 | + |
| 38 | + // ----- 10 ints for map settings / info |
| 39 | + rawCs2dMap.uptime_of_system = reader.readInt(); |
| 40 | + rawCs2dMap.usgn_id_of_the_map_author = reader.readInt(); |
| 41 | + rawCs2dMap.map_daylight_time = reader.readInt(); |
| 42 | + reader.skip(Cs2dByteInfo.INT, 7); |
| 43 | + |
| 44 | + // ----- 10 strings for map settings / info |
| 45 | + rawCs2dMap.name_of_the_map_author = reader.readString(); |
| 46 | + rawCs2dMap.name_of_the_program_used_to_save_the_map = reader.readString(); |
| 47 | + reader.skipStringNulls(8); |
| 48 | + |
| 49 | + // ----- More map settings |
| 50 | + String[] tempStringArray = split(reader.readString(), new char[] { 'x', '$', '%' }); |
| 51 | + int map_xy_size = Integer.parseInt(tempStringArray[0]); |
| 52 | + rawCs2dMap.tile_count = Integer.parseInt(tempStringArray[1]); |
| 53 | + rawCs2dMap.currentSystemTime = Integer.parseInt(tempStringArray[2]); |
| 54 | + rawCs2dMap.systemUpTime = Long.parseLong(tempStringArray[3]); |
| 55 | + rawCs2dMap.filename_of_the_tilset_image = reader.readString(); |
| 56 | + //rawCs2dMap.number_of_tiles_required_from_this_tileset = reader.readByte(); |
| 57 | + reader.readByte(); // skip number_of_tiles_required_from_this_tileset as its auto-generated during write |
| 58 | + rawCs2dMap.map_width = reader.readInt(); |
| 59 | + rawCs2dMap.map_height = reader.readInt(); |
| 60 | + if (rawCs2dMap.map_width * rawCs2dMap.map_height != map_xy_size) |
| 61 | + { |
| 62 | + throw new Cs2dMapReadException("(map_xsize (in tiles) * map_ysize (in tiles)) = " + map_xy_size + " of the map file is inconsistant with the map width/height (" + rawCs2dMap.map_width + "," + rawCs2dMap.map_height + "=" + (rawCs2dMap.map_width * rawCs2dMap.map_height) + ")"); |
| 63 | + } |
| 64 | + rawCs2dMap.filename_of_map_background_image = reader.readString(); |
| 65 | + rawCs2dMap.background_scroll_x_speed = reader.readInt(); |
| 66 | + rawCs2dMap.background_scroll_y_speed = reader.readInt(); |
| 67 | + rawCs2dMap.map_background_color_red = reader.readByte(); |
| 68 | + rawCs2dMap.map_background_color_green = reader.readByte(); |
| 69 | + rawCs2dMap.map_background_color_blue = reader.readByte(); |
| 70 | + |
| 71 | + // ----- Header Test |
| 72 | + if (reader.readString().equals(Cs2dByteInfo.REVERSE_UNREALSOFTWARE) == false) |
| 73 | + { |
| 74 | + throw new Cs2dMapReadException("header check failed: " + Cs2dByteInfo.REVERSE_UNREALSOFTWARE); |
| 75 | + } |
| 76 | + |
| 77 | + // (2) Tile Modes |
| 78 | + rawCs2dMap.tile_modes = new RawByte[rawCs2dMap.tile_count + 1]; |
| 79 | + for (int i = 0; i < rawCs2dMap.tile_count + 1; i++) |
| 80 | + { |
| 81 | + rawCs2dMap.tile_modes[i] = reader.readByte(); |
| 82 | + } |
| 83 | + |
| 84 | + // (3) Tile Heights |
| 85 | + switch (rawCs2dMap.save_tile_heights_with_map.getInt()) |
| 86 | + { |
| 87 | + case 0: |
| 88 | + // READ (ignore) |
| 89 | + // UPGRADE TO MODE 2 |
| 90 | + rawCs2dMap.save_tile_heights_with_map.set(2); |
| 91 | + rawCs2dMap.tile_height_in_pixels = new int[rawCs2dMap.tile_count + 1]; |
| 92 | + rawCs2dMap.tile_3D_modifier = new RawByteFlags[rawCs2dMap.tile_count + 1]; |
| 93 | + for (int i = 0; i < rawCs2dMap.tile_count + 1; i++) |
| 94 | + { |
| 95 | + rawCs2dMap.tile_height_in_pixels[i] = 0; |
| 96 | + rawCs2dMap.tile_3D_modifier[i] = RawByteFlags.EMPTY(); |
| 97 | + } |
| 98 | + break; |
| 99 | + case 1: // If "save tile heights" is 1 (only used in 1.0.0.3 pre-release): |
| 100 | + // READ |
| 101 | + rawCs2dMap.tile_height_in_pixels = new int[rawCs2dMap.tile_count + 1]; |
| 102 | + for (int i = 0; i < rawCs2dMap.tile_count + 1; i++) |
| 103 | + { |
| 104 | + rawCs2dMap.tile_height_in_pixels[i] = reader.readInt(); |
| 105 | + } |
| 106 | + // UPGRADE TO MODE 2 |
| 107 | + rawCs2dMap.save_tile_heights_with_map.set(2); |
| 108 | + rawCs2dMap.tile_3D_modifier = new RawByteFlags[rawCs2dMap.tile_count + 1]; |
| 109 | + for (int i = 0; i < rawCs2dMap.tile_count + 1; i++) |
| 110 | + { |
| 111 | + rawCs2dMap.tile_3D_modifier[i] = RawByteFlags.EMPTY(); |
| 112 | + } |
| 113 | + break; |
| 114 | + case 2: // Else If "save tile heights" is 2 (default since 1.0.0.3): |
| 115 | + // READ |
| 116 | + rawCs2dMap.tile_height_in_pixels = new int[rawCs2dMap.tile_count + 1]; |
| 117 | + rawCs2dMap.tile_3D_modifier = new RawByteFlags[rawCs2dMap.tile_count + 1]; |
| 118 | + for (int i = 0; i < rawCs2dMap.tile_count + 1; i++) |
| 119 | + { |
| 120 | + rawCs2dMap.tile_height_in_pixels[i] = reader.readShort() & 0xFFFF; |
| 121 | + rawCs2dMap.tile_3D_modifier[i] = reader.readRawByteFlags(); |
| 122 | + } |
| 123 | + break; |
| 124 | + default: |
| 125 | + throw new Cs2dMapReadException("byte \"use modifiers in this map\" contained unknown value: " + rawCs2dMap.save_tile_heights_with_map.getByte()); |
| 126 | + } |
| 127 | + |
| 128 | + // (4) Map |
| 129 | + rawCs2dMap.map = new RawCs2dTile[rawCs2dMap.map_width + 1][rawCs2dMap.map_height + 1]; |
| 130 | + for (int x = 0; x < rawCs2dMap.map_width + 1; x++) |
| 131 | + { |
| 132 | + for (int y = 0; y < rawCs2dMap.map_height + 1; y++) |
| 133 | + { |
| 134 | + rawCs2dMap.map[x][y] = new RawCs2dTile(reader); |
| 135 | + } |
| 136 | + } |
| 137 | + if (use_modifiers_in_this_map) |
| 138 | + { |
| 139 | + for (int x = 0; x < rawCs2dMap.map_width + 1; x++) |
| 140 | + { |
| 141 | + for (int y = 0; y < rawCs2dMap.map_height + 1; y++) |
| 142 | + { |
| 143 | + rawCs2dMap.map[x][y].readModifiers(reader); |
| 144 | + } |
| 145 | + } |
| 146 | + } |
| 147 | + |
| 148 | + // (5) Entities |
| 149 | + int entity_count = reader.readInt(); |
| 150 | + for (int i = 0; i < entity_count; i++) |
| 151 | + { |
| 152 | + rawCs2dMap.entities.add(new RawCs2dEntity(reader)); |
| 153 | + } |
| 154 | + |
| 155 | + // (6) End of file |
| 156 | + if (reader.available() > 0) |
| 157 | + { |
| 158 | + throw new Cs2dUnexpectedEOFException("read a total of " + reader.getPosition() + " bytes and expected EOF but found ~" + reader.available() + " residual bytes!", reader.getPosition(), reader.dumpStream()); |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + return new Cs2dMap(rawCs2dMap); |
| 163 | + } |
| 164 | + |
| 165 | + private static String[] split(String string, char[] pattern) |
| 166 | + { |
| 167 | + List<String> array = new ArrayList<>(); |
| 168 | + for (int i = 0; i < pattern.length; i++) |
| 169 | + { |
| 170 | + char patternCharacter = pattern[i]; |
| 171 | + int location = string.indexOf(patternCharacter); |
| 172 | + if (location == -1) |
| 173 | + { |
| 174 | + throw new Cs2dMapReadException("unable to find pattern " + patternCharacter + " in string " + string); |
| 175 | + } |
| 176 | + String element = string.substring(0, location); |
| 177 | + array.add(element); |
| 178 | + string = string.substring(location + 1); |
| 179 | + } |
| 180 | + array.add(string); |
| 181 | + return array.stream().toArray(String[]::new); |
| 182 | + } |
| 183 | +} |
0 commit comments