/*
* Copyright (C) 2006-2011 IsmAvatar <IsmAvatar@gmail.com>
* Copyright (C) 2006, 2007, 2008 Clam <clamisgood@gmail.com>
* Copyright (C) 2007, 2009 Quadduc <quadduc@gmail.com>
*
* This file is part of LateralGM.
* LateralGM is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package org.lateralgm.file;
import static org.lateralgm.main.Util.deRef;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.List;
import org.lateralgm.components.impl.ResNode;
import org.lateralgm.file.iconio.ICOFile;
import org.lateralgm.main.Util;
import org.lateralgm.resources.Background;
import org.lateralgm.resources.Font;
import org.lateralgm.resources.GameInformation;
import org.lateralgm.resources.GameSettings;
import org.lateralgm.resources.GmObject;
import org.lateralgm.resources.Include;
import org.lateralgm.resources.Path;
import org.lateralgm.resources.Resource;
import org.lateralgm.resources.ResourceReference;
import org.lateralgm.resources.Room;
import org.lateralgm.resources.Script;
import org.lateralgm.resources.Sound;
import org.lateralgm.resources.Sprite;
import org.lateralgm.resources.Timeline;
import org.lateralgm.resources.Background.PBackground;
import org.lateralgm.resources.Font.PFont;
import org.lateralgm.resources.GameInformation.PGameInformation;
import org.lateralgm.resources.GameSettings.PGameSettings;
import org.lateralgm.resources.GameSettings.ProgressBar;
import org.lateralgm.resources.GmObject.PGmObject;
import org.lateralgm.resources.Path.PPath;
import org.lateralgm.resources.Room.PRoom;
import org.lateralgm.resources.Script.PScript;
import org.lateralgm.resources.Sound.PSound;
import org.lateralgm.resources.Sprite.PSprite;
import org.lateralgm.resources.library.LibAction;
import org.lateralgm.resources.sub.Action;
import org.lateralgm.resources.sub.ActionContainer;
import org.lateralgm.resources.sub.Argument;
import org.lateralgm.resources.sub.BackgroundDef;
import org.lateralgm.resources.sub.Constant;
import org.lateralgm.resources.sub.Event;
import org.lateralgm.resources.sub.Instance;
import org.lateralgm.resources.sub.MainEvent;
import org.lateralgm.resources.sub.Moment;
import org.lateralgm.resources.sub.PathPoint;
import org.lateralgm.resources.sub.Tile;
import org.lateralgm.resources.sub.Trigger;
import org.lateralgm.resources.sub.View;
import org.lateralgm.resources.sub.BackgroundDef.PBackgroundDef;
import org.lateralgm.resources.sub.Instance.PInstance;
import org.lateralgm.resources.sub.Tile.PTile;
import org.lateralgm.resources.sub.View.PView;
import org.lateralgm.util.PropertyMap;
public final class GmFileWriter
{
private GmFileWriter()
{
}
public static void writeGmFile(GmFile f, ResNode root) throws IOException
{
int ver = f.fileVersion;
long savetime = System.currentTimeMillis();
GmStreamEncoder out = null;
out = new GmStreamEncoder(f.filename);
out.write4(1234321);
out.write4(ver);
if (ver == 530) out.write4(0);
int gameId = f.gameSettings.get(PGameSettings.GAME_ID);
if (ver == 701)
{
out.write4(0); //bob
out.write4(0); //fred
out.write4(248); //seed
out.write(gameId & 0xFF);
out.setSeed(248);
out.write3(gameId >>> 8);
}
else
out.write4(gameId);
out.write((byte[]) f.gameSettings.get(PGameSettings.DPLAY_GUID)); //16 bytes
writeSettings(f,out,savetime);
if (ver >= 800)
{
writeTriggers(f,out);
writeConstants(f,out);
}
writeSounds(f,out);
writeSprites(f,out);
writeBackgrounds(f,out);
writePaths(f,out);
writeScripts(f,out);
writeFonts(f,out);
writeTimelines(f,out);
writeGmObjects(f,out);
writeRooms(f,out);
out.write4(f.lastInstanceId);
out.write4(f.lastTileId);
if (ver >= 700)
{
writeIncludedFiles(f,out);
writePackages(f,out);
}
writeGameInformation(f,out);
//Library Creation Code
out.write4(500);
out.write4(0);
//Room Execution Order
out.write4(ver >= 700 ? 700 : 540);
out.write4(0);
writeTree(out,root);
out.close();
}
public static void writeSettings(GmFile f, GmStreamEncoder out, long savetime) throws IOException
{
int ver = f.fileVersion;
ver = ver >= 810 ? 810 : ver >= 800 ? 800 : ver >= 701 ? 702 : ver;
out.write4(ver >= 800 ? 800 : ver);
if (ver >= 800) out.beginDeflate();
GameSettings g = f.gameSettings;
PropertyMap<PGameSettings> p = g.properties;
out.writeBool(p,PGameSettings.START_FULLSCREEN);
if (ver >= 600) out.writeBool(p,PGameSettings.INTERPOLATE);
out.writeBool(p,PGameSettings.DONT_DRAW_BORDER,PGameSettings.DISPLAY_CURSOR);
out.write4(p,PGameSettings.SCALING);
out.writeBool(p,PGameSettings.ALLOW_WINDOW_RESIZE,PGameSettings.ALWAYS_ON_TOP);
out.write4(Util.getGmColor((Color) p.get(PGameSettings.COLOR_OUTSIDE_ROOM)));
out.writeBool(p,PGameSettings.SET_RESOLUTION);
out.write4(GmFile.GS_DEPTH_CODE.get(p.get(PGameSettings.COLOR_DEPTH)));
out.write4(GmFile.GS_RESOL_CODE.get(p.get(PGameSettings.RESOLUTION)));
out.write4(GmFile.GS_FREQ_CODE.get(p.get(PGameSettings.FREQUENCY)));
out.writeBool(p,PGameSettings.DONT_SHOW_BUTTONS,PGameSettings.USE_SYNCHRONIZATION);
if (ver >= 800) out.writeBool(p,PGameSettings.DISABLE_SCREENSAVERS);
out.writeBool(p,PGameSettings.LET_F4_SWITCH_FULLSCREEN,PGameSettings.LET_F1_SHOW_GAME_INFO,
PGameSettings.LET_ESC_END_GAME,PGameSettings.LET_F5_SAVE_F6_LOAD);
if (ver >= 702)
out.writeBool(p,PGameSettings.LET_F9_SCREENSHOT,PGameSettings.TREAT_CLOSE_AS_ESCAPE);
out.write4(GmFile.GS_PRIORITY_CODE.get(p.get(PGameSettings.GAME_PRIORITY)));
out.writeBool(p,PGameSettings.FREEZE_ON_LOSE_FOCUS);
out.write4(GmFile.GS_PROGBAR_CODE.get(p.get(PGameSettings.LOAD_BAR_MODE)));
if (p.get(PGameSettings.LOAD_BAR_MODE) == ProgressBar.CUSTOM)
{
if (p.get(PGameSettings.BACK_LOAD_BAR) != null)
{
out.write4(ver < 800 ? 10 : 1);
out.writeZlibImage((BufferedImage) p.get(PGameSettings.BACK_LOAD_BAR));
}
else
out.write4(ver < 800 ? -1 : 0);
if (p.get(PGameSettings.FRONT_LOAD_BAR) != null)
{
out.write4(ver < 800 ? 10 : 1);
out.writeZlibImage((BufferedImage) p.get(PGameSettings.FRONT_LOAD_BAR));
}
else
out.write4(ver < 800 ? -1 : 0);
}
out.writeBool(p,PGameSettings.SHOW_CUSTOM_LOAD_IMAGE);
if (p.get(PGameSettings.SHOW_CUSTOM_LOAD_IMAGE))
{
if (p.get(PGameSettings.LOADING_IMAGE) != null)
{
out.write4(ver < 800 ? 10 : 1);
out.writeZlibImage((BufferedImage) p.get(PGameSettings.LOADING_IMAGE));
}
else
out.write4(ver < 800 ? -1 : 0);
}
out.writeBool(p,PGameSettings.IMAGE_PARTIALLY_TRANSPARENTY);
out.write4(p,PGameSettings.LOAD_IMAGE_ALPHA);
out.writeBool(p,PGameSettings.SCALE_PROGRESS_BAR);
//FIXME: GM8 icons
Util.fixIcon((ICOFile) g.get(PGameSettings.GAME_ICON),f.fileVersion);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
((ICOFile) g.get(PGameSettings.GAME_ICON)).write(baos);
out.write4(baos.size());
baos.writeTo(out);
out.writeBool(p,PGameSettings.DISPLAY_ERRORS,PGameSettings.WRITE_TO_LOG,
PGameSettings.ABORT_ON_ERROR);
out.write4((p.get(PGameSettings.TREAT_UNINIT_AS_0) ? 1 : 0)
| ((Boolean) p.get(PGameSettings.ERROR_ON_ARGS) && ver >= 810 ? 2 : 0));
out.writeStr(p,PGameSettings.AUTHOR);
if (ver <= 600)
{
try
{
out.write4(Integer.parseInt((String) p.get(PGameSettings.VERSION)));
}
catch (NumberFormatException e)
{
out.write4(100);
}
}
else
out.writeStr(p,PGameSettings.VERSION);
p.put(PGameSettings.LAST_CHANGED,GmFile.longTimeToGmTime(savetime));
out.writeD(p,PGameSettings.LAST_CHANGED);
out.writeStr(p,PGameSettings.INFORMATION);
if (ver < 800)
{
out.write4(f.constants.size());
for (Constant con : f.constants)
{
out.writeStr(con.name);
out.writeStr(con.value);
}
if (ver == 542 || ver == 600)
{
out.write4(f.includes.size());
for (Include inc : f.includes)
out.writeStr(inc.filepath);
out.write4(GmFile.GS_INCFOLDER_CODE.get(p.get(PGameSettings.INCLUDE_FOLDER)));
out.writeBool(p,PGameSettings.OVERWRITE_EXISTING,PGameSettings.REMOVE_AT_GAME_END);
}
}
if (ver >= 702)
{
out.write4(p,PGameSettings.VERSION_MAJOR,PGameSettings.VERSION_MINOR,
PGameSettings.VERSION_RELEASE,PGameSettings.VERSION_BUILD);
out.writeStr(p,PGameSettings.COMPANY,PGameSettings.PRODUCT,PGameSettings.COPYRIGHT,
PGameSettings.DESCRIPTION);
if (ver >= 800) out.writeD(g.getLastChanged());
}
out.endDeflate();
}
public static void writeTriggers(GmFile f, GmStreamEncoder out) throws IOException
{
if (f.fileVersion < 800) return;
out.write4(800);
out.write4(f.triggers.size());
for (Trigger t : f.triggers)
{
out.beginDeflate();
out.writeBool(true); //trigger exists
out.write4(800);
out.writeStr(t.name);
out.writeStr(t.condition);
out.write4(t.checkStep);
out.writeStr(t.constant);
out.endDeflate();
}
out.writeD(f.gameSettings.getLastChanged());
}
public static void writeConstants(GmFile f, GmStreamEncoder out) throws IOException
{
if (f.fileVersion < 800) return;
out.write4(800);
out.write4(f.constants.size());
for (Constant c : f.constants)
{
out.writeStr(c.name);
out.writeStr(c.value);
}
out.writeD(f.gameSettings.getLastChanged());
}
public static void writeSounds(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
ver = ver >= 800 ? 800 : ver >= 600 ? 600 : 440;
out.write4(ver == 800 ? 800 : 400);
out.write4(f.sounds.lastId + 1);
for (int i = 0; i <= f.sounds.lastId; i++)
{
if (ver == 800) out.beginDeflate();
Sound snd = f.sounds.getUnsafe(i);
out.writeBool(snd != null);
if (snd != null)
{
out.writeStr(snd.getName());
if (ver == 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(ver);
out.write4(GmFile.SOUND_CODE.get(snd.get(PSound.KIND)));
out.writeStr(snd.properties,PSound.FILE_TYPE,PSound.FILE_NAME);
if (snd.data != null)
{
out.writeBool(true);
if (ver == 800)
{
out.write4(snd.data.length);
out.write(snd.data);
}
else
out.compress(snd.data);
}
else
out.writeBool(false);
int effects = 0;
int n = 1;
for (PSound k : GmFile.SOUND_FX_FLAGS)
{
if (snd.get(k)) effects |= n;
n <<= 1;
}
out.write4(effects);
out.writeD(snd.properties,PSound.VOLUME,PSound.PAN);
out.writeBool(snd.properties,PSound.PRELOAD);
}
out.endDeflate();
}
}
public static void writeSprites(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
ver = ver >= 800 ? 800 : ver >= 542 ? 542 : 400;
out.write4(ver == 800 ? 800 : 400);
out.write4(f.sprites.lastId + 1);
for (int i = 0; i <= f.sprites.lastId; i++)
{
if (ver == 800) out.beginDeflate();
Sprite spr = f.sprites.getUnsafe(i);
out.writeBool(spr != null);
if (spr != null)
{
out.writeStr(spr.getName());
if (ver == 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(ver);
if (ver < 800)
{
out.write4(spr.subImages.getWidth());
out.write4(spr.subImages.getHeight());
out.write4(spr.properties,PSprite.BB_LEFT,PSprite.BB_RIGHT,PSprite.BB_BOTTOM,
PSprite.BB_TOP);
out.writeBool(spr.properties,PSprite.TRANSPARENT,PSprite.SMOOTH_EDGES,PSprite.PRELOAD);
out.write4(GmFile.SPRITE_BB_CODE.get(spr.get(PSprite.BB_MODE)));
out.writeBool(spr.get(PSprite.SHAPE) == Sprite.MaskShape.PRECISE);
}
out.write4(spr.properties,PSprite.ORIGIN_X,PSprite.ORIGIN_Y);
out.write4(spr.subImages.size());
for (int j = 0; j < spr.subImages.size(); j++)
{
BufferedImage sub = spr.subImages.get(j);
if (ver == 800)
{
out.write4(800);
int w = sub.getWidth();
int h = sub.getHeight();
out.write4(w);
out.write4(h);
if (w != 0 && h != 0) out.writeBGRAImage(sub,(Boolean) spr.get(PSprite.TRANSPARENT));
}
else
{
out.write4(10);
out.writeZlibImage(sub);
}
}
if (ver >= 800)
{
out.write4(GmFile.SPRITE_MASK_CODE.get(spr.get(PSprite.SHAPE)));
out.write4(spr.properties,PSprite.ALPHA_TOLERANCE);
out.writeBool(spr.properties,PSprite.SEPARATE_MASK);
out.write4(GmFile.SPRITE_BB_CODE.get(spr.get(PSprite.BB_MODE)));
out.write4(spr.properties,PSprite.BB_LEFT,PSprite.BB_RIGHT,PSprite.BB_BOTTOM,
PSprite.BB_TOP);
}
}
out.endDeflate();
}
}
public static void writeBackgrounds(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
ver = ver >= 710 ? 710 : ver >= 543 ? 543 : 400;
out.write4(ver == 710 ? 800 : 400);
out.write4(f.backgrounds.lastId + 1);
for (int i = 0; i <= f.backgrounds.lastId; i++)
{
if (ver == 710) out.beginDeflate();
Background back = f.backgrounds.getUnsafe(i);
out.writeBool(back != null);
if (back != null)
{
out.writeStr(back.getName());
if (ver == 710) out.writeD(f.gameSettings.getLastChanged());
out.write4(ver);
if (ver < 710)
{
out.write4(back.getWidth());
out.write4(back.getHeight());
out.writeBool(back.properties,PBackground.TRANSPARENT,PBackground.SMOOTH_EDGES,
PBackground.PRELOAD,PBackground.USE_AS_TILESET);
}
else
out.writeBool(back.properties,PBackground.USE_AS_TILESET);
out.write4(back.properties,PBackground.TILE_WIDTH,PBackground.TILE_HEIGHT,
PBackground.H_OFFSET,PBackground.V_OFFSET,PBackground.H_SEP,PBackground.V_SEP);
BufferedImage bi = back.getBackgroundImage();
if (ver < 710)
{
if (bi != null)
{
out.writeBool(true);
out.write4(10);
out.writeZlibImage(bi);
}
else
out.writeBool(false);
}
else
{
out.write4(800);
int w = bi == null ? 0 : bi.getWidth();
int h = bi == null ? 0 : bi.getHeight();
out.write4(w);
out.write4(h);
if (w != 0 && h != 0) out.writeBGRAImage(bi,(Boolean) back.get(PBackground.TRANSPARENT));
}
}
out.endDeflate();
}
}
public static void writePaths(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
if (ver > 800) ver = 800;
out.write4(ver == 800 ? 800 : 420);
out.write4(f.paths.lastId + 1);
for (int i = 0; i <= f.paths.lastId; i++)
{
if (ver == 800) out.beginDeflate();
Path path = f.paths.getUnsafe(i);
out.writeBool(path != null);
if (path != null)
{
out.writeStr(path.getName());
if (ver == 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(530);
out.writeBool(path.properties,PPath.SMOOTH,PPath.CLOSED);
out.write4(path.properties,PPath.PRECISION);
out.writeId((ResourceReference<?>) path.get(PPath.BACKGROUND_ROOM));
out.write4(path.properties,PPath.SNAP_X,PPath.SNAP_Y);
out.write4(path.points.size());
for (PathPoint p : path.points)
{
out.writeD(p.getX());
out.writeD(p.getY());
out.writeD(p.getSpeed());
}
}
out.endDeflate();
}
}
public static void writeScripts(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
ver = ver >= 800 ? 800 : 400;
out.write4(ver);
out.write4(f.scripts.lastId + 1);
for (int i = 0; i <= f.scripts.lastId; i++)
{
if (ver == 800) out.beginDeflate();
Script scr = f.scripts.getUnsafe(i);
out.writeBool(scr != null);
if (scr != null)
{
out.writeStr(scr.getName());
if (ver == 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(ver);
out.writeStr(scr.properties,PScript.CODE);
}
out.endDeflate();
}
}
public static void writeFonts(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
out.write4(ver >= 800 ? 800 : 540);
out.write4(f.fonts.lastId + 1);
for (int i = 0; i <= f.fonts.lastId; i++)
{
if (ver >= 800) out.beginDeflate();
Font font = f.fonts.getUnsafe(i);
out.writeBool(font != null);
if (font != null)
{
out.writeStr(font.getName());
if (ver >= 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(ver >= 800 ? 800 : 540);
out.writeStr(font.properties,PFont.FONT_NAME);
out.write4(font.properties,PFont.SIZE);
out.writeBool(font.properties,PFont.BOLD,PFont.ITALIC);
if (ver >= 810)
{
out.write2((Integer) font.get(PFont.RANGE_MIN));
out.write((Integer) font.get(PFont.CHARSET));
out.write((Integer) font.get(PFont.ANTIALIAS));
}
else
out.write4(font.properties,PFont.RANGE_MIN);
out.write4(font.properties,PFont.RANGE_MAX);
}
out.endDeflate();
}
}
public static void writeTimelines(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
if (ver > 800) ver = 800;
out.write4(ver == 800 ? 800 : 500);
out.write4(f.timelines.lastId + 1);
for (int i = 0; i <= f.timelines.lastId; i++)
{
if (ver == 800) out.beginDeflate();
Timeline time = f.timelines.getUnsafe(i);
out.writeBool(time != null);
if (time != null)
{
out.writeStr(time.getName());
if (ver == 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(500);
out.write4(time.moments.size());
for (Moment mom : time.moments)
{
out.write4(mom.stepNo);
writeActions(out,mom);
}
}
out.endDeflate();
}
}
public static void writeGmObjects(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
if (ver > 800) ver = 800;
out.write4(ver == 800 ? 800 : 400);
out.write4(f.gmObjects.lastId + 1);
for (int i = 0; i <= f.gmObjects.lastId; i++)
{
if (ver == 800) out.beginDeflate();
GmObject obj = f.gmObjects.getUnsafe(i);
out.writeBool(obj != null);
if (obj != null)
{
out.writeStr(obj.getName());
if (ver == 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(430);
out.writeId((ResourceReference<?>) obj.get(PGmObject.SPRITE));
out.writeBool(obj.properties,PGmObject.SOLID,PGmObject.VISIBLE);
out.write4(obj.properties,PGmObject.DEPTH);
out.writeBool(obj.properties,PGmObject.PERSISTENT);
out.writeId((ResourceReference<?>) obj.get(PGmObject.PARENT),-100);
out.writeId((ResourceReference<?>) obj.get(PGmObject.MASK));
out.write4(10);
for (int j = 0; j < 11; j++)
{
MainEvent me = obj.mainEvents.get(j);
for (int k = me.events.size(); k > 0; k--)
{
Event ev = me.events.get(k - 1);
if (j == MainEvent.EV_COLLISION)
out.writeId(ev.other);
else
out.write4(ev.id);
writeActions(out,ev);
}
out.write4(-1);
}
}
out.endDeflate();
}
}
public static void writeRooms(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
if (ver > 800) ver = 800;
out.write4(ver == 800 ? 800 : 420);
out.write4(f.rooms.lastId + 1);
for (int i = 0; i <= f.rooms.lastId; i++)
{
if (ver == 800) out.beginDeflate();
Room rm = f.rooms.getUnsafe(i);
out.writeBool(rm != null);
if (rm != null)
{
out.writeStr(rm.getName());
if (ver == 800) out.writeD(f.gameSettings.getLastChanged());
out.write4(541);
out.writeStr(rm.properties,PRoom.CAPTION);
out.write4(rm.properties,PRoom.WIDTH,PRoom.HEIGHT,PRoom.SNAP_Y,PRoom.SNAP_X);
out.writeBool(rm.properties,PRoom.ISOMETRIC);
out.write4(rm.properties,PRoom.SPEED);
out.writeBool(rm.properties,PRoom.PERSISTENT);
out.write4(Util.getGmColor((Color) rm.get(PRoom.BACKGROUND_COLOR)));
out.writeBool(rm.properties,PRoom.DRAW_BACKGROUND_COLOR);
out.writeStr(rm.properties,PRoom.CREATION_CODE);
out.write4(rm.backgroundDefs.size());
for (BackgroundDef back : rm.backgroundDefs)
{
out.writeBool(back.properties,PBackgroundDef.VISIBLE,PBackgroundDef.FOREGROUND);
out.writeId((ResourceReference<?>) back.properties.get(PBackgroundDef.BACKGROUND));
out.write4(back.properties,PBackgroundDef.X,PBackgroundDef.Y);
out.writeBool(back.properties,PBackgroundDef.TILE_HORIZ,PBackgroundDef.TILE_VERT);
out.write4(back.properties,PBackgroundDef.H_SPEED,PBackgroundDef.V_SPEED);
out.writeBool(back.properties,PBackgroundDef.STRETCH);
}
out.writeBool(rm.properties,PRoom.ENABLE_VIEWS);
out.write4(rm.views.size());
for (View view : rm.views)
{
out.writeBool(view.properties,PView.VISIBLE);
out.write4(view.properties,PView.VIEW_X,PView.VIEW_Y,PView.VIEW_W,PView.VIEW_H,
PView.PORT_X,PView.PORT_Y,PView.PORT_W,PView.PORT_H,PView.BORDER_H,PView.BORDER_V,
PView.SPEED_H,PView.SPEED_V);
out.writeId((ResourceReference<?>) view.properties.get(PView.OBJECT));
}
out.write4(rm.instances.size());
for (Instance in : rm.instances)
{
out.write4(in.getPosition().x);
out.write4(in.getPosition().y);
ResourceReference<GmObject> or = in.properties.get(PInstance.OBJECT);
out.writeId(or);
out.write4((Integer) in.properties.get(PInstance.ID));
out.writeStr(in.getCreationCode());
out.writeBool(in.isLocked());
}
out.write4(rm.tiles.size());
for (Tile tile : rm.tiles)
{
out.write4(tile.getRoomPosition().x);
out.write4(tile.getRoomPosition().y);
ResourceReference<Background> rb = tile.properties.get(PTile.BACKGROUND);
out.writeId(rb);
out.write4(tile.getBackgroundPosition().x);
out.write4(tile.getBackgroundPosition().y);
out.write4(tile.getSize().width);
out.write4(tile.getSize().height);
out.write4(tile.getDepth());
out.write4((Integer) tile.properties.get(PTile.ID));
out.writeBool(tile.isLocked());
}
out.writeBool(rm.properties,PRoom.REMEMBER_WINDOW_SIZE);
out.write4(rm.properties,PRoom.EDITOR_WIDTH,PRoom.EDITOR_HEIGHT);
out.writeBool(rm.properties,PRoom.SHOW_GRID,PRoom.SHOW_OBJECTS,PRoom.SHOW_TILES,
PRoom.SHOW_BACKGROUNDS,PRoom.SHOW_FOREGROUNDS,PRoom.SHOW_VIEWS,
PRoom.DELETE_UNDERLYING_OBJECTS,PRoom.DELETE_UNDERLYING_TILES);
out.write4(rm.properties,PRoom.CURRENT_TAB,PRoom.SCROLL_BAR_X,PRoom.SCROLL_BAR_Y);
}
out.endDeflate();
}
}
public static void writeIncludedFiles(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
ver = ver > 800 ? 800 : ver >= 620 ? 620 : 0;
if (ver < 620) return;
out.write4(ver);
out.write4(f.includes.size());
for (Include i : f.includes)
{
if (ver >= 800)
{
out.beginDeflate();
out.writeD(f.gameSettings.getLastChanged());
}
out.write4(ver);
out.writeStr(i.filename);
out.writeStr(i.filepath);
out.writeBool(i.isOriginal);
out.write4(i.size);
if (i.data != null)
{
out.writeBool(true);
out.write4(i.data.length);
out.write(i.data);
}
else
out.writeBool(false);
out.write4(i.export);
out.writeStr(i.exportFolder);
out.writeBool(i.overwriteExisting);
out.writeBool(i.freeMemAfterExport);
out.writeBool(i.removeAtGameEnd);
out.endDeflate();
}
}
public static void writePackages(GmFile f, GmStreamEncoder out) throws IOException
{
if (f.fileVersion < 700) return;
out.write4(700);
out.write4(f.packages.size());
for (String s : f.packages)
out.writeStr(s);
}
public static void writeGameInformation(GmFile f, GmStreamEncoder out) throws IOException
{
int ver = f.fileVersion;
ver = ver >= 800 ? 800 : /*ver >= 620 ? 620 : */ver >= 600 ? 600 : 430;
out.write4(ver);
if (ver == 800) out.beginDeflate();
GameInformation g = f.gameInfo;
PropertyMap<PGameInformation> p = g.properties;
out.write4(Util.getGmColor((Color) p.get(PGameInformation.BACKGROUND_COLOR)));
if (ver < 800)
out.writeBool(p,PGameInformation.MIMIC_GAME_WINDOW);
else
out.writeBool(!(Boolean) p.get(PGameInformation.MIMIC_GAME_WINDOW));
out.writeStr(p,PGameInformation.FORM_CAPTION);
out.write4(p,PGameInformation.LEFT,PGameInformation.TOP,PGameInformation.WIDTH,
PGameInformation.HEIGHT);
out.writeBool(p,PGameInformation.SHOW_BORDER,PGameInformation.ALLOW_RESIZE,
PGameInformation.STAY_ON_TOP,PGameInformation.PAUSE_GAME);
if (ver >= 800) out.writeD(f.gameSettings.getLastChanged());
out.writeStr(p,PGameInformation.TEXT);
out.endDeflate();
}
public static void writeTree(GmStreamEncoder out, ResNode root) throws IOException
{
Enumeration<?> e = root.preorderEnumeration();
e.nextElement();
while (e.hasMoreElements())
{
ResNode node = (ResNode) e.nextElement();
out.write4(node.status);
out.write4(GmFile.RESOURCE_CODE.get(node.kind));
Resource<?,?> res = deRef((ResourceReference<?>) node.getRes());
if (res != null)
out.write4(res.getId());
else
out.write4(0);
out.writeStr((String) node.getUserObject());
out.write4(node.getChildCount());
}
}
public static void writeActions(GmStreamEncoder out, ActionContainer container)
throws IOException
{
out.write4(400);
out.write4(container.actions.size());
for (Action act : container.actions)
{
LibAction la = act.getLibAction();
out.write4(440);
out.write4(la.parent != null ? la.parent.id : la.parentId);
out.write4(la.id);
out.write4(la.actionKind);
out.writeBool(la.allowRelative);
out.writeBool(la.question);
out.writeBool(la.canApplyTo);
out.write4(la.execType);
if (la.execType == Action.EXEC_FUNCTION)
out.writeStr(la.execInfo);
else
out.write4(0);
if (la.execType == Action.EXEC_CODE)
out.writeStr(la.execInfo);
else
out.write4(0);
List<Argument> args = act.getArguments();
out.write4(args.size());
out.write4(args.size());
for (Argument arg : args)
out.write4(arg.kind);
ResourceReference<GmObject> at = act.getAppliesTo();
if (at != null)
{
if (at == GmObject.OBJECT_OTHER)
out.write4(-2);
else if (at == GmObject.OBJECT_SELF)
out.write4(-1);
else
out.writeId(at,-100);
}
else
out.write4(-100);
out.writeBool(act.isRelative());
out.write4(args.size());
for (Argument arg : args)
switch (arg.kind)
{
case Argument.ARG_SPRITE:
case Argument.ARG_SOUND:
case Argument.ARG_BACKGROUND:
case Argument.ARG_PATH:
case Argument.ARG_SCRIPT:
case Argument.ARG_GMOBJECT:
case Argument.ARG_ROOM:
case Argument.ARG_FONT:
case Argument.ARG_TIMELINE:
Resource<?,?> r = deRef((ResourceReference<?>) arg.getRes());
if (r != null)
out.writeStr(Integer.toString(r.getId()));
else
out.writeStr("-1"); //$NON-NLS-1$
break;
default:
out.writeStr(arg.getVal());
break;
}
out.writeBool(act.isNot());
}
}
}