package com.kartoflane.superluminal2.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.unsynchronized.BlockData;
import org.unsynchronized.ClassDesc;
import org.unsynchronized.Content;
import org.unsynchronized.EnumObject;
import org.unsynchronized.Field;
import org.unsynchronized.Instance;
import org.unsynchronized.JDeserialize;
import org.unsynchronized.StringObject;
import com.kartoflane.superluminal2.components.enums.Directions;
import com.kartoflane.superluminal2.components.enums.Images;
import com.kartoflane.superluminal2.components.enums.Races;
import com.kartoflane.superluminal2.components.enums.Systems;
import com.kartoflane.superluminal2.core.Database;
import com.kartoflane.superluminal2.core.Grid;
import com.kartoflane.superluminal2.core.Grid.Snapmodes;
import com.kartoflane.superluminal2.ftl.AugmentObject;
import com.kartoflane.superluminal2.ftl.DoorObject;
import com.kartoflane.superluminal2.ftl.DroneList;
import com.kartoflane.superluminal2.ftl.DroneObject;
import com.kartoflane.superluminal2.ftl.GameObject;
import com.kartoflane.superluminal2.ftl.GibObject;
import com.kartoflane.superluminal2.ftl.MountObject;
import com.kartoflane.superluminal2.ftl.RoomObject;
import com.kartoflane.superluminal2.ftl.ShipObject;
import com.kartoflane.superluminal2.ftl.StationObject;
import com.kartoflane.superluminal2.ftl.SystemObject;
import com.kartoflane.superluminal2.ftl.WeaponList;
import com.kartoflane.superluminal2.ftl.WeaponObject;
public class SHPUtils {
private static Map<Instance, GameObject> instanceGameMap = null;
private static ShipObject ship = null;
public static ShipObject loadShipSHP(File file) throws FileNotFoundException, IOException {
if (!file.exists())
throw new FileNotFoundException(file.getAbsolutePath());
ship = null;
JDeserialize jdes = new JDeserialize(file.getAbsolutePath());
FileInputStream fis = new FileInputStream(file);
jdes.run(fis, true);
fis.close();
Instance shipInstance = (Instance) jdes.getContent().get(0);
instanceGameMap = new HashMap<Instance, GameObject>();
boolean playerShip = bool(getFieldValueByName(shipInstance, "isPlayer"));
ship = new ShipObject(playerShip);
String v = string(getFieldValueByName(shipInstance, "blueprintName"));
if (v != null)
ship.setBlueprintName(v);
v = string(getFieldValueByName(shipInstance, "shipName"));
if (v != null)
ship.setShipName(v);
v = string(getFieldValueByName(shipInstance, "shipClass"));
if (v != null)
ship.setShipClass(v);
v = string(getFieldValueByName(shipInstance, "descr"));
if (v != null)
ship.setShipDescription(v);
v = string(getFieldValueByName(shipInstance, "imageName"));
if (v != null)
ship.setImageNamespace(v);
v = string(getFieldValueByName(shipInstance, "layout"));
if (v != null)
ship.setLayout(v);
int i = integer(getFieldValueByName(shipInstance, "minSec"));
ship.setMinSector(Math.max(1, i));
i = integer(getFieldValueByName(shipInstance, "maxSec"));
ship.setMaxSector(Math.max(1, i));
i = integer(getFieldValueByName(shipInstance, "horizontal"));
ship.setHorizontal(i);
i = integer(getFieldValueByName(shipInstance, "vertical"));
ship.setVertical(i);
i = integer(getFieldValueByName(shipInstance, "weaponSlots"));
ship.setWeaponSlots(i);
i = integer(getFieldValueByName(shipInstance, "droneSlots"));
ship.setDroneSlots(i);
i = integer(getFieldValueByName(shipInstance, "hullHealth"));
ship.setHealth(i);
i = integer(getFieldValueByName(shipInstance, "reactorPower"));
ship.setPower(i);
i = integer(getFieldValueByName(shipInstance, "missiles"));
ship.setMissilesAmount(i);
i = integer(getFieldValueByName(shipInstance, "drones"));
ship.setDronePartsAmount(i);
Point p = point(getFieldValueByName(shipInstance, "offset"));
ship.setXOffset(p.x);
ship.setYOffset(p.y);
Point anchor = point(getFieldValueByName(shipInstance, "anchor"));
Rectangle r = rect(getFieldValueByName(shipInstance, "ellipse"));
ship.setEllipse(r);
r = rect(getFieldValueByName(shipInstance, "imageRect"));
r.x -= anchor.x;
r.y -= anchor.y;
ship.setHullDimensions(r);
v = string(getFieldValueByName(shipInstance, "imagePath"));
if (v != null) {
File f = new File(v);
if (f.exists())
ship.setImage(Images.HULL, "file:" + v);
}
v = string(getFieldValueByName(shipInstance, "floorPath"));
if (v != null) {
File f = new File(v);
if (f.exists())
ship.setImage(Images.FLOOR, "file:" + v);
}
v = string(getFieldValueByName(shipInstance, "cloakPath"));
if (v != null) {
File f = new File(v);
if (f.exists())
ship.setImage(Images.CLOAK, "file:" + v);
}
v = string(getFieldValueByName(shipInstance, "shieldPath"));
if (v != null) {
File f = new File(v);
if (f.exists())
ship.setImage(Images.SHIELD, "file:" + v);
}
v = string(getFieldValueByName(shipInstance, "miniPath"));
if (v != null) {
File f = new File(v);
if (f.exists())
ship.setImage(Images.THUMBNAIL, "file:" + v);
}
Map<Object, Object> map = null;
Object o = null;
o = getFieldValueByName(shipInstance, "startMap");
if (o != null) {
map = map(o);
// System -> boolean
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Systems sys = system(entry.getKey());
boolean available = bool(entry.getValue());
ship.getSystem(sys).setAvailable(available);
}
}
o = getFieldValueByName(shipInstance, "powerMap");
if (o != null) {
map = map(o);
// System -> integer
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Systems sys = system(entry.getKey());
int level = integer(entry.getValue());
ship.getSystem(sys).setLevelStart(level);
}
}
o = getFieldValueByName(shipInstance, "levelMap");
if (o != null) {
map = map(o);
// System -> integer
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Systems sys = system(entry.getKey());
int level = integer(entry.getValue());
ship.getSystem(sys).setLevelMax(level);
}
}
o = getFieldValueByName(shipInstance, "slotMap");
if (o != null) {
map = map(o);
// System -> integer
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Systems sys = system(entry.getKey());
if (!sys.canContainStation())
continue;
int slot = integer(entry.getValue());
SystemObject system = ship.getSystem(sys);
StationObject station = system.getStation();
station.setSlotId(slot);
}
}
o = getFieldValueByName(shipInstance, "slotDirMap");
if (o != null) {
map = map(o);
// System -> Direction
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Systems sys = system(entry.getKey());
if (!sys.canContainStation())
continue;
Directions dir = direction(entry.getValue());
SystemObject system = ship.getSystem(sys);
StationObject station = system.getStation();
station.setSlotDirection(dir);
}
}
o = getFieldValueByName(shipInstance, "crewMap");
if (o != null) {
map = map(o);
// Crew -> integer
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Races race = race(entry.getKey());
int count = integer(entry.getValue());
ship.setCrewMin(race, count);
for (int in = 0; in < count; in++)
ship.changeCrew(Races.NO_CREW, race);
}
}
o = getFieldValueByName(shipInstance, "crewMaxMap");
if (o != null) {
map = map(o);
// Crew -> integer
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Races race = race(entry.getKey());
int count = integer(entry.getValue());
ship.setCrewMax(race, count);
}
}
Collection<Object> col = null;
o = null;
o = getFieldValueByName(shipInstance, "rooms");
if (o != null) {
col = collection(o);
// RoomObject
for (Object ob : col) {
GameObject go = room(ob, anchor);
ship.add(go);
}
}
o = getFieldValueByName(shipInstance, "doors");
if (o != null) {
col = collection(o);
// DoorObject
for (Object ob : col) {
GameObject go = door(ob, anchor);
ship.add(go);
}
}
o = getFieldValueByName(shipInstance, "gibs");
if (o != null) {
col = collection(o);
// GibObject
for (Object ob : col) {
GameObject go = gib(ob);
ship.add(go);
}
}
o = getFieldValueByName(shipInstance, "mounts");
if (o != null) {
col = collection(o);
// MountObject
for (Object ob : col) {
GameObject go = mount(ob, anchor);
ship.add(go);
}
}
Database db = Database.getInstance();
boolean bySet = bool(getFieldValueByName(shipInstance, "dronesBySet"));
col = collection(getFieldValueByName(shipInstance, "droneSet"));
if (bySet) {
for (Object ob : col) {
DroneList list = db.getDroneList(string(ob));
if (list != null)
ship.setDroneList(list);
break;
}
} else {
for (Object ob : col) {
DroneObject drone = db.getDrone(string(ob));
if (drone != null)
ship.changeDrone(Database.DEFAULT_DRONE_OBJ, drone);
}
}
bySet = bool(getFieldValueByName(shipInstance, "weaponsBySet"));
col = collection(getFieldValueByName(shipInstance, "weaponSet"));
if (bySet) {
for (Object ob : col) {
WeaponList list = db.getWeaponList(string(ob));
if (list != null)
ship.setWeaponList(list);
break;
}
} else {
for (Object ob : col) {
WeaponObject weapon = db.getWeapon(string(ob));
if (weapon != null)
ship.changeWeapon(Database.DEFAULT_WEAPON_OBJ, weapon);
}
}
col = collection(getFieldValueByName(shipInstance, "augmentSet"));
for (Object ob : col) {
AugmentObject aug = db.getAugment(string(ob));
if (aug != null)
ship.changeAugment(Database.DEFAULT_AUGMENT_OBJ, aug);
}
instanceGameMap.clear();
instanceGameMap = null;
System.gc();
return ship;
}
private static Map.Entry<Field, Object> getFieldByName(Instance i, ClassDesc cd, String name) {
if (i == null || cd == null || name == null)
throw new IllegalArgumentException("Argument must not be null.");
for (Map.Entry<Field, Object> entry : i.fielddata.get(cd).entrySet()) {
if (entry.getKey().name.equals(name))
return entry;
}
return null;
}
private static Map.Entry<Field, Object> getFieldByName(Instance i, String name) {
if (i == null || name == null)
throw new IllegalArgumentException("Argument must not be null.");
for (ClassDesc cd : i.fielddata.keySet()) {
Map.Entry<Field, Object> result = getFieldByName(i, cd, name);
if (result != null)
return result;
}
return null;
}
private static Object getFieldValueByName(Instance i, ClassDesc cd, String name) {
if (i == null || cd == null || name == null)
throw new IllegalArgumentException("Argument must not be null.");
Map.Entry<Field, Object> result = getFieldByName(i, cd, name);
if (result != null)
return result.getValue();
return null;
}
private static Object getFieldValueByName(Instance i, String name) {
if (i == null || name == null)
throw new IllegalArgumentException("Argument must not be null.");
Map.Entry<Field, Object> result = getFieldByName(i, name);
if (result != null)
return result.getValue();
return null;
}
private static String string(Object o) {
if (o == null)
return null;
if (o instanceof String)
return (String) o;
else if (o instanceof StringObject)
return ((StringObject) o).value;
else
throw new IllegalArgumentException("Not a String: " + o.getClass());
}
private static Point point(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
Point result = new Point(0, 0);
try {
result.x = integer(getFieldValueByName(i, "x"));
result.y = integer(getFieldValueByName(i, "y"));
} catch (Exception e) {
throw new IllegalArgumentException("Not a Point: " + o.getClass());
}
return result;
}
private static Rectangle rect(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
Rectangle result = new Rectangle(0, 0, 0, 0);
try {
result.x = integer(getFieldValueByName(i, "x"));
result.y = integer(getFieldValueByName(i, "y"));
result.width = integer(getFieldValueByName(i, "width"));
result.height = integer(getFieldValueByName(i, "height"));
} catch (Exception e) {
throw new IllegalArgumentException("Not a Rectangle: " + o.getClass());
}
return result;
}
private static Map<Object, Object> map(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
Map<Object, Object> result = new HashMap<Object, Object>();
try {
for (Map.Entry<ClassDesc, List<Content>> entry : i.annotations.entrySet()) {
Object k = null, v = null;
for (Content c : entry.getValue()) {
if (c instanceof BlockData == false) {
if (k == null)
k = c;
else
v = c;
if (k != null && v != null) {
result.put(k, v);
k = null;
v = null;
}
}
}
}
} catch (Exception e) {
throw new IllegalArgumentException("Not a Map: " + o.getClass());
}
return result;
}
private static Collection<Object> collection(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
Collection<Object> result = new ArrayList<Object>();
try {
for (Map.Entry<ClassDesc, List<Content>> entry : i.annotations.entrySet()) {
for (Content c : entry.getValue()) {
if (c instanceof BlockData == false)
result.add(c);
}
}
} catch (Exception e) {
throw new IllegalArgumentException("Not a Collection: " + o.getClass());
}
return result;
}
private static boolean bool(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Boolean) {
return (Boolean) o;
} else if (o instanceof String) {
return Boolean.valueOf((String) o);
} else if (o instanceof StringObject) {
return Boolean.valueOf(((StringObject) o).value);
} else if (o instanceof Instance) {
Instance i = (Instance) o;
return bool(getFieldValueByName(i, "value"));
} else
throw new IllegalArgumentException("Not a Boolean: " + o.getClass());
}
private static int integer(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Integer) {
return (Integer) o;
} else if (o instanceof String) {
return Integer.valueOf((String) o);
} else if (o instanceof StringObject) {
return Integer.valueOf(((StringObject) o).value);
} else if (o instanceof Instance) {
Instance i = (Instance) o;
return integer(getFieldValueByName(i, "value"));
} else
throw new IllegalArgumentException("Not an Integer: " + o.getClass());
}
private static double doubel(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Double) {
return (Double) o;
} else if (o instanceof Float) {
return (Float) o;
} else if (o instanceof String) {
return Double.valueOf((String) o);
} else if (o instanceof StringObject) {
return Double.valueOf(((StringObject) o).value);
} else if (o instanceof Instance) {
Instance i = (Instance) o;
return doubel(getFieldValueByName(i, "value"));
} else
throw new IllegalArgumentException("Not a Double or Float: " + o.getClass());
}
private static Systems system(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Systems)
return (Systems) o;
else if (o instanceof String)
return Systems.valueOf(((String) o).toUpperCase());
else if (o instanceof StringObject)
return system(((StringObject) o).value);
else if (o instanceof EnumObject)
return system(((EnumObject) o).value);
else
throw new IllegalArgumentException("Not a System: " + o.getClass());
}
private static Directions direction(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Directions)
return (Directions) o;
else if (o instanceof String)
return Directions.parseDir((String) o);
else if (o instanceof StringObject)
return direction(((StringObject) o).value);
else if (o instanceof EnumObject)
return direction(((EnumObject) o).value);
else
throw new IllegalArgumentException("Not a Direction: " + o.getClass());
}
private static Races race(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Races)
return (Races) o;
else if (o instanceof String)
return Races.valueOf(((String) o).toUpperCase());
else if (o instanceof StringObject)
return race(((StringObject) o).value);
else
throw new IllegalArgumentException("Not a Race: " + o.getClass());
}
private static RoomObject room(Object o, Point anchor) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
RoomObject result = new RoomObject();
result.setId(integer(getFieldValueByName(i, "id")));
SystemObject system = ship.getSystem(system(getFieldValueByName(i, "sys")));
system.setRoom(result);
Rectangle r = rect(getFieldValueByName(i, "bounds"));
result.setSize(Math.max(1, r.width / 35), Math.max(1, r.height / 35));
result.setLocation((r.x - anchor.x) / 35, (r.y - anchor.y) / 35);
instanceGameMap.put(i, result);
return result;
}
private static DoorObject door(Object o, Point anchor) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
DoorObject result = new DoorObject();
result.setHorizontal(bool(getFieldValueByName(i, "horizontal")));
o = getFieldValueByName(i, "leftRoom");
if (o != null)
result.setLeftRoom((RoomObject) instanceGameMap.get((Instance) o));
o = getFieldValueByName(i, "rightRoom");
if (o != null)
result.setRightRoom((RoomObject) instanceGameMap.get((Instance) o));
Rectangle r = rect(getFieldValueByName(i, "bounds"));
r.x += 35 / 2 - anchor.x;
r.y += 35 / 2 - anchor.y;
Point p = Grid.getInstance().snapToGrid(r.x, r.y, Snapmodes.CELL);
result.setLocation(p.x / 35, p.y / 35);
instanceGameMap.put(i, result);
return result;
}
private static GibObject gib(Object o) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
GibObject result = new GibObject();
String path = string(getFieldValueByName(i, "path"));
if (path != null) {
File f = new File(path);
if (f.exists())
result.setImagePath("file:" + path);
}
result.setId(integer(getFieldValueByName(i, "number")));
result.setAlias(string(getFieldValueByName(i, "ID")));
result.setDirectionMin(integer(getFieldValueByName(i, "minDir")));
result.setDirectionMax(integer(getFieldValueByName(i, "maxDir")));
result.setVelocityMin(doubel(getFieldValueByName(i, "minVel")));
result.setVelocityMax(doubel(getFieldValueByName(i, "maxVel")));
result.setAngularMin(doubel(getFieldValueByName(i, "minAng")));
result.setAngularMax(doubel(getFieldValueByName(i, "maxAng")));
Point offset = point(getFieldValueByName(i, "position"));
result.setOffset(offset.x, offset.y);
instanceGameMap.put(i, result);
return result;
}
private static MountObject mount(Object o, Point anchor) {
if (o == null)
throw new IllegalArgumentException("Argument must not be null.");
if (o instanceof Instance == false)
throw new IllegalArgumentException("Argument must be an Instance: " + o);
Instance i = (Instance) o;
MountObject result = new MountObject();
int id = integer(getFieldValueByName(i, "gib"));
for (GameObject go : instanceGameMap.values()) {
if (go instanceof GibObject) {
GibObject g = (GibObject) go;
if (g.getId() == id)
result.setGib(g);
}
}
result.setRotated(bool(getFieldValueByName(i, "rotate")));
result.setMirrored(bool(getFieldValueByName(i, "mirror")));
result.setDirection(direction(getFieldValueByName(i, "slide")));
Point offset = point(getFieldValueByName(i, "orig"));
result.setLocation(offset.x - anchor.x, offset.y - anchor.x);
instanceGameMap.put(i, result);
return result;
}
}