User:Fuebar: Difference between revisions

From PZwiki
(-- →‎File Formats: for modding or whatever.)
 
m (-- clear the documentation from my user page)
 
Line 1: Line 1:
==File Formats==
[[Modding/File Formats|File format documentation]].
 
Since I'm not sure where to put this for now, or if it's warranted, here it is, for nobody to read or use and for me to procrastinate. Up-to-date as of build 12 (2013-11-12).
 
===map_sand.bin===
 
A simple contiguous array of big-endian 32-bit integers. On loading, each integer is stored in a specific global option variable used to control things like zombie attributes and game speed, when the power will go out, etc. All the options you can set at the creation of a Sandbox game. Useful for tweaking options after you've already created your game.
 
Note: If the world version is < 5 (world version is read in as a big-endian 32-bit integer from '''map_ver.bin''' the same way these are), you have to leave out Temperature and Rain when reading in variables.
 
<code>
    <font color="blue">int</font> Zombies, Distribution, Survivors, Speed, DayLength, StartMonth, StartTime, WaterShut, ElecShut, Loot, Temperature, Rain;
    <font color="blue">static class ZombieStats</font>
    {
        <font color="blue">static int</font> Speed, Strength, Toughness, Transmission, Mortality, Reanimate, Cognition, Memory, Decomposition, Sight, Hearing, Smell;
    }<br>
    BigEndianBinaryReader br; <font color="#008000">// implementation left out for brevity. anything that can read four bytes in big-endian order from a file works.</font><br>
    Zombies = br.ReadInt32();
    Distribution = br.ReadInt32();
    . . .
    Rain = br.ReadInt32();<br>
    ZombieStats.Speed = br.ReadInt32();
    . . .
    ZombieStats.Smell = br.ReadInt32();
    <font color="#008000">// order is essential, exactly as listed above in the int declarations</font>
</code>
 
If any new Sandbox options are added in you'll have to check /zombie/SandboxOptions.class (decompile it with Java Decompiler) and look at the load() function.
 
Example file contents:
<code>
    00 00 00 03 | 00 00 00 01 | 00 00 00 01 | 00 00 00 03
    00 00 00 05 | 00 00 00 07 | 00 00 00 01 | 00 00 00 05
    etc., total of six lines of this length
</code>
 
===TexturePacks (.pack files)===
These are the files located in /media/texturepacks/, Characters.pack, Tiles.pack, and UI.pack. Reading them is simple, the implementation will probably be 20 or 30 lines long.
 
Each file contains a number of 'pages' which are basically PNG images with an associated array of offset coordinates, widths, heights, and names, that are specify smaller rectangles on the PNG file that are to be copied into their own individual images. This is called a [https://en.wikipedia.org/wiki/Texture_atlas texture atlas] and is a common practice in game development.
 
The integers in this file are little-endian, i.e. the least significant bytes come first. This is the default on my system, so no special stream reader was required, but you may have to use/write a little-endian reader if your system defaults to big-endian.
 
The first four bytes of the file specify a 32-bit integer, which tells you how many pages (atlas images) are located within. Every byte after this belongs to a page, and follows the structure outlined below.
<code>
    int32, length of the char[] to follow
    char[], name of this texture page
    int32, number of entries in the page
    int32, represents a boolean value, true if non-zero. Titled 'mask' in the code, honestly not sure what it does. Not necessary for extraction purposes.<br>
    [entries - outlined below]<br>
    byte[], PNG data, byte[] { 49, 45, 4E, 44, AE, 42, 60, 82, EF, BE, AD, DE } marks the end of the file, they don't have to be included in the PNG's byte array.
    The next page starts immediately after the byte pattern specified above.
</code>
 
The first entry comes immediately after the <code>mask</code> int32, there are as many entries as determined by the int preceding <code>mask</code>. You'll probably want to create a struct/class to hold the info contained in each entry, though you could do with indexed arrays as well. Each entry contains the info you need to copy the subimages out of the PNG data, and some information irrelevant to that as well.
The format is most easily demonstrated with code.
<code>
    int32, length of the char[] to follow
    char[], name of this specific subtexture
    int32, x-coord of the upper left corner of this subimage on the subtexture
    int32, y-coord of the upper left corner of this subimage on the subtexture
    int32, width of the subtexture
    int32, height of the subtexture
    int32, number of pixels of transparent padding to the left of the image (i.e., x offset)
    int32, number of pixels of transparent padding on top of the image (i.e., y offset)
    int32, actual width of the subtexture, after including padding. Sometimes width + x-offset is less than this value, in which case padding is required on the right as well.
    int32, actual height of the subtexture, after including padding. Sometimes height + y-offset is less than this value, in which case padding is required at the bottom as well.
</code>
 
In simpler terms, the first int32 of the entry contains the length of the char array defining its name that follows it. The next eight int32s fill the values { x, y, w, h, ox, oy, fx, fy }. After the last int32 of the subtexture's entry, if we're not on the last subtexture, the following int32 will define the length of the char array defining that subtexture's name and so on.
 
(x, y) = offset within the entire PNG the image begins at<br>
(w, h) = size of the image ''on the atlas''<br>
(ox, oy) = offset within the (fx, fy) bounds to put the upper left corner of the image we got from (x, y)<br>
(fx, fy) = full desired size of the images, for most inventory images this is 32x32<br>
 
For example, the Apple inventory item entry on the page 'ninventory0' has the following values: <code>x = 184, y = 274, w = 28, h = 32, ox = 3, oy = 0, fx = 32, fy = 32;</code>
 
So to get this image, we'd load the PNG data following these entries into memory, use some method to cut a 28x32 subtexture out of the PNG at (184, 274), and then write those pixels into a 32x32 image beginning at (3, 0).

Latest revision as of 07:33, 14 November 2013