/* * Copyright (C) 2006, 2007, 2008, 2010, 2011 IsmAvatar <IsmAvatar@gmail.com> * Copyright (C) 2006, 2007 Clam <clamisgood@gmail.com> * Copyright (C) 2007, 2009 Quadduc <quadduc@gmail.com> * * This file is part of LateralGM. * * LateralGM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LateralGM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License (COPYING) for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.lateralgm.file; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.text.DateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.EnumMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import org.lateralgm.file.iconio.ICOFile; import org.lateralgm.main.LGM; import org.lateralgm.main.UpdateSource; import org.lateralgm.main.UpdateSource.UpdateEvent; import org.lateralgm.main.UpdateSource.UpdateListener; import org.lateralgm.main.UpdateSource.UpdateTrigger; import org.lateralgm.messages.Messages; 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.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.GameSettings.ColorDepth; import org.lateralgm.resources.GameSettings.Frequency; import org.lateralgm.resources.GameSettings.IncludeFolder; import org.lateralgm.resources.GameSettings.PGameSettings; import org.lateralgm.resources.GameSettings.Priority; import org.lateralgm.resources.GameSettings.ProgressBar; import org.lateralgm.resources.GameSettings.Resolution; import org.lateralgm.resources.Sound.PSound; import org.lateralgm.resources.Sound.SoundKind; import org.lateralgm.resources.Sprite.BBMode; import org.lateralgm.resources.Sprite.MaskShape; import org.lateralgm.resources.sub.Constant; import org.lateralgm.resources.sub.Instance; import org.lateralgm.resources.sub.Tile; import org.lateralgm.resources.sub.Trigger; import org.lateralgm.resources.sub.Instance.PInstance; import org.lateralgm.resources.sub.Tile.PTile; public class GmFile implements UpdateListener { //Game Settings Enums public static final ColorDepth[] GS_DEPTHS = { ColorDepth.NO_CHANGE,ColorDepth.BIT_16, ColorDepth.BIT_32 }; public static final Map<ColorDepth,Integer> GS_DEPTH_CODE; public static final Resolution[] GS5_RESOLS = { Resolution.RES_640X480,Resolution.RES_800X600, Resolution.RES_1024X768,Resolution.RES_1280X1024,Resolution.NO_CHANGE,Resolution.RES_320X240, Resolution.RES_1600X1200 }; public static final Resolution[] GS_RESOLS = { Resolution.NO_CHANGE,Resolution.RES_320X240, Resolution.RES_640X480,Resolution.RES_800X600,Resolution.RES_1024X768, Resolution.RES_1280X1024,Resolution.RES_1600X1200 }; public static final Map<Resolution,Integer> GS_RESOL_CODE; public static final Frequency[] GS_FREQS = { Frequency.NO_CHANGE,Frequency.FREQ_60, Frequency.FREQ_70,Frequency.FREQ_85,Frequency.FREQ_100,Frequency.FREQ_120 }; public static final Map<Frequency,Integer> GS_FREQ_CODE; public static final Priority[] GS_PRIORITIES = { Priority.NORMAL,Priority.HIGH,Priority.HIGHEST }; public static final Map<Priority,Integer> GS_PRIORITY_CODE; public static final ProgressBar[] GS_PROGBARS = { ProgressBar.NONE,ProgressBar.DEFAULT, ProgressBar.CUSTOM }; public static final Map<ProgressBar,Integer> GS_PROGBAR_CODE; public static final IncludeFolder[] GS_INCFOLDERS = { IncludeFolder.MAIN,IncludeFolder.TEMP }; public static final Map<IncludeFolder,Integer> GS_INCFOLDER_CODE; static { EnumMap<ColorDepth,Integer> m = new EnumMap<ColorDepth,Integer>(ColorDepth.class); for (int i = 0; i < GS_DEPTHS.length; i++) m.put(GS_DEPTHS[i],i); GS_DEPTH_CODE = Collections.unmodifiableMap(m); EnumMap<Resolution,Integer> m2 = new EnumMap<Resolution,Integer>(Resolution.class); for (int i = 0; i < GS_RESOLS.length; i++) m2.put(GS_RESOLS[i],i); GS_RESOL_CODE = Collections.unmodifiableMap(m2); EnumMap<Frequency,Integer> m3 = new EnumMap<Frequency,Integer>(Frequency.class); for (int i = 0; i < GS_FREQS.length; i++) m3.put(GS_FREQS[i],i); GS_FREQ_CODE = Collections.unmodifiableMap(m3); EnumMap<Priority,Integer> m4 = new EnumMap<Priority,Integer>(Priority.class); for (int i = 0; i < GS_PRIORITIES.length; i++) m4.put(GS_PRIORITIES[i],i); GS_PRIORITY_CODE = Collections.unmodifiableMap(m4); EnumMap<ProgressBar,Integer> m5 = new EnumMap<ProgressBar,Integer>(ProgressBar.class); for (int i = 0; i < GS_PROGBARS.length; i++) m5.put(GS_PROGBARS[i],i); GS_PROGBAR_CODE = Collections.unmodifiableMap(m5); EnumMap<IncludeFolder,Integer> m6 = new EnumMap<IncludeFolder,Integer>(IncludeFolder.class); for (int i = 0; i < GS_INCFOLDERS.length; i++) m6.put(GS_INCFOLDERS[i],i); GS_INCFOLDER_CODE = Collections.unmodifiableMap(m6); } public static final Resource.Kind[] RESOURCE_KIND = { null,Resource.Kind.OBJECT, Resource.Kind.SPRITE,Resource.Kind.SOUND,Resource.Kind.ROOM,null,Resource.Kind.BACKGROUND, Resource.Kind.SCRIPT,Resource.Kind.PATH,Resource.Kind.FONT,Resource.Kind.GAMEINFO, Resource.Kind.GAMESETTINGS,Resource.Kind.TIMELINE,Resource.Kind.EXTENSIONS }; public static final Map<Resource.Kind,Integer> RESOURCE_CODE; static { EnumMap<Resource.Kind,Integer> m = new EnumMap<Resource.Kind,Integer>(Resource.Kind.class); for (int i = 0; i < RESOURCE_KIND.length; i++) if (RESOURCE_KIND[i] != null) m.put(RESOURCE_KIND[i],i); RESOURCE_CODE = Collections.unmodifiableMap(m); } public static final PSound[] SOUND_FX_FLAGS = { PSound.CHORUS,PSound.ECHO,PSound.FLANGER, PSound.GARGLE,PSound.REVERB }; public static final SoundKind[] SOUND_KIND = { SoundKind.NORMAL,SoundKind.BACKGROUND, SoundKind.SPATIAL,SoundKind.MULTIMEDIA }; public static final Map<SoundKind,Integer> SOUND_CODE; static { EnumMap<SoundKind,Integer> m = new EnumMap<SoundKind,Integer>(SoundKind.class); for (int i = 0; i < SOUND_KIND.length; i++) m.put(SOUND_KIND[i],i); SOUND_CODE = Collections.unmodifiableMap(m); } public static final BBMode[] SPRITE_BB_MODE = { BBMode.AUTO,BBMode.FULL,BBMode.MANUAL }; public static final Map<BBMode,Integer> SPRITE_BB_CODE; static { EnumMap<BBMode,Integer> m = new EnumMap<BBMode,Integer>(BBMode.class); for (int i = 0; i < SPRITE_BB_MODE.length; i++) m.put(SPRITE_BB_MODE[i],i); SPRITE_BB_CODE = Collections.unmodifiableMap(m); } public static final MaskShape[] SPRITE_MASK_SHAPE = { MaskShape.PRECISE,MaskShape.RECTANGLE, MaskShape.DISK,MaskShape.DIAMOND }; public static final Map<MaskShape,Integer> SPRITE_MASK_CODE; static { EnumMap<MaskShape,Integer> m = new EnumMap<MaskShape,Integer>(MaskShape.class); for (int i = 0; i < SPRITE_MASK_SHAPE.length; i++) m.put(SPRITE_MASK_SHAPE[i],i); SPRITE_MASK_CODE = Collections.unmodifiableMap(m); } /** One of 530, 600, 701, 800, 810 */ public int fileVersion = 810; public String filename = null; private final EnumMap<Resource.Kind,ResourceList<?>> resMap; public final ResourceList<Sprite> sprites = new ResourceList<Sprite>(Sprite.class); public final ResourceList<Sound> sounds = new ResourceList<Sound>(Sound.class); public final ResourceList<Background> backgrounds = new ResourceList<Background>(//force newline Background.class); public final ResourceList<Path> paths = new ResourceList<Path>(Path.class); public final ResourceList<Script> scripts = new ResourceList<Script>(Script.class); public final ResourceList<Font> fonts = new ResourceList<Font>(Font.class); public final ResourceList<Timeline> timelines = new ResourceList<Timeline>(Timeline.class); public final ResourceList<GmObject> gmObjects = new ResourceList<GmObject>(GmObject.class); public final ResourceList<Room> rooms = new ResourceList<Room>(Room.class); public List<Trigger> triggers = new ArrayList<Trigger>(); public List<Constant> constants = new ArrayList<Constant>(); public List<Include> includes = new ArrayList<Include>(); public List<String> packages = new ArrayList<String>(); public GameInformation gameInfo = new GameInformation(); public GameSettings gameSettings = new GameSettings(); public int lastInstanceId = 100000; public int lastTileId = 10000000; private final UpdateTrigger updateTrigger = new UpdateTrigger(); public final UpdateSource updateSource = new UpdateSource(this,updateTrigger); public GmFile() { resMap = new EnumMap<Resource.Kind,ResourceList<?>>(Resource.Kind.class); resMap.put(Resource.Kind.SPRITE,sprites); resMap.put(Resource.Kind.SOUND,sounds); resMap.put(Resource.Kind.BACKGROUND,backgrounds); resMap.put(Resource.Kind.PATH,paths); resMap.put(Resource.Kind.SCRIPT,scripts); resMap.put(Resource.Kind.FONT,fonts); resMap.put(Resource.Kind.TIMELINE,timelines); resMap.put(Resource.Kind.OBJECT,gmObjects); resMap.put(Resource.Kind.ROOM,rooms); for (ResourceList<?> rl : resMap.values()) { rl.updateSource.addListener(this); } Random random = new Random(); gameSettings.put(PGameSettings.GAME_ID,random.nextInt(100000001)); random.nextBytes((byte[]) gameSettings.get(PGameSettings.DPLAY_GUID)); try { String loc = "org/lateralgm/file/default.ico"; InputStream filein; File file = new File(loc); if (!file.exists()) filein = LGM.class.getClassLoader().getResourceAsStream(loc); else filein = new FileInputStream(file); gameSettings.put(PGameSettings.GAME_ICON,new ICOFile(filein)); } catch (Exception ex) { System.err.println(Messages.getString("GmFile.NOICON")); //$NON-NLS-1$ System.err.println(ex.getMessage()); ex.printStackTrace(); } } public static Calendar gmBaseTime() { Calendar res = Calendar.getInstance(); res.set(1899,11,29,23,59,59); return res; } public static double longTimeToGmTime(long time) { return (time - gmBaseTime().getTimeInMillis()) / 86400000d; } public static String gmTimeToString(double time) { Calendar base = gmBaseTime(); base.setTimeInMillis(base.getTimeInMillis() + ((long) (time * 86400000))); return DateFormat.getDateTimeInstance().format(base.getTime()); } // Returns the ResourceList corresponding to given Resource constant public ResourceList<?> getList(Resource.Kind res) { return resMap.get(res); } public void defragIds() { Iterator<ResourceList<?>> iter = resMap.values().iterator(); while (iter.hasNext()) iter.next().defragIds(); lastInstanceId = 100000; lastTileId = 10000000; for (Room r : rooms) { for (Instance j : r.instances) j.properties.put(PInstance.ID,++lastInstanceId); for (Tile j : r.tiles) j.properties.put(PTile.ID,++lastTileId); } } public static List<Constant> copyConstants(List<Constant> source) { List<Constant> dest = new ArrayList<Constant>(); for (Constant c : source) dest.add(c.copy()); return dest; } public void updated(UpdateEvent e) { updateTrigger.fire(e); } }