├── .gitignore ├── hl2parse-binary ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── technofovea │ └── hl2parse │ ├── OffsetBuffer.java │ ├── ParseUtil.java │ ├── Vector3f.java │ ├── bsp │ ├── BinaryBspAnalyzer.java │ ├── BspLumpHeader.java │ ├── BspParseException.java │ ├── GameLumpHeader.java │ ├── GamePropSection.java │ ├── SourceMapAnalyzer.java │ └── package.html │ ├── mdl │ ├── ModelData.java │ ├── ModelFlag.java │ ├── ModelParseException.java │ ├── ModelSection.java │ ├── PhyData.java │ ├── PhyParseException.java │ └── package.html │ └── registry │ ├── BlobDword.java │ ├── BlobFolder.java │ ├── BlobNode.java │ ├── BlobParseFailure.java │ ├── BlobRaw.java │ ├── BlobText.java │ ├── BlobValue.java │ ├── CdrParser.java │ ├── CellCollection.java │ ├── CellItem.java │ ├── ClientRegistry.java │ ├── RegParser.java │ └── package.html ├── hl2parse-common ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── technofovea │ │ │ └── hl2parse │ │ │ ├── JxPathUtil.java │ │ │ ├── entdata │ │ │ ├── DefaultPathFixer.java │ │ │ ├── DependencyFinder.java │ │ │ ├── EntdataException.java │ │ │ ├── MapEntity.java │ │ │ ├── PathFixer.java │ │ │ ├── ValueSource.java │ │ │ └── package.html │ │ │ ├── fgd │ │ │ ├── ChoicesValue.java │ │ │ ├── FgdEntClass.java │ │ │ ├── FgdInput.java │ │ │ ├── FgdOutput.java │ │ │ ├── FgdProperty.java │ │ │ ├── FgdSpec.java │ │ │ ├── FlagValue.java │ │ │ ├── VisGroup.java │ │ │ └── package.html │ │ │ ├── vdf │ │ │ ├── GameConfigReader.java │ │ │ ├── GameInfoReader.java │ │ │ ├── MaterialReader.java │ │ │ ├── ParticleManifestReader.java │ │ │ ├── PropDataReader.java │ │ │ ├── SoundScapeReader.java │ │ │ ├── SteamMetaReader.java │ │ │ ├── VdfAttribute.java │ │ │ ├── VdfNode.java │ │ │ ├── VdfRoot.java │ │ │ └── package.html │ │ │ └── xml │ │ │ ├── MaterialRefList.java │ │ │ └── MaterialReference.java │ └── resources │ │ └── com │ │ └── technofovea │ │ └── hl2parse │ │ └── vdf │ │ └── DefaultMaterials.xml │ └── test │ └── resources │ └── log4j.xml ├── hl2parse-parsers ├── pom.xml └── src │ └── main │ ├── antlr3 │ └── com │ │ └── technofovea │ │ └── hl2parse │ │ ├── fgd │ │ └── ForgeGameData.g │ │ └── vdf │ │ ├── SloppyParser.g │ │ └── ValveTokenLexer.g │ └── java │ └── com │ └── technofovea │ └── hl2parse │ ├── ParserException.java │ └── fgd │ ├── DefaultLoader.java │ └── FgdLoader.java ├── hl2parse-tests ├── pom.xml └── src │ └── test │ ├── java │ └── com │ │ └── technofovea │ │ └── hl2parse │ │ ├── bsp │ │ └── BspParseTest.java │ │ ├── entdata │ │ └── EntityProcessingTest.java │ │ ├── fgd │ │ ├── BaselineTest.java │ │ └── CombinationTest.java │ │ ├── mdl │ │ └── ModelDataTest.java │ │ ├── registry │ │ └── ClientRegistryTest.java │ │ ├── vdf │ │ └── ParseTest.java │ │ └── xml │ │ └── XmlTest.java │ └── resources │ ├── com │ └── technofovea │ │ └── hl2parse │ │ ├── bsp │ │ ├── test_bsp_parse.bsp │ │ ├── test_bsp_parse.log │ │ ├── test_bsp_parse.vmf │ │ └── test_bsp_parse.vmx │ │ ├── entdata │ │ ├── base.fgd │ │ ├── ctf_2fort.ent │ │ └── tf.fgd │ │ ├── fgd │ │ ├── cyclic1.fgd │ │ ├── cyclic2.fgd │ │ ├── imported1.fgd │ │ ├── imported2.fgd │ │ ├── importer.fgd │ │ ├── inherit_test.fgd │ │ └── overall.fgd │ │ ├── mdl │ │ ├── buoy_ref.mdl │ │ └── buoy_ref.phy │ │ ├── utest.bsp │ │ └── vdf │ │ ├── Cloud001c.vmt │ │ ├── GameConfig.txt │ │ ├── SteamAppData.vdf │ │ ├── ammo_red_bg.vmt │ │ ├── blendcobbletocobblesnow001.vmt │ │ ├── blue001.vmt │ │ ├── brickwall001.vmt │ │ ├── bubble.vmt │ │ ├── computerwall005.vmt │ │ ├── cp_dustbowl.ent │ │ ├── detailsprites_2fort.vmt │ │ ├── dirtroad001.vmt │ │ ├── dispenser.vmt │ │ ├── dota_english.txt │ │ ├── glasswindow001a.vmt │ │ ├── particle_rockettrail1.vmt │ │ ├── particles_manifest.txt │ │ ├── pl_goldrush.ent │ │ ├── scorch1.vmt │ │ ├── soundscapes_2fort.txt │ │ ├── tf2_gameinfo.txt │ │ ├── toolstrigger.vmt │ │ ├── utest.ent │ │ ├── water_2fort.vmt │ │ └── water_2fort_beneath.vmt │ └── log4j.xml ├── license_header.txt ├── pom.xml └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | hl2parse-*/target/** 2 | hl2parse-*/apidocs/** 3 | -------------------------------------------------------------------------------- /hl2parse-binary/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.technofovea 7 | hl2parse 8 | 1.2.2-SNAPSHOT 9 | 10 | 11 | hl2parse-binary 12 | hl2parse-binary 13 | 14 | 15 | 16 | 17 | 18 | 19 | com.technofovea 20 | hl2parse-common 21 | compile 22 | 23 | 24 | 25 | junit 26 | junit 27 | test 28 | 29 | 30 | 31 | org.slf4j 32 | slf4j-api 33 | 34 | 35 | 36 | org.slf4j 37 | slf4j-log4j12 38 | 39 | 40 | 41 | 42 | ${basedir}/.. 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/OffsetBuffer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse; 14 | 15 | import java.nio.ByteBuffer; 16 | import java.nio.ByteOrder; 17 | 18 | 19 | /** 20 | * This class manages a buffer which is a slice from a parent buffer. The main 21 | * benefit is that it remembers its own offset, which is useful for debugging. 22 | * 23 | * Note that this class sets the resulting child buffers to little-endian. 24 | * @author Darien Hager 25 | */ 26 | public class OffsetBuffer { 27 | 28 | /** 29 | * The parent buffer 30 | */ 31 | protected ByteBuffer parent; 32 | /** 33 | * The offset in the parent at which the child buffer begins 34 | */ 35 | protected int parentOffset; 36 | /** 37 | * The created child buffer which is a view of the parent 38 | */ 39 | protected ByteBuffer buf; 40 | 41 | 42 | /** 43 | * Creates and manages a new sliced "view" of a buffer. 44 | * 45 | * @param parent The parent buffer to create a sliced view of. 46 | * @param parentOffset The offset at which to start the slice 47 | * @param len The length of the slice 48 | */ 49 | public OffsetBuffer(ByteBuffer parent, int parentOffset, int len) { 50 | this.parent = parent; 51 | this.parentOffset = parentOffset; 52 | 53 | int pos = parent.position(); 54 | int lim = parent.limit(); 55 | 56 | parent.position(parentOffset); 57 | parent.limit(parentOffset+len); 58 | this.buf = parent.slice(); 59 | parent.position(pos); 60 | parent.limit(lim); 61 | 62 | this.buf.order(ByteOrder.LITTLE_ENDIAN); 63 | 64 | } 65 | 66 | 67 | 68 | /** 69 | * Get the child-buffer being managed by this object. This buffer 70 | * will generally be in little-endian mode. 71 | * @return A buffer which is a view of the parent 72 | */ 73 | public ByteBuffer getBuf() { 74 | return buf; 75 | } 76 | 77 | /** 78 | * Gets the original parent buffer 79 | * @return The parent buffer 80 | */ 81 | public ByteBuffer getParent() { 82 | return parent; 83 | } 84 | 85 | /** 86 | * Retrieves the offset in the parent buffer at which the child buffer begins. 87 | * @return A position within the parent buffer 88 | */ 89 | public int getParentOffset() { 90 | return parentOffset; 91 | } 92 | /** 93 | * Retrieves the position in the parent buffer which corresponds to 94 | * the current position of the child buffer, taking the offset into account. 95 | * @return A position in the parent buffer 96 | */ 97 | public int getAbsolutePosition(){ 98 | return parentOffset + buf.position(); 99 | } 100 | 101 | 102 | } 103 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/ParseUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse; 14 | 15 | 16 | 17 | import java.io.File; 18 | import java.io.FileInputStream; 19 | import java.io.IOException; 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | import java.nio.MappedByteBuffer; 23 | import java.nio.channels.FileChannel; 24 | import java.util.Arrays; 25 | import java.util.BitSet; 26 | 27 | /** 28 | * Miscellaneous utilities for parsing both binary and text-based files. 29 | * @author Darien Hager 30 | */ 31 | public class ParseUtil { 32 | 33 | /** 34 | * The null byte terminator used in C-style strings 35 | */ 36 | public static final int NULL_TERMINATOR = 0x00; 37 | static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); 38 | 39 | /** 40 | * Given an integer value, reinterpret it as a string stored in four bytes. 41 | * 42 | * This is useful for a few places where developers have chosen integer IDs 43 | * which map to a human-readable mnemonic value. 44 | * 45 | * @param i The integer to interpret 46 | * @param reversed True for big-endian, false for little-endian 47 | * @return A string representation of the integer 48 | */ 49 | public static String toAscii(int i, boolean reversed) { 50 | byte[] bytes = new byte[4]; 51 | if (!reversed) { 52 | bytes[0] = (byte) (i >> 24); 53 | bytes[1] = (byte) ((i << 8) >> 24); 54 | bytes[2] = (byte) ((i << 16) >> 24); 55 | bytes[3] = (byte) ((i << 24) >> 24); 56 | } else { 57 | bytes[3] = (byte) (i >> 24); 58 | bytes[2] = (byte) ((i << 8) >> 24); 59 | bytes[1] = (byte) ((i << 16) >> 24); 60 | bytes[0] = (byte) ((i << 24) >> 24); 61 | } 62 | return new String(bytes); 63 | } 64 | 65 | /** 66 | * Given an array of bytes, return a string of hexadecimal characters. 67 | * @param bytes The byte array to interpret 68 | * @return A series of (upper-cased) hexadecimal characters, without any leading values such as 0x 69 | */ 70 | public static String toHex(byte[] bytes) { 71 | StringBuilder sb = new StringBuilder(); 72 | for (byte b : bytes) { 73 | sb.append(HEX_CHARS[(b & 0xF0) >>> 4]); 74 | sb.append(HEX_CHARS[b & 0x0F]); 75 | } 76 | 77 | return sb.toString(); 78 | } 79 | 80 | public static String toHex(byte b){ 81 | return toHex(new byte[]{b}); 82 | } 83 | 84 | /** 85 | * Interprets the bytes inside the given buffer as a hexadecimal string. 86 | * 87 | * The data in the buffer between its position and limit will be used, and the position will 88 | * be restored to its original value afterwards. 89 | * 90 | * @param buf The buffer to interpret, using the data between its position and limit. 91 | * @return A string of (upper-cased) hexadecimal, with no leading prefix (ex. 0x) 92 | */ 93 | public static String toHex(ByteBuffer buf) { 94 | int orig = buf.position(); 95 | StringBuilder sb = new StringBuilder(); 96 | while (buf.remaining() > 0) { 97 | byte b = buf.get(); 98 | sb.append(HEX_CHARS[(b & 0xF0) >>> 4]); 99 | sb.append(HEX_CHARS[b & 0x0F]); 100 | } 101 | 102 | buf.position(orig); 103 | return sb.toString(); 104 | } 105 | 106 | /** 107 | * Reads a null-terminated string from the current position of the given bytebuffer. 108 | * @param bb ByteBuffer to read from 109 | * @param limit The maximum number of characters to read before giving up. 110 | * @return The ASCII string that was found 111 | */ 112 | public static String readString(ByteBuffer bb, int limit) { 113 | int max = Math.min(limit, bb.remaining()); 114 | byte[] name = new byte[max]; 115 | bb.get(name); 116 | return readString(name, max); 117 | } 118 | 119 | /** 120 | * Reads a null-terminated string from the current position of the given byte array. 121 | * @param buf ByteBuffer to read from 122 | * @param limit The maximum number of characters to read before giving up. 123 | * @return The ASCII string that was found 124 | */ 125 | public static String readString(byte[] buf, int limit) { 126 | int max = Math.min(limit, buf.length); 127 | int firstnull = max; 128 | for (int i = 0; i 129 | < buf.length; i++) { 130 | if (buf[i] == NULL_TERMINATOR) { 131 | firstnull = i; 132 | break; 133 | 134 | } 135 | } 136 | return new String(Arrays.copyOf(buf, firstnull)); 137 | } 138 | 139 | /** 140 | * Maps the given file into memory and returns a representative buffer. 141 | * @param target The file to load 142 | * @return A read-only buffer of corresponding data in little-endian mode. 143 | * @throws IOException If an error occurred accessing or mapping the file. 144 | */ 145 | public static MappedByteBuffer mapFile(File target) throws IOException { 146 | FileInputStream fos = new FileInputStream(target); 147 | FileChannel fc = fos.getChannel(); 148 | MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, target.length()); 149 | mbb.order(ByteOrder.LITTLE_ENDIAN); 150 | return mbb; 151 | } 152 | 153 | /** 154 | * Reads a series of bytes from the given buffer, turning them into a 155 | * little-endian bit-set. The ByteBuffer's position is advanced appropriately. 156 | * 157 | * Thus the three-byte series of 10000001,00001000,00000000 has set flags 158 | * at positions 0,7, and 11 159 | * @param bb ByteBuffer to read from 160 | * @param numbytes Number of bytes to read. 161 | * @return A new BitSet with the correct areas set/unset 162 | */ 163 | public static BitSet readBitset(ByteBuffer bb, int numbytes) { 164 | byte[] barr = new byte[numbytes]; 165 | 166 | bb.get(barr); 167 | BitSet ret = new BitSet(numbytes * 8); 168 | 169 | for (int i_byte = 0; i_byte < barr.length; i_byte++) { 170 | for (int i = 0; i < 8; i++) { 171 | int idx = i_byte*8 + i; 172 | boolean isSet = (barr[i_byte] & (1 << i) )>0; 173 | ret.set(idx,isSet); 174 | } 175 | } 176 | return ret; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/Vector3f.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse; 14 | 15 | import java.nio.BufferUnderflowException; 16 | import java.nio.ByteBuffer; 17 | import java.nio.ByteOrder; 18 | 19 | /** 20 | * Utility class to represent 12-byte vectors 21 | * @author Darien Hager 22 | */ 23 | public class Vector3f { 24 | 25 | static final int BYTELEN = 4; 26 | static final int NUMVALS = 3; 27 | 28 | float x; 29 | float y; 30 | float z; 31 | 32 | /** 33 | * Creates a new object, attempting to draw from data in the given buffer. 34 | * @param b The buffer that data will be read from. The buffer's position 35 | * value will be changed when the constructor completes. 36 | * @throws BufferUnderflowException If the buffer does not have enough data availible. 37 | */ 38 | public Vector3f(ByteBuffer b) { 39 | super(); 40 | byte[] backing = new byte[NUMVALS*BYTELEN]; 41 | b.get(backing); 42 | 43 | ByteBuffer temp = ByteBuffer.wrap(backing); 44 | temp.order(ByteOrder.LITTLE_ENDIAN); 45 | 46 | x = temp.getFloat(); 47 | y = temp.getFloat(); 48 | z = temp.getFloat(); 49 | 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return x + ", " + y + ", " + z; 55 | } 56 | 57 | public String toStringRounded() { 58 | return Math.round(x) + ", " + Math.round(y) + ", " + Math.round(z); 59 | } 60 | 61 | public byte[] toBytes() { 62 | byte[] backing = new byte[NUMVALS*BYTELEN]; 63 | ByteBuffer b = ByteBuffer.wrap(backing); 64 | b.putFloat(x); 65 | b.putFloat(y); 66 | b.putFloat(z); 67 | return backing; 68 | } 69 | 70 | public float getX() { 71 | return x; 72 | } 73 | 74 | public float getY() { 75 | return y; 76 | } 77 | 78 | public float getZ() { 79 | return z; 80 | } 81 | 82 | public void setX(float x) { 83 | this.x = x; 84 | } 85 | 86 | public void setY(float y) { 87 | this.y = y; 88 | } 89 | 90 | public void setZ(float z) { 91 | this.z = z; 92 | } 93 | 94 | 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/bsp/BinaryBspAnalyzer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.bsp; 14 | 15 | import com.technofovea.hl2parse.OffsetBuffer; 16 | import com.technofovea.hl2parse.ParseUtil; 17 | import java.nio.BufferUnderflowException; 18 | import java.nio.ByteBuffer; 19 | import java.nio.ByteOrder; 20 | import java.util.Arrays; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | /** 25 | * This class serves as a base for writing classes which interpret the venerable BSP map format. 26 | * @todo Refactor into factory methods 27 | * @author Darien Hager 28 | */ 29 | public abstract class BinaryBspAnalyzer { 30 | 31 | private static final Logger logger = LoggerFactory.getLogger(BinaryBspAnalyzer.class); 32 | /** 33 | * The buffer (probably mapped) which represents the whole file data. 34 | * Should be read-only and little-endian. 35 | */ 36 | protected ByteBuffer coreBuffer; 37 | /** 38 | * The version code found within the map 39 | */ 40 | protected int version; 41 | /** 42 | * Header data for each of the BSP lumps 43 | */ 44 | protected BspLumpHeader[] lumps; 45 | 46 | /** 47 | * Creates a new analyzer against the given bytebuffer. 48 | * @param bb The data to analyze, from the current position to the limit 49 | * @throws BspParseException If there were any errors parsing 50 | */ 51 | public BinaryBspAnalyzer(ByteBuffer bb) throws BspParseException { 52 | logger.debug("Processing map data ({} bytes)", bb.remaining()); 53 | 54 | coreBuffer = bb.asReadOnlyBuffer(); 55 | coreBuffer.order(ByteOrder.LITTLE_ENDIAN); 56 | 57 | try { 58 | loadBasic(); 59 | } catch (BufferUnderflowException bue) { 60 | throw new BspParseException(bue); 61 | } 62 | } 63 | 64 | private void loadBasic() throws BspParseException { 65 | final int num_lumps = getNumLumps(); 66 | final byte[] expected_hdr = getInitialHeader(); 67 | lumps = new BspLumpHeader[num_lumps]; 68 | byte[] hdr = new byte[expected_hdr.length]; 69 | 70 | coreBuffer.get(hdr); 71 | if (!Arrays.equals(hdr, expected_hdr)) { 72 | String hexHdr = ParseUtil.toHex(hdr); 73 | String hexExpected = ParseUtil.toHex(expected_hdr); 74 | throw new BspParseException("File does not begin with expected header. Expected "+hexExpected+" but got "+hexHdr); 75 | } 76 | 77 | int versionNumber = coreBuffer.getInt(); 78 | logger.debug("Map version is {}", versionNumber); 79 | if (!handlesVersion(versionNumber)) { 80 | throw new BspParseException("Cannot handle file format version " + versionNumber); 81 | } 82 | version = versionNumber; 83 | 84 | for (int i = 0; i < getNumLumps(); i++) { 85 | logger.trace("Loading lump header #{}", i); 86 | lumps[i] = new BspLumpHeader(coreBuffer); 87 | } 88 | 89 | 90 | 91 | } 92 | 93 | /** 94 | * Get a buffer containing the payload data for the given lump. 95 | * @param lumpNum The lump to retrieve 96 | * @return The data, or null if the given lump does not exist 97 | */ 98 | protected OffsetBuffer getLumpData(int lumpNum) { 99 | if (lumpNum < 0 || lumpNum >= lumps.length) { 100 | logger.error("BSP lump {} was out-of-range and could not be found", lumpNum); 101 | return null; 102 | } 103 | BspLumpHeader l = lumps[lumpNum]; 104 | 105 | return new OffsetBuffer(coreBuffer, l.getOffset(), l.getLength()); 106 | } 107 | 108 | /** 109 | * Checks whether a given BSP version is supported by this analyzer 110 | * @param version The version number to check 111 | * @return True if supported, false otherwise 112 | */ 113 | protected abstract boolean handlesVersion(int version); 114 | 115 | /** 116 | * Get the number of lumps expected in this file 117 | * @return The number of lumps which are supported 118 | */ 119 | protected abstract int getNumLumps(); 120 | 121 | /** 122 | * Get the expected header for the file 123 | * @return The bytes expected 124 | */ 125 | protected abstract byte[] getInitialHeader(); 126 | } 127 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/bsp/BspLumpHeader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.bsp; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | /** 18 | * Stores header information for a BSP lump 19 | * @author Darien Hager 20 | */ 21 | public class BspLumpHeader { 22 | 23 | //TODO handle the reordering in Version 21 L4d 24 | /** 25 | * The length of the lump identifier bytes 26 | */ 27 | protected static int IDENT_LEN = 4; 28 | /** 29 | * The offset of the game lump within the data 30 | */ 31 | protected int offset; 32 | /** 33 | * The length of the game lump 34 | */ 35 | protected int length; 36 | /** 37 | * The version number for the game lump 38 | */ 39 | protected int version; 40 | /** 41 | * The identity code given to this lump 42 | */ 43 | protected byte[] identCode = new byte[IDENT_LEN]; 44 | 45 | /** 46 | * Creates a new BspLumpHeader, drawing from the given buffer 47 | * @param lumpData The buffer to be read from. On success, the buffer's position will have been advanced. 48 | * @throws BspParseException If the lump header is invalid. 49 | */ 50 | public BspLumpHeader(ByteBuffer lumpData) throws BspParseException { 51 | final int originalPosition = lumpData.position(); 52 | boolean resetPosition = true; 53 | 54 | try { 55 | offset = lumpData.getInt(); 56 | length = lumpData.getInt(); 57 | version = lumpData.getInt(); 58 | lumpData.get(identCode); 59 | 60 | if (offset < 0) { 61 | throw new BspParseException("Lump header has negative offset"); 62 | } 63 | if (length < 0) { 64 | throw new BspParseException("Lump header has negative length"); 65 | } 66 | resetPosition = false; // Success, no need to reset 67 | 68 | } finally { 69 | if (resetPosition) { 70 | lumpData.position(originalPosition); 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * Retrieves the lump identifier bytes 77 | * @return A series of bytes of length {@link #IDENT_LEN} 78 | */ 79 | public byte[] getIdentCode() { 80 | return identCode; 81 | } 82 | 83 | /** 84 | * Get the length of the data this header refers to 85 | * @return The data length in bytes 86 | */ 87 | public int getLength() { 88 | return length; 89 | } 90 | 91 | /** 92 | * Get the offset of the data this header refers to, relative 93 | * to the start of the BSP file 94 | * @return The offset at which this lump's data begins 95 | */ 96 | public int getOffset() { 97 | return offset; 98 | } 99 | 100 | /** 101 | * Get the version number associated with this lump 102 | * @return A version number 103 | */ 104 | public int getVersion() { 105 | return version; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/bsp/BspParseException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.bsp; 14 | 15 | /** 16 | * Thrown to indicate that a problem has occurred while parsing the binary data 17 | * of a BSP file or subsections within it. 18 | * 19 | * @author Darien Hager 20 | */ 21 | public class BspParseException extends Exception { 22 | 23 | public BspParseException(Throwable cause) { 24 | super(cause); 25 | } 26 | 27 | public BspParseException(String message, Throwable cause) { 28 | super(message, cause); 29 | } 30 | 31 | public BspParseException(String message) { 32 | super(message); 33 | } 34 | 35 | public BspParseException() { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/bsp/GameLumpHeader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.bsp; 14 | 15 | import com.technofovea.hl2parse.ParseUtil; 16 | import java.nio.ByteBuffer; 17 | import java.util.Arrays; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | /** 22 | * Holds metadata about a "game lump", not to be confused with a {@link BspLumpHeader}, 23 | * game lumps are one more level of abstraction and are found within a BSP lump. 24 | * 25 | * @author Darien Hager 26 | */ 27 | public class GameLumpHeader { 28 | 29 | private static final Logger logger = LoggerFactory.getLogger(GameLumpHeader.class); 30 | private int offset; 31 | private int length; 32 | private short version; 33 | private short flags; 34 | private final int id; 35 | 36 | /** 37 | * Attempts to create a new object from header data in the given bytebuffer. 38 | * @param lumpSection The buffer to be read from. On success, the buffer's position will have been advanced. 39 | * @throws BspParseException If an error occurred while processing. 40 | */ 41 | public GameLumpHeader(ByteBuffer lumpSection) throws BspParseException { 42 | final int originalPosition = lumpSection.position(); 43 | boolean resetPosition = true; 44 | try { 45 | id = lumpSection.getInt(); 46 | flags = lumpSection.getShort(); 47 | version = lumpSection.getShort(); 48 | offset = lumpSection.getInt(); 49 | length = lumpSection.getInt(); 50 | 51 | if (offset < 0) { 52 | throw new BspParseException("Game lump header has negative offset"); 53 | } 54 | if (length < 0) { 55 | throw new BspParseException("Game lump header has negative length"); 56 | } 57 | 58 | if (logger.isDebugEnabled()) { 59 | String hexName = ParseUtil.toAscii(id, true); 60 | logger.debug("Game-lump created. ID {} ({}), version {}, offset {}, length {}", new Object[]{id, hexName, version, offset, length}); 61 | } 62 | resetPosition = false; // Success, no need to reset 63 | } finally { 64 | if (resetPosition) { 65 | lumpSection.position(originalPosition); 66 | } 67 | } 68 | } 69 | 70 | /** 71 | * Turns a "nice" 4-character string name for a game lump into a game lump ID. 72 | * The ID is little-endian, meaning "prps" is reversed before becoming "1936749168" 73 | * @param str String to convert, should be 4 characters or less. 74 | * @return The integer value, or -1 on error 75 | */ 76 | public static int stringToId(String str) { 77 | if (str.length() > 4) { 78 | logger.error("Game-lump 'hex label' was greater than four digits: " + str); 79 | return -1; 80 | } 81 | StringBuilder sb = new StringBuilder(str); 82 | sb.reverse(); 83 | byte[] bytes = sb.toString().getBytes(); 84 | if (bytes.length < 4) { 85 | //TODO verify that it adds zero to the correct end of the byte array 86 | bytes = Arrays.copyOf(bytes, 4); 87 | } 88 | ByteBuffer temp = ByteBuffer.wrap(bytes); 89 | return temp.getInt(); 90 | 91 | } 92 | 93 | /** 94 | * Get the length of the data this header refers to 95 | * @return The data length in bytes 96 | */ 97 | public int getLength() { 98 | return length; 99 | } 100 | 101 | /** 102 | * Get the offset within the game-lump of the data this refers to 103 | * @return The offset in bytes 104 | */ 105 | public int getOffset() { 106 | return offset; 107 | } 108 | 109 | /** 110 | * Get the version of the game-lump 111 | * @return A version number 112 | */ 113 | public short getVersion() { 114 | return version; 115 | } 116 | 117 | /** 118 | * Get any flags associated with this game-lump 119 | * @return Flags, represented as a single number 120 | */ 121 | public short getFlags() { 122 | return flags; 123 | } 124 | 125 | /** 126 | * Get the game-lump's numeric ID 127 | * @return The ID 128 | */ 129 | public int getId() { 130 | return id; 131 | } 132 | 133 | @Override 134 | public boolean equals(Object obj) { 135 | if (obj == null) { 136 | return false; 137 | } 138 | if (getClass() != obj.getClass()) { 139 | return false; 140 | } 141 | final GameLumpHeader other = (GameLumpHeader) obj; 142 | if (this.offset != other.offset) { 143 | return false; 144 | } 145 | if (this.length != other.length) { 146 | return false; 147 | } 148 | if (this.version != other.version) { 149 | return false; 150 | } 151 | if (this.flags != other.flags) { 152 | return false; 153 | } 154 | if (this.id != other.id) { 155 | return false; 156 | } 157 | return true; 158 | } 159 | 160 | @Override 161 | public int hashCode() { 162 | int hash = 7; 163 | hash = 73 * hash + this.offset; 164 | hash = 73 * hash + this.length; 165 | hash = 73 * hash + this.version; 166 | hash = 73 * hash + this.flags; 167 | hash = 73 * hash + this.id; 168 | return hash; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/bsp/GamePropSection.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.bsp; 14 | 15 | import com.technofovea.hl2parse.Vector3f; 16 | import java.nio.ByteBuffer; 17 | 18 | /** 19 | * Parses and encapsulates data for an item in the "props" game-lump, allowing access 20 | * to information about "static" props which are compiled into 21 | * the map. 22 | * 23 | * @author Darien Hager 24 | */ 25 | public class GamePropSection { 26 | 27 | private Vector3f origin; 28 | private Vector3f rotation; 29 | private int propNameIndex; 30 | private int firstLeaf; 31 | private int leafCount; 32 | private byte solid; 33 | private byte flags; 34 | private int skin; 35 | private float fadeMinDist; 36 | private float fadeMaxDist; 37 | private Vector3f lightingOrigin; 38 | private float forcedFadeScale = 0f; 39 | private byte[] unknown1 = new byte[4]; 40 | 41 | /** 42 | * Creates a new game-prop entry by pulling data from the given buffer. 43 | * 44 | * @param hdr The header file to use for version information 45 | * @param buf The game-lump data to parse from. When finished the buffer's 46 | * position should already be advanced to the next prop or to the end. 47 | */ 48 | public GamePropSection(GameLumpHeader hdr, ByteBuffer buf) { 49 | 50 | origin = new Vector3f(buf); 51 | rotation = new Vector3f(buf); // Actually a euler rotation 52 | propNameIndex = buf.getShort(); 53 | firstLeaf = buf.getShort(); 54 | leafCount = buf.getShort(); 55 | solid = buf.get(); 56 | flags = buf.get(); 57 | 58 | skin = buf.getInt(); 59 | fadeMinDist = buf.getFloat(); 60 | fadeMaxDist = buf.getFloat(); 61 | 62 | lightingOrigin = new Vector3f(buf); 63 | if (hdr.getVersion() >= 5) { 64 | forcedFadeScale = buf.getFloat(); 65 | } 66 | if (hdr.getVersion() >= 6) { 67 | buf.get(unknown1); 68 | } 69 | } 70 | 71 | /** 72 | * Gets the maximum fade distance 73 | * @return The distance at which this prop completely fades out 74 | */ 75 | public float getFadeMaxDist() { 76 | return fadeMaxDist; 77 | } 78 | 79 | /** 80 | * Gets the minimum fade distance 81 | * @return The distance at which this prop begins to fade out. 82 | */ 83 | public float getFadeMinDist() { 84 | return fadeMinDist; 85 | } 86 | 87 | public int getFirstLeaf() { 88 | return firstLeaf; 89 | } 90 | 91 | /** 92 | * Retrieves any flags associated with this prop as a byte 93 | * @return A byte representing eight boolean flags. 94 | */ 95 | public byte getFlags() { 96 | return flags; 97 | } 98 | 99 | public float getForcedFadeScale() { 100 | return forcedFadeScale; 101 | } 102 | 103 | public int getLeafCount() { 104 | return leafCount; 105 | } 106 | 107 | public Vector3f getLightingOrigin() { 108 | return lightingOrigin; 109 | } 110 | 111 | /** 112 | * Get the origin of the prop 113 | * @return The origin in X,Y,Z coordinates 114 | */ 115 | public Vector3f getOrigin() { 116 | return origin; 117 | } 118 | 119 | /** 120 | * Get the index number used for identifying this prop among the list of 121 | * names embedded elsewhere in the file. 122 | * @return The index ID for this prop within a map 123 | */ 124 | public int getPropNameIndex() { 125 | return propNameIndex; 126 | } 127 | 128 | public Vector3f getRotation() { 129 | return rotation; 130 | } 131 | 132 | /** 133 | * Get the skin ID associated with this prop 134 | * @return A zero-indexed skin ID 135 | */ 136 | public int getSkin() { 137 | return skin; 138 | } 139 | 140 | public byte getSolid() { 141 | return solid; 142 | } 143 | 144 | public byte[] getUnknown1() { 145 | return unknown1; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/bsp/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Contains classes for interpreting binary data in Source maps. 4 | 5 | These classes are geared towards reading information about static props and 6 | brush textures. 7 | 8 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/mdl/ModelFlag.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.mdl; 14 | 15 | /** 16 | * 17 | * @author Darien Hager 18 | */ 19 | public enum ModelFlag { 20 | 21 | /** 22 | * This flag is set if no hitbox information was specified 23 | */ 24 | STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX(0), 25 | /** 26 | * NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild 27 | * models when we change materials. 28 | */ 29 | STUDIOHDR_FLAGS_USES_ENV_CUBEMAP(1), 30 | /** 31 | * Use this when there are translucent parts to the model but we're not going to sort it 32 | */ 33 | STUDIOHDR_FLAGS_FORCE_OPAQUE(2), 34 | /** 35 | * Use this when we want to render the opaque parts during the opaque pass 36 | * and the translucent parts during the translucent pass 37 | */ 38 | STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS(3), 39 | /** 40 | * This is set any time the .qc files has $staticprop in it 41 | * Means there's no bones and no transforms 42 | */ 43 | STUDIOHDR_FLAGS_STATIC_PROP(4), 44 | /** 45 | * NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild 46 | * models when we change materials. 47 | */ 48 | STUDIOHDR_FLAGS_USES_FB_TEXTURE(5), 49 | /** 50 | * This flag is set by studiomdl.exe if a separate "$shadowlod" entry was present 51 | * for the .mdl (the shadow lod is the last entry in the lod list if present) 52 | */ 53 | STUDIOHDR_FLAGS_HASSHADOWLOD(6), 54 | /** 55 | * NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild 56 | * models when we change materials. 57 | */ 58 | STUDIOHDR_FLAGS_USES_BUMPMAPPING(7), 59 | /** 60 | * NOTE: This flag is set when we should use the actual materials on the shadow LOD 61 | * instead of overriding them with the default one (necessary for translucent shadows) 62 | */ 63 | STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS(8), 64 | /** 65 | * NOTE: This flag is set when we should use the actual materials on the shadow LOD 66 | * instead of overriding them with the default one (necessary for translucent shadows) 67 | */ 68 | STUDIOHDR_FLAGS_OBSOLETE(9), 69 | STUDIOHDR_FLAGS_UNUSED(10), 70 | /** 71 | * NOTE: This flag is set at mdl build time 72 | */ 73 | STUDIOHDR_FLAGS_NO_FORCED_FADE(11), 74 | /** 75 | * NOTE: The npc will lengthen the viseme check to always include two phonemes 76 | */ 77 | STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE(12), 78 | /** 79 | * This flag is set when the .qc has $constantdirectionallight in it 80 | * If set, we use constantdirectionallightdot to calculate light intensity 81 | * rather than the normal directional dot product 82 | * only valid if STUDIOHDR_FLAGS_STATIC_PROP is also set 83 | */ 84 | STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT(13), 85 | /** 86 | * Flag to mark delta flexes as already converted from disk format to memory format 87 | */ 88 | STUDIOHDR_FLAGS_FLEXES_CONVERTED(14), 89 | /** 90 | * Indicates the studiomdl was built in preview mode 91 | */ 92 | STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE(15), 93 | /** 94 | * Ambient boost (runtime flag) 95 | */ 96 | STUDIOHDR_FLAGS_AMBIENT_BOOST(16), 97 | /** 98 | * Don't cast shadows from this model (useful on first-person models) 99 | */ 100 | STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS(17), 101 | /** 102 | * alpha textures should cast shadows in vrad on this model (ONLY prop_static!) 103 | */ 104 | STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS(18),; 105 | private int bitIndex; 106 | 107 | private ModelFlag(int bitIndex) { 108 | this.bitIndex = bitIndex; 109 | } 110 | 111 | public int getBitIndex() { 112 | return bitIndex; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/mdl/ModelParseException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.mdl; 14 | 15 | /** 16 | * 17 | * @author Darien Hager 18 | */ 19 | public class ModelParseException extends Exception { 20 | 21 | public ModelParseException(Throwable cause) { 22 | super(cause); 23 | } 24 | 25 | public ModelParseException(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public ModelParseException(String message) { 30 | super(message); 31 | } 32 | 33 | public ModelParseException() { 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/mdl/ModelSection.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.mdl; 14 | 15 | /** 16 | * Enumerates various sections within a model MDL file 17 | * @author Darien Hager 18 | */ 19 | public enum ModelSection { 20 | 21 | BONE, 22 | BONECONTROLLER, 23 | HITBOXSET, 24 | LOCALANIM, 25 | LOCALSEQ, 26 | TEXTURE, 27 | CDTEXTURE, 28 | SKIN, 29 | BODYPART, 30 | LOCALATTACHMENT, 31 | LOCALNODE, 32 | LOCALNODENAME, 33 | FLEXDESC, 34 | FLEXCONTROLLER, 35 | FLEXRULE, 36 | IKCHAIN, 37 | MOUTH, 38 | LOCALPOSEPARAM, 39 | SURFACEPROP, 40 | KEYVALUE, 41 | LOCALIKAUTOPLAYLOCK, 42 | INCLUDEMODEL, 43 | SZANIMBLOCKNAME, 44 | ANIMBLOCK, 45 | BONETABLEBYNAME, 46 | UNUSED4, 47 | FLEXCONTROLLERUI, 48 | STUDIOHDR2, 49 | 50 | ; 51 | } 52 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/mdl/PhyData.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | 14 | package com.technofovea.hl2parse.mdl; 15 | 16 | import com.technofovea.hl2parse.ParseUtil; 17 | import java.nio.BufferUnderflowException; 18 | import java.nio.ByteBuffer; 19 | import java.nio.ByteOrder; 20 | import java.nio.CharBuffer; 21 | import java.nio.charset.Charset; 22 | import java.util.BitSet; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | /** 27 | * Interprets a PHY file. 28 | * @author Darien Hager 29 | */ 30 | public class PhyData { 31 | 32 | protected static final Charset CHARSET = Charset.forName("ASCII"); 33 | private static final Logger logger = LoggerFactory.getLogger(PhyData.class); 34 | ByteBuffer bb; 35 | int id = -1; 36 | int checksum = 0; 37 | int solidCount = 0; 38 | ByteBuffer[] collisionSections = null; 39 | String propData = null; 40 | 41 | public PhyData(ByteBuffer bb) throws PhyParseException { 42 | this.bb = bb; 43 | bb.order(ByteOrder.LITTLE_ENDIAN); 44 | logger.debug("Parsing phy data, {} remaining", this.bb.remaining()); 45 | try { 46 | load(); 47 | } catch (BufferUnderflowException bue) { 48 | throw new PhyParseException(bue); 49 | } 50 | } 51 | 52 | private void load() { 53 | 54 | int hdrsize = readInt(); 55 | id = readInt(); 56 | solidCount = readInt(); 57 | checksum = bb.getInt(); 58 | 59 | int extra = (hdrsize) - bb.position(); 60 | if (extra > 0) { 61 | bb.position(bb.position() + extra); 62 | } 63 | 64 | collisionSections = new ByteBuffer[solidCount]; 65 | 66 | for (int i = 0; i < collisionSections.length; i++) { 67 | int len = bb.getInt(); 68 | int oldLimit = bb.limit(); 69 | bb.limit(bb.position() + len); 70 | ByteBuffer sectionData = bb.slice(); 71 | sectionData.order(ByteOrder.LITTLE_ENDIAN); 72 | 73 | bb.position(bb.limit()); 74 | bb.limit(oldLimit); 75 | collisionSections[i] = sectionData; 76 | } 77 | propData = ParseUtil.readString(bb, bb.remaining()); 78 | //propData = cb.toString(); 79 | 80 | 81 | 82 | 83 | } 84 | 85 | private int readShort() { 86 | return bb.getShort(); 87 | } 88 | 89 | private int readInt() { 90 | return bb.getInt(); 91 | } 92 | 93 | private byte[] readBytes(int count) { 94 | byte[] ret = new byte[count]; 95 | bb.get(ret); 96 | return ret; 97 | } 98 | 99 | private byte readByte() { 100 | return bb.get(); 101 | } 102 | 103 | private float readFloat() { 104 | return bb.getFloat(); 105 | } 106 | 107 | private String readString(int len) { 108 | return ParseUtil.readString(bb, len); 109 | } 110 | 111 | private int[] readIntArray(int size) { 112 | int[] ret = new int[size]; 113 | for (int i = 0; i < ret.length; i++) { 114 | ret[i] = bb.getInt(); 115 | } 116 | return ret; 117 | } 118 | 119 | 120 | public int getChecksum() { 121 | return checksum; 122 | } 123 | 124 | public ByteBuffer[] getCollisionSections() { 125 | return collisionSections; 126 | } 127 | 128 | public int getId() { 129 | return id; 130 | } 131 | 132 | public String getPropData() { 133 | return propData; 134 | } 135 | 136 | public int getSolidCount() { 137 | return solidCount; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/mdl/PhyParseException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.mdl; 14 | 15 | /** 16 | * 17 | * @author Darien Hager 18 | */ 19 | public class PhyParseException extends Exception { 20 | 21 | public PhyParseException(Throwable cause) { 22 | super(cause); 23 | } 24 | 25 | public PhyParseException(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public PhyParseException(String message) { 30 | super(message); 31 | } 32 | 33 | public PhyParseException() { 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/mdl/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Classes to interpret the source MDL model file format. 4 | 5 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/BlobDword.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import com.technofovea.hl2parse.ParseUtil; 16 | import java.nio.ByteBuffer; 17 | 18 | /** 19 | * 20 | * @author Darien Hager 21 | */ 22 | public class BlobDword extends BlobValue{ 23 | 24 | byte[] dword; 25 | 26 | public BlobDword(String name, ByteBuffer realValue) { 27 | super(name); 28 | dword = new byte[4]; 29 | realValue.get(dword); 30 | } 31 | 32 | @Override 33 | public DataType getType() { 34 | return DataType.DWORD; 35 | } 36 | 37 | public byte[] getDword() { 38 | return dword; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return (getName()+":"+ParseUtil.toHex(dword)); 44 | } 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/BlobFolder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import java.nio.ByteBuffer; 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | /** 20 | * 21 | * @author Darien Hager 22 | */ 23 | public class BlobFolder extends BlobNode{ 24 | 25 | public enum FolderItemType{ 26 | FOLDER(1), 27 | FILE(2); 28 | 29 | public static FolderItemType fromNumber(int typeNum){ 30 | for(FolderItemType t: FolderItemType.values()){ 31 | if(t.getNumericCode() == typeNum){ 32 | return t; 33 | } 34 | } 35 | return null; 36 | } 37 | public static FolderItemType fromDescriptor(ByteBuffer meta) { 38 | int typeNum = meta.get(); 39 | return fromNumber(typeNum); 40 | } 41 | 42 | private int num; 43 | private FolderItemType(int num) { 44 | this.num = num; 45 | } 46 | public int getNumericCode(){ 47 | return num; 48 | } 49 | 50 | } 51 | 52 | 53 | String name; 54 | Map folders = new HashMap(); 55 | Map values = new HashMap(); 56 | public BlobFolder(String name) { 57 | this.name=name; 58 | } 59 | 60 | public Map getFolders() { 61 | return folders; 62 | } 63 | 64 | public Map getValues() { 65 | return values; 66 | } 67 | 68 | public String getName() { 69 | return name; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return "{"+getName()+":"+values.toString()+","+folders.toString()+"}"; 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/BlobNode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | /** 18 | * 19 | * @author Darien Hager 20 | */ 21 | public abstract class BlobNode { 22 | 23 | ByteBuffer sourceBuffer = null; 24 | 25 | public boolean hasSourceBuffer() { 26 | return sourceBuffer != null; 27 | } 28 | 29 | //TODO write to buffer 30 | } 31 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/BlobParseFailure.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | /** 16 | * 17 | * @author Darien Hager 18 | */ 19 | public class BlobParseFailure extends Exception{ 20 | 21 | public BlobParseFailure(Throwable cause) { 22 | super(cause); 23 | } 24 | 25 | public BlobParseFailure(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public BlobParseFailure(String message) { 30 | super(message); 31 | } 32 | 33 | public BlobParseFailure() { 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/BlobRaw.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import java.lang.ref.WeakReference; 16 | import java.nio.ByteBuffer; 17 | 18 | /** 19 | * 20 | * @author Darien Hager 21 | */ 22 | public class BlobRaw extends BlobValue { 23 | 24 | ByteBuffer data; 25 | WeakReference byteVersion = null; 26 | 27 | public BlobRaw(String name, ByteBuffer realValue) { 28 | super(name); 29 | data = realValue.asReadOnlyBuffer(); 30 | 31 | } 32 | 33 | @Override 34 | public DataType getType() { 35 | return DataType.RAW; 36 | } 37 | 38 | public ByteBuffer asBuffer() { 39 | return data; 40 | } 41 | 42 | public synchronized byte[] getRaw() { 43 | byte[] cached = byteVersion.get(); 44 | if (cached != null) { 45 | return cached; 46 | } else { 47 | data.clear(); 48 | byte[] raw = new byte[data.remaining()]; 49 | data.get(raw); 50 | byteVersion = new WeakReference(raw); 51 | return raw; 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/BlobText.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | /** 18 | * 19 | * @author Darien Hager 20 | */ 21 | public class BlobText extends BlobValue{ 22 | 23 | String text; 24 | 25 | public BlobText(String name, ByteBuffer realValue) { 26 | super(name); 27 | text = RegParser.getText(realValue); 28 | } 29 | 30 | @Override 31 | public DataType getType() { 32 | return DataType.TEXT; 33 | } 34 | 35 | public String getText() { 36 | return text; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return (getName()+":"+getText()); 42 | } 43 | 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/BlobValue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | /** 18 | * 19 | * @author Darien Hager 20 | */ 21 | public abstract class BlobValue extends BlobNode { 22 | public enum DataType{ 23 | TEXT(0), 24 | DWORD(1), 25 | RAW(2); 26 | 27 | public static DataType fromNumber(int typeNum){ 28 | for(DataType t: DataType.values()){ 29 | if(t.getNumericCode() == typeNum){ 30 | return t; 31 | } 32 | } 33 | return null; 34 | } 35 | public static DataType fromDescriptor(ByteBuffer meta) { 36 | int typeNum = meta.get(); 37 | return fromNumber(typeNum); 38 | } 39 | 40 | private int num; 41 | private DataType(int num) { 42 | this.num = num; 43 | } 44 | public int getNumericCode(){ 45 | return num; 46 | } 47 | 48 | 49 | } 50 | 51 | String name; 52 | 53 | public BlobValue(String name) { 54 | this.name = name; 55 | } 56 | 57 | public abstract DataType getType(); 58 | 59 | public String getName() { 60 | return name; 61 | } 62 | 63 | 64 | 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/CellCollection.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import com.technofovea.hl2parse.registry.CellItem; 16 | import java.nio.ByteBuffer; 17 | import java.util.ArrayList; 18 | import java.util.Iterator; 19 | import java.util.List; 20 | 21 | /** 22 | * 23 | * @author Darien Hager 24 | */ 25 | public class CellCollection implements Iterable{ 26 | List items = new ArrayList(); 27 | int underflow = 0; 28 | 29 | public Iterator iterator() { 30 | return items.iterator(); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/CellItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | class CellItem { 18 | 19 | CellItem(ByteBuffer meta, ByteBuffer payload) { 20 | super(); 21 | this.meta = meta; 22 | this.payload = payload; 23 | } 24 | private ByteBuffer meta; 25 | private ByteBuffer payload; 26 | 27 | /** 28 | * @return the meta 29 | */ 30 | public ByteBuffer getMeta() { 31 | return meta; 32 | } 33 | 34 | /** 35 | * @return the payload 36 | */ 37 | public ByteBuffer getPayload() { 38 | return payload; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/ClientRegistry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import com.technofovea.hl2parse.JxPathUtil; 16 | import java.nio.ByteBuffer; 17 | import java.util.ArrayList; 18 | import java.util.Iterator; 19 | import java.util.List; 20 | import org.apache.commons.jxpath.JXPathContext; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | /** 25 | * 26 | * @author Darien Hager 27 | */ 28 | public class ClientRegistry { 29 | 30 | private static final Logger logger = LoggerFactory.getLogger(ClientRegistry.class); 31 | protected static final String CDR_SECTION_NAME = "ContentDescriptionRecord"; 32 | BlobFolder root; 33 | CdrParser cdr = null; 34 | JXPathContext ctx; 35 | 36 | public ClientRegistry(BlobFolder root) throws BlobParseFailure { 37 | this.root = root; 38 | ctx = JXPathContext.newContext(root); 39 | JxPathUtil.addFunctions(ctx); 40 | cdr = createCdr(); 41 | } 42 | 43 | CdrParser createCdr() throws BlobParseFailure { 44 | logger.debug("Finding compressed " + CDR_SECTION_NAME + " section"); 45 | BlobRaw br = (BlobRaw) ctx.getValue("/values[@name='" + CDR_SECTION_NAME + "']"); 46 | if (br == null) { 47 | throw new BlobParseFailure("Could not find " + CDR_SECTION_NAME + " segment. Check that Steam is up-to-date."); 48 | } 49 | 50 | logger.debug("Extracting compressed CDR section"); 51 | ByteBuffer expandedBuf = RegParser.decompress(br.asBuffer()); 52 | 53 | logger.debug("Creating reader for decompressed CDR data"); 54 | CdrParser cp = new CdrParser(expandedBuf); 55 | return cp; 56 | } 57 | 58 | public CdrParser getContentDescriptionRecord() { 59 | return cdr; 60 | } 61 | 62 | public JXPathContext getRootContext() { 63 | return ctx; 64 | } 65 | 66 | public List getUsernames() { 67 | logger.debug("Retrieving known Steam username(s)"); 68 | 69 | Iterator users = (Iterator) ctx.iterate("/folders[@name='_Users']/folders/*/name"); 70 | List ret = new ArrayList(); 71 | while (users.hasNext()) { 72 | ret.add(users.next()); 73 | } 74 | logger.debug("Usernames found: {}", ret); 75 | return ret; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /hl2parse-binary/src/main/java/com/technofovea/hl2parse/registry/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Classes for interpreting metadata within Steam's clientregistry.blob file. 4 | 5 | -------------------------------------------------------------------------------- /hl2parse-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.technofovea 7 | hl2parse 8 | 1.2.2-SNAPSHOT 9 | ../pom.xml 10 | 11 | 12 | hl2parse-common 13 | hl2parse-common 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | commons-jxpath 22 | commons-jxpath 23 | 24 | 25 | 26 | junit 27 | junit 28 | test 29 | 30 | 31 | 32 | org.slf4j 33 | slf4j-api 34 | 35 | 36 | org.slf4j 37 | slf4j-log4j12 38 | 39 | 40 | 41 | 42 | 43 | ${basedir}/.. 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/JxPathUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse; 14 | 15 | import org.apache.commons.jxpath.ClassFunctions; 16 | import org.apache.commons.jxpath.JXPathContext; 17 | 18 | /** 19 | * This utility class provides a few simple methods for dealing with JXPath 20 | * expressions. 21 | * 22 | * @author Darien Hager 23 | */ 24 | public class JxPathUtil { 25 | 26 | /** 27 | * Adds custom functions onto a context which correspond to 28 | * static methods on this class, such as {@link #startswith(java.lang.String, java.lang.String)} 29 | * @param context The context to alter. 30 | */ 31 | public static void addFunctions(JXPathContext context) { 32 | context.setFunctions(new ClassFunctions(JxPathUtil.class, "custom")); 33 | } 34 | 35 | /** 36 | * A convenience function, this performs a *case-insensitive* equality test, 37 | * unlike the normal [a=b] xpath convention. 38 | * @param a A string 39 | * @param b A string 40 | * @return True if the two strings are equal, ignoring case. False otherwise. 41 | */ 42 | public static boolean equals(String a, String b) { 43 | if (a == null) { 44 | return false; 45 | } 46 | return a.equalsIgnoreCase(b); 47 | } 48 | 49 | /** 50 | * This function performs a case-insensitive starts-with test. 51 | * @param s The string to examine 52 | * @param prefix The prefix to try 53 | * @return True if the first string starts with the second, ignoring case. 54 | */ 55 | public static boolean startswith(String s, String prefix) { 56 | if (s == null || prefix == null) { 57 | return false; 58 | } 59 | return s.toLowerCase().startsWith(prefix.toLowerCase()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/entdata/DefaultPathFixer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.entdata; 14 | 15 | /** 16 | * A default implementation of {@link PathFixer}, this singleton attempts to 17 | * correct material, sound, and sprite paths. In some cases the sprite/material 18 | * distinction is ambiguous, and no extension is added. 19 | * 20 | * @author Darien Hager 21 | */ 22 | public class DefaultPathFixer implements PathFixer { 23 | 24 | private static DefaultPathFixer instance; 25 | 26 | String nonPathPrefix = ":"; 27 | 28 | private DefaultPathFixer() { 29 | } 30 | 31 | /** 32 | * Get the singleton instance of this fixer 33 | * @return The singleton 34 | */ 35 | public static DefaultPathFixer getInstance() { 36 | synchronized (DefaultPathFixer.class) { 37 | if (instance == null) { 38 | instance = new DefaultPathFixer(); 39 | } 40 | } 41 | return instance; 42 | 43 | } 44 | 45 | public String fixPath(String origPath,ValueSource src) { 46 | if(DependencyFinder.PROPTYPE_MATERIAL.equalsIgnoreCase(src.getDataType())){ 47 | return fixMaterial(origPath,src); 48 | }else if(DependencyFinder.PROPTYPE_SOUND.equalsIgnoreCase(src.getDataType())){ 49 | return fixSound(origPath,src); 50 | }else if(DependencyFinder.PROPTYPE_SPRITE.equalsIgnoreCase(src.getDataType())){ 51 | return fixMaterial(origPath, src); 52 | }else if(DependencyFinder.PROPTYPE_DECAL.equalsIgnoreCase(src.getDataType())){ 53 | return fixMaterial(origPath,src); 54 | }else if("vtf".equalsIgnoreCase(src.getDataType())){ 55 | return fixTexture(origPath,src); 56 | } 57 | return origPath; 58 | } 59 | 60 | 61 | private String fixMaterial(String origPath, ValueSource src) { 62 | String path = origPath; 63 | path = path.replace("\\", "/"); 64 | if (!path.toLowerCase().endsWith(".vmt") && !path.toLowerCase().endsWith(".spr")) { 65 | path = path + ".vmt"; 66 | } 67 | if (!path.toLowerCase().startsWith("materials/")) { 68 | path = "materials/" + path; 69 | } 70 | return path; 71 | } 72 | 73 | private String fixTexture(String origPath, ValueSource src) { 74 | String path = origPath; 75 | path = path.replace("\\", "/"); 76 | if (!path.toLowerCase().endsWith(".vtf")) { 77 | path = path + ".vtf"; 78 | } 79 | if (!path.toLowerCase().startsWith("materials/")) { 80 | path = "materials/" + path; 81 | } 82 | return path; 83 | } 84 | 85 | private String fixSound(String origPath, ValueSource src) { 86 | String path = origPath; 87 | path = path.replace("\\", "/"); 88 | if(!path.contains("/") && !path.toLowerCase().endsWith(".wav")){ 89 | // Probably a symbolic sound, like Ambient.Hum 90 | return getNonPathPrefix() + origPath; 91 | } 92 | if(!path.toLowerCase().endsWith(".wav")){ 93 | path = path + ".wav"; 94 | } 95 | if(!path.toLowerCase().startsWith("sound/")){ 96 | path = "sound/" + path; 97 | } 98 | return path; 99 | } 100 | 101 | /** 102 | * Get the string prefix which is added when a non-path value is encountered 103 | * @return A string prefix 104 | */ 105 | public String getNonPathPrefix() { 106 | return nonPathPrefix; 107 | } 108 | 109 | /** 110 | * Set the string prefix to be added when a non-path value is encountered 111 | * @param nonPathPrefix A string to prefix non-paths with, ideally a value 112 | * which will be unambiguous when seen. 113 | */ 114 | public void setNonPathPrefix(String nonPathPrefix) { 115 | this.nonPathPrefix = nonPathPrefix; 116 | } 117 | 118 | 119 | 120 | } 121 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/entdata/EntdataException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.entdata; 14 | 15 | /** 16 | * Thrown when there is a problem parsing entity data. 17 | * @author Darien Hager 18 | */ 19 | public class EntdataException extends Exception { 20 | 21 | public EntdataException(Throwable cause) { 22 | super(cause); 23 | } 24 | 25 | public EntdataException(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public EntdataException(String message) { 30 | super(message); 31 | } 32 | 33 | public EntdataException() { 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/entdata/MapEntity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.entdata; 14 | 15 | import com.technofovea.hl2parse.vdf.VdfAttribute; 16 | import com.technofovea.hl2parse.vdf.VdfNode; 17 | import java.util.ArrayList; 18 | import java.util.HashMap; 19 | import java.util.HashSet; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Set; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | /** 27 | * Represents a single entity found within a map. 28 | * 29 | * @author Darien Hager 30 | */ 31 | public class MapEntity { 32 | 33 | private static final Logger logger = LoggerFactory.getLogger(MapEntity.class); 34 | static String KEY_CLASS = "classname"; 35 | static String KEY_ID = "hammerid"; 36 | /** 37 | * The class-name of this entity 38 | */ 39 | protected String entityClass = null; 40 | /** 41 | * The optional Hammer-ID of this entity, or -1 if none found. 42 | */ 43 | protected int hammerId = -1; 44 | /** 45 | * The property keys and values associated with this entity. Note that in 46 | * several situations it is permissible for multiple key/value pairs using 47 | * the same key. 48 | */ 49 | protected Map> attrs = new HashMap>(); 50 | 51 | /** 52 | * Creates a new list of entity objects after the map entity data has been 53 | * parsed into a {@link VdfNode} tree. 54 | * @param rootNode The root node for the tree. 55 | * @return A list of map entities, possibly blank. 56 | * @throws EntdataException If there was a problem interpreting the tree. 57 | */ 58 | public static List fromVdf(VdfNode rootNode) throws EntdataException { 59 | List entities = new ArrayList(); 60 | for (VdfNode entNode : rootNode.getChildren()) { 61 | MapEntity e = new MapEntity(entNode); 62 | entities.add(e); 63 | } 64 | return entities; 65 | } 66 | 67 | /** 68 | * Creates a new map entity with the given keys and values. Keys are 69 | * automatically checked for class-name information. 70 | * 71 | * @param attributes All attributes on this entity, including class-name and 72 | * other "special" values. 73 | * @throws EntdataException If there was a problem interpreting the data. 74 | */ 75 | public MapEntity(Map> attributes) throws EntdataException { 76 | if (!attributes.containsKey(KEY_CLASS)) { 77 | throw new EntdataException("No class-name specified for entity"); 78 | } 79 | if (!(attributes.get(KEY_CLASS).size() < 1)) { 80 | throw new EntdataException("No class-name specified for entity"); 81 | } 82 | 83 | entityClass = attributes.remove(KEY_CLASS).get(0).toLowerCase().trim(); 84 | for (String key : attributes.keySet()) { 85 | key = key.trim().toLowerCase(); 86 | List vals = attributes.get(key); 87 | if (key.equalsIgnoreCase(KEY_ID)) { 88 | 89 | try { 90 | hammerId = Integer.parseInt(vals.get(0).toLowerCase()); 91 | } catch (NumberFormatException nfe) { 92 | throw new EntdataException("Invalid hammer ID: " + vals); 93 | } 94 | } else { 95 | if(vals.size()>0){ 96 | this.attrs.put(key, vals); 97 | }//TODO log? 98 | } 99 | } 100 | 101 | } 102 | 103 | /** 104 | * Creates a new map entity from an isolated {@link VdfNode} 105 | * 106 | * @param entityNode The node containing key/value mappings describing the entity. 107 | * @throws EntdataException If there was a problem interpreting the data. 108 | */ 109 | public MapEntity(VdfNode entityNode) throws EntdataException { 110 | 111 | if (entityNode.getChildren().size() > 0) { 112 | throw new EntdataException("Entity nodes may not have child blocks, but " + entityNode.getChildren().size() + " found."); 113 | } 114 | for (VdfAttribute attr : entityNode.getAttributes()) { 115 | String key = attr.getName().toLowerCase().trim(); 116 | String val = attr.getValue(); 117 | 118 | 119 | 120 | if (key.equalsIgnoreCase(KEY_CLASS)) { 121 | entityClass = val.toLowerCase(); 122 | } else if (key.equalsIgnoreCase(KEY_ID)) { 123 | try { 124 | hammerId = Integer.parseInt(val.toLowerCase()); 125 | } catch (NumberFormatException nfe) { 126 | throw new EntdataException("Invalid hammer ID: " + val); 127 | } 128 | } else { 129 | if (!attrs.containsKey(key)) { 130 | attrs.put(key, new ArrayList()); 131 | } 132 | attrs.get(key).add(val); 133 | 134 | 135 | } 136 | } 137 | if (entityClass == null) { 138 | throw new EntdataException("No entity class found"); 139 | } 140 | if (hammerId == -1) { 141 | // Apparently this isn't the terrible case I thought it was. 142 | } 143 | } 144 | /** 145 | * Retrieve the class-name of this entity (ex. prop_dynamic) 146 | * @return The class-name 147 | */ 148 | public String getEntityClass() { 149 | return entityClass; 150 | } 151 | 152 | /** 153 | * Retrieve the hammer-ID for this entity. 154 | * @return A hammer-ID or -1 if not found 155 | */ 156 | public int getHammerId() { 157 | return hammerId; 158 | } 159 | 160 | /** 161 | * Gets a set of all property-names on this entity. Note that this does not 162 | * include "special" values like the class-name or hammer-id. 163 | * @return A set of property names. 164 | */ 165 | public Set getKeys() { 166 | return new HashSet(attrs.keySet()); 167 | } 168 | 169 | /** 170 | * Check if the given property-name is defined for this entity. 171 | * @param propertyName The property-name to check. 172 | * @return True if found, false otherwise. 173 | */ 174 | public boolean containsKey(String propertyName) { 175 | return attrs.containsKey(propertyName); 176 | } 177 | 178 | /** 179 | * Retrieves the list of values associated with a particular property name 180 | * on this entity, or null if none found. 181 | * @param propertyName The property-name to retrieve data for. 182 | * @return A list of values set for the given property. 183 | */ 184 | public List getValues(String propertyName) { 185 | return new ArrayList(attrs.get(propertyName)); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/entdata/PathFixer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.entdata; 14 | 15 | /** 16 | * A PathFixer is responsible for taking strings (and associated 17 | * {@link ValueSource} objects) and returning a "proper" path. For example, a 18 | * material may be found as "folder/file", lacking the implicit parts that would 19 | * turn it into "materials/folder/file.vmt". 20 | * 21 | * @author Darien Hager 22 | */ 23 | public interface PathFixer { 24 | 25 | /** 26 | * Given a string and details about where it was found, attempt to convert 27 | * it into a relative file path. 28 | * 29 | * If the value does not correspond to a file path (such as symbolic sound 30 | * names like Ambient.Hum) then a string is returned beginning with the 31 | * non-path prefix. 32 | * 33 | * @param origPath The original path or string 34 | * @param src The source where it was found 35 | * @return A relative path or 36 | */ 37 | public String fixPath(String origPath, ValueSource src); 38 | 39 | /** 40 | * Returns a string used by {@link #fixPath(java.lang.String, com.technofovea.hl2parse.entdata.ValueSource)} 41 | * to prefix non-path values. Typically this should be a character which is 42 | * not part of any typical valid path, such as a colon. 43 | * @return The string used to prefix non-path values 44 | */ 45 | public String getNonPathPrefix(); 46 | } 47 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/entdata/ValueSource.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.entdata; 14 | 15 | /** 16 | * Represents a source for entity values. 17 | */ 18 | public class ValueSource { 19 | 20 | /** 21 | * The entity-class to get values from 22 | */ 23 | String className; 24 | /** 25 | * The property-name on the entity to get a value from 26 | */ 27 | String propertyName; 28 | /** 29 | * The type (typically specified by FGD) of the value(s) 30 | */ 31 | String dataType; 32 | 33 | 34 | 35 | /** 36 | * Creates a new object with the given class/property names and datatype. 37 | * @param className The class-name 38 | * @param propertyName The property-name 39 | * @param dataType The datatype for the property 40 | */ 41 | public ValueSource(String className, String propertyName, String dataType) { 42 | //TODO investigate how case-sensitivity comes into play 43 | this.className = className; 44 | this.propertyName = propertyName; 45 | this.dataType = dataType; 46 | } 47 | 48 | 49 | 50 | 51 | /** 52 | * Gets the entity class-name of this source 53 | * @return An entity class name 54 | */ 55 | public String getClassName() { 56 | return className; 57 | } 58 | 59 | /** 60 | * The name of the property on the entity which is being targeted 61 | * @return A string property name 62 | */ 63 | public String getPropertyName() { 64 | return propertyName; 65 | } 66 | 67 | /** 68 | * Gets the data type associated with the property values 69 | * @return A string for the datatype, as used in FGDs 70 | */ 71 | public String getDataType() { 72 | return dataType; 73 | } 74 | 75 | 76 | 77 | 78 | @Override 79 | public String toString() { 80 | return "{" + className + "," + propertyName + ":" + dataType + "}"; 81 | } 82 | 83 | @Override 84 | public boolean equals(Object obj) { 85 | if (obj == null) { 86 | return false; 87 | } 88 | if (getClass() != obj.getClass()) { 89 | return false; 90 | } 91 | final ValueSource other = (ValueSource) obj; 92 | if ((this.className == null) ? (other.className != null) : !this.className.equalsIgnoreCase(other.className)) { 93 | return false; 94 | } 95 | if ((this.propertyName == null) ? (other.propertyName != null) : !this.propertyName.equalsIgnoreCase(other.propertyName)) { 96 | return false; 97 | } 98 | if ((this.dataType == null) ? (other.dataType != null) : !this.dataType.equalsIgnoreCase(other.dataType)) { 99 | return false; 100 | } 101 | return true; 102 | } 103 | 104 | @Override 105 | public int hashCode() { 106 | int hash = 7; 107 | hash = 97 * hash + (this.className != null ? this.className.hashCode() : 0); 108 | hash = 97 * hash + (this.propertyName != null ? this.propertyName.hashCode() : 0); 109 | hash = 97 * hash + (this.dataType != null ? this.dataType.hashCode() : 0); 110 | return hash; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/entdata/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tools for interpreting entity data for maps, and to mine that data in conjunction with FGD information. 4 | 5 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/ChoicesValue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | /** 16 | * Represents a possible value for an FgdProperty of type "choices" 17 | * @author Darien Hager 18 | */ 19 | public class ChoicesValue implements Comparable{ 20 | 21 | private String value; 22 | private String description; 23 | 24 | public ChoicesValue(String value, String description) { 25 | this.value= value; 26 | this.description = description; 27 | } 28 | 29 | public String getDescription() { 30 | return description; 31 | } 32 | 33 | public String getValue() { 34 | return value; 35 | } 36 | 37 | 38 | 39 | public String toText() { 40 | String valueOutput = FgdSpec.quoteVal(value); 41 | String ret = valueOutput + ":\""+getDescription()+"\""; 42 | return ret; 43 | } 44 | 45 | public int compareTo(ChoicesValue o) { 46 | int difference = this.getValue().compareTo(o.getValue()); 47 | if(difference != 0){ 48 | return difference; 49 | } 50 | return this.getDescription().compareTo(o.getDescription()); 51 | } 52 | 53 | @Override 54 | public boolean equals(Object obj) { 55 | if (obj == null) { 56 | return false; 57 | } 58 | if (getClass() != obj.getClass()) { 59 | return false; 60 | } 61 | final ChoicesValue other = (ChoicesValue) obj; 62 | if ((this.value == null) ? (other.value != null) : !this.value.equals(other.value)) { 63 | return false; 64 | } 65 | if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) { 66 | return false; 67 | } 68 | return true; 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | int hash = 3; 74 | hash = 23 * hash + (this.value != null ? this.value.hashCode() : 0); 75 | hash = 23 * hash + (this.description != null ? this.description.hashCode() : 0); 76 | return hash; 77 | } 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | } 89 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/FgdInput.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | /** 16 | * Represents an anonymous input on an entity-class. 17 | * @author Darien Hager 18 | */ 19 | public class FgdInput { 20 | 21 | private static final String INPUT_QUALIFIER = "input"; 22 | 23 | private String type; 24 | private String description; 25 | 26 | public FgdInput(String type) { 27 | this(type,""); 28 | } 29 | 30 | public FgdInput(String type, String description) { 31 | this.type = type; 32 | this.description = description; 33 | } 34 | 35 | public String getDescription() { 36 | return description; 37 | } 38 | 39 | public void setDescription(String description) { 40 | this.description = description; 41 | } 42 | 43 | 44 | 45 | public String getType() { 46 | return type; 47 | } 48 | 49 | public void setType(String type) { 50 | this.type = type; 51 | } 52 | 53 | public String toText(String name) { 54 | StringBuilder sb = new StringBuilder(); 55 | sb.append(INPUT_QUALIFIER); 56 | sb.append(" "); 57 | sb.append(name); 58 | sb.append("("); 59 | sb.append(type); 60 | sb.append(") : \""); 61 | sb.append(description); 62 | sb.append("\" "); 63 | return sb.toString(); 64 | } 65 | 66 | @Override 67 | public boolean equals(Object obj) { 68 | if (obj == null) { 69 | return false; 70 | } 71 | if (getClass() != obj.getClass()) { 72 | return false; 73 | } 74 | final FgdInput other = (FgdInput) obj; 75 | if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) { 76 | return false; 77 | } 78 | if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) { 79 | return false; 80 | } 81 | return true; 82 | } 83 | 84 | @Override 85 | public int hashCode() { 86 | int hash = 7; 87 | hash = 29 * hash + (this.type != null ? this.type.hashCode() : 0); 88 | hash = 29 * hash + (this.description != null ? this.description.hashCode() : 0); 89 | return hash; 90 | } 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | } 101 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/FgdOutput.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | /** 16 | * Represents an anonymous output on an entity-class. 17 | * @author Darien 18 | */ 19 | public class FgdOutput { 20 | 21 | private static final String OUTPUT_QUALIFIER = "output"; 22 | 23 | private String type; 24 | private String description; 25 | 26 | public FgdOutput(String type) { 27 | this(type,""); 28 | } 29 | 30 | public FgdOutput(String type, String description) { 31 | this.type = type; 32 | this.description = description; 33 | } 34 | 35 | public String getDescription() { 36 | return description; 37 | } 38 | 39 | public void setDescription(String description) { 40 | this.description = description; 41 | } 42 | 43 | 44 | public String getType() { 45 | return type; 46 | } 47 | 48 | public void setType(String type) { 49 | this.type = type; 50 | } 51 | 52 | public String toText(String name) { 53 | StringBuilder sb = new StringBuilder(); 54 | sb.append(OUTPUT_QUALIFIER); 55 | sb.append(" "); 56 | sb.append(name); 57 | sb.append("("); 58 | sb.append(type); 59 | sb.append(") : \""); 60 | sb.append(description); 61 | sb.append("\" "); 62 | return sb.toString(); 63 | } 64 | 65 | @Override 66 | public boolean equals(Object obj) { 67 | if (obj == null) { 68 | return false; 69 | } 70 | if (getClass() != obj.getClass()) { 71 | return false; 72 | } 73 | final FgdOutput other = (FgdOutput) obj; 74 | if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) { 75 | return false; 76 | } 77 | if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) { 78 | return false; 79 | } 80 | return true; 81 | } 82 | 83 | @Override 84 | public int hashCode() { 85 | int hash = 3; 86 | hash = 97 * hash + (this.type != null ? this.type.hashCode() : 0); 87 | hash = 97 * hash + (this.description != null ? this.description.hashCode() : 0); 88 | return hash; 89 | } 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/FgdProperty.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /** 19 | * Represents an anonymous property on an entity-class. Certain accessors on 20 | * this class only make sense if the object's type is set correctly. 21 | * @author Darien Hager 22 | */ 23 | public class FgdProperty { 24 | public static final String TYPE_CHOICES = "choices"; 25 | public static final String TYPE_FLAGS = "flags"; 26 | 27 | String type; 28 | boolean readonly = false; 29 | String shortDesc = ""; 30 | String longDesc = ""; 31 | String defaultVal = ""; 32 | List flags = new ArrayList(); 33 | List options = new ArrayList(); 34 | 35 | 36 | 37 | public String getType() { 38 | return type; 39 | } 40 | 41 | public void setType(String type) { 42 | this.type = type; 43 | } 44 | 45 | public boolean isReadonly() { 46 | return readonly; 47 | } 48 | 49 | public void setReadonly(boolean readonly) { 50 | this.readonly = readonly; 51 | } 52 | 53 | /** 54 | * Only applicable if the type of this property is set to "flags" 55 | * @return A modifiable list of flags. 56 | */ 57 | public List getFlags() { 58 | return flags; 59 | } 60 | 61 | /** 62 | * Only applicable if the type of this property is set to "choices" 63 | * @return A modifiable list of options. 64 | */ 65 | public List getOptions() { 66 | return options; 67 | } 68 | 69 | public String toText(String name) { 70 | 71 | StringBuilder sb = new StringBuilder(); 72 | sb.append(name); 73 | sb.append("("); 74 | sb.append(type); 75 | sb.append(") "); 76 | 77 | sb.append(": \""); 78 | sb.append(shortDesc); 79 | sb.append("\" : "); 80 | 81 | // If default value is integer, do not quote 82 | String temp = FgdSpec.quoteVal(defaultVal); 83 | sb.append(temp); 84 | 85 | sb.append(" : \""); 86 | sb.append(longDesc); 87 | sb.append("\" "); 88 | 89 | if (TYPE_CHOICES.equalsIgnoreCase(type)) { 90 | sb.append("=\n[\n"); 91 | for (ChoicesValue o : options) { 92 | sb.append(o.toText()); 93 | sb.append("\n"); 94 | } 95 | sb.append("]"); 96 | } else if (TYPE_FLAGS.equalsIgnoreCase(type)) { 97 | sb.append("=\n[\n"); 98 | 99 | for (FlagValue f : flags) { 100 | sb.append(f.toText()); 101 | sb.append("\n"); 102 | } 103 | sb.append("]"); 104 | } else { 105 | } 106 | 107 | return sb.toString(); 108 | } 109 | 110 | void setShortDescription(String str) { 111 | shortDesc = str; 112 | if(shortDesc == null){ 113 | shortDesc = ""; 114 | } 115 | } 116 | 117 | void setLongDescription(String str) { 118 | longDesc = str; 119 | if(longDesc == null){ 120 | longDesc = ""; 121 | } 122 | } 123 | 124 | void setDefault(String str) { 125 | defaultVal = str; 126 | if(defaultVal == null){ 127 | defaultVal = ""; 128 | } 129 | } 130 | 131 | public String getDefaultVal() { 132 | return defaultVal; 133 | } 134 | 135 | public String getLongDesc() { 136 | return longDesc; 137 | } 138 | 139 | public String getShortDesc() { 140 | return shortDesc; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/FgdSpec.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | import java.util.HashMap; 16 | import java.util.HashSet; 17 | import java.util.Map; 18 | import java.util.Set; 19 | 20 | /** 21 | * Represents an FGD 'document' and associated data. 22 | * @author Darien Hager 23 | */ 24 | public class FgdSpec { 25 | 26 | Map definedClasses = new HashMap(); 27 | Map visGroups = new HashMap(); 28 | boolean boundsSet = false; 29 | int mapMin = -32768; 30 | int mapMax = 32768; 31 | Set excludedMaterials = new HashSet(); 32 | 33 | static String cleanQuotes(String input) { 34 | return input.replace("\"", " "); 35 | } 36 | 37 | static String quoteVal(String value) { 38 | try { 39 | int i = Integer.parseInt(value); 40 | return value; 41 | } catch (NumberFormatException nfe) { 42 | return "\"" + value + "\""; 43 | } 44 | 45 | } 46 | 47 | 48 | public int getMapMax() { 49 | return mapMax; 50 | } 51 | 52 | public void setMapBounds(int mapMin, int mapMax) throws IllegalArgumentException { 53 | if (mapMax < mapMin) { 54 | throw new IllegalArgumentException("Maximum value is less than minimum value"); 55 | } 56 | this.mapMin = mapMin; 57 | this.mapMax = mapMax; 58 | boundsSet = true; 59 | } 60 | 61 | public void setMapBounds(String mapMin, String mapMax) throws IllegalArgumentException { 62 | int low = Integer.parseInt(mapMin); 63 | int high = Integer.parseInt(mapMax); 64 | setMapBounds(low, high); 65 | } 66 | 67 | public int getMapMin() { 68 | return mapMin; 69 | } 70 | 71 | public void addEntClass(String name, FgdEntClass item) { 72 | definedClasses.put(name, item); 73 | } 74 | 75 | public FgdEntClass getEntClass(String name) { 76 | return definedClasses.get(name); 77 | } 78 | 79 | public Set getEntClassNames() { 80 | return new HashSet(definedClasses.keySet()); 81 | } 82 | 83 | public void clearEntClases() { 84 | definedClasses.clear(); 85 | } 86 | 87 | public VisGroup getVisGroup(String name) { 88 | return visGroups.get(name); 89 | } 90 | 91 | public Set getVisGroupNames() { 92 | return new HashSet(visGroups.keySet()); 93 | } 94 | 95 | public void addVisGroup(String name, VisGroup grp) { 96 | visGroups.put(name, grp); 97 | } 98 | 99 | public Set getExcludedMaterials() { 100 | return excludedMaterials; 101 | } 102 | 103 | public void setExcludedMaterials(Set excludedMaterials) { 104 | this.excludedMaterials = excludedMaterials; 105 | } 106 | 107 | 108 | 109 | public String toText() { 110 | StringBuilder sb = new StringBuilder(); 111 | if (boundsSet) { 112 | sb.append("@mapsize(" + mapMin + "," + mapMax + ")\n"); 113 | } 114 | if (excludedMaterials.size()>0){ 115 | sb.append("@MaterialExclusion\n["); 116 | for(String item : excludedMaterials){ 117 | sb.append(quoteVal(item)); 118 | sb.append("\n"); 119 | } 120 | sb.append("]\n"); 121 | } 122 | for(String groupName : visGroups.keySet()){ 123 | VisGroup vg = visGroups.get(groupName); 124 | sb.append("@AutoVisGroup = "); 125 | sb.append(groupName); 126 | sb.append("\n[\n"); 127 | for(String subName : vg.getSectionNames()){ 128 | sb.append(quoteVal(subName)); 129 | sb.append("\n[\n"); 130 | for(String item : vg.getSectionItems(subName)){ 131 | 132 | sb.append(quoteVal(item)); 133 | sb.append("\n"); 134 | } 135 | sb.append("]\n"); 136 | } 137 | sb.append("]\n"); 138 | 139 | 140 | 141 | } 142 | for (String clazzName : definedClasses.keySet()) { 143 | FgdEntClass entClass = definedClasses.get(clazzName); 144 | sb.append(entClass.toText(clazzName)); 145 | } 146 | return sb.toString(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/FlagValue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | /** 16 | * Represents a possible value for an FgdProperty of type "flags" 17 | * @author Darien Hager 18 | */ 19 | public class FlagValue implements Comparable{ 20 | 21 | private int intValue; 22 | private String name; 23 | private boolean defaultOn; 24 | 25 | public FlagValue(int intValue, String name, boolean defaultOn) { 26 | this.intValue = intValue; 27 | this.name = name; 28 | this.defaultOn = defaultOn; 29 | } 30 | 31 | public boolean isDefaultOn() { 32 | return defaultOn; 33 | } 34 | 35 | public int getIntValue() { 36 | return intValue; 37 | } 38 | 39 | public String getName() { 40 | return name; 41 | } 42 | 43 | public String toText() { 44 | String ret =getIntValue() + ":\""+getName()+"\":"; 45 | if(isDefaultOn()){ 46 | ret = ret + "1"; 47 | }else{ 48 | ret = ret + "0"; 49 | } 50 | return ret; 51 | } 52 | 53 | @Override 54 | public boolean equals(Object obj) { 55 | if (obj == null) { 56 | return false; 57 | } 58 | if (getClass() != obj.getClass()) { 59 | return false; 60 | } 61 | final FlagValue other = (FlagValue) obj; 62 | if (this.intValue != other.intValue) { 63 | return false; 64 | } 65 | if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { 66 | return false; 67 | } 68 | if (this.defaultOn != other.defaultOn) { 69 | return false; 70 | } 71 | return true; 72 | } 73 | 74 | @Override 75 | public int hashCode() { 76 | int hash = 7; 77 | hash = 59 * hash + this.intValue; 78 | hash = 59 * hash + (this.name != null ? this.name.hashCode() : 0); 79 | hash = 59 * hash + (this.defaultOn ? 1 : 0); 80 | return hash; 81 | } 82 | 83 | public int compareTo(FlagValue other) { 84 | int valueDifference = this.getIntValue() - other.getIntValue(); 85 | if(valueDifference != 0){ 86 | return valueDifference; 87 | } 88 | 89 | // Same numbers? Weird but possible, so then sort by the string. 90 | return this.getName().compareTo(other.getName()); 91 | } 92 | 93 | 94 | 95 | 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/VisGroup.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | import java.util.Collection; 16 | import java.util.HashMap; 17 | import java.util.HashSet; 18 | import java.util.Map; 19 | import java.util.Set; 20 | 21 | /** 22 | * 23 | * @author Darien Hager 24 | */ 25 | public class VisGroup { 26 | 27 | Map> sections = new HashMap>(); 28 | 29 | public Set getSectionNames(){ 30 | return new HashSet(sections.keySet()); 31 | } 32 | 33 | public void removeSection(String name){ 34 | sections.remove(name); 35 | } 36 | public Set getSectionItems(String name){ 37 | return sections.get(name); 38 | } 39 | public void addSection(String name, Collection entityNames){ 40 | sections.put(name, new HashSet(entityNames)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/fgd/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Classes to parse FGD (Forge Game Data) files which are used in the Source SDK. 4 | 5 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/GameInfoReader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | import com.technofovea.hl2parse.JxPathUtil; 16 | import java.io.File; 17 | import java.util.ArrayList; 18 | import java.util.Iterator; 19 | import java.util.List; 20 | import org.apache.commons.jxpath.JXPathContext; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | /** 25 | * 26 | * @author Darien Hager 27 | */ 28 | public class GameInfoReader { 29 | 30 | public static final String PLACEHOLDER_ALLSOURCE = "all_source_engine_paths"; // Relative to main appid OR additional ones 31 | public static final String PLACEHOLDER_GAMEINFODIR = "gameinfo_path"; // Relative to gameinfo file's parent directory 32 | public static final String PATH_DELIM = "|"; // Marks beginning and end of placeholders 33 | public static final String DEFAULT_FILENAME = "gameinfo.txt"; 34 | 35 | private static final Logger logger = LoggerFactory.getLogger(GameInfoReader.class); 36 | VdfRoot root; 37 | JXPathContext context; 38 | File sourceFile; 39 | 40 | public GameInfoReader(VdfRoot rootNode, File sourceFile) { 41 | this.sourceFile = sourceFile; 42 | root = rootNode; 43 | context = JXPathContext.newContext(root); 44 | JxPathUtil.addFunctions(context); 45 | 46 | } 47 | 48 | /** 49 | * Retrieves the path to the souce file. This is relevant since some paths 50 | * within the data are relative to the location of the file itself. 51 | * @return The File which was parsed. Potentially null, depending on usage. 52 | */ 53 | public File getSourceFile() { 54 | return sourceFile; 55 | } 56 | 57 | public String getGameName() { 58 | return (String) context.getValue("children[custom:equals(name,'GameInfo')]/attributes[custom:equals(name,'game')]/value"); 59 | } 60 | 61 | public int getSteamAppId() { 62 | String id = (String) context.getValue("children[custom:equals(name,'GameInfo')]/children[custom:equals(name,'FileSystem')]/attributes[custom:equals(name,'SteamAppId')]/value"); 63 | return Integer.parseInt(id); 64 | } 65 | 66 | public List getSearchPaths() { 67 | List ret = new ArrayList(); 68 | Iterator iter = (Iterator) context.iterate("children[custom:equals(name,'GameInfo')]/children[custom:equals(name,'FileSystem')]/children[custom:equals(name,'SearchPaths')]/attributes[custom:equals(name,'game')]/value"); 69 | while (iter.hasNext()) { 70 | ret.add(iter.next()); 71 | } 72 | return ret; 73 | } 74 | /* 75 | static List dereferenceSearchPaths(List paths, File gameInfoDirectory, File appIdDirectory ){ 76 | 77 | } 78 | */ 79 | 80 | public List getAdditionalIds() { 81 | List ret = new ArrayList(); 82 | Iterator iter = (Iterator) context.iterate("children[custom:equals(name,'GameInfo')]/children[custom:equals(name,'FileSystem')]/attributes[custom:equals(name,'AdditionalContentId')]/value"); 83 | while (iter.hasNext()) { 84 | ret.add(Integer.parseInt(iter.next())); 85 | } 86 | return ret; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/MaterialReader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | import com.technofovea.hl2parse.*; 16 | import com.technofovea.hl2parse.xml.MaterialRefList; 17 | import com.technofovea.hl2parse.xml.MaterialReference; 18 | import java.io.InputStream; 19 | import java.util.HashSet; 20 | import java.util.Iterator; 21 | import java.util.Set; 22 | import javax.xml.bind.JAXBContext; 23 | import javax.xml.bind.JAXBException; 24 | import javax.xml.bind.Marshaller; 25 | import javax.xml.bind.Unmarshaller; 26 | import org.apache.commons.jxpath.JXPathContext; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | /** 31 | * 32 | * @author Darien Hager 33 | */ 34 | public class MaterialReader { 35 | 36 | public static final MaterialRefList getDefaultMaterialSettings() throws JAXBException { 37 | InputStream is = MaterialReader.class.getResourceAsStream("DefaultMaterials.xml"); 38 | return loadFromXml(is); 39 | } 40 | 41 | public static final MaterialRefList loadFromXml(InputStream stream) throws JAXBException { 42 | JAXBContext jc = JAXBContext.newInstance(MaterialReference.class, MaterialRefList.class); 43 | Unmarshaller um = jc.createUnmarshaller(); 44 | Marshaller m = jc.createMarshaller(); 45 | m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 46 | 47 | Object o = um.unmarshal(stream); 48 | return (MaterialRefList) o; 49 | } 50 | private static final Logger logger = LoggerFactory.getLogger(MaterialReader.class); 51 | static final String PATCH_INCLUDE = "include"; 52 | VdfRoot root; 53 | JXPathContext context; 54 | MaterialRefList props; 55 | Set textures = new HashSet(); 56 | Set materials = new HashSet(); 57 | 58 | public MaterialReader(VdfRoot rootNode, MaterialRefList props) { 59 | root = rootNode; 60 | context = JXPathContext.newContext(root); 61 | JxPathUtil.addFunctions(context); 62 | 63 | 64 | Iterator allAttribs = context.iterate("//attributes"); 65 | 66 | while (allAttribs.hasNext()) { 67 | VdfAttribute attrPair = allAttribs.next(); 68 | String key = attrPair.getName(); 69 | // Strip trailing "2"s for blend texture variations 70 | if (key.endsWith("2")) { 71 | logger.trace("Found 2-suffixed attribute variation: {}", key); 72 | key = key.substring(0, key.length() - 1); 73 | } 74 | 75 | 76 | if (key.equalsIgnoreCase(PATCH_INCLUDE)) { 77 | // According to docs, the patch shader's "include" directive 78 | // required a complete path with extension, ex. 79 | // materials/foo/bar.vmt 80 | // So we don't prefix or suffix this one 81 | logger.trace("Found possible patch-include shader material: {}", key); 82 | 83 | materials.add(attrPair.getValue()); 84 | } 85 | 86 | for (MaterialReference ref : props) { 87 | if (!ref.hasName(key)) { // Case insensitive 88 | continue; 89 | } 90 | String val = attrPair.getValue(); 91 | if (ref.hasIgnoreValue(val)) { // Case sensitive 92 | continue; 93 | } 94 | 95 | switch (ref.getType()) { 96 | case MATERIAL: 97 | logger.trace("Found material: {}", val); 98 | if (!val.toLowerCase().endsWith(".vmt")) { 99 | val += ".vmt"; 100 | } 101 | materials.add("materials/" + val); 102 | break; 103 | case TEXTURE: 104 | logger.trace("Found texture: {}", val); 105 | if (!val.toLowerCase().endsWith(".vtf")) { 106 | val += ".vtf"; 107 | } 108 | textures.add("materials/" + val); 109 | break; 110 | } 111 | break; // Break loop 112 | } 113 | } 114 | } 115 | 116 | public Set getMaterials() { 117 | return new HashSet(materials); 118 | } 119 | 120 | public Set getTextures() { 121 | return new HashSet(textures); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/ParticleManifestReader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | 16 | import com.technofovea.hl2parse.JxPathUtil; 17 | import java.util.ArrayList; 18 | import java.util.Iterator; 19 | import java.util.List; 20 | import org.apache.commons.jxpath.JXPathContext; 21 | 22 | /** 23 | * 24 | * @author Darien Hager 25 | */ 26 | public class ParticleManifestReader { 27 | 28 | 29 | private static final String CACHE_MARK = "!"; 30 | private static final String KEY_NAME = "file"; 31 | private VdfRoot root; 32 | private JXPathContext context; 33 | 34 | public ParticleManifestReader(VdfRoot rootNode) { 35 | root = rootNode; 36 | context = JXPathContext.newContext(root); 37 | JxPathUtil.addFunctions(context); 38 | 39 | context.getVariables().declareVariable("filekey", KEY_NAME); 40 | } 41 | 42 | public List getPcfs() { 43 | Iterator scapes = context.iterate("children[1]/attributes[custom:equals(name,$filekey)]/value"); 44 | List ret = new ArrayList(); 45 | while (scapes.hasNext()) { 46 | String path = (String) scapes.next(); 47 | if (path.startsWith(CACHE_MARK)) { 48 | path = path.substring(CACHE_MARK.length()); 49 | } 50 | ret.add(path); 51 | } 52 | return ret; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/PropDataReader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | import com.technofovea.hl2parse.JxPathUtil; 16 | import java.util.ArrayList; 17 | import java.util.HashSet; 18 | import java.util.Iterator; 19 | import java.util.List; 20 | import java.util.Set; 21 | import org.apache.commons.jxpath.JXPathContext; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | /** 26 | * 27 | * @author Darien Hager 28 | */ 29 | public class PropDataReader { 30 | 31 | private static final Logger logger = LoggerFactory.getLogger(PropDataReader.class); 32 | VdfRoot root; 33 | JXPathContext context; 34 | 35 | public PropDataReader(VdfRoot rootNode) { 36 | root = rootNode; 37 | context = JXPathContext.newContext(root); 38 | JxPathUtil.addFunctions(context); 39 | } 40 | 41 | public List getRagdollModels() { 42 | Iterator allSnds = context.iterate("children[custom:equals(name,'break')]/attributes[custom:equals(name,'ragdoll')]/value"); 43 | 44 | List ret = new ArrayList(); 45 | while (allSnds.hasNext()) { 46 | String path = allSnds.next(); 47 | ret.add("models/" + path + ".mdl"); 48 | } 49 | return ret; 50 | } 51 | 52 | public List getRigidGibModels() { 53 | Iterator allSnds = context.iterate("children[custom:equals(name,'break')]/attributes[custom:equals(name,'model')]/value"); 54 | 55 | List ret = new ArrayList(); 56 | while (allSnds.hasNext()) { 57 | String path = allSnds.next(); 58 | ret.add(path); 59 | } 60 | return ret; 61 | } 62 | 63 | public Set getAllGibs() { 64 | Set ret = new HashSet(); 65 | ret.addAll(getRagdollModels()); 66 | ret.addAll(getRigidGibModels()); 67 | return ret; 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/SoundScapeReader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | 16 | import com.technofovea.hl2parse.JxPathUtil; 17 | import java.util.ArrayList; 18 | import java.util.Iterator; 19 | import java.util.List; 20 | import org.apache.commons.jxpath.JXPathContext; 21 | 22 | /** 23 | * 24 | * @author Darien Hager 25 | */ 26 | public class SoundScapeReader { 27 | 28 | private static final String KEY_WAV = "wave"; 29 | 30 | private VdfNode root; 31 | private JXPathContext context; 32 | public SoundScapeReader(VdfRoot rootNode) { 33 | root = rootNode; 34 | context = JXPathContext.newContext(root); 35 | JxPathUtil.addFunctions(context); 36 | context.getVariables().declareVariable("wavkey",KEY_WAV); 37 | } 38 | public List getSoundFiles(){ 39 | Iterator allSnds = context.iterate("//attributes[custom:equals(name,$wavkey)]/value"); 40 | 41 | List ret = new ArrayList(); 42 | while (allSnds.hasNext()) { 43 | String path = allSnds.next(); 44 | ret.add("sound/"+path); 45 | } 46 | return ret; 47 | } 48 | public List getSoundscapeNames(){ 49 | Iterator scapes = context.iterate("/children/name"); 50 | List ret = new ArrayList(); 51 | while (scapes.hasNext()) { 52 | ret.add((String) scapes.next()); 53 | } 54 | return ret; 55 | 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/SteamMetaReader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | import com.technofovea.hl2parse.*; 16 | import com.technofovea.hl2parse.JxPathUtil; 17 | import com.technofovea.hl2parse.vdf.VdfAttribute; 18 | import com.technofovea.hl2parse.vdf.VdfRoot; 19 | import java.util.HashSet; 20 | import java.util.Iterator; 21 | import java.util.Set; 22 | import org.apache.commons.jxpath.JXPathContext; 23 | 24 | /** 25 | * 26 | * @author Darien Hager 27 | */ 28 | public class SteamMetaReader { 29 | 30 | VdfRoot root; 31 | JXPathContext context; 32 | 33 | 34 | 35 | public SteamMetaReader(VdfRoot rootNode) { 36 | root = rootNode; 37 | context = JXPathContext.newContext(root); 38 | JxPathUtil.addFunctions(context); 39 | 40 | 41 | } 42 | 43 | public String getAutoLogon() { 44 | return (String) context.getValue("children[custom:equals(name,'SteamAppData')]/attributes[custom:equals(name,'AutoLoginUser')]/value"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/VdfAttribute.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | /** 16 | * 17 | * @author Darien Hager 18 | */ 19 | public class VdfAttribute { 20 | 21 | private String name = ""; 22 | private String value = ""; 23 | 24 | VdfAttribute(String key, String value) { 25 | 26 | this.name = key; 27 | this.value = value; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "{"+this.name+":"+this.value+"}"; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public String getValue() { 40 | return value; 41 | } 42 | 43 | public void setName(String name) { 44 | this.name = name; 45 | } 46 | 47 | public void setValue(String value) { 48 | this.value = value; 49 | } 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/VdfNode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /** 19 | * Used for parsing Valve's various similarly-formatted files. For convenience, many 20 | * accessors on this class throw exceptions since calling them implicitly signifies 21 | * you expect the data to be arranged a certain way. 22 | * 23 | * @author Darien Hager 24 | */ 25 | public class VdfNode { 26 | 27 | private String name = ""; 28 | private List children = new ArrayList(); 29 | private List attributes = new ArrayList(); 30 | 31 | public VdfNode(){ 32 | } 33 | 34 | //TODO custom equality? Deep equality? 35 | 36 | 37 | 38 | @Override 39 | public String toString() { 40 | return toString(0, false); 41 | } 42 | 43 | public String toPrettyString() { 44 | return toString(0, true); 45 | } 46 | 47 | protected String toString(int indentLevel, boolean pretty) { 48 | StringBuilder sb = new StringBuilder(); 49 | 50 | StringBuilder tabs = new StringBuilder(); 51 | for (int i = 0; i < indentLevel; i++) { 52 | tabs.append("\t"); 53 | } 54 | if (hasName()) { 55 | sb.append(tabs); 56 | sb.append("\""); 57 | sb.append(getName()); 58 | sb.append("\""); 59 | sb.append("\n"); 60 | } 61 | sb.append(tabs); 62 | sb.append("{\n"); 63 | 64 | int maxKeyLen = 0; 65 | if (pretty) { 66 | // Pad everything so the key/value pairs are easy to read, so we 67 | // need a first pass to calculate lengths 68 | for (VdfAttribute att : attributes) { 69 | if (att.getName().length() > maxKeyLen) { 70 | maxKeyLen = att.getName().length(); 71 | } 72 | } 73 | } 74 | for (VdfAttribute att : attributes) { 75 | 76 | sb.append(tabs); 77 | sb.append("\t"); 78 | sb.append("\""); 79 | sb.append(att.getName()); 80 | sb.append("\""); 81 | if (pretty) { 82 | sb.append(" "); 83 | for (int i = 0; i < maxKeyLen - att.getName().length(); i++) { 84 | sb.append(" "); 85 | } 86 | } else { 87 | sb.append(" "); 88 | } 89 | sb.append("\""); 90 | sb.append(att.getValue()); 91 | sb.append("\""); 92 | 93 | sb.append("\n"); 94 | 95 | } 96 | for (VdfNode vn : children) { 97 | String childString = vn.toString(indentLevel + 1, pretty); 98 | sb.append(childString); 99 | } 100 | sb.append(tabs); 101 | sb.append("}\n"); 102 | return sb.toString(); 103 | } 104 | 105 | public boolean addChild(VdfNode n) { 106 | if (n == this) { 107 | return false; 108 | } 109 | return children.add(n); 110 | } 111 | 112 | public void addAttribute(String key, String value) { 113 | VdfAttribute va = new VdfAttribute(key, value); 114 | attributes.add(va); 115 | return; 116 | } 117 | 118 | public void setName(String s) { 119 | name = s; 120 | } 121 | 122 | public List getChildren() { 123 | return children; 124 | } 125 | 126 | public boolean hasName() { 127 | return (name != null); 128 | } 129 | 130 | public String getName() { 131 | if (name == null) { 132 | return ""; 133 | } 134 | return name; 135 | } 136 | 137 | public List getAttributes() { 138 | return attributes; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/VdfRoot.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.vdf; 14 | 15 | /** 16 | * 17 | * @author Darien Hager 18 | */ 19 | public class VdfRoot extends VdfNode{ 20 | 21 | @Override 22 | public String toString(int indentLevel, boolean pretty) { 23 | StringBuilder sb = new StringBuilder(); 24 | 25 | for(VdfNode vn : getChildren()){ 26 | sb.append(vn.toString(indentLevel,pretty)); 27 | } 28 | return sb.toString(); 29 | } 30 | 31 | @Override 32 | public boolean hasName() { 33 | return false; 34 | } 35 | 36 | @Override 37 | public String getName() { 38 | return ""; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/vdf/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Classes for parsing and traversing "Valve Data Format" files, a type of 4 | hierarchical data commonly used by the Source engine. 5 | 6 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/xml/MaterialRefList.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.xml; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Iterator; 17 | import java.util.List; 18 | import java.util.ListIterator; 19 | import javax.xml.bind.annotation.XmlAccessType; 20 | import javax.xml.bind.annotation.XmlAccessorType; 21 | import javax.xml.bind.annotation.XmlElement; 22 | import javax.xml.bind.annotation.XmlRootElement; 23 | 24 | /** 25 | * 26 | * @author Darien Hager 27 | */ 28 | @XmlRootElement 29 | @XmlAccessorType(XmlAccessType.NONE) 30 | public class MaterialRefList implements Iterable{ 31 | 32 | @XmlElement(required=true,name="item") 33 | protected List items = new ArrayList(); 34 | 35 | public List getItems() { 36 | return items; 37 | } 38 | 39 | public void setItems(List items) { 40 | this.items = items; 41 | } 42 | 43 | public int size() { 44 | return items.size(); 45 | } 46 | 47 | public MaterialReference remove(int index) { 48 | return items.remove(index); 49 | } 50 | 51 | public Iterator iterator() { 52 | return items.iterator(); 53 | } 54 | 55 | public MaterialReference get(int index) { 56 | return items.get(index); 57 | } 58 | 59 | public boolean contains(MaterialReference o) { 60 | return items.contains(o); 61 | } 62 | 63 | public void clear() { 64 | items.clear(); 65 | } 66 | 67 | public boolean add(MaterialReference e) { 68 | return items.add(e); 69 | } 70 | 71 | public String toString() { 72 | return items.toString(); 73 | } 74 | 75 | public ListIterator listIterator(int index) { 76 | return items.listIterator(index); 77 | } 78 | 79 | public ListIterator listIterator() { 80 | return items.listIterator(); 81 | } 82 | 83 | 84 | 85 | 86 | 87 | 88 | } 89 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/java/com/technofovea/hl2parse/xml/MaterialReference.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.xml; 14 | 15 | import java.util.HashSet; 16 | import java.util.Set; 17 | import javax.xml.bind.annotation.XmlAccessType; 18 | import javax.xml.bind.annotation.XmlAccessorType; 19 | import javax.xml.bind.annotation.XmlElement; 20 | import javax.xml.bind.annotation.XmlEnum; 21 | import javax.xml.bind.annotation.XmlEnumValue; 22 | import javax.xml.bind.annotation.XmlList; 23 | import javax.xml.bind.annotation.XmlType; 24 | 25 | /** 26 | * Represents a material property that references another asset. For example, 27 | * $basetexture references an external texture. 28 | * @author Darien Hager 29 | */ 30 | @XmlAccessorType(XmlAccessType.NONE) 31 | public class MaterialReference { 32 | 33 | @XmlType 34 | @XmlEnum(value = String.class) 35 | public static enum ReferenceType { 36 | 37 | @XmlEnumValue("texture") 38 | TEXTURE, 39 | 40 | @XmlEnumValue("material") 41 | MATERIAL 42 | } 43 | 44 | 45 | @XmlElement(required = true) 46 | @XmlList // Allows whitespace-separation 47 | protected Set names = new HashSet();; 48 | @XmlElement(required = false,name="ignoreValue") 49 | protected Set ignoreValues = new HashSet(); 50 | @XmlElement(required = false, defaultValue="texture") 51 | protected ReferenceType type = ReferenceType.TEXTURE; 52 | 53 | public Set getIgnoreValues() { 54 | return ignoreValues; 55 | } 56 | 57 | public void setIgnoreValues(Set ignoreValues) { 58 | this.ignoreValues = ignoreValues; 59 | } 60 | 61 | public Set getNames() { 62 | return names; 63 | } 64 | 65 | public void setNames(Set names) { 66 | this.names = new HashSet(); 67 | for(String n: names){ 68 | this.names.add(n.toLowerCase()); 69 | } 70 | } 71 | 72 | public ReferenceType getType() { 73 | return type; 74 | } 75 | 76 | public void setType(ReferenceType type) { 77 | this.type = type; 78 | } 79 | 80 | public void addName(String name){ 81 | names.add(name.toLowerCase()); 82 | } 83 | 84 | public void addIgnoreValue(String val){ 85 | ignoreValues.add(val); 86 | } 87 | 88 | public boolean hasName(String name){ 89 | return names.contains(name.toLowerCase()); 90 | } 91 | 92 | public boolean hasIgnoreValue(String val){ 93 | return ignoreValues.contains(val); 94 | } 95 | 96 | @Override 97 | public boolean equals(Object obj) { 98 | if (obj == null) { 99 | return false; 100 | } 101 | if (getClass() != obj.getClass()) { 102 | return false; 103 | } 104 | final MaterialReference other = (MaterialReference) obj; 105 | if (this.names != other.names && (this.names == null || !this.names.equals(other.names))) { 106 | return false; 107 | } 108 | if (this.ignoreValues != other.ignoreValues && (this.ignoreValues == null || !this.ignoreValues.equals(other.ignoreValues))) { 109 | return false; 110 | } 111 | if (this.type != other.type && (this.type == null || !this.type.equals(other.type))) { 112 | return false; 113 | } 114 | return true; 115 | } 116 | 117 | @Override 118 | public int hashCode() { 119 | int hash = 7; 120 | hash = 97 * hash + (this.names != null ? this.names.hashCode() : 0); 121 | hash = 97 * hash + (this.ignoreValues != null ? this.ignoreValues.hashCode() : 0); 122 | hash = 97 * hash + (this.type != null ? this.type.hashCode() : 0); 123 | return hash; 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /hl2parse-common/src/main/resources/com/technofovea/hl2parse/vdf/DefaultMaterials.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | $basetexture 12 | texture 13 | 14 | 15 | $bumpmap 16 | 17 | 18 | $normalmap 19 | 20 | 21 | $detail 22 | 23 | 24 | $dudvmap 25 | 26 | 27 | $refracttinttexture 28 | 29 | 30 | $envmapmask 31 | 32 | 33 | $parallaxmap 34 | 35 | 36 | $ambientoccltexture 37 | 38 | 39 | $hdrcompressedtexture $hdrbasetexture 40 | 41 | 42 | $lightwarptexture 43 | 44 | 45 | $refracttinttexture 46 | 47 | 48 | $phongexponenttexture 49 | 50 | 51 | $fallbackmaterial 52 | material 53 | 54 | 55 | $bottommaterial 56 | material 57 | 58 | 59 | $underwateroverlay 60 | material 61 | 62 | 63 | $refracttexture 64 | _rt_WaterRefraction 65 | texture 66 | 67 | 68 | $envmap 69 | env_cubemap 70 | texture 71 | 72 | 73 | $reflecttexture 74 | _rt_WaterReflection 75 | texture 76 | 77 | 78 | $fallbackmaterial 79 | material 80 | 81 | 82 | 83 | 84 | 85 | $FleshInteriorTexture 86 | $FleshNormalTexture 87 | $FleshBorderTexture1D 88 | $FleshInteriorNoiseTexture 89 | $FleshSubsurfaceTexture 90 | 91 | 92 | $FleshCubeTexture 93 | env_cubemap 94 | material 95 | 96 | -------------------------------------------------------------------------------- /hl2parse-common/src/test/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /hl2parse-parsers/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.technofovea 7 | hl2parse 8 | 1.2.2-SNAPSHOT 9 | 10 | 11 | hl2parse-parsers 12 | hl2parse-parsers 13 | 14 | 15 | 16 | 17 | org.antlr 18 | antlr3-maven-plugin 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | com.technofovea 28 | hl2parse-common 29 | 30 | 31 | 32 | org.antlr 33 | antlr-runtime 34 | 35 | 36 | 37 | junit 38 | junit 39 | test 40 | 41 | 42 | 43 | org.slf4j 44 | slf4j-api 45 | 46 | 47 | org.slf4j 48 | slf4j-log4j12 49 | 50 | 51 | 52 | 53 | 54 | ${basedir}/.. 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /hl2parse-parsers/src/main/antlr3/com/technofovea/hl2parse/vdf/SloppyParser.g: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | parser grammar SloppyParser; 14 | options{ 15 | tokenVocab=ValveTokenLexer; 16 | } 17 | 18 | 19 | @header { 20 | package com.technofovea.hl2parse.vdf; 21 | import com.technofovea.hl2parse.ParserException; 22 | 23 | /* 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | */ 27 | } 28 | @rulecatch { 29 | catch (RecognitionException ex) { 30 | // Instead of printing out error messages, just exit early with an exception. 31 | if(ex instanceof ParserException){ 32 | throw(ex); 33 | } 34 | ParserException carrier = new ParserException(this,ex); 35 | throw carrier; 36 | } 37 | } 38 | 39 | main returns [VdfRoot root] 40 | @init{ 41 | root = new VdfRoot(); 42 | } 43 | : WS* block[root] (WS* block[root])* WS* 44 | ; 45 | 46 | item[VdfNode parent] 47 | : block[parent] 48 | | scalar[parent] 49 | ; 50 | 51 | block[VdfNode parent] 52 | @init{ 53 | VdfNode current = new VdfNode(); 54 | } 55 | : (bn=blockName WS?)? LBRACE WS* (item[current] (WS+ item[current])* WS*)? RBRACE 56 | { 57 | current.setName($bn.text); 58 | parent.addChild(current); 59 | } 60 | ; 61 | 62 | blockName 63 | : (STRING)=> STRING 64 | | unquotedMess 65 | ; 66 | scalar[VdfNode parent] 67 | : (STRING STRING)=> nt=STRING vt=STRING 68 | { 69 | parent.addAttribute($nt.text,$vt.text); 70 | } 71 | | n=scalarName WS+ v=scalarVal 72 | { 73 | parent.addAttribute($n.text,$v.text); 74 | } 75 | ; 76 | scalarName 77 | : (STRING)=> STRING 78 | | unquotedMess 79 | ; 80 | scalarVal 81 | : (STRING)=> STRING 82 | | unquotedMess 83 | ; 84 | 85 | unquotedMess 86 | : (~(STRING|QUOT|COLON|EQUALS|LSQUARE|RSQUARE|LPAREN|RPAREN|LBRACE|RBRACE|WS|COMMENT))+ 87 | ; 88 | 89 | 90 | -------------------------------------------------------------------------------- /hl2parse-parsers/src/main/antlr3/com/technofovea/hl2parse/vdf/ValveTokenLexer.g: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | lexer grammar ValveTokenLexer; 14 | 15 | @header { 16 | package com.technofovea.hl2parse.vdf; 17 | import com.technofovea.hl2parse.ParserException; 18 | 19 | /* 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | */ 23 | } 24 | 25 | 26 | 27 | 28 | @members{ 29 | 30 | public boolean mismatchIsUnwantedToken(IntStream input, int ttype) { 31 | // Disable error-recovery method 32 | return false; 33 | } 34 | 35 | public boolean mismatchIsMissingToken(IntStream input, BitSet follow) { 36 | // Disable error-recovery method 37 | return false; 38 | } 39 | } 40 | 41 | AT : '@'; 42 | COMMA : ','; 43 | EXCL : '!'; 44 | PLUS : '+'; 45 | AMPERSAND : '&'; 46 | STAR : '*'; 47 | DOLLAR : '$'; 48 | EQUALS : '='; 49 | COLON : ':'; 50 | LSQUARE : '['; 51 | RSQUARE : ']'; 52 | LPAREN : '('; 53 | RPAREN : ')'; 54 | LBRACE : '{'; 55 | RBRACE : '}'; 56 | BSLASH : '\\'; 57 | PERCENT : '%'; 58 | LESSER : '<'; 59 | GREATER : '>'; 60 | PIPE : '|'; 61 | SLASH : '/'; 62 | NULL : '\u0000'; 63 | 64 | fragment DIGIT : '0'..'9'; 65 | fragment ALPHA : 'a'..'z'|'A'..'Z'; 66 | fragment UNDERSCORE : '_'; 67 | fragment QUOT : '"'; 68 | 69 | 70 | IDENT : (ALPHA|UNDERSCORE)(ALPHA|DIGIT|UNDERSCORE)* 71 | ; 72 | 73 | FLOAT : DOT DIGIT+ 74 | | INT DOT DIGIT+ 75 | ; 76 | 77 | INT : MINUS? DIGIT+ ; 78 | 79 | 80 | MINUS : '-'; 81 | DOT : '.'; 82 | 83 | STRING 84 | : QUOT ( ~QUOT | '\\"')* QUOT 85 | { 86 | setText(getText().substring(1, getText().length()-1)); 87 | } 88 | ; 89 | 90 | fragment CRETURN : '\r'; 91 | fragment NLINE : '\n'; 92 | fragment SPACE : ' '; 93 | fragment TAB : '\t'; 94 | 95 | COMMENT 96 | : '//' ~(CRETURN|NLINE)* (CRETURN|NLINE|EOF) {$channel=HIDDEN;} 97 | ; 98 | 99 | 100 | 101 | WS : (SPACE|TAB|CRETURN|NLINE)+ 102 | ; 103 | 104 | 105 | /* 106 | Note that @rulecatch does nothing in the lexer, recommended way is to create 107 | a final "bad" rule to do things. 108 | See http://www.mail-archive.com/il-antlr-interest@googlegroups.com/msg02132.html 109 | 110 | 111 | BADINPUT : . { System.err.println("The character '" + $text + "' is not a legal character in this language or something."); } ; 112 | 113 | 114 | //ParserException carrier = new ParserException(this,ex); 115 | //throw carrier; 116 | */ 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /hl2parse-parsers/src/main/java/com/technofovea/hl2parse/ParserException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse; 14 | 15 | 16 | 17 | 18 | import org.antlr.runtime.BaseRecognizer; 19 | import org.antlr.runtime.RecognitionException; 20 | 21 | /** 22 | * Used by text parsers to indicate that an error has occurred while parsing 23 | * text data files. 24 | * @author Darien Hager 25 | */ 26 | public class ParserException extends RecognitionException { 27 | 28 | String header; 29 | String message; 30 | RecognitionException cause; 31 | public ParserException(BaseRecognizer parser, RecognitionException cause) { 32 | super(cause.input); 33 | // Parent class doesn't do causes! 34 | initCause(cause); 35 | 36 | header = parser.getErrorHeader(cause); 37 | message = parser.getErrorMessage(cause, parser.getTokenNames()); 38 | } 39 | 40 | @Override 41 | public String getMessage() { 42 | return header+": "+message; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return getClass().getSimpleName()+": "+getMessage(); 48 | } 49 | /* 50 | @Override 51 | public Throwable getCause() { 52 | return cause; 53 | } 54 | */ 55 | 56 | 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /hl2parse-parsers/src/main/java/com/technofovea/hl2parse/fgd/DefaultLoader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | import java.io.File; 16 | import java.io.FileInputStream; 17 | import java.io.IOException; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import org.antlr.runtime.ANTLRInputStream; 21 | import org.antlr.runtime.CharStream; 22 | import org.antlr.runtime.CommonTokenStream; 23 | import org.antlr.runtime.RecognitionException; 24 | 25 | /** 26 | * 27 | * @author Darien Hager 28 | */ 29 | public class DefaultLoader implements FgdLoader { 30 | 31 | List history = new ArrayList(); 32 | File workingDir = null; 33 | 34 | public static FgdLoader fillSpec(File target, FgdSpec spec) throws IOException, RecognitionException{ 35 | FgdLoader ldr = new DefaultLoader(); 36 | CharStream stream = ldr.getStream(target.getAbsolutePath()); 37 | ForgeGameDataLexer lexer = new ForgeGameDataLexer(stream); 38 | ForgeGameDataParser parser = new ForgeGameDataParser(new CommonTokenStream(lexer)); 39 | parser.main(spec, ldr); 40 | return ldr; 41 | } 42 | 43 | 44 | public DefaultLoader() { 45 | } 46 | 47 | public CharStream getStream(String path) throws IOException { 48 | File target; 49 | if (workingDir == null) { 50 | target = new File(path); 51 | } else { 52 | target = new File(workingDir, path); 53 | } 54 | if (history.contains(target)) { 55 | throw new IOException("Cyclic include detected with target: " + path); 56 | } 57 | 58 | ANTLRInputStream ais = new ANTLRInputStream(new FileInputStream(target)); 59 | 60 | if(workingDir == null){ 61 | workingDir = target.getParentFile(); 62 | } 63 | history.add(target); 64 | return ais; 65 | } 66 | 67 | public void reset() { 68 | history.clear(); 69 | workingDir = null; 70 | } 71 | /* 72 | public void loadFrom(File fgd) throws IOException, RecognitionException { 73 | loadFrom(fgd, new ArrayList()); 74 | } 75 | 76 | public void loadFrom(File fgd, List history) throws IOException, RecognitionException { 77 | if (history.contains(fgd)) { 78 | // Cyclic importing detected. We don't want an infinite loop, so... 79 | throw new IOException("Cyclic include directives detected."); 80 | } 81 | history.add(fgd); 82 | ANTLRInputStream ais = new ANTLRInputStream(new FileInputStream(fgd)); 83 | ForgeGameDataLexer lexer = new ForgeGameDataLexer(ais); 84 | ForgeGameDataParser parser = new ForgeGameDataParser(new CommonTokenStream(lexer)); 85 | parser.main(fgd, this, history); 86 | } 87 | * 88 | */ 89 | } 90 | -------------------------------------------------------------------------------- /hl2parse-parsers/src/main/java/com/technofovea/hl2parse/fgd/FgdLoader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | import java.io.IOException; 16 | import org.antlr.runtime.CharStream; 17 | 18 | /** 19 | * Since FGDs can import one-another from relative paths, a loader is responsible 20 | * for maintaining the correct context, resolving those paths, loading the data, 21 | * and guarding against cyclic dependencies. 22 | * 23 | * @author Darien Hager 24 | */ 25 | public interface FgdLoader { 26 | 27 | public void reset(); 28 | 29 | public CharStream getStream(String path) throws IOException; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /hl2parse-tests/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.technofovea 7 | hl2parse 8 | 1.2.2-SNAPSHOT 9 | 10 | 11 | hl2parse-tests 12 | hl2parse-tests 13 | 14 | 15 | 16 | 17 | 18 | 19 | com.technofovea 20 | hl2parse-common 21 | 22 | 23 | com.technofovea 24 | hl2parse-parsers 25 | 26 | 27 | com.technofovea 28 | hl2parse-binary 29 | 30 | 31 | 32 | org.slf4j 33 | slf4j-api 34 | 35 | 36 | org.slf4j 37 | slf4j-log4j12 38 | 39 | 40 | 41 | junit 42 | junit 43 | test 44 | 45 | 46 | 47 | 48 | 49 | 50 | ${basedir}/.. 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/java/com/technofovea/hl2parse/bsp/BspParseTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.bsp; 14 | 15 | import com.technofovea.hl2parse.bsp.SourceMapAnalyzer; 16 | import com.technofovea.hl2parse.ParseUtil; 17 | import java.io.File; 18 | import java.io.FileReader; 19 | import java.io.LineNumberReader; 20 | import java.nio.ByteBuffer; 21 | import java.util.Enumeration; 22 | import java.util.HashSet; 23 | import java.util.Map; 24 | import java.util.Set; 25 | import java.util.zip.ZipEntry; 26 | import java.util.zip.ZipFile; 27 | import org.junit.Assert; 28 | import org.junit.Test; 29 | 30 | /** 31 | * 32 | * @author Darien 33 | */ 34 | public class BspParseTest { 35 | 36 | static final String BSP_LOC = "test_bsp_parse.bsp"; 37 | //static final String BSP_LOC = "../sdk_ctf_2fort.bsp"; 38 | 39 | @Test 40 | public void testBspParsing() throws Exception { 41 | ByteBuffer bb = ParseUtil.mapFile(new File(this.getClass().getResource(BSP_LOC).toURI())); 42 | 43 | SourceMapAnalyzer sma = new SourceMapAnalyzer(bb); 44 | 45 | Set expectedMaterials = new HashSet(); 46 | expectedMaterials.add("materials/BRICK/BRICKFLOOR001A"); 47 | expectedMaterials.add("materials/STONE/STONEWALL006B"); 48 | expectedMaterials.add("materials/STONE/STONEWALL033A"); 49 | expectedMaterials.add("materials/PLASTER/PLASTERCEILING003A"); 50 | 51 | // Two decals 52 | expectedMaterials.add("materials/wood/wooddoor008a"); 53 | expectedMaterials.add("materials/decals/decalgraffiti003a"); 54 | 55 | /*//Tool textures 56 | expectedMaterials.add("materials/TOOLS/TOOLSTRIGGER"); 57 | expectedMaterials.add("materials/TOOLS/TOOLSSKYBOX"); 58 | */ 59 | 60 | /*//Cubemaps 61 | expectedMaterials.add("materials/maps/test_bsp_parse/tile/tilefloor001b_0_0_-896"); 62 | expectedMaterials.add("materials/maps/test_bsp_parse/tile/tilefloor001b_352_352_-896"); 63 | expectedMaterials.add("materials/maps/test_bsp_parse/tile/tilefloor009b_0_0_-896"); 64 | expectedMaterials.add("materials/maps/test_bsp_parse/stone/stonestair001a_0_0_-896"); 65 | */ 66 | 67 | 68 | Set foundTextures = new HashSet(); 69 | for (String found : sma.getBrushTextures()) { 70 | foundTextures.add(found.toLowerCase()); 71 | } 72 | for (String expected : expectedMaterials) { 73 | expected = expected.toLowerCase(); 74 | Assert.assertTrue(expected, foundTextures.contains(expected)); 75 | } 76 | 77 | Map> foundStaticProps = sma.getStaticPropSkins(); 78 | 79 | Assert.assertTrue(foundStaticProps.get("models/props_trainstation/bench_indoor001a.mdl").contains(0)); 80 | Assert.assertTrue(foundStaticProps.get("models/props_trainstation/column_light001b.mdl").contains(1)); 81 | Assert.assertTrue(foundStaticProps.get("models/props_trainstation/trashcan_indoor001a.mdl").contains(0)); 82 | Assert.assertTrue(foundStaticProps.get("models/props_trainstation/payphone001a.mdl").contains(0)); 83 | 84 | } 85 | 86 | /* 87 | @Test 88 | public void testEntdataParsing() throws Exception { 89 | ByteBuffer bb = ParseUtil.mapFile(new File(this.getClass().getResource(BSP_LOC).toURI())); 90 | 91 | SourceMapAnalyzer sma = new SourceMapAnalyzer(bb); 92 | 93 | String entData = sma.getEntData(); 94 | VdfParser vfp = new VdfParser(entData); 95 | VdfNode n = vfp.go(); 96 | MapEntityData med = new MapEntityData(n); 97 | 98 | Set foundDynamicModels = med.getDynamicModels(); 99 | Set expectedDynamicModels = new HashSet(); 100 | 101 | expectedDynamicModels.add("models/props_borealis/bluebarrel001.mdl"); 102 | 103 | for (String expected : expectedDynamicModels) { 104 | Assert.assertTrue(expected, foundDynamicModels.contains(expected)); 105 | } 106 | } 107 | */ 108 | @Test 109 | public void testPackedFiles() throws Exception { 110 | ByteBuffer bb = ParseUtil.mapFile(new File(this.getClass().getResource(BSP_LOC).toURI())); 111 | 112 | SourceMapAnalyzer sma = new SourceMapAnalyzer(bb); 113 | 114 | Set packedFilePaths = new HashSet(); 115 | ZipFile zf = sma.getPackedFiles(); 116 | Enumeration en = zf.entries(); 117 | while (en.hasMoreElements()) { 118 | ZipEntry entry = en.nextElement(); 119 | packedFilePaths.add(entry.getName()); 120 | //System.out.println(entry.getName()); 121 | } 122 | 123 | Assert.assertTrue(packedFilePaths.contains("materials/maps/test_bsp_parse/cubemapdefault.vtf")); 124 | 125 | if (false) { 126 | File f = sma.getPackedFile("materials/maps/test_bsp_parse/tile/tilefloor001b_352_352_-896.vmt"); 127 | FileReader fr = new FileReader(f); 128 | LineNumberReader lnr = new LineNumberReader(fr); 129 | String line = ""; 130 | while(line != null){ 131 | line = lnr.readLine(); 132 | System.out.println(line); 133 | } 134 | sma.getPackedFile("materials/maps/test_bsp_parse/tile/tilefloor001b_352_352_-896.vmt"); 135 | sma.getPackedFile("materials/maps/test_bsp_parse/tile/tilefloor001b_352_352_-896.vmt"); 136 | 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/java/com/technofovea/hl2parse/entdata/EntityProcessingTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.entdata; 14 | 15 | import com.technofovea.hl2parse.fgd.DefaultLoader; 16 | import com.technofovea.hl2parse.fgd.FgdEntClass; 17 | import com.technofovea.hl2parse.fgd.FgdSpec; 18 | import com.technofovea.hl2parse.vdf.SloppyParser; 19 | import com.technofovea.hl2parse.vdf.ValveTokenLexer; 20 | import com.technofovea.hl2parse.vdf.VdfRoot; 21 | import java.io.File; 22 | import java.io.InputStream; 23 | import java.util.Collection; 24 | import java.util.HashSet; 25 | import java.util.List; 26 | import java.util.Set; 27 | import org.antlr.runtime.ANTLRInputStream; 28 | import org.antlr.runtime.CommonTokenStream; 29 | import org.junit.Assert; 30 | import org.junit.Test; 31 | 32 | /** 33 | * 34 | * @author Darien 35 | */ 36 | public class EntityProcessingTest { 37 | 38 | private boolean checkContains(Collection c, String target) { 39 | boolean found = false; 40 | for (String s : c) { 41 | if (target.equalsIgnoreCase(s)) { 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | 48 | @Test 49 | public void temp() throws Exception { 50 | 51 | final String fgdPath = "tf.fgd"; 52 | final String entPath = "ctf_2fort.ent"; 53 | 54 | 55 | File srcFile = new File(getClass().getResource(fgdPath).toURI()); 56 | InputStream entStream = getClass().getResourceAsStream(entPath); 57 | ValveTokenLexer vfp = new ValveTokenLexer(new ANTLRInputStream(entStream)); 58 | SloppyParser sp = new SloppyParser(new CommonTokenStream(vfp)); 59 | VdfRoot entRoot = sp.main(); 60 | List ents = MapEntity.fromVdf(entRoot); 61 | 62 | FgdSpec spec = new FgdSpec(); 63 | DefaultLoader.fillSpec(srcFile,spec); 64 | 65 | System.out.println(spec.toText()); 66 | 67 | final String entName = "func_respawnroom"; 68 | FgdEntClass spawnroom = spec.getEntClass(entName); // Get normal version 69 | Assert.assertNotNull(spawnroom); 70 | System.out.println(spawnroom.toText(entName)); // Print sparse form 71 | FgdEntClass combined = spawnroom.getInherited(spec); // Do inheritance 72 | System.out.println(combined.toText(entName)); // Print combined form 73 | 74 | 75 | DependencyFinder df = new DependencyFinder(spec, ents, DefaultPathFixer.getInstance()); 76 | 77 | 78 | Set sounds = new HashSet(); 79 | for (ValueSource ep : df.getPropertiesByType(DependencyFinder.PROPTYPE_SOUND)) { 80 | sounds.addAll(df.getValues(ep)); 81 | } 82 | Assert.assertTrue(sounds.contains(":Ambient.MachineHum")); 83 | 84 | // Note that this test does NOT include prop_static entities, because 85 | // those are packaged differently into the BSP file. 86 | Set models = new HashSet(); 87 | for (ValueSource ep : df.getPropertiesByType(DependencyFinder.PROPTYPE_MODEL)) { 88 | models.addAll(df.getValues(ep)); 89 | } 90 | Assert.assertTrue(models.contains("models/props_gameplay/resupply_locker.mdl")); 91 | Assert.assertTrue(models.contains("models/props_skybox/sunnoon.mdl")); 92 | 93 | Set decals = new HashSet(); 94 | for (ValueSource ep : df.getPropertiesByType(DependencyFinder.PROPTYPE_DECAL)) { 95 | decals.addAll(df.getValues(ep)); 96 | } 97 | //TODO use some decals in our test file! 98 | 99 | Set sprites = new HashSet(); 100 | for (ValueSource ep : df.getPropertiesByType(DependencyFinder.PROPTYPE_SPRITE)) { 101 | sprites.addAll(df.getValues(ep)); 102 | } 103 | Assert.assertTrue(sprites.contains("materials/Sprites/light_glow03.vmt")); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/java/com/technofovea/hl2parse/fgd/BaselineTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | import java.io.File; 16 | import java.net.URL; 17 | import org.apache.log4j.Level; 18 | import org.junit.Assert; 19 | import org.junit.Test; 20 | 21 | /** 22 | * 23 | * @author Darien Hager 24 | */ 25 | public class BaselineTest { 26 | 27 | @Test 28 | public void test1() throws Exception { 29 | org.apache.log4j.Logger.getRootLogger().setLevel(Level.ALL); 30 | 31 | URL fileUrl = getClass().getResource("overall.fgd"); 32 | File srcFile = new File(fileUrl.toURI()); 33 | FgdSpec spec = new FgdSpec(); 34 | DefaultLoader.fillSpec(srcFile,spec); 35 | 36 | System.out.println(spec.toText()); 37 | // This test has no classes by design 38 | Assert.assertEquals(0,spec.getEntClassNames().size()); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/java/com/technofovea/hl2parse/fgd/CombinationTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.fgd; 14 | 15 | import java.io.File; 16 | import java.io.IOException; 17 | import java.net.URL; 18 | import java.util.Collections; 19 | import java.util.HashSet; 20 | import java.util.Map; 21 | import java.util.Set; 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | import static org.junit.Assert.*; 25 | 26 | /** 27 | * 28 | * @author Darien 29 | */ 30 | public class CombinationTest { 31 | 32 | @Test 33 | public void testMultipleInheritance() throws Exception { 34 | 35 | URL fileUrl = getClass().getResource("inherit_test.fgd"); 36 | File srcFile = new File(fileUrl.toURI()); 37 | FgdSpec spec = new FgdSpec(); 38 | DefaultLoader.fillSpec(srcFile,spec); 39 | 40 | //System.out.println(spec.toText()); 41 | FgdEntClass combined = spec.getEntClass("CyberBird").getInherited(spec); 42 | 43 | Assert.assertEquals("PointClass", combined.getType()); 44 | Set expectedProps = new HashSet(); 45 | expectedProps.add("manufacturer"); 46 | expectedProps.add("airating"); 47 | expectedProps.add("engines"); 48 | expectedProps.add("wingcount"); 49 | expectedProps.add("maxheight"); 50 | expectedProps.add("conflictingproperty"); 51 | Assert.assertEquals(expectedProps, combined.getProps().keySet()); 52 | 53 | 54 | // Test that our reference to a property is directly referring to an object 55 | // associated with a parent ent-class object. 56 | final Map machineProps = Collections.unmodifiableMap(spec.getEntClass("Machine").getProps()); 57 | 58 | FgdProperty base = machineProps.get("manufacturer"); 59 | FgdProperty inherited = combined.getProps().get("manufacturer"); 60 | Assert.assertEquals(base, inherited); 61 | 62 | // Test that the inheritance order was correct 63 | FgdProperty expectedConflicter = machineProps.get("conflictingproperty"); 64 | FgdProperty conflicter = combined.getProps().get("conflictingproperty"); 65 | Assert.assertEquals(expectedConflicter, conflicter); 66 | 67 | } 68 | 69 | @Test 70 | public void testImporting() throws Exception { 71 | 72 | final String ALPHA = "Alpha"; 73 | final String BETA = "Beta"; 74 | final String DELTA = "Delta"; 75 | final String EPSILON = "Epsilon"; 76 | final String GAMMA = "Gamma"; 77 | 78 | URL fileUrl = getClass().getResource("importer.fgd"); 79 | File srcFile = new File(fileUrl.toURI()); 80 | FgdSpec spec = new FgdSpec(); 81 | DefaultLoader.fillSpec(srcFile,spec); 82 | 83 | 84 | 85 | Set expectedClasses = new HashSet(); 86 | expectedClasses.add(ALPHA); 87 | expectedClasses.add(BETA); 88 | expectedClasses.add(GAMMA); 89 | expectedClasses.add(DELTA); 90 | expectedClasses.add(EPSILON); 91 | 92 | Assert.assertTrue(spec.getEntClassNames().containsAll(expectedClasses)); 93 | 94 | 95 | // Test that our order-based erasing happened appropriately 96 | final Set deltaKeyset = spec.getEntClass(DELTA).getProps().keySet(); 97 | final Set gammaKeyset = spec.getEntClass(EPSILON).getProps().keySet(); 98 | 99 | Assert.assertTrue(deltaKeyset.contains("eraser")); 100 | Assert.assertFalse(deltaKeyset.contains("erased")); 101 | Assert.assertTrue(gammaKeyset.contains("eraser")); 102 | Assert.assertFalse(gammaKeyset.contains("erased")); 103 | 104 | } 105 | 106 | @Test(timeout = 5000) 107 | public void testCyclicImports() throws Exception { 108 | // Just make sure they don't fail horribly. They're certainly invalid. 109 | URL fileUrl = getClass().getResource("cyclic1.fgd"); 110 | File srcFile = new File(fileUrl.toURI()); 111 | FgdSpec spec = new FgdSpec(); 112 | DefaultLoader.fillSpec(srcFile,spec); 113 | 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/java/com/technofovea/hl2parse/mdl/ModelDataTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.mdl; 14 | 15 | import com.technofovea.hl2parse.ParseUtil; 16 | import com.technofovea.hl2parse.vdf.PropDataReader; 17 | import com.technofovea.hl2parse.vdf.SloppyParser; 18 | import com.technofovea.hl2parse.vdf.ValveTokenLexer; 19 | import com.technofovea.hl2parse.vdf.VdfRoot; 20 | import java.io.File; 21 | import java.nio.ByteBuffer; 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import org.antlr.runtime.ANTLRStringStream; 28 | import org.antlr.runtime.CharStream; 29 | import org.antlr.runtime.CommonTokenStream; 30 | import org.antlr.runtime.RecognitionException; 31 | import org.junit.Assert; 32 | import org.junit.Ignore; 33 | import org.junit.Test; 34 | 35 | /** 36 | * 37 | * @author darien.hager 38 | */ 39 | public class ModelDataTest { 40 | 41 | static final String BUOY_MODEL = "buoy_ref.mdl"; 42 | static final String PHY_MODEL = "buoy_ref.phy"; 43 | 44 | 45 | protected static VdfRoot parseVdf(String data) throws RecognitionException { 46 | CharStream cs = new ANTLRStringStream(data); 47 | ValveTokenLexer lexer = new ValveTokenLexer(cs); 48 | SloppyParser parser = new SloppyParser(new CommonTokenStream(lexer)); 49 | VdfRoot root = parser.main(); 50 | return root; 51 | } 52 | 53 | @Test 54 | public void testBuoyModel() throws Exception { 55 | 56 | final int skinCount = 3; 57 | 58 | ByteBuffer bb = ParseUtil.mapFile(new File(this.getClass().getResource(BUOY_MODEL).toURI())); 59 | ModelData md = new ModelData(bb); 60 | 61 | Assert.assertEquals("props_swamp/buoy_ref.mdl", md.getModelName()); 62 | 63 | Assert.assertEquals(skinCount, md.getSkinCount()); 64 | 65 | List expectedPaths = new ArrayList(); 66 | expectedPaths.add("materials/models/props_swamp/"); 67 | Assert.assertEquals(expectedPaths, md.getTextureSearchPaths()); 68 | 69 | /* 70 | * A quick explanation: MDLs store "skins" as a sort of replacement table. 71 | * Just because a texture appears in the list from getTexturesForSkin() 72 | * doesn't necessarily mean that it will be used, only that it would 73 | * replace whatever was in that same Nth position. 74 | */ 75 | Map> expectedSkins = new HashMap>(); 76 | expectedSkins.put(0, Arrays.asList(new String[]{"buoy_diffuse.vmt", "buoy_diffuse2.vmt","buoy_diffuse3.vmt"})); 77 | expectedSkins.put(1, Arrays.asList(new String[]{"buoy_diffuse2.vmt","buoy_diffuse2.vmt","buoy_diffuse3.vmt"})); 78 | expectedSkins.put(2, Arrays.asList(new String[]{"buoy_diffuse3.vmt","buoy_diffuse2.vmt","buoy_diffuse3.vmt"})); 79 | 80 | Map> actualSkins = new HashMap>(); 81 | for(int i = 0; i < skinCount; i++){ 82 | actualSkins.put(i, md.getTexturesForSkin(i)); 83 | } 84 | Assert.assertEquals(expectedSkins, actualSkins); 85 | 86 | 87 | } 88 | 89 | @Test 90 | public void testBuoyPhy() throws Exception { 91 | ByteBuffer bb = ParseUtil.mapFile(new File(this.getClass().getResource(PHY_MODEL).toURI())); 92 | 93 | PhyData pd = new PhyData(bb); 94 | 95 | String rawPropData = pd.getPropData(); 96 | 97 | VdfRoot root = parseVdf(rawPropData); 98 | PropDataReader pdr = new PropDataReader(root); 99 | 100 | //System.out.println(rawPropData); 101 | 102 | /* 103 | * TODO pick a different freely-distributable model with multiple gibs 104 | * Until then this isn't a very good test. 105 | */ 106 | Assert.assertEquals(0, pdr.getAllGibs().size()); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/java/com/technofovea/hl2parse/registry/ClientRegistryTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.registry; 14 | 15 | import com.technofovea.hl2parse.ParseUtil; 16 | import com.technofovea.hl2parse.registry.CdrParser.AppDependency; 17 | import java.io.File; 18 | import java.io.IOException; 19 | import java.nio.ByteBuffer; 20 | import java.util.ArrayList; 21 | import java.util.Collections; 22 | import java.util.HashMap; 23 | import java.util.HashSet; 24 | import java.util.Iterator; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.Set; 28 | import org.apache.log4j.Level; 29 | import org.junit.Assert; 30 | import org.junit.Before; 31 | import org.junit.Ignore; 32 | import org.junit.Test; 33 | 34 | /** 35 | * 36 | * @author darien.hager 37 | */ 38 | public class ClientRegistryTest { 39 | 40 | static final File BLOB_SOURCE = new File("c:\\Program Files\\Steam\\ClientRegistry.blob"); 41 | static final int EXPECTED_VERSION = 1; 42 | static final int APPID_HALFLIFE = 70; 43 | static final int APPID_SOURCE_SDK = 211; 44 | private Map cachedAppNames = new HashMap(); 45 | 46 | @Before 47 | public void setup() throws Exception { 48 | cachedAppNames.clear(); 49 | } 50 | 51 | @Test 52 | public void parseClientRegistry() throws Exception { 53 | 54 | if(!BLOB_SOURCE.exists()){ 55 | throw new IllegalStateException("Cannot test, Steam's clientregistry.blob does not exist on local machine. " + 56 | "Due to security concerns, it is not included with distributed code. " + 57 | "This test case looks for it in: "+BLOB_SOURCE.getAbsolutePath()); 58 | } 59 | ByteBuffer buf = ParseUtil.mapFile(BLOB_SOURCE); 60 | BlobFolder root = RegParser.parseClientRegistry(buf); 61 | Assert.assertEquals("TopKey", root.getName()); 62 | } 63 | 64 | @Test 65 | public void getContentDescriptionRecord() throws BlobParseFailure, IOException { 66 | ByteBuffer buf = ParseUtil.mapFile(BLOB_SOURCE); 67 | BlobFolder root = RegParser.parseClientRegistry(buf); 68 | ClientRegistry cr = new ClientRegistry(root); 69 | CdrParser cp = cr.getContentDescriptionRecord(); 70 | String name = cp.getAppName(APPID_HALFLIFE); 71 | Assert.assertEquals("Half-Life", name); 72 | 73 | name = cp.getAppName(APPID_SOURCE_SDK); 74 | Assert.assertEquals("Source SDK", name); 75 | 76 | 77 | } 78 | 79 | @Test 80 | public void getAppDependencies() throws Exception { 81 | 82 | ByteBuffer buf = ParseUtil.mapFile(BLOB_SOURCE); 83 | BlobFolder root = RegParser.parseClientRegistry(buf); 84 | ClientRegistry cr = new ClientRegistry(root); 85 | CdrParser cp = cr.getContentDescriptionRecord(); 86 | 87 | Set foundNames = new HashSet(); 88 | List deps = cp.getAppDependencies(APPID_HALFLIFE); 89 | for (AppDependency i : deps) { 90 | foundNames.add(cp.getAppName(i.appid)); 91 | } 92 | 93 | Set expectedNames = new HashSet(); 94 | expectedNames.add("Half-Life Base Content"); 95 | expectedNames.add("Base Goldsrc Shared Binaries"); 96 | expectedNames.add("Base Goldsrc Shared Content"); 97 | expectedNames.add("Base Goldsrc Shared Platform"); 98 | 99 | Assert.assertEquals(expectedNames, foundNames); 100 | 101 | } 102 | 103 | private String getAppNameCached(CdrParser cp, int id) throws BlobParseFailure { 104 | if (cachedAppNames.containsKey(id)) { 105 | return cachedAppNames.get(id); 106 | } 107 | String s = cp.getAppName(id); 108 | cachedAppNames.put(id, s); 109 | return s; 110 | } 111 | 112 | @Ignore 113 | @Test 114 | public void printAppForWiki() throws Exception { 115 | Level origLogLevel = org.apache.log4j.Logger.getRootLogger().getLevel(); 116 | org.apache.log4j.Logger.getRootLogger().setLevel(Level.OFF); 117 | ByteBuffer buf = ParseUtil.mapFile(BLOB_SOURCE); 118 | BlobFolder root = RegParser.parseClientRegistry(buf); 119 | ClientRegistry cr = new ClientRegistry(root); 120 | CdrParser cp = cr.getContentDescriptionRecord(); 121 | 122 | Set appIdBag = new HashSet(cp.getAllAppIds()); 123 | Set temp = new HashSet(appIdBag); 124 | 125 | Iterator iterScreen = temp.iterator(); 126 | while(iterScreen.hasNext()){ 127 | int id = iterScreen.next(); 128 | List deps = cp.getAppDependencies(id); 129 | for (AppDependency dep : deps) { 130 | appIdBag.remove(dep.appid); 131 | 132 | } 133 | } 134 | 135 | List appIds = new ArrayList(appIdBag); 136 | Collections.sort(appIds); 137 | int limiter = 0; 138 | for (int id : appIds) { 139 | limiter++; 140 | String name = getAppNameCached(cp, id); 141 | if (name.startsWith("ValveTestApp")) { 142 | continue; 143 | } 144 | List deps = cp.getAppDependencies(id); 145 | Set tempset = new HashSet(); 146 | String priString = "* '''" + id + " " + name + "''' "; 147 | String fname = cp.getAppFolderName(id); 148 | if(!name.equalsIgnoreCase(fname) && fname != null && (!"".equals(fname))){ 149 | priString += "("+")"; 150 | } 151 | System.out.println(priString); 152 | Iterator iter = deps.iterator(); 153 | while (iter.hasNext()) { 154 | AppDependency dep = iter.next(); 155 | if (tempset.contains(dep)) { 156 | iter.remove(); 157 | } else { 158 | tempset.add(dep); 159 | } 160 | } 161 | Collections.sort(deps); 162 | for (AppDependency dep : deps) { 163 | if(dep.appid == id){ 164 | continue; 165 | } 166 | String depString = "** " + dep.appid + " " + getAppNameCached(cp, dep.appid); 167 | if (dep.optional) { 168 | depString += " (optional)"; 169 | } 170 | System.out.println(depString); 171 | 172 | } 173 | 174 | 175 | 176 | if (limiter > 500) { 177 | //break; 178 | } 179 | } 180 | 181 | org.apache.log4j.Logger.getRootLogger().setLevel(origLogLevel); 182 | 183 | 184 | 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/java/com/technofovea/hl2parse/xml/XmlTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011 Darien Hager 3 | * 4 | * This code is part of the "HL2Parse" project, and is licensed under 5 | * a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 6 | * either a summary of conditions or the full legal text, please visit: 7 | * 8 | * http://creativecommons.org/licenses/by-sa/3.0/ 9 | * 10 | * Permissions beyond the scope of this license may be available 11 | * at http://technofovea.com/ . 12 | */ 13 | package com.technofovea.hl2parse.xml; 14 | 15 | import com.technofovea.hl2parse.vdf.ParseTest; 16 | import java.io.InputStream; 17 | import javax.xml.bind.JAXBContext; 18 | import javax.xml.bind.Marshaller; 19 | import javax.xml.bind.Unmarshaller; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | /** 24 | * 25 | * @author Darien Hager 26 | */ 27 | public class XmlTest { 28 | 29 | @Test 30 | public void go() throws Exception { 31 | InputStream is = ParseTest.class.getResourceAsStream("DefaultMaterials.xml"); 32 | Assert.assertNotNull(is); 33 | JAXBContext jc = JAXBContext.newInstance(MaterialReference.class, MaterialRefList.class); 34 | Unmarshaller um = jc.createUnmarshaller(); 35 | Marshaller m = jc.createMarshaller(); 36 | m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 37 | 38 | Object o = um.unmarshal(is); 39 | System.out.println(o); 40 | 41 | 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/bsp/test_bsp_parse.bsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DHager/hl2parse/4477e012e0b306c6758db4d6bad9065975f3ac78/hl2parse-tests/src/test/resources/com/technofovea/hl2parse/bsp/test_bsp_parse.bsp -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/entdata/base.fgd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DHager/hl2parse/4477e012e0b306c6758db4d6bad9065975f3ac78/hl2parse-tests/src/test/resources/com/technofovea/hl2parse/entdata/base.fgd -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/fgd/cyclic1.fgd: -------------------------------------------------------------------------------- 1 | @include "cyclic2.fgd" -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/fgd/cyclic2.fgd: -------------------------------------------------------------------------------- 1 | @include "cyclic1.fgd" -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/fgd/imported1.fgd: -------------------------------------------------------------------------------- 1 | @PointClass = Delta 2 | [ 3 | erased(string) : "Wiped out by declaration in included file" 4 | ] 5 | @include "imported2.fgd" 6 | 7 | @PointClass = Beta 8 | [ 9 | placeholder(string) 10 | ] 11 | 12 | @PointClass = Epsilon 13 | [ 14 | eraser(string) : "Wipes out declaration in included file" 15 | ] -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/fgd/imported2.fgd: -------------------------------------------------------------------------------- 1 | @PointClass = Gamma 2 | [ 3 | placeholder(string) 4 | ] 5 | 6 | @PointClass = Delta 7 | [ 8 | eraser(string) : "Erases prior 'Delta' definition" 9 | ] 10 | 11 | @PointClass = Epsilon 12 | [ 13 | erased(string) : "Wiped out declaration from the includer file" 14 | ] -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/fgd/importer.fgd: -------------------------------------------------------------------------------- 1 | @include "imported1.fgd" 2 | 3 | @PointClass = Alpha 4 | [ 5 | placeholder(string) 6 | ] -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/fgd/inherit_test.fgd: -------------------------------------------------------------------------------- 1 | @BaseClass = Flying 2 | [ 3 | maxheight(integer) : "Max flying height" : 0 : "The highest this thing can fly" + 4 | " before problems occur." 5 | ] 6 | 7 | @BaseClass = Machine 8 | [ 9 | manufacturer(string) : "Manf. Name" : "" : "The name of the manufacturer" 10 | conflictingproperty(string): "TestingMachine" : "" : "A test property" 11 | ] 12 | 13 | @BaseClass = Animal 14 | [ 15 | conflictingproperty(string): "TestingAnimal" : "" : "A test property" 16 | phylum(choices) : "Phylum" : 0 : "The animal phylum this entity belongs to" = 17 | [ 18 | 0: "unspecified" 19 | 1: "porifera" 20 | 2: "cnidaria" 21 | 3: "ctenophora" 22 | 4: "platyhelminthes" 23 | 5: "nemertea" 24 | 6: "rotifera" 25 | 7: "gastrotricha" 26 | 8: "nematomorpha" 27 | 9: "nematoda" 28 | 10: "acanthocephala" 29 | 11: "bryozoa" 30 | 12: "tardigrada" 31 | 13: "brachiopoda" 32 | 14: "mollusca" 33 | 15: "annelida" 34 | 16: "sipunculoidea" 35 | 17: "arthropoda" 36 | 18: "chaetognatha" 37 | 19: "echinodermata" 38 | 20: "hemichordata" 39 | 21: "chordata" 40 | ] 41 | ] 42 | 43 | @PointClass base(Animal,Flying) = FlyingAnimal : "An animal which can fly" 44 | [ 45 | wingcount(integer): "Wing count" : 2 : "Number of wings" 46 | ] 47 | 48 | @PointClass base(Machine,Flying) = FlyingMachine : "A machine which can fly" 49 | [ 50 | engines(integer): "Engine count" : 2 : "Number of engines" 51 | ] 52 | 53 | @PointClass base(FlyingAnimal, FlyingMachine) = CyberBird : "A flying birdlike cyborg." 54 | [ 55 | airating(integer): "AI rating" : 100 : "AI rating in adjusted IQ points" 56 | ] 57 | 58 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/fgd/overall.fgd: -------------------------------------------------------------------------------- 1 | @MaterialExclusion 2 | [ 3 | // Names of the sub-directories we don't want to load materials from 4 | "alpha" 5 | "beta" 6 | "gamma/delta" 7 | ] 8 | 9 | @AutoVisGroup = "Tool Brushes" 10 | [ 11 | "Vis Clusters" 12 | [ 13 | "func_viscluster" 14 | ] 15 | ] 16 | 17 | @AutoVisGroup = "Custom" 18 | [ 19 | "AI, Choreo" 20 | [ 21 | "ai_speechfilter" 22 | "bot_controller" 23 | "bot_generator" 24 | "bot_hint_sentrygun" 25 | ] 26 | 27 | "Cameras" 28 | [ 29 | "info_observer_point" 30 | "game_intro_viewpoint" 31 | "info_camera_link" 32 | ] 33 | 34 | 35 | "Sound" 36 | [ 37 | "ambient_generic" 38 | "env_microphone" 39 | ] 40 | ] -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/mdl/buoy_ref.mdl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DHager/hl2parse/4477e012e0b306c6758db4d6bad9065975f3ac78/hl2parse-tests/src/test/resources/com/technofovea/hl2parse/mdl/buoy_ref.mdl -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/mdl/buoy_ref.phy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DHager/hl2parse/4477e012e0b306c6758db4d6bad9065975f3ac78/hl2parse-tests/src/test/resources/com/technofovea/hl2parse/mdl/buoy_ref.phy -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/utest.bsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DHager/hl2parse/4477e012e0b306c6758db4d6bad9065975f3ac78/hl2parse-tests/src/test/resources/com/technofovea/hl2parse/utest.bsp -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/Cloud001c.vmt: -------------------------------------------------------------------------------- 1 | "UnlitGeneric" 2 | { 3 | "$baseTexture" "skybox/Cloud001c" 4 | "$translucent" 1 5 | "$nofog" "1" 6 | "%keywords" "tf" 7 | } 8 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/GameConfig.txt: -------------------------------------------------------------------------------- 1 | "Configs" 2 | { 3 | "Games" 4 | { 5 | "Half-Life 2: Episode Two" 6 | { 7 | "GameDir" "c:\program files\steam\steamapps\STEAMLOGON\half-life 2 episode two\ep2" 8 | "hammer" 9 | { 10 | "GameData0" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\halflife2.fgd" 11 | "TextureFormat" "5" 12 | "MapFormat" "4" 13 | "DefaultTextureScale" "0.250000" 14 | "DefaultLightmapScale" "16" 15 | "GameExe" "c:\program files\steam\steamapps\STEAMLOGON\half-life 2 episode two\hl2.exe" 16 | "DefaultSolidEntity" "func_detail" 17 | "DefaultPointEntity" "info_player_start" 18 | "BSP" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vbsp.exe" 19 | "Vis" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vvis.exe" 20 | "Light" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vrad.exe" 21 | "GameExeDir" "c:\program files\steam\steamapps\STEAMLOGON\half-life 2 episode two" 22 | "MapDir" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk_content\ep2\mapsrc" 23 | "BSPDir" "c:\program files\steam\steamapps\STEAMLOGON\half-life 2 episode two\ep2\maps" 24 | "CordonTexture" "tools\toolsskybox" 25 | "MaterialExcludeCount" "0" 26 | } 27 | } 28 | "Team Fortress 2" 29 | { 30 | "GameDir" "c:\program files\steam\steamapps\STEAMLOGON\team fortress 2\tf" 31 | "hammer" 32 | { 33 | "GameData0" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\tf-abs.fgd" 34 | "TextureFormat" "5" 35 | "MapFormat" "4" 36 | "DefaultTextureScale" "0.250000" 37 | "DefaultLightmapScale" "16" 38 | "GameExe" "c:\program files\steam\steamapps\STEAMLOGON\team fortress 2\hl2.exe" 39 | "DefaultSolidEntity" "func_detail" 40 | "DefaultPointEntity" "prop_static" 41 | "BSP" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vbsp.exe" 42 | "Vis" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vvis.exe" 43 | "Light" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vrad.exe" 44 | "GameExeDir" "c:\program files\steam\steamapps\STEAMLOGON\team fortress 2" 45 | "MapDir" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk_content\tf\mapsrc" 46 | "BSPDir" "c:\program files\steam\steamapps\STEAMLOGON\team fortress 2\tf\maps" 47 | "CordonTexture" "tools\toolsskybox" 48 | "MaterialExcludeCount" "0" 49 | } 50 | } 51 | "Portal" 52 | { 53 | "GameDir" "c:\program files\steam\steamapps\STEAMLOGON\portal\portal" 54 | "hammer" 55 | { 56 | "GameData0" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\portal.fgd" 57 | "TextureFormat" "5" 58 | "MapFormat" "4" 59 | "DefaultTextureScale" "0.250000" 60 | "DefaultLightmapScale" "16" 61 | "GameExe" "c:\program files\steam\steamapps\STEAMLOGON\portal\hl2.exe" 62 | "DefaultSolidEntity" "func_detail" 63 | "DefaultPointEntity" "info_player_start" 64 | "BSP" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vbsp.exe" 65 | "Vis" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vvis.exe" 66 | "Light" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk\bin\orangebox\bin\vrad.exe" 67 | "GameExeDir" "c:\program files\steam\steamapps\STEAMLOGON\portal" 68 | "MapDir" "c:\program files\steam\steamapps\STEAMLOGON\sourcesdk_content\portal\mapsrc" 69 | "BSPDir" "c:\program files\steam\steamapps\STEAMLOGON\portal\portal\maps" 70 | "CordonTexture" "tools\toolsskybox" 71 | "MaterialExcludeCount" "0" 72 | } 73 | } 74 | } 75 | "SDKVersion" "3" 76 | } 77 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/SteamAppData.vdf: -------------------------------------------------------------------------------- 1 | "SteamAppData" 2 | { 3 | "RememberPassword" "0" 4 | "AutoLoginUser" "user@example.com" 5 | "terr_@hotmail.com" 6 | { 7 | "User" "user@example.com" 8 | "AccountCreated" "1" 9 | "ShowNotifyTrayHintDialog" "1" 10 | "hash" "" 11 | } 12 | } -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/ammo_red_bg.vmt: -------------------------------------------------------------------------------- 1 | "UnlitGeneric" 2 | { 3 | "LEVEL 3" 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/glasswindow001a.vmt: -------------------------------------------------------------------------------- 1 | "LightmappedGeneric" 2 | { 3 | "$baseTexture" "glass/glasswindow001a" 4 | "$surfaceprop" "glass" 5 | "$translucent" 1 6 | "$envmap" "env_cubemap" 7 | "$envmapcontrast" ".5" 8 | // "$envmapsaturation" 1 9 | "$envmaptint" "[ .9 .9 .9]" 10 | "%keywords" "tf" 11 | "$basetexturetransform" "center .5 .5 scale 4 4 rotate 45 translate 0 0" 12 | } 13 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/particle_rockettrail1.vmt: -------------------------------------------------------------------------------- 1 | "UnlitGeneric" 2 | { 3 | // Original shader: BaseTimesVertexColorAlphaBlend 4 | "$basetexture" "particle/particle_rocketrail1" 5 | "$translucent" "1" 6 | // "$vertexcolor" "1" 7 | "$vertexalpha" "1" 8 | // "$additive" "1" 9 | } 10 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/particles_manifest.txt: -------------------------------------------------------------------------------- 1 | particles_manifest 2 | { 3 | "file" "!particles/error.pcf" 4 | "file" "!particles/rockettrail.pcf" 5 | "file" "particles/smoke_blackbillow.pcf" 6 | "file" "!particles/teleport_status.pcf" 7 | "file" "!particles/explosion.pcf" 8 | "file" "!particles/player_recent_teleport.pcf" 9 | "file" "!particles/rocketjumptrail.pcf" 10 | "file" "!particles/rocketbackblast.pcf" 11 | "file" "!particles/flamethrower.pcf" 12 | "file" "!particles/burningplayer.pcf" 13 | "file" "!particles/blood_impact.pcf" 14 | "file" "!particles/blood_trail.pcf" 15 | "file" "!particles/muzzle_flash.pcf" 16 | "file" "!particles/teleported_fx.pcf" 17 | "file" "!particles/cig_smoke.pcf" 18 | "file" "!particles/crit.pcf" 19 | "file" "!particles/medicgun_beam.pcf" 20 | "file" "!particles/water.pcf" 21 | "file" "!particles/stickybomb.pcf" 22 | "file" "!particles/buildingdamage.pcf" 23 | "file" "!particles/nailtrails.pcf" 24 | "file" "!particles/speechbubbles.pcf" 25 | "file" "!particles/bullet_tracers.pcf" 26 | "file" "!particles/nemesis.pcf" 27 | "file" "!particles/disguise.pcf" 28 | "file" "!particles/sparks.pcf" 29 | "file" "!particles/flag_particles.pcf" 30 | "file" "!particles/buildingdamage.pcf" 31 | "file" "!particles/shellejection.pcf" 32 | "file" "!particles/medicgun_attrib.pcf" 33 | "file" "!particles/item_fx.pcf" 34 | "file" "!particles/cinefx.pcf" 35 | "file" "!particles/impact_fx.pcf" 36 | "file" "!particles/conc_stars.pcf" 37 | "file" "!particles/class_fx.pcf" 38 | "file" "!particles/dirty_explode.pcf" 39 | "file" "!particles/smoke_blackbillow_hoodoo.pcf" 40 | } 41 | 42 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/scorch1.vmt: -------------------------------------------------------------------------------- 1 | "DecalModulate" 2 | { 3 | "$translucent" 1 4 | "$basetexture" "Decals/scorch1" 5 | "$decal" 1 6 | "$decalscale" 0.25 7 | } 8 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/soundscapes_2fort.txt: -------------------------------------------------------------------------------- 1 | // DSP Effects 2 | // 0 : "Normal (off)" 3 | // 1 : "Generic" 4 | // 2 : "Metal Small" 5 | // 3 : "Metal Medium" 6 | // 4 : "Metal Large" 7 | // 5 : "Tunnel Small" 8 | // 6 : "Tunnel Medium" 9 | // 7 : "Tunnel Large" 10 | // 8 : "Chamber Small" 11 | // 9 : "Chamber Medium" 12 | // 10: "Chamber Large" 13 | // 11: "Bright Small" 14 | // 12: "Bright Medium" 15 | // 13: "Bright Large" 16 | // 14: "Water 1" 17 | // 15: "Water 2" 18 | // 16: "Water 3" 19 | // 17: "Concrete Small" 20 | // 18: "Concrete Medium" 21 | // 19: "Concrete Large" 22 | // 20: "Big 1" 23 | // 21: "Big 2" 24 | // 22: "Big 3" 25 | // 23: "Cavern Small" 26 | // 24: "Cavern Medium" 27 | // 25: "Cavern Large" 28 | // 26: "Weirdo 1" 29 | // 27: "Weirdo 2" 30 | // 28: "Weirdo 3" 31 | 32 | // ATTN_NONE 0.0f 33 | // ATTN_NORM 0.8f 75dB 34 | // ATTN_IDLE 2.0f 60dB 35 | // ATTN_STATIC 1.25f 66dB 36 | // ATTN_RICOCHET 1.5f 65dB 37 | // ATTN_GUNFIRE 0.27f 140dB 38 | 39 | // SNDLVL_50dB = 50, // 3.9 40 | // SNDLVL_55dB = 55, // 3.0 41 | // SNDLVL_IDLE = 60, // 2.0 42 | // SNDLVL_TALKING = 60, // 2.0 43 | // SNDLVL_60dB = 60, // 2.0 44 | // SNDLVL_65dB = 65, // 1.5 45 | // SNDLVL_STATIC = 66, // 1.25 46 | // SNDLVL_70dB = 70, // 1.0 47 | // SNDLVL_NORM = 75, 48 | // SNDLVL_75dB = 75, // 0.8 49 | // SNDLVL_80dB = 80, // 0.7 50 | // SNDLVL_85dB = 85, // 0.6 51 | // SNDLVL_90dB = 90, // 0.5 52 | // SNDLVL_95dB = 95, 53 | // SNDLVL_100dB = 100, // 0.4 54 | // SNDLVL_105dB = 105, 55 | // SNDLVL_120dB = 120, 56 | // SNDLVL_130dB = 130, 57 | // SNDLVL_GUNFIRE = 140, // 0.27 58 | // SNDLVL_140dB = 140, // 0.2 59 | // SNDLVL_150dB = 150, // 0.2 60 | 61 | 62 | "2fort.Underground" 63 | { 64 | "dsp" 1 65 | 66 | 67 | "playlooping" 68 | { 69 | volume ".6" 70 | "pitch" "100" 71 | "wave" ambient/underground.wav 72 | } 73 | 74 | "playlooping" 75 | { 76 | volume .30 77 | "pitch" "100" 78 | "wave" "ambient/machine_hum2.wav" 79 | } 80 | 81 | "playlooping" 82 | { 83 | "volume" ".75" 84 | "pitch" "100" 85 | "position" "0" 86 | "attenuation" "0.7" 87 | "wave" "ambient/machine_hum.wav" 88 | } 89 | 90 | "playlooping" 91 | { 92 | "volume" ".4" 93 | "pitch" "100" 94 | "position" "1" 95 | "attenuation" "0.7" 96 | "wave" "ambient/computer_tape.wav" 97 | } 98 | 99 | "playlooping" 100 | { 101 | "volume" ".75" 102 | "pitch" "100" 103 | "position" "2" 104 | "attenuation" "0.7" 105 | "wave" "ambient/computer_working.wav" 106 | } 107 | 108 | "playlooping" 109 | { 110 | "volume" ".4" 111 | "pitch" "100" 112 | "position" "3" 113 | "attenuation" "0.7" 114 | "wave" "ambient/computer_tape2.wav" 115 | } 116 | 117 | "playlooping" 118 | { 119 | "volume" ".75" 120 | "pitch" "100" 121 | "position" "4" 122 | "attenuation" "0.7" 123 | "wave" "ambient/command_center.wav" 124 | } 125 | 126 | "playlooping" 127 | { 128 | "volume" ".75" 129 | "pitch" "100" 130 | "position" "5" 131 | "attenuation" "0.7" 132 | "wave" "ambient/printer.wav" 133 | } 134 | } 135 | 136 | 2fort.Underground2 137 | { 138 | "dsp" "1" 139 | 140 | 141 | playlooping 142 | { 143 | "volume" ".6" 144 | "pitch" "100" 145 | "wave" "ambient/underground.wav" 146 | } 147 | 148 | "playlooping" 149 | { 150 | "volume" ".3" 151 | "pitch" "100" 152 | "wave" "ambient/machine_hum2.wav" 153 | } 154 | 155 | "playlooping" 156 | { 157 | "volume" ".75" 158 | "pitch" "100" 159 | "position" "0" 160 | "attenuation" "0.7" 161 | "wave" "ambient/machine_hum.wav" 162 | } 163 | 164 | "playlooping" 165 | { 166 | "volume" ".4" 167 | "pitch" "100" 168 | "position" "1" 169 | "attenuation" "0.7" 170 | "wave" "ambient/computer_tape.wav" 171 | } 172 | 173 | "playlooping" 174 | { 175 | "volume" ".75" 176 | "pitch" "100" 177 | "position" "2" 178 | "attenuation" "0.7" 179 | "wave" "ambient/computer_working.wav" 180 | } 181 | 182 | "playlooping" 183 | { 184 | "volume" ".4" 185 | "pitch" "100" 186 | "position" "3" 187 | "attenuation" "0.7" 188 | "wave" "ambient/computer_tape2.wav" 189 | } 190 | 191 | "playlooping" 192 | { 193 | "volume" ".85" 194 | "pitch" "100" 195 | "position" "4" 196 | "attenuation" "0.7" 197 | "wave" "ambient/command_center.wav" 198 | } 199 | 200 | "playlooping" 201 | { 202 | "volume" ".85" 203 | "pitch" "100" 204 | "position" "5" 205 | "attenuation" "0.7" 206 | "wave" "ambient/printer.wav" 207 | } 208 | } 209 | 210 | "2fort.OutdoorPond" 211 | { 212 | "dsp" "1" 213 | 214 | "playlooping" 215 | { 216 | "volume" ".35" 217 | "pitch" "100" 218 | "wave" "ambient/outdoors_quiet_birds.wav" 219 | } 220 | 221 | "playlooping" 222 | { 223 | "volume" ".35" 224 | "pitch" "100" 225 | "wave" "ambient/outdoors.wav" 226 | } 227 | 228 | "playlooping" 229 | { 230 | "volume" ".45" 231 | "pitch" "100" 232 | "wave" "ambient/pondlife.wav" 233 | } 234 | 235 | "playlooping" 236 | { 237 | "volume" ".15" 238 | "pitch" "100" 239 | "wave" "ambient/pondwater.wav" 240 | } 241 | 242 | "playrandom" 243 | { 244 | "time" "5,15" 245 | "volume" ".35" 246 | "pitch" "100" 247 | "position" "0" 248 | "attenuation" "0.25" 249 | "rndwave" 250 | { 251 | "wave" "ambient/cow1.wav" 252 | "wave" "ambient/cow2.wav" 253 | "wave" "ambient/cow3.wav" 254 | "wave" "ambient/bird1.wav" 255 | "wave" "ambient/bird2.wav" 256 | "wave" "ambient/bird3.wav" 257 | } 258 | } 259 | 260 | "playlooping" 261 | { 262 | "volume" ".35" 263 | "pitch" "100" 264 | "position" "1" 265 | "attenuation" "0.7" 266 | "wave" "ambient/train_engine_idle.wav" 267 | } 268 | 269 | "playlooping" 270 | { 271 | "volume" ".35" 272 | "pitch" "100" 273 | "position" "2" 274 | "attenuation" "0.7" 275 | "wave" "ambient/engine_idle.wav" 276 | } 277 | 278 | } 279 | 280 | 281 | "2fort.OutdoorFort" 282 | { 283 | "dsp" "1" 284 | 285 | "playlooping" 286 | { 287 | "volume" ".35" 288 | "pitch" "100" 289 | "wave" "ambient/outdoors_quiet_birds.wav" 290 | } 291 | 292 | "playlooping" 293 | { 294 | "volume" ".35" 295 | "pitch" "100" 296 | "wave" "ambient/outdoors.wav" 297 | } 298 | 299 | 300 | "playrandom" 301 | { 302 | "time" "5,15" 303 | "volume" ".35" 304 | "pitch" "100" 305 | "position" "0" 306 | "attenuation" "0.7" 307 | "rndwave" 308 | { 309 | "wave" "ambient/cow1.wav" 310 | "wave" "ambient/cow2.wav" 311 | "wave" "ambient/cow3.wav" 312 | "wave" "ambient/bird1.wav" 313 | "wave" "ambient/bird2.wav" 314 | "wave" "ambient/bird3.wav" 315 | } 316 | } 317 | 318 | 319 | "playlooping" 320 | { 321 | "volume" ".35" 322 | "pitch" "100" 323 | "position" "1" 324 | "attenuation" ".07" 325 | "wave" "ambient/factory_outdoor.wav" 326 | } 327 | } 328 | 329 | "2fort.Indoor" 330 | { 331 | "dsp" "1" 332 | 333 | "playlooping" 334 | { 335 | "volume" "1" 336 | "pitch" "100" 337 | "wave" "ambient/indoors.wav" 338 | } 339 | } -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/tf2_gameinfo.txt: -------------------------------------------------------------------------------- 1 | "GameInfo" 2 | { 3 | game "Team Fortress 2" 4 | gamelogo 1 5 | type multiplayer_only 6 | nomodels 1 7 | nohimodel 1 8 | nocrosshair 0 9 | hidden_maps 10 | { 11 | "test_speakers" 1 12 | "test_hardware" 1 13 | } 14 | nodegraph 0 15 | GameData "tf.fgd" 16 | InstancePath "maps/instances/" 17 | advcrosshair 1 18 | 19 | 20 | FileSystem 21 | { 22 | SteamAppId 440 // This will mount all the GCFs we need (240=CS:S, 220=HL2). 23 | ToolsAppId 211 // Tools will load this (ie: source SDK caches) to get things like materials\debug, materials\editor, etc. 24 | 25 | // 26 | // The code that loads this file automatically does a few things here: 27 | // 28 | // 1. For each "Game" search path, it adds a "GameBin" path, in \bin 29 | // 2. For each "Game" search path, it adds another "Game" path in front of it with _ at the end. 30 | // For example: c:\hl2\cstrike on a french machine would get a c:\hl2\cstrike_french path added to it. 31 | // 3. For the first "Game" search path, it adds a search path called "MOD". 32 | // 4. For the first "Game" search path, it adds a search path called "DEFAULT_WRITE_PATH". 33 | // 34 | 35 | // 36 | // Search paths are relative to the base directory, which is where hl2.exe is found. 37 | // 38 | // |gameinfo_path| points at the directory where gameinfo.txt is. 39 | // We always want to mount that directory relative to gameinfo.txt, so 40 | // people can mount stuff in c:\mymod, and the main game resources are in 41 | // someplace like c:\program files\valve\steam\steamapps\\half-life 2. 42 | // 43 | SearchPaths 44 | { 45 | Game |gameinfo_path|. 46 | Game tf 47 | Game |all_source_engine_paths|hl2 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/toolstrigger.vmt: -------------------------------------------------------------------------------- 1 | "LightmappedGeneric" 2 | { 3 | // Original shader: BaseTimesLightmapAlphaBlend 4 | "$translucent" 1 5 | "$basetexture" "Tools/toolstrigger" 6 | "%compiletrigger" 1 7 | "%keywords" "airexchange,borealis,c17downtown,c17industrial,c17sewers,c17skyscraper,c17trainstation,combine,kraken,wasteland" 8 | } 9 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/utest.ent: -------------------------------------------------------------------------------- 1 | { 2 | "world_maxs" "496 496 496" 3 | "world_mins" "-496 -496 16" 4 | "skyname" "some_sky_texture" 5 | "maxpropscreenwidth" "-1" 6 | "detailvbsp" "detail_custom.vbsp" 7 | "detailmaterial" "detail/detailsprites_custom" 8 | "classname" "worldspawn" 9 | "mapversion" "5" 10 | "hammerid" "1" 11 | } 12 | { 13 | "origin" "384 -384 128" 14 | "volstart" "0" 15 | "spinup" "0" 16 | "spindown" "0" 17 | "spawnflags" "48" 18 | "radius" "1250" 19 | "preset" "0" 20 | "pitchstart" "100" 21 | "pitch" "100" 22 | "message" "Ambient.Factory" 23 | "lfotype" "0" 24 | "lforate" "0" 25 | "lfomodvol" "0" 26 | "lfomodpitch" "0" 27 | "health" "10" 28 | "fadeoutsecs" "0" 29 | "fadeinsecs" "0" 30 | "cspinup" "0" 31 | "classname" "ambient_generic" 32 | "hammerid" "19" 33 | } 34 | { 35 | "origin" "320 -384 128" 36 | "volstart" "0" 37 | "spinup" "0" 38 | "spindown" "0" 39 | "spawnflags" "48" 40 | "radius" "1250" 41 | "preset" "0" 42 | "pitchstart" "100" 43 | "pitch" "100" 44 | "message" "ambient/alarms/warningbell1.wav" 45 | "lfotype" "0" 46 | "lforate" "0" 47 | "lfomodvol" "0" 48 | "lfomodpitch" "0" 49 | "health" "10" 50 | "fadeoutsecs" "0" 51 | "fadeinsecs" "0" 52 | "cspinup" "0" 53 | "classname" "ambient_generic" 54 | "hammerid" "34" 55 | } 56 | { 57 | "origin" "256 -384 128" 58 | "SunSpreadAngle" "0" 59 | "pitch" "0" 60 | "angles" "0 0 0" 61 | "_lightscaleHDR" "1" 62 | "_lightHDR" "-1 -1 -1 1" 63 | "_light" "255 255 255 200" 64 | "_AmbientScaleHDR" "1" 65 | "_ambientHDR" "-1 -1 -1 1" 66 | "_ambient" "255 255 255 20" 67 | "classname" "light_environment" 68 | "hammerid" "68" 69 | } 70 | { 71 | "origin" "192 -384 128" 72 | "start_active" "0" 73 | "effect_name" "some_particle_system" 74 | "cpoint7_parent" "0" 75 | "cpoint6_parent" "0" 76 | "cpoint5_parent" "0" 77 | "cpoint4_parent" "0" 78 | "cpoint3_parent" "0" 79 | "cpoint2_parent" "0" 80 | "cpoint1_parent" "0" 81 | "angles" "0 0 0" 82 | "classname" "info_particle_system" 83 | "hammerid" "75" 84 | } 85 | { 86 | "origin" "384 -320 128" 87 | "soundscape" "custom.soundscape" 88 | "radius" "128" 89 | "classname" "env_soundscape" 90 | "hammerid" "341" 91 | } 92 | 93 | 94 | -------------------------------------------------------------------------------- /hl2parse-tests/src/test/resources/com/technofovea/hl2parse/vdf/water_2fort.vmt: -------------------------------------------------------------------------------- 1 | "Water" 2 | { 3 | 4 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /license_header.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 Darien Hager 2 | 3 | This code is part of the "HL2Parse" project, and is licensed under 4 | a Creative Commons Attribution-ShareAlike 3.0 Unported License. For 5 | either a summary of conditions or the full legal text, please visit: 6 | 7 | http://creativecommons.org/licenses/by-sa/3.0/ 8 | 9 | Permissions beyond the scope of this license may be available 10 | at http://technofovea.com/ . 11 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | HL2Parse is a library for interpreting certain files from Valve Software and the "Source" game engine. 2 | 3 | You may use it through the Maven repository by adding the following to your POM: 4 | 5 | 6 | 7 | dhager-github 8 | DHager's Github Maven Repository 9 | http://dhager.github.com/mvn-repo/releases 10 | 11 | --------------------------------------------------------------------------------