package rts.utils;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.luawars.Log;
import org.newdawn.slick.AngelCodeFont;
import org.newdawn.slick.Image;
import org.newdawn.slick.Music;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Sound;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.loading.DeferredResource;
import org.newdawn.slick.loading.LoadingList;
import org.newdawn.slick.particles.ConfigurableEmitter;
import org.newdawn.slick.particles.ParticleIO;
import org.newdawn.slick.particles.ParticleSystem;
import org.newdawn.slick.util.ResourceLoader;
import rts.core.engine.map.Map;
/**
* This class provide access to all resources contents in a single jar.
*
* Use the init() method with the jar path location to initialize the resources,
* then the loadNextResource() and isLoadComplete() to load data progressively.
*
* After loading you can use data with getters method.
*
* Example: SpriteSheet sheet = Resources.getSprite("mySpriteSheet");
*
* BE CAREFUL !
*
* The jar must contain the following directory structure:
*
* Width and height of sprite sheet must be specified in the file name like
* this:
*
* width_height_name.png
*
* Example: 40_40_sprites.png
*
* /resources /fonts /images /maps /musics /sounds /sprites /systems
*
* @author Vincent PIRAULT
*
*/
public class ResourceManager {
private static final String TILESET_LOCATION = "resources/maps";
private static final boolean FONT_WITH_CACHE = false;
private static HashMap<String, AngelCodeFont> fonts = new HashMap<String, AngelCodeFont>();
private static HashMap<String, Image> images = new HashMap<String, Image>();
private static HashMap<String, Map> maps = new HashMap<String, Map>();
private static HashMap<String, Music> musics = new HashMap<String, Music>();
private static HashMap<String, Sound> sounds = new HashMap<String, Sound>();
private static HashMap<String, SpriteSheet> sprites = new HashMap<String, SpriteSheet>();
private static HashMap<String, String> systemsAndEmitters = new HashMap<String, String>();
private static LoadingList list;
private static int advancement;
/**
* Initialize the content of the resources list.
*
* @param jarLocation
* The location of the jar that contain resources.
* @throws IOException
* If the jar location is false.
* @throws SlickException
* If a resource can't be loaded from the jar.
*/
public static void init(String jarLocation) throws IOException, SlickException {
list = LoadingList.get();
Log.debug("ResourceManager.init(" + jarLocation + ")");
JarFile jarFile = new JarFile(jarLocation);
Enumeration<JarEntry> e = jarFile.entries();
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
String path = je.getName();
if (path.startsWith("resources") && path.length() > 10) {
String dataInfo = path.split("/")[1];
if (!path.endsWith("/")) {
String name = path.split("/")[2].split("[.]")[0];
if (dataInfo.equals("images")) {
list.add(new DeferredImage(name, path));
} else {
if (dataInfo.equals("sprites")) {
String[] info = name.split("_");
if (info.length > 1) {
int tw = Integer.parseInt(info[0]);
int th = Integer.parseInt(info[1]);
if (info.length == 4) {
list.add(new DeferredSprite(info[2] + "_" + info[3], path, tw, th));
} else
list.add(new DeferredSprite(info[2], path, tw, th));
}
} else {
if (dataInfo.equals("sounds")) {
list.add(new DeferredSound(name, path));
} else {
if (dataInfo.equals("musics")) {
list.add(new DeferredMusic(name, path));
} else {
if (dataInfo.equals("systems")) {
systemsAndEmitters.put(name, path);
} else {
if (dataInfo.equals("maps") && path.endsWith(".tmx")) {
list.add(new DeferredMap(name, path, TILESET_LOCATION));
} else {
if (dataInfo.equals("fonts") && !path.endsWith(".png")) {
list.add(new DeferredFont(name, path.split("[.]")[0]));
}
}
}
}
}
}
}
}
}
}
}
/**
* Load the next resource of the list.
*/
public static void loadNextResource() {
if (LoadingList.get().getRemainingResources() > 0) {
DeferredResource nextResource = LoadingList.get().getNext();
try {
Log.trace(Log.me() + ": " + nextResource.getDescription());
nextResource.load();
} catch (IOException e) {
e.printStackTrace();
}
}
if (LoadingList.get().getTotalResources() > 0)
advancement = (100 * (LoadingList.get().getTotalResources() - LoadingList.get().getRemainingResources())) / LoadingList.get().getTotalResources();
}
/**
* Check if there is no more remaining resource to load.
*
* @return true if there is no more resource to load, false otherwise.
*/
public static boolean isLoadComplete() {
return LoadingList.get().getRemainingResources() == 0;
}
/**
* The advancement of the resource list loading in percentage.
*
* @return the advancement in percentage ( 0 - 100 ).
*/
public static int getAdvancement() {
return advancement;
}
/*
* Delegate Getters/Setters to access data by name.
*/
/**
* Get a font from the resources.
*
* @param name
* the name of the font.
* @return the requested font or null if the resource was not found.
*/
public static AngelCodeFont getFont(String name) {
return fonts.get(name);
}
/**
* Get an image from the resources.
*
* @param name
* the name of the image.
* @return the requested image or null if the resource was not found.
*/
public static Image getImage(String name) {
return images.get(name);
}
/**
* Get a map from the resources.
*
* @param name
* the name of the map.
* @return the requested map or null if the resource was not found.
*/
public static Map getMap(String name) {
return maps.get(name);
}
/**
* Get all the map loaded by the ResourceManager.
*
* @return a hashmap with all loaded maps.
*/
public static HashMap<String, Map> getAllMaps() {
return maps;
}
/**
* Get a music from the resources.
*
* @param name
* the name of the music.
* @return the requested music or null if the resource was not found.
*/
public static Music getMusic(String name) {
return musics.get(name);
}
/**
* Get a sound from the resources.
*
* @param name
* the name of the sound.
* @return the requested sound or null if the resource was not found.
*/
public static Sound getSound(String name) {
return sounds.get(name);
}
/**
* Get a sprite from the resources.
*
* @param name
* the name of the sprite.
* @return the requested sprite or null if the resource was not found.
*/
public static SpriteSheet getSpriteSheet(String name) {
return sprites.get(name);
}
/**
* Get a particle system from the resources.
*
* @param name
* the name of the particle system.
* @return the requested particle system or null if the resource was not
* found.
* @throws IOException
* If the system can't be loaded.
*/
public static ParticleSystem getSystem(String name) throws IOException {
return ParticleIO.loadConfiguredSystem(systemsAndEmitters.get(name));
}
/**
* Get a particle emitter from the resources.
*
* @param name
* the name of the particle emitter.
* @return the requested particle emitter or null if the resource was not
* found.
* @throws IOException
* If the emitter can't be loaded.
*/
public static ConfigurableEmitter getEmitter(String name) throws IOException {
return ParticleIO.loadEmitter(systemsAndEmitters.get(name));
}
/*
* Useful classes to load deferred resources.
*/
private static class DeferredFont implements DeferredResource {
private String name;
private String path;
public DeferredFont(String name, String path) {
this.name = name;
this.path = path;
}
public String getDescription() {
return "Deferred font";
}
public void load() throws IOException {
try {
AngelCodeFont font = new AngelCodeFont(name, Thread.currentThread().getContextClassLoader().getResourceAsStream(path + ".fnt"), Thread
.currentThread().getContextClassLoader().getResourceAsStream(path + ".png"), FONT_WITH_CACHE);
ResourceManager.fonts.put(name, font);
} catch (SlickException e) {
e.printStackTrace();
}
}
}
private static class DeferredImage implements DeferredResource {
private String name;
private String path;
public DeferredImage(String name, String path) {
this.name = name;
this.path = path;
}
public String getDescription() {
return "Deferred image";
}
public void load() throws IOException {
try {
Image image = new Image(path);
ResourceManager.images.put(name, image);
} catch (SlickException e) {
e.printStackTrace();
}
}
}
private static class DeferredMap implements DeferredResource {
private String name;
private String path;
private String tilePath;
public DeferredMap(String name, String path, String tilePath) {
this.name = name;
this.path = path;
this.tilePath = tilePath;
}
public String getDescription() {
return "Deferred Map";
}
public void load() throws IOException {
try {
Map map = new Map(name, Thread.currentThread().getContextClassLoader().getResourceAsStream(path), tilePath);
ResourceManager.maps.put(name, map);
} catch (SlickException e1) {
e1.printStackTrace();
}
}
}
private static class DeferredSprite implements DeferredResource {
private String name;
private String path;
private int tileWidth;
private int tileHeight;
public DeferredSprite(String name, String path, int tileWidth, int tileHeight) {
this.name = name;
this.path = path;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
}
public String getDescription() {
return "Deferred sprite";
}
public void load() throws IOException {
try {
ResourceManager.sprites.put(name, new SpriteSheet(name, Thread.currentThread().getContextClassLoader().getResourceAsStream(path), tileWidth,
tileHeight));
//ResourceManager.sprites.put(name, new SpriteSheet(name, ResourceLoader.getResourceAsStream(path), tileWidth, tileHeight));
} catch (SlickException e) {
e.printStackTrace();
}
}
}
private static class DeferredSound implements DeferredResource {
private String name;
private String path;
public DeferredSound(String name, String path) {
super();
this.name = name;
this.path = path;
}
public String getDescription() {
return "Deferred sound";
}
public void load() throws IOException {
try {
ResourceManager.sounds.put(name, new Sound(path));
} catch (SlickException e) {
e.printStackTrace();
}
}
}
private static class DeferredMusic implements DeferredResource {
private String name;
private String path;
public DeferredMusic(String name, String path) {
super();
this.name = name;
this.path = path;
}
public String getDescription() {
return "Deferred music";
}
public void load() throws IOException {
try {
//ResourceManager.musics.put(name, new Music(path, true));
ResourceManager.musics.put(name, new Music(path));
} catch (SlickException e) {
e.printStackTrace();
}
}
}
}