Package com.pointcliki.dizgruntled.rez

Source Code of com.pointcliki.dizgruntled.rez.MonolithWWD

package com.pointcliki.dizgruntled.rez;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

import org.newdawn.slick.Image;
import org.newdawn.slick.geom.Vector2f;

import com.pointcliki.dizgruntled.GruntzGame;
import com.pointcliki.dizgruntled.Logic;
import com.pointcliki.dizgruntled.LogicFactory;

/**
* This class represents and parses a WapWorld level.
*
* @author Hugheth
* @since alpha 2.5
*/
public class MonolithWWD {

    protected MonolithFile fFile;
    protected Image fImage;
    protected Vector2f fOffset;
    protected int fWidth;
    protected int fHeight;
    protected int fWorld;
    protected int[] fTiles;
    protected Logic[] fLogics;
   
    /**
     * Create a new WWD representation
     * @param file The monolith file that contains the WWD file's data
     */
    public MonolithWWD(MonolithFile file) {
      fFile = file;
         
      // Get the world i.e. Rocky Roads
      fWorld = file.data()[469] - 48;
     
      // Get the uncompressed raw data to parse tiles and logics
      byte[] s = raw();
     
      // Get the width and height of the map, in tiles
      fWidth = MonolithResource.readInteger(s, 96);
      fHeight = MonolithResource.readInteger(s, 100);
     
      /*
      FileOutputStream w;
      try {
        w = new FileOutputStream("out.txt");
        w.write(s);
        w.close();
      } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      */
     
      int n = 160;
      // If we are in a map with a scrolling background, skip past the first
      // tile group as this draws the background
      if (MonolithResource.readByte(s, 16) == 66) {
        int area2 = fWidth * fHeight;
        fWidth = MonolithResource.readInteger(s, 256);
        fHeight = MonolithResource.readInteger(s, 260);

        n = 320 + area2 * 4;
      }
     
      // Get the area of the map
      int area = fWidth * fHeight;
      fTiles = new int[area];
     
      // Read the tile data
      for (int i = 0; i < area; i++) {
        fTiles[i] = MonolithResource.readInteger(s, n);
        n += 4;
      }
     
      // Store the logics
      ArrayList<Logic> logics = new ArrayList<Logic>();
     
      // Create a logic factory to handle the creation of in-game logics
      LogicFactory factory = new LogicFactory();
     
      int l = s.length;
      // Skip to the start of the logics
      n += 7;
      // If we have a scrolling background we need to skip some more
      if (MonolithResource.readInteger(s, n) == 1313818964) n += 5;
           
      // Read logics
      try {
        while (n + 284 < l) {
          // Data of the logic
          int dataOffset = n;
          // String lengths
          int nameLength = MonolithResource.readInteger(s, n + 4);
          int logicLength = MonolithResource.readInteger(s, n + 8);
          int graphicLength = MonolithResource.readInteger(s, n + 12);
          int aniLength = MonolithResource.readInteger(s, n + 16);
         
          if (logicLength == 0) break;
         
          // Skip to name / image / animation of the logic
          n += 284;
         
          // Get the logic, graphic file and animation/sound file if there is one
          n += nameLength;
          String logicRef = new String(Arrays.copyOfRange(s, n, n + logicLength));
          n += logicLength;
          String graphicRef = new String(Arrays.copyOfRange(s, n, n + graphicLength)).replace('_', '/');
          n += graphicLength;
          String aniRef = new String(Arrays.copyOfRange(s, n, n + aniLength)).replace('_', '/');
          n += aniLength;
         
          if (!logicRef.matches("[A-Za-z]+")) break;
         
          // Map to correct world if a level reference
          if (graphicRef.startsWith("LEVEL")) graphicRef = "AREA" + fWorld + "/IMAGEZ" + graphicRef.substring(5);
          else if (graphicRef.length() > 0) graphicRef = "GAME/IMAGEZ" + graphicRef.substring(4);
         
          if (aniRef.startsWith("LEVEL")) aniRef = "AREA" + fWorld + "/ANIZ" + aniRef.substring(5);
          else if (aniRef.length() > 0) aniRef = "GAME/ANIZ" + aniRef.substring(4);
         
          // For some reason, ambient files are sometimes incorrectly called "AREAXLOOP" rather than "AMBIENTXLOOP"
          if (GruntzGame.resourceManager().rez().file(aniRef, "ani") == null) aniRef = aniRef.replace("AREA", "AMBIENT");
         
          // Check that the string exists
          Logic log = factory.createFromWWD(logicRef, graphicRef, aniRef, Arrays.copyOfRange(s, dataOffset, dataOffset + 284));
          if (log != null) logics.add(log);
          else if (!logicRef.equals("GiantRock")) System.err.println("Failed to find controller for logic " + logicRef);
        }
      } catch (Exception e) {
        // Finish parsing errors if an exception occurs
      }
      fLogics = logics.toArray(new Logic[logics.size()]);
      // Print out parse count
      System.out.println("Loaded WWD with " + logics.size() + " logics");
    }
   
    /**
     * This method decompresses the compressed part of the file
     * that stores all the tile and logic information of the map.
     *
     * @return The decompressed data
     */
    public byte[] raw() {
      byte[] b = Arrays.copyOfRange(fFile.data(), 1524, fFile.data().length - 1);
      // WWD uses the deflate algorithm, so use an inflater
      Inflater d = new Inflater();
      d.setInput(b, 0, b.length);
      ByteArrayOutputStream output = new ByteArrayOutputStream(1024);
      try {
        int count = 1;
        byte[] out = new byte[1024];
        while (!d.finished() && count > 0) {
          count = d.inflate(out);
                output.write(out, 0, count);
        }
        output.close();
        return output.toByteArray();
      } catch (DataFormatException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return null;
    }

    public int width() {
      return fWidth;
    }
    public int height() {
      return fHeight;
    }
   
    public int tile(int i) {
      return fTiles[i];
    }
   
    public int world() {
      return fWorld;
    }
   
    public Logic[] logics() {
      return fLogics;
    }
   
    public static int readID(byte[] data) {
      return MonolithResource.readInteger(data, 0);
    }
   
    public static Vector2f readPosition(byte[] data) {
      return new Vector2f(MonolithResource.readInteger(data, 20), MonolithResource.readInteger(data, 24));
    }
    public static int readPowerup(byte[] data) {
      return MonolithResource.readInteger(data, 60);
    }
    public static int readPoints(byte[] data) {
      return MonolithResource.readInteger(data, 56);
    }
    public static int readSmarts(byte[] data) {
      return MonolithResource.readInteger(data, 68);
    }
    public static int readSpeed(byte[] data) {
      return MonolithResource.readInteger(data, 240);
    }
    public static int readRect(byte[] data, int n) {
      return MonolithResource.readInteger(data, 76 + n * 4);
    }
    public static int readDamage(byte[] data) {
      return MonolithResource.readInteger(data, 64);
    }
    public static int readHealth(byte[] data) {
      return MonolithResource.readInteger(data, 72);
    }
}
TOP

Related Classes of com.pointcliki.dizgruntled.rez.MonolithWWD

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.