Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.nio.file.Files;
- import java.nio.file.Path;
- import java.nio.file.Paths;
- import java.nio.file.StandardCopyOption;
- import java.util.Arrays;
- public class Main {
- public static void main(String[] args) throws IOException {
- //setting output
- boolean to_file = false;
- if (to_file) {
- PrintStream printStream = new PrintStream(new FileOutputStream(new File("D:/SteamLibrary/steamapps/common/Left 4 Dead 2/left4dead2/maps/output.txt")));
- System.setOut(printStream);
- }
- String[] names = {
- "c1m1_hotel",
- "c1m2_streets",
- "c1m3_mall",
- "c1m4_atrium",
- "c2m1_highway",
- "c2m2_fairgrounds",
- "c2m3_coaster",
- "c2m4_barns",
- "c2m5_concert",
- "c3m1_plankcountry",
- "c3m2_swamp",
- "c3m3_shantytown",
- "c3m4_plantation",
- "c4m1_milltown_a",
- "c4m2_sugarmill_a",
- "c4m3_sugarmill_b",
- "c4m4_milltown_b",
- "c4m5_milltown_escape",
- "c5m1_waterfront",
- "c5m2_park",
- "c5m3_cemetery",
- "c5m4_quarter",
- "c5m5_bridge",
- "c6m1_riverbank",
- "c6m2_bedlam",
- "c6m3_port",
- "c7m1_docks",
- "c7m2_barge",
- "c7m3_port",
- "c8m1_apartment",
- "c8m2_subway",
- "c8m3_sewers",
- "c8m4_interior",
- "c8m5_rooftop",
- "c9m1_alleys",
- "c9m2_lots",
- "c10m1_caves",
- "c10m2_drainage",
- "c10m3_ranchhouse",
- "c10m4_mainstreet",
- "c10m5_houseboat",
- "c11m1_greenhouse",
- "c11m2_offices",
- "c11m3_garage",
- "c11m4_terminal",
- "c11m5_runway",
- "C12m1_hilltop",
- "C12m2_traintunnel",
- "C12m3_bridge",
- "C12m4_barn",
- "C12m5_cornfield",
- "c13m1_alpinecreek",
- "c13m2_southpinestream",
- "c13m3_memorialbridge",
- "c13m4_cutthroatcreek"
- };
- for (String mapname: names) {
- work(mapname);
- }
- }
- static void work(String mapname) throws IOException {
- //reading file
- String path_str = "D:/SteamLibrary/steamapps/common/Left 4 Dead 2/left4dead2/maps/" + mapname + ".bsp";
- Path path = Paths.get(path_str);
- byte[] b = Files.readAllBytes(path);
- byte[] b_edited = subArray(b, 0, b.length);
- System.out.println(path_str + " contains " + b.length + " bytes");
- System.out.println("-----------------------------");
- //reading magic number and version
- int magic_number = readInteger(b, 0);
- int bsp_version = readInteger(b, 4);
- if (magic_number == (('P'<<24)+('S'<<16)+('B'<<8)+'V')) {
- System.out.println("VBSP version " + bsp_version);
- } else {
- System.out.println("Unknown magic number " + toHex(magic_number));
- }
- System.out.println("-----------------------------");
- //reading lump directory array
- int[] lump_start = new int[64];
- int[] lump_length = new int[64];
- for (int i = 0; i < 64; i++) {
- int offset = 12 + i*16;
- byte[] lump = subArray(b, offset, 16);
- lump_start[i] = readInteger(lump, 0);
- lump_length[i] = readInteger(lump, 4);
- String start_percent = 100 * lump_start[i] / b.length + "% of file";
- String length_percent = 100 * lump_length[i] / b.length + "% of file";
- System.out.println("lump " + i + " starts from " + toHex(lump_start[i]) + " (" + start_percent + ") and has length of " + toHex(lump_length[i]) + " (" + length_percent + ")");
- }
- System.out.println("-----------------------------");
- //reading TexdataStringTable (lump 44)
- byte[] texdataStringTable = subArray(b, lump_start[44], lump_length[44]);
- System.out.println("TexdataStringTable has length of " + texdataStringTable.length + " bytes");
- int number_of_textures = texdataStringTable.length / 4;
- System.out.println("Number of textures: " + number_of_textures);
- if (number_of_textures * 4 != texdataStringTable.length) System.err.println("Error wrong TexdataStringTable");
- int[] textureStringOffsets = new int[number_of_textures];
- System.out.print("textureStringOffsets: ");
- for (int i = 0; i < number_of_textures; i++) {
- int offset = i * 4;
- textureStringOffsets[i] = readInteger(texdataStringTable, offset);
- System.out.print(textureStringOffsets[i]);
- if (i != number_of_textures - 1) System.out.print(",");
- }
- System.out.println();
- System.out.println("-----------------------------");
- //reading TexdataStringData (lump 43)
- byte[] texdataStringData = subArray(b, lump_start[43], lump_length[43]);
- System.out.println("TexdataStringData has length of " + texdataStringData.length + " bytes");
- String[] texture_names = new String[number_of_textures];
- for (int i = 0; i < number_of_textures; i++) {
- int offset = textureStringOffsets[i];
- int offset_next = (i == number_of_textures - 1) ? texdataStringData.length : textureStringOffsets[i + 1];
- int length = offset_next - offset - 1;
- byte[] str_bytes = subArray(texdataStringData, offset, length);
- texture_names[i] = new String(str_bytes, "UTF-8");
- System.out.print("[" + i + "]" + texture_names[i]);
- if (i != number_of_textures - 1) System.out.print(",");
- }
- System.out.println();
- System.out.println("-----------------------------");
- //reading Texdata (lump 2)
- byte[] texdata = subArray(b, lump_start[2], lump_length[2]);
- System.out.println("Texdata has length of " + texdata.length + " bytes");
- int[] texData_indices = new int[number_of_textures];
- for (int i = 0; i < number_of_textures; i++) {
- int offset = i * 32 + 12;
- texData_indices[i] = readInteger(texdata, offset);
- System.out.print(texData_indices[i]);
- if (i != number_of_textures - 1) System.out.print(",");
- }
- System.out.println();
- System.out.println("-----------------------------");
- //reading Texinfo (lump 6)
- byte[] texinfo = subArray(b, lump_start[6], lump_length[6]);
- System.out.println("Texinfo has length of " + texinfo.length + " bytes");
- int texinfo_entries = texinfo.length / 72;
- if (texinfo_entries * 72 != texinfo.length) System.err.println("Error wrong Texinfo");
- System.out.println("Texinfo has " + texinfo_entries + " entries");
- int skybox_changed = 0;
- int nodraw_changed = 0;
- for (int i = 0; i < texinfo_entries; i++) {
- int offset = i * 72 + 64;
- int flags = readInteger(texinfo, offset);
- System.out.print(toBin(flags));
- int texdata_index = readInteger(texinfo, offset + 4);
- int texture_index = texData_indices[texdata_index];
- String texture_name = texture_names[texture_index];
- System.out.print(" " + texture_index + " " + texture_name);
- boolean is_skybox = (flags & (1 << 2)) != 0;
- if (is_skybox) {
- System.out.print(" - SKYBOX");
- //editing
- int address_of_byte = lump_start[6] + offset;
- byte _b = b[address_of_byte];
- _b &= Integer.reverse(1 << 2);
- b_edited[address_of_byte] = _b;
- System.out.print(" - changing to " + toBin(readInteger(b_edited, address_of_byte)));
- skybox_changed++;
- }
- boolean is_nodraw = (flags & (1 << 7)) != 0;
- if (is_nodraw) {
- System.out.print(" - NODRAW");
- //editing
- writeInteger(b_edited, lump_start[6] + offset, 0);
- int new_texture_index = -1;
- for (int i2 = 0; i2 < texture_names.length; i2++) {
- if (texture_names[i2].equalsIgnoreCase("CONCRETE/CONCRETE_EXT_01")) {
- new_texture_index = i2;
- break;
- }
- }
- int new_texdata_index = -1;
- if (new_texture_index != -1) {
- for (int i2 = 0; i2 < texData_indices.length; i2++) {
- if (texData_indices[i2] == new_texture_index) {
- new_texdata_index = i2;
- break;
- }
- }
- }
- if (new_texdata_index != -1) {
- System.out.print(" - new textdata index " + new_texdata_index);
- writeInteger(b_edited, lump_start[6] + offset + 4, new_texdata_index);
- System.out.print(" - checking, result is " + readInteger(b_edited, lump_start[6] + offset + 4));
- }
- System.out.print(" - changing to " + toBin(readInteger(b_edited, lump_start[6] + offset)));
- nodraw_changed++;
- }
- System.out.println();
- }
- System.out.println("-----------------------------");
- //reading Brush (lump 18)
- int clips_changed = 0;
- byte[] brush = subArray(b, lump_start[18], lump_length[18]);
- System.out.println("Brush has length of " + brush.length + " bytes");
- int number_of_brushes = brush.length / 12;
- System.out.println("Number of brushes: " + number_of_brushes);
- if (number_of_brushes * 12 != brush.length) System.err.println("Error wrong Brush");
- for (int i = 0; i < number_of_brushes; i++) {
- int offset = i * 12 + 8;
- int flags = readInteger(brush, offset);
- System.out.print(toBin(flags));
- boolean is_playerclip = (flags & 0x10000) != 0;
- boolean is_monsterclip = (flags & 0x20000) != 0;
- if (is_playerclip & !is_monsterclip) {
- System.out.print(" - PLAYERCLIP_ONLY");
- writeInteger(b_edited, lump_start[18] + offset, 0x8000000); //CONTENTS_DETAIL 0x8000000 - brushes to be added after vis leafs
- clips_changed++;
- }
- System.out.println();
- }
- System.out.println("-----------------------------");
- //writing to file
- try (FileOutputStream fos = new FileOutputStream("D:/SteamLibrary/steamapps/common/Left 4 Dead 2/left4dead2/maps/" + mapname + "_skybox.bsp")) {
- fos.write(b_edited);
- }
- System.out.println("success");
- System.out.println("skybox changed: " + skybox_changed);
- System.out.println("nodraw changed: " + nodraw_changed);
- System.out.println("clips changed: " + clips_changed);
- Files.copy(new File("D:/SteamLibrary/steamapps/common/Left 4 Dead 2/left4dead2/maps/" + mapname + ".nav").toPath(),
- new File("D:/SteamLibrary/steamapps/common/Left 4 Dead 2/left4dead2/maps/" + mapname + "_skybox.nav").toPath(),
- StandardCopyOption.REPLACE_EXISTING);
- System.out.println("navigation file created for " + mapname);
- }
- static int readInteger(byte[] b, int offset) { //little-endian
- return ((b[offset+3]&0xff)<<24)+((b[offset+2]&0xff)<<16)+((b[offset+1]&0xff)<<8)+(b[offset]&0xff);
- }
- static void writeInteger(byte[] b, int offset, int val) { //little-endian
- //((b[offset+3]&0xff)<<24)+((b[offset+2]&0xff)<<16)+((b[offset+1]&0xff)<<8)+(b[offset]&0xff);
- b[offset+3] = (byte) (val / 0xffffff); //старший разряд
- b[offset+2] = (byte) (val / 0xffff);
- b[offset+1] = (byte) (val / 0xff);
- b[offset] = (byte) (val); //младший разряд
- }
- static String toHex(int val) {
- return String.format("0x%08X", val);
- }
- static String toBin(int val) {
- //return "0b" + Integer.toBinaryString(val);
- return "0b" + String.format("%32s", Integer.toBinaryString(val)).replace(' ', '0');
- }
- static byte[] subArray(byte[] array, int start, int length) {
- return Arrays.copyOfRange(array, start, start + length);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement