Entirely rewritten ION, world saving, added map movement etc
This commit is contained in:
@@ -204,4 +204,10 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
|
|||||||
{
|
{
|
||||||
Mouse.setGrabbed(grab);
|
Mouse.setGrabbed(grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isKeyDown(int key)
|
||||||
|
{
|
||||||
|
return Keyboard.isKeyDown(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,15 +22,12 @@ import mightypork.rogue.screens.main_menu.ScreenMainMenu;
|
|||||||
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
|
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
|
||||||
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
|
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
|
||||||
import mightypork.rogue.screens.test_render.ScreenTestRender;
|
import mightypork.rogue.screens.test_render.ScreenTestRender;
|
||||||
import mightypork.rogue.world.PlayerInfo;
|
|
||||||
import mightypork.rogue.world.World;
|
|
||||||
import mightypork.rogue.world.WorldPos;
|
|
||||||
import mightypork.rogue.world.item.Item;
|
import mightypork.rogue.world.item.Item;
|
||||||
import mightypork.rogue.world.map.Level;
|
import mightypork.rogue.world.map.Level;
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.util.control.eventbus.EventBus;
|
import mightypork.util.control.eventbus.EventBus;
|
||||||
import mightypork.util.control.eventbus.events.Event;
|
import mightypork.util.control.eventbus.events.Event;
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.ion.Ion;
|
||||||
import mightypork.util.logging.Log;
|
import mightypork.util.logging.Log;
|
||||||
import mightypork.util.logging.writers.LogWriter;
|
import mightypork.util.logging.writers.LogWriter;
|
||||||
|
|
||||||
@@ -109,12 +106,9 @@ public final class App extends BaseApp {
|
|||||||
@Override
|
@Override
|
||||||
protected void preInit()
|
protected void preInit()
|
||||||
{
|
{
|
||||||
Ion.registerIonizable(Item.ION_MARK, Item.class);
|
Ion.registerBinary(Item.ION_MARK, Item.class);
|
||||||
Ion.registerIonizable(Level.ION_MARK, Level.class);
|
Ion.registerBinary(Level.ION_MARK, Level.class);
|
||||||
Ion.registerIonizable(PlayerInfo.ION_MARK, PlayerInfo.class);
|
Ion.registerBinary(Tile.ION_MARK, Tile.class);
|
||||||
Ion.registerIonizable(Tile.ION_MARK, Tile.class);
|
|
||||||
Ion.registerIonizable(World.ION_MARK, World.class);
|
|
||||||
Ion.registerIonizable(WorldPos.ION_MARK, WorldPos.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ import java.util.Random;
|
|||||||
|
|
||||||
import mightypork.gamecore.gui.screens.Screen;
|
import mightypork.gamecore.gui.screens.Screen;
|
||||||
import mightypork.gamecore.gui.screens.ScreenLayer;
|
import mightypork.gamecore.gui.screens.ScreenLayer;
|
||||||
|
import mightypork.gamecore.input.InputSystem;
|
||||||
|
import mightypork.gamecore.input.KeyStroke;
|
||||||
|
import mightypork.gamecore.input.Keys;
|
||||||
import mightypork.rogue.world.MapGenerator;
|
import mightypork.rogue.world.MapGenerator;
|
||||||
import mightypork.rogue.world.World;
|
import mightypork.rogue.world.World;
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.ion.Ion;
|
||||||
|
|
||||||
|
|
||||||
public class WorldLayer extends ScreenLayer {
|
public class WorldLayer extends ScreenLayer {
|
||||||
@@ -17,17 +20,82 @@ public class WorldLayer extends ScreenLayer {
|
|||||||
{
|
{
|
||||||
super(screen);
|
super(screen);
|
||||||
|
|
||||||
|
// FIXME just temporary test here
|
||||||
|
|
||||||
final Random rand = new Random();
|
final Random rand = new Random();
|
||||||
final World w = MapGenerator.createWorld(rand.nextLong());
|
final World w = MapGenerator.createWorld(rand.nextLong());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Ion.toFile("amap.ion", w);
|
Ion.toFile("amap.ion", w);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// final World w;
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// w = Ion.fromFile("amap.ion", World.class);
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// System.exit(1);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
final WorldRenderer wr = new WorldRenderer(w);
|
final WorldRenderer wr = new WorldRenderer(w);
|
||||||
wr.setRect(root);
|
wr.setRect(root);
|
||||||
root.add(wr);
|
root.add(wr);
|
||||||
|
|
||||||
|
bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
w.getPlayer().walk(-1, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
w.getPlayer().walk(1, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bindKey(new KeyStroke(true, Keys.UP), new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
w.getPlayer().walk(0, -1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
w.getPlayer().walk(0, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
w.getPlayer().setTargetListener(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
if (InputSystem.isKeyDown(Keys.LEFT)) {
|
||||||
|
w.getPlayer().walk(-1, 0);
|
||||||
|
} else if (InputSystem.isKeyDown(Keys.RIGHT)) {
|
||||||
|
w.getPlayer().walk(1, 0);
|
||||||
|
} else if (InputSystem.isKeyDown(Keys.UP)) {
|
||||||
|
w.getPlayer().walk(0, -1);
|
||||||
|
} else if (InputSystem.isKeyDown(Keys.DOWN)) {
|
||||||
|
w.getPlayer().walk(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import mightypork.gamecore.gui.components.painters.TextPainter;
|
|||||||
import mightypork.gamecore.render.fonts.GLFont;
|
import mightypork.gamecore.render.fonts.GLFont;
|
||||||
import mightypork.rogue.Res;
|
import mightypork.rogue.Res;
|
||||||
import mightypork.util.constraints.num.Num;
|
import mightypork.util.constraints.num.Num;
|
||||||
import mightypork.util.constraints.num.mutable.NumVar;
|
|
||||||
import mightypork.util.constraints.vect.Vect;
|
import mightypork.util.constraints.vect.Vect;
|
||||||
import mightypork.util.constraints.vect.mutable.VectVar;
|
import mightypork.util.constraints.vect.mutable.VectVar;
|
||||||
import mightypork.util.math.color.Color;
|
import mightypork.util.math.color.Color;
|
||||||
@@ -21,23 +20,14 @@ class MenuButton extends ClickableComponent {
|
|||||||
private final Vect offsetActive = Vect.make(this.height().perc(-5), Num.ZERO);
|
private final Vect offsetActive = Vect.make(this.height().perc(-5), Num.ZERO);
|
||||||
private final Color color;
|
private final Color color;
|
||||||
|
|
||||||
private final double ALPHA_OFF = 0.6;
|
|
||||||
private final double ALPHA_ON = 1;
|
|
||||||
|
|
||||||
private final double SH_ALPHA_OFF = 0.1;
|
|
||||||
private final double SH_ALPHA_ON = 0.5;
|
|
||||||
|
|
||||||
private final NumVar alphaMul = Num.makeVar(ALPHA_OFF);
|
|
||||||
private final NumVar alphaMulSh = Num.makeVar(SH_ALPHA_OFF);
|
|
||||||
|
|
||||||
|
|
||||||
public MenuButton(String text, Color color)
|
public MenuButton(String text, Color color)
|
||||||
{
|
{
|
||||||
this.color = color.withAlpha(alphaMul);
|
this.color = color;
|
||||||
|
|
||||||
this.painter = new TextPainter(font, AlignX.CENTER, this.color, text);
|
this.painter = new TextPainter(font, AlignX.CENTER, this.color, text);
|
||||||
this.painter.setRect(this.shrink(this.height().perc(8)).move(offset));
|
this.painter.setRect(this.shrink(this.height().perc(8)).move(offset));
|
||||||
this.painter.setShadow(Color.BLACK.withAlpha(alphaMulSh), height().div(24).toVectXY());
|
this.painter.setShadow(Color.BLACK.withAlpha(0.3), height().div(24).toVectXY());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -46,12 +36,8 @@ class MenuButton extends ClickableComponent {
|
|||||||
{
|
{
|
||||||
if (isMouseOver()) {
|
if (isMouseOver()) {
|
||||||
offset.setTo(offsetActive);
|
offset.setTo(offsetActive);
|
||||||
alphaMul.setTo(ALPHA_ON);
|
|
||||||
alphaMulSh.setTo(SH_ALPHA_ON);
|
|
||||||
} else {
|
} else {
|
||||||
offset.setTo(Vect.ZERO);
|
offset.setTo(Vect.ZERO);
|
||||||
alphaMul.setTo(ALPHA_OFF);
|
|
||||||
alphaMulSh.setTo(SH_ALPHA_OFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
painter.render();
|
painter.render();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package mightypork.rogue.world;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import mightypork.rogue.world.map.Level;
|
import mightypork.rogue.world.map.Level;
|
||||||
|
import mightypork.rogue.world.tile.TileModel;
|
||||||
import mightypork.rogue.world.tile.Tiles;
|
import mightypork.rogue.world.tile.Tiles;
|
||||||
|
|
||||||
|
|
||||||
@@ -20,33 +21,30 @@ public class MapGenerator {
|
|||||||
final World w = new World();
|
final World w = new World();
|
||||||
w.setSeed(seed);
|
w.setSeed(seed);
|
||||||
|
|
||||||
final int levels = 4 + rand.nextInt(6);
|
w.addLevel(createLevel(rand.nextLong(), Tiles.CRYSTAL_FLOOR, Tiles.CRYSTAL_WALL));
|
||||||
|
w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
|
||||||
for (int i = 0; i < levels; i++) {
|
|
||||||
w.addLevel(createLevel(rand.nextLong()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO place on start position
|
// TODO place on start position
|
||||||
w.setPlayer(new PlayerInfo(10, 10, 0));
|
w.getPlayer().teleport(new WorldPos(10, 10, 0));
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Level createLevel(long seed)
|
private static Level createLevel(long seed, TileModel floor, TileModel wall)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
final Level lm = new Level(20, 20);
|
final Level lm = new Level(20, 20);
|
||||||
lm.setSeed(seed);
|
lm.setSeed(seed);
|
||||||
|
|
||||||
lm.fill(Tiles.CRYSTAL_FLOOR);
|
lm.fill(floor);
|
||||||
|
|
||||||
final Random rand = new Random();
|
final Random rand = new Random();
|
||||||
rand.setSeed(seed);
|
rand.setSeed(seed);
|
||||||
|
|
||||||
for (int i = 0; i < 150; i++) {
|
for (int i = 0; i < 150; i++) {
|
||||||
lm.setTile(Tiles.CRYSTAL_WALL, rand.nextInt(20), rand.nextInt(20));
|
lm.setTile(wall, rand.nextInt(20), rand.nextInt(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
return lm;
|
return lm;
|
||||||
|
|||||||
@@ -6,13 +6,7 @@ package mightypork.rogue.world;
|
|||||||
*
|
*
|
||||||
* @author MightyPork
|
* @author MightyPork
|
||||||
*/
|
*/
|
||||||
public interface MapObserver {
|
public interface MapObserver extends WorldEntity {
|
||||||
|
|
||||||
/**
|
|
||||||
* @return observer's position
|
|
||||||
*/
|
|
||||||
public WorldPos getPosition();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return observed range (in tiles)
|
* @return observed range (in tiles)
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package mightypork.rogue.world;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mightypork.util.constraints.vect.Vect;
|
||||||
|
import mightypork.util.constraints.vect.mutable.VectAnimated;
|
||||||
|
import mightypork.util.control.timing.Updateable;
|
||||||
|
import mightypork.util.ion.IonBundle;
|
||||||
|
import mightypork.util.ion.IonBundled;
|
||||||
|
import mightypork.util.math.Easing;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player info
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class Player implements IonBundled, MapObserver, Updateable {
|
||||||
|
|
||||||
|
private final WorldPos position = new WorldPos();
|
||||||
|
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
|
||||||
|
private final WorldPos target = new WorldPos();
|
||||||
|
private Runnable targetListener;
|
||||||
|
|
||||||
|
|
||||||
|
public Player()
|
||||||
|
{
|
||||||
|
walkOffset.setDefaultDuration(0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Player(int x, int y, int floor)
|
||||||
|
{
|
||||||
|
this.position.setTo(x, y, floor);
|
||||||
|
this.target.setTo(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Player(WorldPos pos)
|
||||||
|
{
|
||||||
|
this(pos.x, pos.y, pos.floor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonBundle in) throws IOException
|
||||||
|
{
|
||||||
|
in.loadBundled("pos", position);
|
||||||
|
in.loadBundled("target", target);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonBundle out) throws IOException
|
||||||
|
{
|
||||||
|
out.putBundled("pos", position);
|
||||||
|
out.putBundled("target", target);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldPos getLogicalPosition()
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vect getVisualOffset()
|
||||||
|
{
|
||||||
|
return walkOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewRange()
|
||||||
|
{
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void teleport(WorldPos pos)
|
||||||
|
{
|
||||||
|
position.setTo(pos);
|
||||||
|
target.setTo(pos);
|
||||||
|
walkOffset.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void walk(int offsetX, int offsetY)
|
||||||
|
{
|
||||||
|
this.target.setTo(position.x + offsetX, position.y + offsetY, this.position.floor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(double delta)
|
||||||
|
{
|
||||||
|
if (!walkOffset.isFinished()) {
|
||||||
|
walkOffset.update(delta);
|
||||||
|
if (walkOffset.isFinished()) {
|
||||||
|
position.add(walkOffset.xi(), walkOffset.yi(), position.floor);
|
||||||
|
walkOffset.reset();
|
||||||
|
targetListener.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (walkOffset.isFinished() && !target.equals(position)) {
|
||||||
|
|
||||||
|
int x = (target.x - position.x);
|
||||||
|
if (x > 0) x = 1;
|
||||||
|
if (x < 0) x = -1;
|
||||||
|
int y = (target.y - position.y);
|
||||||
|
if (y > 0) y = 1;
|
||||||
|
if (y < 0) y = -1;
|
||||||
|
|
||||||
|
walkOffset.animate(x, y, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setTargetListener(Runnable r)
|
||||||
|
{
|
||||||
|
this.targetListener = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.IonBundle;
|
|
||||||
import mightypork.util.files.ion.IonConstructor;
|
|
||||||
import mightypork.util.files.ion.Ionizable;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Player info
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public class PlayerInfo implements Ionizable, MapObserver {
|
|
||||||
|
|
||||||
public static final short ION_MARK = 708;
|
|
||||||
|
|
||||||
public WorldPos position = new WorldPos();
|
|
||||||
|
|
||||||
|
|
||||||
@IonConstructor
|
|
||||||
public PlayerInfo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public PlayerInfo(int x, int y, int floor)
|
|
||||||
{
|
|
||||||
this.position.setTo(x, y, floor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public PlayerInfo(WorldPos pos)
|
|
||||||
{
|
|
||||||
this.position = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
final IonBundle ib = (IonBundle) Ion.readObject(in);
|
|
||||||
|
|
||||||
position = ib.get("pos", position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
final IonBundle ib = new IonBundle();
|
|
||||||
|
|
||||||
ib.put("pos", position);
|
|
||||||
|
|
||||||
Ion.writeObject(out, ib);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short getIonMark()
|
|
||||||
{
|
|
||||||
return ION_MARK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WorldPos getPosition()
|
|
||||||
{
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getViewRange()
|
|
||||||
{
|
|
||||||
return 15;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,8 +2,7 @@ package mightypork.rogue.world;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.util.ArrayList;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -14,19 +13,15 @@ import mightypork.util.constraints.rect.RectConst;
|
|||||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||||
import mightypork.util.constraints.vect.VectConst;
|
import mightypork.util.constraints.vect.VectConst;
|
||||||
import mightypork.util.control.timing.Updateable;
|
import mightypork.util.control.timing.Updateable;
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.ion.IonBundle;
|
||||||
import mightypork.util.files.ion.IonBundle;
|
import mightypork.util.ion.IonBundled;
|
||||||
import mightypork.util.files.ion.Ionizable;
|
|
||||||
import mightypork.util.files.ion.templates.StreamableArrayList;
|
|
||||||
|
|
||||||
|
|
||||||
public class World implements Ionizable, Updateable {
|
public class World implements IonBundled, Updateable {
|
||||||
|
|
||||||
public static final short ION_MARK = 706;
|
private final ArrayList<Level> levels = new ArrayList<>();
|
||||||
|
|
||||||
private StreamableArrayList<Level> levels = new StreamableArrayList<>();
|
private final Player player = new Player();
|
||||||
|
|
||||||
private PlayerInfo player = new PlayerInfo();
|
|
||||||
|
|
||||||
private transient final Set<MapObserver> observers = new HashSet<>();
|
private transient final Set<MapObserver> observers = new HashSet<>();
|
||||||
|
|
||||||
@@ -35,36 +30,20 @@ public class World implements Ionizable, Updateable {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(InputStream in) throws IOException
|
public void load(IonBundle in) throws IOException
|
||||||
{
|
{
|
||||||
// world data
|
in.loadBundled("player", player);
|
||||||
final IonBundle ib = (IonBundle) Ion.readObject(in);
|
seed = in.get("seed", 0L);
|
||||||
player = ib.get("player", player);
|
in.loadSequence("levels", levels);
|
||||||
seed = ib.get("seed", seed);
|
|
||||||
|
|
||||||
Ion.readSequence(in, levels);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(OutputStream out) throws IOException
|
public void save(IonBundle out) throws IOException
|
||||||
{
|
{
|
||||||
final IonBundle ib = new IonBundle();
|
out.putBundled("player", player);
|
||||||
ib.put("player", player);
|
out.put("seed", seed);
|
||||||
ib.put("seed", seed);
|
out.putSequence("levels", levels);
|
||||||
Ion.writeObject(out, ib);
|
|
||||||
|
|
||||||
Ion.writeSequence(out, levels);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setPlayer(PlayerInfo player)
|
|
||||||
{
|
|
||||||
removeObserver(this.player);
|
|
||||||
|
|
||||||
this.player = player;
|
|
||||||
|
|
||||||
addObserver(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -86,19 +65,14 @@ public class World implements Ionizable, Updateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short getIonMark()
|
|
||||||
{
|
|
||||||
return ION_MARK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(double delta)
|
public void update(double delta)
|
||||||
{
|
{
|
||||||
|
player.update(delta);
|
||||||
|
|
||||||
for (int level = 0; level < levels.size(); level++) {
|
for (int level = 0; level < levels.size(); level++) {
|
||||||
for (final MapObserver observer : observers) {
|
for (final MapObserver observer : observers) {
|
||||||
if (observer.getPosition().floor == level) {
|
if (observer.getLogicalPosition().floor == level) {
|
||||||
levels.get(level).update(observer, delta);
|
levels.get(level).update(observer, delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +82,7 @@ public class World implements Ionizable, Updateable {
|
|||||||
|
|
||||||
public Level getLevelForObserver(MapObserver observer)
|
public Level getLevelForObserver(MapObserver observer)
|
||||||
{
|
{
|
||||||
return levels.get(observer.getPosition().floor);
|
return levels.get(observer.getLogicalPosition().floor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -138,19 +112,22 @@ public class World implements Ionizable, Updateable {
|
|||||||
|
|
||||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||||
|
|
||||||
final int playerX = player.getPosition().x;
|
final double playerX = player.getLogicalPosition().x + player.getVisualOffset().x();
|
||||||
final int playerY = player.getPosition().y;
|
final double playerY = player.getLogicalPosition().y + player.getVisualOffset().y();
|
||||||
|
|
||||||
// total map area
|
// total map area
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
final RectConst mapRect = vpCenter.startRect().grow(
|
final RectConst mapRect = vpCenter.startRect().grow(
|
||||||
playerX*tileSize,
|
playerX*tileSize,
|
||||||
playerY*tileSize,//
|
|
||||||
(floor.getWidth() - playerX) * tileSize,
|
(floor.getWidth() - playerX) * tileSize,
|
||||||
|
playerY*tileSize,
|
||||||
(floor.getHeight() - playerY) * tileSize
|
(floor.getHeight() - playerY) * tileSize
|
||||||
).freeze();
|
).freeze();
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
|
System.out.println(playerX + "," + playerY + " : " + mapRect);
|
||||||
|
System.out.println(floor.getWidth() + "," + floor.getHeight());
|
||||||
|
|
||||||
// tiles to render
|
// tiles to render
|
||||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
|
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
|
||||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
|
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
|
||||||
@@ -177,4 +154,10 @@ public class World implements Ionizable, Updateable {
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Player getPlayer()
|
||||||
|
{
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package mightypork.rogue.world;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.util.constraints.vect.Vect;
|
||||||
|
|
||||||
|
|
||||||
|
public interface WorldEntity {
|
||||||
|
|
||||||
|
WorldPos getLogicalPosition();
|
||||||
|
|
||||||
|
|
||||||
|
Vect getVisualOffset();
|
||||||
|
}
|
||||||
@@ -2,12 +2,9 @@ package mightypork.rogue.world;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.ion.IonBundle;
|
||||||
import mightypork.util.files.ion.IonConstructor;
|
import mightypork.util.ion.IonBundled;
|
||||||
import mightypork.util.files.ion.Ionizable;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,57 +12,88 @@ import mightypork.util.files.ion.Ionizable;
|
|||||||
*
|
*
|
||||||
* @author MightyPork
|
* @author MightyPork
|
||||||
*/
|
*/
|
||||||
public class WorldPos implements Ionizable {
|
public class WorldPos implements IonBundled {
|
||||||
|
|
||||||
public static final short ION_MARK = 707;
|
|
||||||
|
|
||||||
public int x, y, floor;
|
public int x, y, floor;
|
||||||
|
|
||||||
|
|
||||||
public WorldPos(int x, int y, int z)
|
public WorldPos(int x, int y, int floor)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.floor = z;
|
this.floor = floor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@IonConstructor
|
|
||||||
public WorldPos()
|
public WorldPos()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(InputStream in) throws IOException
|
public void load(IonBundle in) throws IOException
|
||||||
{
|
{
|
||||||
x = Ion.readInt(in);
|
x = in.get("x", 0);
|
||||||
y = Ion.readInt(in);
|
y = in.get("y", 0);
|
||||||
floor = Ion.readInt(in);
|
floor = in.get("z", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(OutputStream out) throws IOException
|
public void save(IonBundle out) throws IOException
|
||||||
{
|
{
|
||||||
Ion.writeInt(out, x);
|
out.put("x", x);
|
||||||
Ion.writeInt(out, y);
|
out.put("y", y);
|
||||||
Ion.writeInt(out, floor);
|
out.put("z", floor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
public void setTo(int x, int y, int floor)
|
||||||
public short getIonMark()
|
|
||||||
{
|
|
||||||
return ION_MARK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setTo(int x, int y, int z)
|
|
||||||
{
|
{
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.floor = z;
|
this.floor = floor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setTo(WorldPos other)
|
||||||
|
{
|
||||||
|
this.x = other.x;
|
||||||
|
this.y = other.y;
|
||||||
|
this.floor = other.floor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + floor;
|
||||||
|
result = prime * result + x;
|
||||||
|
result = prime * result + y;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj)
|
||||||
|
{
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null) return false;
|
||||||
|
if (!(obj instanceof WorldPos)) return false;
|
||||||
|
final WorldPos other = (WorldPos) obj;
|
||||||
|
if (floor != other.floor) return false;
|
||||||
|
if (x != other.x) return false;
|
||||||
|
if (y != other.y) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void add(int x, int y, int floor)
|
||||||
|
{
|
||||||
|
setTo(this.x + x, this.y + y, this.floor + floor);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,16 @@ package mightypork.rogue.world.item;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.ion.IonBinary;
|
||||||
import mightypork.util.files.ion.IonConstructor;
|
import mightypork.util.ion.IonInput;
|
||||||
import mightypork.util.files.ion.Ionizable;
|
import mightypork.util.ion.IonOutput;
|
||||||
|
|
||||||
|
|
||||||
public class Item implements Ionizable {
|
public class Item implements IonBinary {
|
||||||
|
|
||||||
public static final short ION_MARK = 701;
|
public static final short ION_MARK = 51;
|
||||||
|
|
||||||
private transient ItemModel model;
|
private transient ItemModel model;
|
||||||
|
|
||||||
@@ -26,7 +24,6 @@ public class Item implements Ionizable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@IonConstructor
|
|
||||||
public Item()
|
public Item()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -46,16 +43,16 @@ public class Item implements Ionizable {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(OutputStream out) throws IOException
|
public void save(IonOutput out) throws IOException
|
||||||
{
|
{
|
||||||
Ion.writeShort(out, (short) id);
|
out.writeIntByte(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(InputStream in) throws IOException
|
public void load(IonInput in) throws IOException
|
||||||
{
|
{
|
||||||
id = Ion.readShort(in);
|
id = in.readIntByte();
|
||||||
|
|
||||||
// if id changed, get new model
|
// if id changed, get new model
|
||||||
if (model == null || id != model.id) model = Items.get(id);
|
if (model == null || id != model.id) model = Items.get(id);
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package mightypork.rogue.world.item;
|
package mightypork.rogue.world.item;
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
|
||||||
import mightypork.util.annotations.DefaultImpl;
|
import mightypork.util.annotations.DefaultImpl;
|
||||||
import mightypork.util.constraints.num.proxy.NumBoundAdapter;
|
|
||||||
import mightypork.util.constraints.rect.Rect;
|
|
||||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||||
import mightypork.util.constraints.rect.proxy.RectBoundAdapter;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class ItemModel {
|
public abstract class ItemModel {
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package mightypork.rogue.world.map;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.util.constraints.rect.Rect;
|
||||||
|
|
||||||
|
|
||||||
|
public class EntityRenderContext extends MapRenderContext {
|
||||||
|
|
||||||
|
public EntityRenderContext(MapAccess map, Rect drawArea)
|
||||||
|
{
|
||||||
|
super(map, drawArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,17 +2,16 @@ package mightypork.rogue.world.map;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import mightypork.rogue.world.MapObserver;
|
import mightypork.rogue.world.MapObserver;
|
||||||
import mightypork.rogue.world.WorldPos;
|
import mightypork.rogue.world.WorldPos;
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.rogue.world.tile.TileModel;
|
import mightypork.rogue.world.tile.TileModel;
|
||||||
import mightypork.rogue.world.tile.Tiles;
|
import mightypork.rogue.world.tile.Tiles;
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.ion.IonBinary;
|
||||||
import mightypork.util.files.ion.IonConstructor;
|
import mightypork.util.ion.IonBundle;
|
||||||
import mightypork.util.files.ion.Ionizable;
|
import mightypork.util.ion.IonInput;
|
||||||
|
import mightypork.util.ion.IonOutput;
|
||||||
import mightypork.util.math.noise.NoiseGen;
|
import mightypork.util.math.noise.NoiseGen;
|
||||||
|
|
||||||
|
|
||||||
@@ -21,9 +20,9 @@ import mightypork.util.math.noise.NoiseGen;
|
|||||||
*
|
*
|
||||||
* @author MightyPork
|
* @author MightyPork
|
||||||
*/
|
*/
|
||||||
public class Level implements MapAccess, Ionizable {
|
public class Level implements MapAccess, IonBinary {
|
||||||
|
|
||||||
public static final int ION_MARK = 702;
|
public static final int ION_MARK = 52;
|
||||||
|
|
||||||
private int width, height;
|
private int width, height;
|
||||||
|
|
||||||
@@ -33,10 +32,9 @@ public class Level implements MapAccess, Ionizable {
|
|||||||
/** Level seed (used for generation and tile variation) */
|
/** Level seed (used for generation and tile variation) */
|
||||||
public long seed;
|
public long seed;
|
||||||
|
|
||||||
private NoiseGen noiseGen;
|
private transient NoiseGen noiseGen;
|
||||||
|
|
||||||
|
|
||||||
@IonConstructor
|
|
||||||
public Level()
|
public Level()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -53,8 +51,6 @@ public class Level implements MapAccess, Ionizable {
|
|||||||
private void buildArray()
|
private void buildArray()
|
||||||
{
|
{
|
||||||
this.tiles = new Tile[height][width];
|
this.tiles = new Tile[height][width];
|
||||||
|
|
||||||
fill(Tiles.NULL_EMPTY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,32 +127,43 @@ public class Level implements MapAccess, Ionizable {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(InputStream in) throws IOException
|
public void load(IonInput in) throws IOException
|
||||||
{
|
{
|
||||||
seed = Ion.readLong(in);
|
// metadata
|
||||||
width = Ion.readInt(in);
|
final IonBundle ib = in.readBundle();
|
||||||
height = Ion.readInt(in);
|
seed = ib.get("seed", 0L);
|
||||||
|
width = ib.get("w", 0);
|
||||||
|
height = ib.get("h", 0);
|
||||||
|
|
||||||
|
// init array of size
|
||||||
buildArray();
|
buildArray();
|
||||||
|
|
||||||
|
// load tiles
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
tiles[y][x] = new Tile();
|
// no mark
|
||||||
tiles[y][x].load(in);
|
final Tile t = new Tile();
|
||||||
|
t.load(in);
|
||||||
|
tiles[y][x] = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(OutputStream out) throws IOException
|
public void save(IonOutput out) throws IOException
|
||||||
{
|
{
|
||||||
Ion.writeLong(out, seed);
|
// metadata
|
||||||
Ion.writeInt(out, width);
|
final IonBundle ib = new IonBundle();
|
||||||
Ion.writeInt(out, height);
|
ib.put("seed", seed);
|
||||||
|
ib.put("w", width);
|
||||||
|
ib.put("h", height);
|
||||||
|
out.writeBundle(ib);
|
||||||
|
|
||||||
|
// tiles (writing this way to save space)
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
|
// no mark to save space
|
||||||
tiles[y][x].save(out);
|
tiles[y][x].save(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,7 +180,7 @@ public class Level implements MapAccess, Ionizable {
|
|||||||
public void update(MapObserver observer, double delta)
|
public void update(MapObserver observer, double delta)
|
||||||
{
|
{
|
||||||
final int viewRange = observer.getViewRange();
|
final int viewRange = observer.getViewRange();
|
||||||
final WorldPos position = observer.getPosition();
|
final WorldPos position = observer.getLogicalPosition();
|
||||||
|
|
||||||
int x1 = position.x - viewRange;
|
int x1 = position.x - viewRange;
|
||||||
int y1 = position.y - viewRange;
|
int y1 = position.y - viewRange;
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package mightypork.rogue.world.map;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.util.constraints.rect.Rect;
|
||||||
|
import mightypork.util.constraints.rect.builders.TiledRect;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class MapRenderContext {
|
||||||
|
|
||||||
|
protected final MapAccess map;
|
||||||
|
protected final TiledRect tiler;
|
||||||
|
private final Rect mapRect;
|
||||||
|
|
||||||
|
|
||||||
|
public MapRenderContext(MapAccess map, Rect drawArea)
|
||||||
|
{
|
||||||
|
this.map = map;
|
||||||
|
this.tiler = drawArea.tiles(map.getWidth(), map.getHeight());
|
||||||
|
this.mapRect = drawArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Rect getRectForTile(int x, int y)
|
||||||
|
{
|
||||||
|
return tiler.tile(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Rect getMapRect()
|
||||||
|
{
|
||||||
|
return mapRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,32 +3,27 @@ package mightypork.rogue.world.map;
|
|||||||
|
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.util.constraints.rect.Rect;
|
import mightypork.util.constraints.rect.Rect;
|
||||||
import mightypork.util.constraints.rect.builders.TiledRect;
|
|
||||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||||
import mightypork.util.math.noise.NoiseGen;
|
import mightypork.util.math.noise.NoiseGen;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context for tile rendering. Provides tile rect, surrounding tiles, rendered
|
* Context for tile rendering.
|
||||||
* tile and random noise values for position-static tile variation.
|
|
||||||
*
|
*
|
||||||
* @author MightyPork
|
* @author MightyPork
|
||||||
*/
|
*/
|
||||||
public final class TileRenderContext implements RectBound {
|
public final class TileRenderContext extends MapRenderContext implements RectBound {
|
||||||
|
|
||||||
private final MapAccess map;
|
public int x;
|
||||||
private final TiledRect tiler;
|
public int y;
|
||||||
private final NoiseGen noise;
|
private final NoiseGen noise;
|
||||||
|
|
||||||
public int x, y;
|
|
||||||
|
|
||||||
|
|
||||||
public TileRenderContext(MapAccess map, Rect drawArea)
|
public TileRenderContext(MapAccess map, Rect drawArea)
|
||||||
{
|
{
|
||||||
this.map = map;
|
super(map, drawArea);
|
||||||
this.tiler = drawArea.tiles(map.getWidth(), map.getHeight());
|
|
||||||
|
|
||||||
this.tiler.setOverlap(0.001); // avoid gaps (rounding error?)
|
this.tiler.setOverlap(0.01); // avoid gaps (rounding error?)
|
||||||
|
|
||||||
this.noise = map.getNoiseGen();
|
this.noise = map.getNoiseGen();
|
||||||
}
|
}
|
||||||
@@ -56,16 +51,6 @@ public final class TileRenderContext implements RectBound {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rect of the current tile to draw
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Rect getRect()
|
|
||||||
{
|
|
||||||
return tiler.tile(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return per-coord noise value 0..1
|
* @return per-coord noise value 0..1
|
||||||
*/
|
*/
|
||||||
@@ -79,4 +64,14 @@ public final class TileRenderContext implements RectBound {
|
|||||||
{
|
{
|
||||||
map.getTile(x, y).render(this);
|
map.getTile(x, y).render(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rect of the current tile to draw
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Rect getRect()
|
||||||
|
{
|
||||||
|
return getRectForTile(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,21 @@ package mightypork.rogue.world.tile;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import mightypork.rogue.world.item.Item;
|
import mightypork.rogue.world.item.Item;
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
import mightypork.rogue.world.map.TileRenderContext;
|
||||||
import mightypork.util.control.timing.Animator;
|
import mightypork.util.control.timing.Animator;
|
||||||
import mightypork.util.control.timing.Updateable;
|
import mightypork.util.control.timing.Updateable;
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.ion.IonBinary;
|
||||||
import mightypork.util.files.ion.IonBundle;
|
import mightypork.util.ion.IonBundle;
|
||||||
import mightypork.util.files.ion.IonConstructor;
|
import mightypork.util.ion.IonInput;
|
||||||
import mightypork.util.files.ion.Ionizable;
|
import mightypork.util.ion.IonOutput;
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public final class Tile implements Ionizable, Updateable {
|
public final class Tile implements IonBinary, Updateable {
|
||||||
|
|
||||||
public static final short ION_MARK = 700;
|
public static final short ION_MARK = 50;
|
||||||
|
|
||||||
private transient TileModel model;
|
private transient TileModel model;
|
||||||
|
|
||||||
@@ -50,7 +47,6 @@ public final class Tile implements Ionizable, Updateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@IonConstructor
|
|
||||||
public Tile()
|
public Tile()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -60,45 +56,45 @@ public final class Tile implements Ionizable, Updateable {
|
|||||||
{
|
{
|
||||||
model.render(context);
|
model.render(context);
|
||||||
|
|
||||||
if (!items.isEmpty()) {
|
if (hasItems()) {
|
||||||
getItemRenderer().render(items.peek(), context);
|
getItemRenderer().render(items.peek(), context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(OutputStream out) throws IOException
|
public void save(IonOutput out) throws IOException
|
||||||
{
|
{
|
||||||
if (model.isNullTile()) throw new RuntimeException("Cannot save null tile.");
|
out.writeIntByte(id);
|
||||||
|
|
||||||
Ion.writeShort(out, (short) id); // tile ID
|
if (model.hasDroppedItems()) {
|
||||||
Ion.writeSequence(out, items); // if empty, writes single END mark
|
out.writeSequence(items);
|
||||||
|
}
|
||||||
|
|
||||||
// models with metadata can save their stuff
|
|
||||||
if (model.hasMetadata()) {
|
if (model.hasMetadata()) {
|
||||||
IonBundle ib = new IonBundle();
|
final IonBundle ib = new IonBundle();
|
||||||
model.saveMetadata(this, ib);
|
model.saveMetadata(this, ib);
|
||||||
Ion.writeObject(out, ib);
|
out.writeBundle(ib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(InputStream in) throws IOException
|
public void load(IonInput in) throws IOException
|
||||||
{
|
{
|
||||||
id = Ion.readShort(in);
|
id = in.readIntByte();
|
||||||
|
|
||||||
// check if model is changed (can happen)
|
// check model
|
||||||
if (model == null || id != model.id) {
|
if (model == null || id != model.id) {
|
||||||
model = Tiles.get(id);
|
model = Tiles.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ion.readSequence(in, items); // if END is found, nothing is read.
|
if (model.hasDroppedItems()) {
|
||||||
|
in.readSequence(items);
|
||||||
|
}
|
||||||
|
|
||||||
// load model's stuff
|
|
||||||
if (model.hasMetadata()) {
|
if (model.hasMetadata()) {
|
||||||
IonBundle ib = (IonBundle) Ion.readObject(in);
|
model.loadMetadata(this, in.readBundle());
|
||||||
model.loadMetadata(this, ib);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +103,7 @@ public final class Tile implements Ionizable, Updateable {
|
|||||||
public void update(double delta)
|
public void update(double delta)
|
||||||
{
|
{
|
||||||
model.update(this, delta);
|
model.update(this, delta);
|
||||||
if (!items.isEmpty()) {
|
if (hasItems()) {
|
||||||
getItemRenderer().update(delta);
|
getItemRenderer().update(delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +127,7 @@ public final class Tile implements Ionizable, Updateable {
|
|||||||
|
|
||||||
public boolean hasItems()
|
public boolean hasItems()
|
||||||
{
|
{
|
||||||
return !items.isEmpty();
|
return model.hasDroppedItems() && !items.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package mightypork.rogue.world.tile;
|
|||||||
|
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
import mightypork.rogue.world.map.TileRenderContext;
|
||||||
import mightypork.util.annotations.DefaultImpl;
|
import mightypork.util.annotations.DefaultImpl;
|
||||||
import mightypork.util.files.ion.IonBundle;
|
import mightypork.util.ion.IonBundle;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,4 +104,13 @@ public abstract class TileModel {
|
|||||||
* @return has data
|
* @return has data
|
||||||
*/
|
*/
|
||||||
public abstract boolean hasMetadata();
|
public abstract boolean hasMetadata();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the tile can hold dropped items. Walls and such can return false
|
||||||
|
* to save disk space (no need to write empty list).
|
||||||
|
*
|
||||||
|
* @return true
|
||||||
|
*/
|
||||||
|
public abstract boolean hasDroppedItems();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ package mightypork.rogue.world.tile.models;
|
|||||||
import mightypork.rogue.world.map.TileRenderContext;
|
import mightypork.rogue.world.map.TileRenderContext;
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.rogue.world.tile.TileModel;
|
import mightypork.rogue.world.tile.TileModel;
|
||||||
import mightypork.util.files.ion.IonBundle;
|
import mightypork.util.ion.IonBundle;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,20 +59,30 @@ public abstract class AbstractNullTile extends TileModel {
|
|||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasMetadata()
|
public boolean hasMetadata()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadMetadata(Tile tile, IonBundle ib)
|
public void loadMetadata(Tile tile, IonBundle ib)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveMetadata(Tile tile, IonBundle ib)
|
public void saveMetadata(Tile tile, IonBundle ib)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDroppedItems()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,4 +20,11 @@ public class Floor extends SimpleTile {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDroppedItems()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import mightypork.rogue.world.map.TileRenderContext;
|
|||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.rogue.world.tile.TileModel;
|
import mightypork.rogue.world.tile.TileModel;
|
||||||
import mightypork.util.annotations.DefaultImpl;
|
import mightypork.util.annotations.DefaultImpl;
|
||||||
import mightypork.util.files.ion.IonBundle;
|
import mightypork.util.ion.IonBundle;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,4 +20,11 @@ public class Wall extends SimpleTile {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDroppedItems()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package mightypork.test;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
|
|
||||||
|
|
||||||
public class TestIonArray {
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException
|
|
||||||
{
|
|
||||||
final byte[] array = new byte[1024 * 8];
|
|
||||||
|
|
||||||
final Random rand = new Random();
|
|
||||||
|
|
||||||
for (int i = 0; i < array.length; i++) {
|
|
||||||
array[i] = (byte) rand.nextInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ion.toFile(new File("hello.ion"), array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package mightypork.test;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
|
|
||||||
|
|
||||||
public class TestIonArray2 {
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException
|
|
||||||
{
|
|
||||||
final int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 99999, 8888888 };
|
|
||||||
|
|
||||||
final OutputStream out = new FileOutputStream("fuck.ion");
|
|
||||||
|
|
||||||
Ion.writeIntArray(out, array);
|
|
||||||
Ion.writeString(out, "HELLO DUDE WHATSUP");
|
|
||||||
Ion.writeCharArray(out, "HERE'S ONE COOL ARRAY!!!".toCharArray());
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
final InputStream in = new FileInputStream("fuck.ion");
|
|
||||||
|
|
||||||
final int[] a = Ion.readIntArray(in);
|
|
||||||
|
|
||||||
for (final int i : a)
|
|
||||||
System.out.println(i);
|
|
||||||
|
|
||||||
final String s = Ion.readString(in);
|
|
||||||
System.out.println(s);
|
|
||||||
|
|
||||||
final char[] v = Ion.readCharArray(in);
|
|
||||||
|
|
||||||
for (final int i : v)
|
|
||||||
System.out.print((char) i);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package mightypork.test;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
|
|
||||||
public class TestRandomSeed {
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
|
|
||||||
{
|
|
||||||
final Random rand = new Random();
|
|
||||||
final long begin = System.currentTimeMillis();
|
|
||||||
|
|
||||||
for (int i = 0; i < 1000000; i++) {
|
|
||||||
rand.setSeed(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println((System.currentTimeMillis() - begin) / 1000D);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
final long begin = System.currentTimeMillis();
|
|
||||||
|
|
||||||
for (int i = 0; i < 1000000; i++) {
|
|
||||||
final Random rand = new Random();
|
|
||||||
rand.setSeed(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println((System.currentTimeMillis() - begin) / 1000D);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package mightypork.test;
|
|
||||||
|
|
||||||
|
|
||||||
public class testworldtofile {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,7 @@ import mightypork.util.math.Easing;
|
|||||||
public class VectAnimated extends VectMutable implements Pauseable, Updateable {
|
public class VectAnimated extends VectMutable implements Pauseable, Updateable {
|
||||||
|
|
||||||
private final NumAnimated x, y, z;
|
private final NumAnimated x, y, z;
|
||||||
private double defaultDuration = 0;
|
private double defaultDuration = 0.5;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,45 +83,30 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable {
|
|||||||
@Override
|
@Override
|
||||||
public void setX(double x)
|
public void setX(double x)
|
||||||
{
|
{
|
||||||
this.x.animate(x, defaultDuration);
|
this.x.setTo(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setY(double y)
|
public void setY(double y)
|
||||||
{
|
{
|
||||||
this.y.animate(y, defaultDuration);
|
this.y.setTo(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setZ(double z)
|
public void setZ(double z)
|
||||||
{
|
{
|
||||||
this.z.animate(z, defaultDuration);
|
this.z.setTo(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add offset with animation
|
|
||||||
*
|
|
||||||
* @param offset added offset
|
|
||||||
* @param duration animation time (seconds)
|
|
||||||
*/
|
|
||||||
public void add(Vect offset, double duration)
|
public void add(Vect offset, double duration)
|
||||||
{
|
{
|
||||||
animate(this.add(offset), duration);
|
animate(this.add(offset), duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Animate to given coordinates in given amount of time
|
|
||||||
*
|
|
||||||
* @param x
|
|
||||||
* @param y
|
|
||||||
* @param z
|
|
||||||
* @param duration animation time (seconds)
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
public VectAnimated animate(double x, double y, double z, double duration)
|
public VectAnimated animate(double x, double y, double z, double duration)
|
||||||
{
|
{
|
||||||
this.x.animate(x, duration);
|
this.x.animate(x, duration);
|
||||||
@@ -131,13 +116,6 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Animate to given vec in given amount of time.
|
|
||||||
*
|
|
||||||
* @param target target (only it's current value will be used)
|
|
||||||
* @param duration animation time (seconds)
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
public VectAnimated animate(Vect target, double duration)
|
public VectAnimated animate(Vect target, double duration)
|
||||||
{
|
{
|
||||||
animate(target.x(), target.y(), target.z(), duration);
|
animate(target.x(), target.y(), target.z(), duration);
|
||||||
@@ -145,6 +123,22 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public VectAnimated animate(double x, double y, double z)
|
||||||
|
{
|
||||||
|
this.x.animate(x, defaultDuration);
|
||||||
|
this.y.animate(y, defaultDuration);
|
||||||
|
this.z.animate(z, defaultDuration);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public VectAnimated animate(Vect target)
|
||||||
|
{
|
||||||
|
animate(target.x(), target.y(), target.z());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the default duration (seconds)
|
* @return the default duration (seconds)
|
||||||
*/
|
*/
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,58 +0,0 @@
|
|||||||
package mightypork.util.files.ion;
|
|
||||||
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.templates.StreamableHashMap;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Data bundle.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Storing data in a bundle guarantees that future versions will be compatible
|
|
||||||
* with the older format. Reading using default values ensures that you will get
|
|
||||||
* some value even if it was not saved in the file.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public class IonBundle extends StreamableHashMap<String, Object> implements Ionizable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an object. If not found, fallback is returned.
|
|
||||||
*
|
|
||||||
* @param key key
|
|
||||||
* @param fallback fallback
|
|
||||||
* @return element
|
|
||||||
*/
|
|
||||||
public <T> T get(String key, T fallback)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
final T itm = (T) super.get(key);
|
|
||||||
if (itm == null) return fallback;
|
|
||||||
return itm;
|
|
||||||
} catch (final ClassCastException e) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store an element. It's allowed to store any object, but only primitive
|
|
||||||
* types, String, their arrays, and Ionizable objects can be successfully
|
|
||||||
* stored to stream..
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object put(String key, Object value)
|
|
||||||
{
|
|
||||||
return super.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short getIonMark()
|
|
||||||
{
|
|
||||||
return Ion.DATA_BUNDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package mightypork.util.files.ion;
|
|
||||||
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Implicit constructor marked like this is intended to be solely used for ION
|
|
||||||
* de-serialization.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Constructors marked like this should create a functional instance with
|
|
||||||
* default values.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This is a descriptive annotation and has no other function.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
@Target(ElementType.CONSTRUCTOR)
|
|
||||||
@Documented
|
|
||||||
public @interface IonConstructor {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package mightypork.util.files.ion;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Data object that can be reconstructed by Ion based on it's mark. Such object
|
|
||||||
* MUST provide an implicit constructor.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* All {@link Ionizable}s must be registered to {@link Ion}, otherwise they
|
|
||||||
* can't be written/loaded using the mark.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public interface Ionizable extends Streamable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Ion mark byte.
|
|
||||||
*
|
|
||||||
* @return Ion mark byte.
|
|
||||||
*/
|
|
||||||
public short getIonMark();
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package mightypork.util.files.ion;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Saveable to a stream.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public interface Streamable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load data from the input stream. Must be compatible with the
|
|
||||||
* <code>save</code> method.
|
|
||||||
*
|
|
||||||
* @param in input stream
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
void load(InputStream in) throws IOException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store data to output stream.
|
|
||||||
*
|
|
||||||
* @param out Output stream
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
void save(OutputStream out) throws IOException;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package mightypork.util.files.ion.templates;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public class StreamableArrayList<E> extends ArrayList<E> implements Streamable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
Ion.readSequence(in, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
Ion.writeSequence(out, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package mightypork.util.files.ion.templates;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public class StreamableHashMap<K, V> extends HashMap<K, V> implements Streamable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
Ion.readMap(in, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
Ion.writeMap(out, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package mightypork.util.files.ion.templates;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class StreamableHashSet<E> extends HashSet<E> implements Streamable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
Ion.readSequence(in, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
Ion.writeSequence(out, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package mightypork.util.files.ion.templates;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public class StreamableLinkedHashMap<K, V> extends LinkedHashMap<K, V> implements Streamable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
Ion.readMap(in, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
Ion.writeMap(out, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package mightypork.util.files.ion.templates;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public class StreamableLinkedList<E> extends LinkedList<E> implements Streamable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
Ion.readSequence(in, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
Ion.writeSequence(out, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package mightypork.util.files.ion.templates;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public class StreamableStack<E> extends Stack<E> implements Streamable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
Ion.readSequence(in, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
Ion.writeSequence(out, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package mightypork.util.files.ion.templates;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import mightypork.util.files.ion.Ion;
|
|
||||||
import mightypork.util.files.ion.Streamable;
|
|
||||||
|
|
||||||
|
|
||||||
public class StreamableTreeSet<E> extends TreeSet<E> implements Streamable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(InputStream in) throws IOException
|
|
||||||
{
|
|
||||||
Ion.readSequence(in, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(OutputStream out) throws IOException
|
|
||||||
{
|
|
||||||
Ion.writeSequence(out, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,296 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import mightypork.util.logging.Log;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Universal data storage system (main API class)
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class Ion {
|
||||||
|
|
||||||
|
// marks for object saving
|
||||||
|
/** Null mark */
|
||||||
|
static final int NULL = 0;
|
||||||
|
/** Boolean mark */
|
||||||
|
static final int BOOLEAN = 1;
|
||||||
|
/** Byte mark */
|
||||||
|
static final int BYTE = 2;
|
||||||
|
/** Character mark */
|
||||||
|
static final int CHAR = 3;
|
||||||
|
/** Short mark */
|
||||||
|
static final int SHORT = 4;
|
||||||
|
/** Integer mark */
|
||||||
|
static final int INT = 5;
|
||||||
|
/** Long mark */
|
||||||
|
static final int LONG = 6;
|
||||||
|
/** Float mark */
|
||||||
|
static final int FLOAT = 7;
|
||||||
|
/** Double mark */
|
||||||
|
static final int DOUBLE = 8;
|
||||||
|
/** String mark */
|
||||||
|
static final int STRING = 9;
|
||||||
|
/** Boolean array mark */
|
||||||
|
static final int BOOLEAN_ARRAY = 10;
|
||||||
|
/** Byte array mark */
|
||||||
|
static final int BYTE_ARRAY = 11;
|
||||||
|
/** Character array mark */
|
||||||
|
static final int CHAR_ARRAY = 12;
|
||||||
|
/** Short array mark */
|
||||||
|
static final int SHORT_ARRAY = 13;
|
||||||
|
/** Integer array mark */
|
||||||
|
static final int INT_ARRAY = 14;
|
||||||
|
/** Long array mark */
|
||||||
|
static final int LONG_ARRAY = 15;
|
||||||
|
/** Float array mark */
|
||||||
|
static final int FLOAT_ARRAY = 16;
|
||||||
|
/** Double array mark */
|
||||||
|
static final int DOUBLE_ARRAY = 17;
|
||||||
|
/** String array mark */
|
||||||
|
static final int STRING_ARRAY = 18;
|
||||||
|
/** Entry mark - start of map or sequence entry */
|
||||||
|
static final int ENTRY = 19;
|
||||||
|
/** End mark - end of sequence or map */
|
||||||
|
static final int END = 20;
|
||||||
|
/** Map mark (built-in data structure) */
|
||||||
|
static final int DATA_BUNDLE = 21;
|
||||||
|
/** Sequence wrapper for bundle */
|
||||||
|
static final int SEQUENCE_WRAPPER = 22;
|
||||||
|
/** Map wrapper for bundle */
|
||||||
|
static final int MAP_WRAPPER = 23;
|
||||||
|
|
||||||
|
// technical 20..39
|
||||||
|
|
||||||
|
/** Ionizables<Mark, Class> */
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private static Class[] registered = new Class[256];
|
||||||
|
|
||||||
|
private static boolean reservedMarkChecking;
|
||||||
|
|
||||||
|
static {
|
||||||
|
reservedMarkChecking = false;
|
||||||
|
|
||||||
|
// register built-ins
|
||||||
|
registerBinary(DATA_BUNDLE, IonBundle.class);
|
||||||
|
registerBinary(SEQUENCE_WRAPPER, IonSequenceWrapper.class);
|
||||||
|
registerBinary(MAP_WRAPPER, IonMapWrapper.class);
|
||||||
|
|
||||||
|
reservedMarkChecking = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register new {@link IonBinary} class for writing/loading.
|
||||||
|
*
|
||||||
|
* @param mark mark to be used 50..255, unless internal
|
||||||
|
* @param objClass class of the registered object
|
||||||
|
*/
|
||||||
|
public static void registerBinary(int mark, Class<? extends IonBinary> objClass)
|
||||||
|
{
|
||||||
|
// negative marks are allowed.
|
||||||
|
if (mark > 255) throw new IllegalArgumentException("Mark must be < 256.");
|
||||||
|
if (mark < 0) throw new IllegalArgumentException("Mark must be positive.");
|
||||||
|
|
||||||
|
if (reservedMarkChecking && mark < 50) {
|
||||||
|
throw new IllegalArgumentException("Marks 0..49 are reserved.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registered[mark] != null) {
|
||||||
|
throw new IllegalArgumentException("Mark " + mark + " is already in use.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
objClass.getConstructor();
|
||||||
|
} catch (NoSuchMethodException | SecurityException e) {
|
||||||
|
throw new IllegalArgumentException("Class " + Log.str(objClass) + " doesn't have an implicit constructor.");
|
||||||
|
}
|
||||||
|
|
||||||
|
registered[mark] = objClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load binary from file and cast.
|
||||||
|
*/
|
||||||
|
public static <T extends IonBinary> T fromFile(String path) throws IOException
|
||||||
|
{
|
||||||
|
return fromFile(new File(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load binary from file and cast.
|
||||||
|
*/
|
||||||
|
public static <T extends IonBinary> T fromFile(File file) throws IOException
|
||||||
|
{
|
||||||
|
try(InputStream in = new FileInputStream(file)) {
|
||||||
|
return fromStream(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load bundled from file and unwrap.
|
||||||
|
*/
|
||||||
|
public static <T extends IonBundled> T fromFile(String path, Class<? extends T> objClass) throws IOException
|
||||||
|
{
|
||||||
|
return fromFile(new File(path), objClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load bundled from file and unwrap.
|
||||||
|
*/
|
||||||
|
public static <T extends IonBundled> T fromFile(File file, Class<? extends T> objClass) throws IOException
|
||||||
|
{
|
||||||
|
try(InputStream in = new FileInputStream(file)) {
|
||||||
|
|
||||||
|
return fromStream(in, objClass);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void toFile(String path, IonBundled obj) throws IOException
|
||||||
|
{
|
||||||
|
toFile(new File(path), obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap bundled and save to file.
|
||||||
|
*/
|
||||||
|
public static void toFile(File file, IonBundled obj) throws IOException
|
||||||
|
{
|
||||||
|
toFile(file, wrap(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write binary to file with mark.
|
||||||
|
*/
|
||||||
|
public static void toFile(String path, IonBinary obj) throws IOException
|
||||||
|
{
|
||||||
|
toFile(new File(path), obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write binary to file with mark.
|
||||||
|
*/
|
||||||
|
public static void toFile(File file, IonBinary obj) throws IOException
|
||||||
|
{
|
||||||
|
try(OutputStream out = new FileOutputStream(file)) {
|
||||||
|
|
||||||
|
toStream(out, obj);
|
||||||
|
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new IOException("Error writing to ION file.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load object from stream based on mark, try to cast.
|
||||||
|
*/
|
||||||
|
public static <T> T fromStream(InputStream in) throws IOException
|
||||||
|
{
|
||||||
|
final IonInput inp = new IonInput(in);
|
||||||
|
|
||||||
|
return (T) inp.readObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load bundled object from stream, unwrap.
|
||||||
|
*/
|
||||||
|
public static <T extends IonBundled> T fromStream(InputStream in, Class<? extends T> objClass) throws IOException
|
||||||
|
{
|
||||||
|
return unwrap(new IonInput(in).readBundle(), objClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write object to output with a mark.
|
||||||
|
*/
|
||||||
|
public static void toStream(OutputStream out, IonBinary obj) throws IOException
|
||||||
|
{
|
||||||
|
new IonOutput(out).writeObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new bundle and write the object to it.
|
||||||
|
*/
|
||||||
|
public static IonBundle wrap(IonBundled content) throws IOException
|
||||||
|
{
|
||||||
|
final IonBundle ib = new IonBundle();
|
||||||
|
content.save(ib);
|
||||||
|
return ib;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to unwrap an object from bundle. The object class must have implicit
|
||||||
|
* accessible constructor.
|
||||||
|
*
|
||||||
|
* @param bundle unwrapped bundle
|
||||||
|
* @param objClass class of desired object
|
||||||
|
* @return the object unwrapped
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static <T extends IonBundled> T unwrap(IonBundle bundle, Class<? extends T> objClass) throws IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
final T inst = objClass.newInstance();
|
||||||
|
inst.load(bundle);
|
||||||
|
return inst;
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new IOException("Could not instantiate " + Log.str(objClass) + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static Class<? extends IonBinary> getClassForMark(int mark)
|
||||||
|
{
|
||||||
|
return registered[mark];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the mark is for a registered {@link IonBinary} object
|
||||||
|
*/
|
||||||
|
static boolean isMarkForBinary(int mark)
|
||||||
|
{
|
||||||
|
return registered[mark] != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure object is registered in the table
|
||||||
|
*
|
||||||
|
* @throws IOException if not registered or class mismatch
|
||||||
|
*/
|
||||||
|
static void assertRegistered(IonBinary obj) throws IOException
|
||||||
|
{
|
||||||
|
final int mark = obj.getIonMark();
|
||||||
|
|
||||||
|
final Class<? extends IonBinary> clz = Ion.getClassForMark(mark);
|
||||||
|
|
||||||
|
if (clz == null) {
|
||||||
|
throw new IOException("Not registered - mark: " + mark + ", class: " + Log.str(obj.getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clz != obj.getClass()) {
|
||||||
|
throw new IOException("Class mismatch - mark: " + mark + ", class: " + Log.str(obj.getClass()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binary ion object
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public interface IonBinary {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data from the input stream.
|
||||||
|
*
|
||||||
|
* @param in input stream
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
void load(IonInput in) throws IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store data to output stream (in such way that the load method will later
|
||||||
|
* be able to read it).
|
||||||
|
*
|
||||||
|
* @param out Output stream
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
void save(IonOutput out) throws IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Ion mark byte.
|
||||||
|
*
|
||||||
|
* @return Ion mark byte.
|
||||||
|
*/
|
||||||
|
public short getIonMark();
|
||||||
|
}
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ion data bundle - simplified Map
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class IonBundle implements IonBinary {
|
||||||
|
|
||||||
|
private final Map<String, Object> backingMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
public void putBundled(String key, IonBundled saved) throws IOException
|
||||||
|
{
|
||||||
|
final IonBundle ib = new IonBundle();
|
||||||
|
saved.save(ib);
|
||||||
|
put(key, ib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <T extends IonBundled> T getBundled(String key, Class<T> objClass) throws IOException
|
||||||
|
{
|
||||||
|
return Ion.unwrap(get(key, (IonBundle) null), objClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void loadBundled(String key, IonBundled loaded) throws IOException
|
||||||
|
{
|
||||||
|
IonBundle ib = get(key, null);
|
||||||
|
|
||||||
|
if (ib == null) ib = new IonBundle();
|
||||||
|
|
||||||
|
loaded.load(ib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <K, V> Map<K, V> getMap(String key)
|
||||||
|
{
|
||||||
|
final Map<K, V> m = new HashMap<>();
|
||||||
|
loadMap(key, m);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <K, V> void loadMap(String key, Map<K, V> map)
|
||||||
|
{
|
||||||
|
final IonMapWrapper imw = get(key, null);
|
||||||
|
if (imw == null) return;
|
||||||
|
map.clear();
|
||||||
|
imw.fill(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <E> Collection<E> getSequence(String key)
|
||||||
|
{
|
||||||
|
final Collection<E> s = new ArrayList<>();
|
||||||
|
loadSequence(key, s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <E> void loadSequence(String key, Collection<E> sequence)
|
||||||
|
{
|
||||||
|
final IonSequenceWrapper isw = get(key, null);
|
||||||
|
if (isw == null) return;
|
||||||
|
sequence.clear();
|
||||||
|
isw.fill(sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Get an object.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* If not found or of type incompatible with fallback, fallback is returned.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param fallback value
|
||||||
|
* @return value
|
||||||
|
*/
|
||||||
|
public <T> T get(String key, T fallback)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
final T itm = (T) backingMap.get(key);
|
||||||
|
if (itm == null) return fallback;
|
||||||
|
return itm;
|
||||||
|
} catch (final ClassCastException e) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, IonBinary value)
|
||||||
|
{
|
||||||
|
if (key == null || value == null) return;
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, boolean value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, char value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, short value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, int value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, long value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, double value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, float value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, String value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, boolean[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, char[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, short[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, int[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, long[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, double[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, float[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void put(String key, String[] value)
|
||||||
|
{
|
||||||
|
backingMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public void putSequence(String key, Collection c)
|
||||||
|
{
|
||||||
|
backingMap.put(key, new IonSequenceWrapper(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public void putMap(String key, Map m)
|
||||||
|
{
|
||||||
|
backingMap.put(key, new IonMapWrapper(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getIonMark()
|
||||||
|
{
|
||||||
|
return Ion.DATA_BUNDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonInput in) throws IOException
|
||||||
|
{
|
||||||
|
in.readMap(backingMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonOutput out) throws IOException
|
||||||
|
{
|
||||||
|
out.writeMap(backingMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return backingMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isEmpty()
|
||||||
|
{
|
||||||
|
return backingMap.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
backingMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object remove(Object key)
|
||||||
|
{
|
||||||
|
return backingMap.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return backingMap.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o)
|
||||||
|
{
|
||||||
|
return backingMap.equals(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return 47 ^ backingMap.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bundled ion object
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public interface IonBundled {
|
||||||
|
|
||||||
|
void load(IonBundle bundle) throws IOException;
|
||||||
|
|
||||||
|
|
||||||
|
void save(IonBundle bundle) throws IOException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,439 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import mightypork.util.error.CorruptedDataException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ion input stream
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class IonInput {
|
||||||
|
|
||||||
|
private final DataInput in;
|
||||||
|
|
||||||
|
|
||||||
|
public IonInput(InputStream in)
|
||||||
|
{
|
||||||
|
this.in = new DataInputStream(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read int 0-255. Suitable when the int was written using
|
||||||
|
* <code>writeIntByte()</code> method.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public int readIntByte() throws IOException
|
||||||
|
{
|
||||||
|
return in.readUnsignedByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read an int 0-65535. Suitable when the int was written using
|
||||||
|
* <code>writeIntShort()</code> method.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public int readIntShort() throws IOException
|
||||||
|
{
|
||||||
|
return in.readUnsignedShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean readBoolean() throws IOException
|
||||||
|
{
|
||||||
|
return in.readBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public byte readByte() throws IOException
|
||||||
|
{
|
||||||
|
return in.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public short readShort() throws IOException
|
||||||
|
{
|
||||||
|
return in.readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public char readChar() throws IOException
|
||||||
|
{
|
||||||
|
return in.readChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int readInt() throws IOException
|
||||||
|
{
|
||||||
|
return in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long readLong() throws IOException
|
||||||
|
{
|
||||||
|
return in.readLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public float readFloat() throws IOException
|
||||||
|
{
|
||||||
|
return in.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public double readDouble() throws IOException
|
||||||
|
{
|
||||||
|
return in.readDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String readString() throws IOException
|
||||||
|
{
|
||||||
|
return in.readUTF();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean[] readBooleans() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final boolean[] arr = new boolean[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readBoolean();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public byte[] readBytes() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final byte[] arr = new byte[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readByte();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public char[] readChars() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final char[] arr = new char[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readChar();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public short[] readShorts() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final short[] arr = new short[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readShort();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int[] readInts() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final int[] arr = new int[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readInt();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long[] readLongs() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final long[] arr = new long[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readLong();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public float[] readFloats() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final float[] arr = new float[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readFloat();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public double[] readDoubles() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final double[] arr = new double[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readDouble();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String[] readStrings() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final String[] arr = new String[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = in.readUTF();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object[] readObjects() throws IOException
|
||||||
|
{
|
||||||
|
final int length = readLength();
|
||||||
|
final Object[] arr = new Object[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
arr[i] = readObject();
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IonBundle readBundle() throws IOException
|
||||||
|
{
|
||||||
|
return (IonBundle) readObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int readMark() throws IOException
|
||||||
|
{
|
||||||
|
return readIntByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int readLength() throws IOException
|
||||||
|
{
|
||||||
|
return readIntShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Read object based on mark; if null mark is found, returns default value.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* If, however, an object of invalid or different type is found, an
|
||||||
|
* exception will be thrown.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param def default value.
|
||||||
|
* @return the loaded object
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T readObject(T def) throws IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
final Object o = readObject();
|
||||||
|
return (T) (o == null ? def : o);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new IOException("Could not load object.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read single object, preceded by a mark.
|
||||||
|
*
|
||||||
|
* @return the loaded object
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public Object readObject() throws IOException
|
||||||
|
{
|
||||||
|
final int mark = readMark();
|
||||||
|
if (Ion.isMarkForBinary(mark)) {
|
||||||
|
IonBinary loaded;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
loaded = Ion.getClassForMark(mark).newInstance();
|
||||||
|
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new RuntimeException("Couldn not load object with mark: " + mark, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded.load(this);
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mark) {
|
||||||
|
case Ion.NULL:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
case Ion.BOOLEAN:
|
||||||
|
return readBoolean();
|
||||||
|
|
||||||
|
case Ion.BYTE:
|
||||||
|
return readByte();
|
||||||
|
|
||||||
|
case Ion.CHAR:
|
||||||
|
return readChar();
|
||||||
|
|
||||||
|
case Ion.SHORT:
|
||||||
|
return readShort();
|
||||||
|
|
||||||
|
case Ion.INT:
|
||||||
|
return readInt();
|
||||||
|
|
||||||
|
case Ion.LONG:
|
||||||
|
return readLong();
|
||||||
|
|
||||||
|
case Ion.FLOAT:
|
||||||
|
return readFloat();
|
||||||
|
|
||||||
|
case Ion.DOUBLE:
|
||||||
|
return readDouble();
|
||||||
|
|
||||||
|
case Ion.STRING:
|
||||||
|
return readString();
|
||||||
|
|
||||||
|
case Ion.BOOLEAN_ARRAY:
|
||||||
|
return readBooleans();
|
||||||
|
|
||||||
|
case Ion.BYTE_ARRAY:
|
||||||
|
return readBytes();
|
||||||
|
|
||||||
|
case Ion.CHAR_ARRAY:
|
||||||
|
return readChars();
|
||||||
|
|
||||||
|
case Ion.SHORT_ARRAY:
|
||||||
|
return readShorts();
|
||||||
|
|
||||||
|
case Ion.INT_ARRAY:
|
||||||
|
return readInts();
|
||||||
|
|
||||||
|
case Ion.LONG_ARRAY:
|
||||||
|
return readLongs();
|
||||||
|
|
||||||
|
case Ion.FLOAT_ARRAY:
|
||||||
|
return readFloats();
|
||||||
|
|
||||||
|
case Ion.DOUBLE_ARRAY:
|
||||||
|
return readDoubles();
|
||||||
|
|
||||||
|
case Ion.STRING_ARRAY:
|
||||||
|
return readStrings();
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new CorruptedDataException("Invalid mark: " + mark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads mark and returns true if the mark is ENTRY, false if the mark is
|
||||||
|
* END. Throws an exception otherwise.
|
||||||
|
*
|
||||||
|
* @return mark was ENTRY
|
||||||
|
* @throws IOException when the mark is neither ENTRY or END.
|
||||||
|
*/
|
||||||
|
public boolean hasNextEntry() throws IOException
|
||||||
|
{
|
||||||
|
final int mark = readMark();
|
||||||
|
if (mark == Ion.ENTRY) return true;
|
||||||
|
if (mark == Ion.END) return false;
|
||||||
|
|
||||||
|
throw new CorruptedDataException("Unexpected mark in sequence: " + mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a sequence of elements into an ArrayList
|
||||||
|
*
|
||||||
|
* @return the collection
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public <T> Collection<T> readSequence() throws IOException
|
||||||
|
{
|
||||||
|
return readSequence(new ArrayList<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load entries into a collection. The collection is cleaned first.
|
||||||
|
*
|
||||||
|
* @param filled collection to populate
|
||||||
|
* @return the collection
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> Collection<T> readSequence(Collection<T> filled) throws IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
filled.clear();
|
||||||
|
while (hasNextEntry()) {
|
||||||
|
filled.add((T) readObject());
|
||||||
|
}
|
||||||
|
return filled;
|
||||||
|
} catch (final ClassCastException e) {
|
||||||
|
throw new CorruptedDataException("Unexpected element type in sequence.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read element pairs into a HashMap
|
||||||
|
*
|
||||||
|
* @return the map
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public <K, V> Map<K, V> readMap() throws IOException
|
||||||
|
{
|
||||||
|
return readMap(new HashMap<K, V>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data into a map. The map is cleaned first.
|
||||||
|
*
|
||||||
|
* @param filled filled map
|
||||||
|
* @return the map
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <K, V> Map<K, V> readMap(Map<K, V> filled) throws IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
filled.clear();
|
||||||
|
while (hasNextEntry()) {
|
||||||
|
final K key = (K) readObject();
|
||||||
|
final V value = (V) readObject();
|
||||||
|
|
||||||
|
filled.put(key, value);
|
||||||
|
}
|
||||||
|
return filled;
|
||||||
|
} catch (final ClassCastException e) {
|
||||||
|
throw new CorruptedDataException("Unexpected element type in map.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
public class IonMapWrapper implements IonBinary {
|
||||||
|
|
||||||
|
private final Map map;
|
||||||
|
|
||||||
|
|
||||||
|
public IonMapWrapper()
|
||||||
|
{
|
||||||
|
map = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IonMapWrapper(Map saved)
|
||||||
|
{
|
||||||
|
map = saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonInput in) throws IOException
|
||||||
|
{
|
||||||
|
map.clear();
|
||||||
|
in.readMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonOutput out) throws IOException
|
||||||
|
{
|
||||||
|
out.writeMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void fill(Map o)
|
||||||
|
{
|
||||||
|
o.clear();
|
||||||
|
o.putAll(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getIonMark()
|
||||||
|
{
|
||||||
|
return Ion.MAP_WRAPPER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,383 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import mightypork.util.logging.Log;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ion output stream
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class IonOutput {
|
||||||
|
|
||||||
|
private final DataOutput out;
|
||||||
|
|
||||||
|
|
||||||
|
public IonOutput(OutputStream out)
|
||||||
|
{
|
||||||
|
this.out = new DataOutputStream(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeBoolean(boolean a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeBoolean(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeByte(int a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeByte(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeShort(int a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeShort(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeChar(int a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeChar(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeInt(int a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeInt(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeIntShort(int a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeShort(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeIntByte(int a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeByte(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeLong(long a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeLong(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeFloat(float a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeFloat(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeDouble(double a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeDouble(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeBytes(String a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeBytes(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeString(String a) throws IOException
|
||||||
|
{
|
||||||
|
out.writeUTF(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeBooleans(boolean[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final boolean a : arr) {
|
||||||
|
out.writeBoolean(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeBytes(byte[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final byte a : arr) {
|
||||||
|
out.writeByte(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeChars(char[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final char a : arr) {
|
||||||
|
out.writeChar(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeShorts(short[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final short a : arr) {
|
||||||
|
out.writeShort(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeInts(int[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final int a : arr) {
|
||||||
|
out.writeInt(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeLongs(long[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final long a : arr) {
|
||||||
|
out.writeLong(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeFloats(float[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final float a : arr) {
|
||||||
|
out.writeFloat(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeDoubles(double[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final double a : arr) {
|
||||||
|
out.writeDouble(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeStrings(String[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final String a : arr) {
|
||||||
|
out.writeUTF(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeBundle(IonBundle bundle) throws IOException
|
||||||
|
{
|
||||||
|
writeObject(bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write array of objects. Supported are Ionizables, primitive types,
|
||||||
|
* String, and their arrays.
|
||||||
|
*
|
||||||
|
* @param arr array to write
|
||||||
|
* @throws IOException on IO error or on invalid object type.
|
||||||
|
*/
|
||||||
|
public void writeObjects(Object[] arr) throws IOException
|
||||||
|
{
|
||||||
|
writeLength(arr.length);
|
||||||
|
for (final Object a : arr) {
|
||||||
|
writeObject(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <T> void writeSequence(Collection<T> sequence) throws IOException
|
||||||
|
{
|
||||||
|
for (final T element : sequence) {
|
||||||
|
writeMark(Ion.ENTRY);
|
||||||
|
writeObject(element);
|
||||||
|
}
|
||||||
|
writeMark(Ion.END);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <K, V> void writeMap(Map<K, V> map) throws IOException
|
||||||
|
{
|
||||||
|
for (final Entry<K, V> e : map.entrySet()) {
|
||||||
|
if (e.getValue() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeMark(Ion.ENTRY);
|
||||||
|
writeObject(e.getKey());
|
||||||
|
writeObject(e.getValue());
|
||||||
|
}
|
||||||
|
writeMark(Ion.END);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void writeMark(int mark) throws IOException
|
||||||
|
{
|
||||||
|
writeIntByte(mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void writeLength(int length) throws IOException
|
||||||
|
{
|
||||||
|
writeIntShort(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write an object. Supported are Ionizable, primitive types, String, and
|
||||||
|
* their arrays.
|
||||||
|
*
|
||||||
|
* @param obj obj to write
|
||||||
|
* @throws IOException on IO error or invalid object type.
|
||||||
|
*/
|
||||||
|
public void writeObject(Object obj) throws IOException
|
||||||
|
{
|
||||||
|
if (obj == null) {
|
||||||
|
writeMark(Ion.NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof IonBinary) {
|
||||||
|
|
||||||
|
final IonBinary ionObject = (IonBinary) obj;
|
||||||
|
|
||||||
|
Ion.assertRegistered(ionObject);
|
||||||
|
|
||||||
|
writeMark(ionObject.getIonMark());
|
||||||
|
ionObject.save(this);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof IonBundled) {
|
||||||
|
throw new IOException("Bundled objects cannot be written to ION stream directly.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Boolean) {
|
||||||
|
writeMark(Ion.BOOLEAN);
|
||||||
|
writeBoolean((Boolean) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Byte) {
|
||||||
|
writeMark(Ion.BYTE);
|
||||||
|
writeByte((Byte) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Character) {
|
||||||
|
writeMark(Ion.CHAR);
|
||||||
|
writeChar((Character) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Short) {
|
||||||
|
writeMark(Ion.SHORT);
|
||||||
|
writeShort((Short) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Integer) {
|
||||||
|
writeMark(Ion.INT);
|
||||||
|
writeInt((Integer) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Long) {
|
||||||
|
writeMark(Ion.LONG);
|
||||||
|
writeLong((Long) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Float) {
|
||||||
|
writeMark(Ion.FLOAT);
|
||||||
|
writeFloat((Float) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Double) {
|
||||||
|
writeMark(Ion.DOUBLE);
|
||||||
|
writeDouble((Double) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof String) {
|
||||||
|
writeMark(Ion.STRING);
|
||||||
|
writeString((String) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof boolean[]) {
|
||||||
|
writeMark(Ion.BOOLEAN_ARRAY);
|
||||||
|
writeBooleans((boolean[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof byte[]) {
|
||||||
|
writeMark(Ion.BYTE_ARRAY);
|
||||||
|
writeBytes((byte[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof char[]) {
|
||||||
|
writeMark(Ion.CHAR_ARRAY);
|
||||||
|
writeChars((char[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof short[]) {
|
||||||
|
writeMark(Ion.SHORT_ARRAY);
|
||||||
|
writeShorts((short[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof int[]) {
|
||||||
|
writeMark(Ion.INT_ARRAY);
|
||||||
|
writeInts((int[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof long[]) {
|
||||||
|
writeMark(Ion.LONG_ARRAY);
|
||||||
|
writeLongs((long[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof float[]) {
|
||||||
|
writeMark(Ion.FLOAT_ARRAY);
|
||||||
|
writeFloats((float[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof double[]) {
|
||||||
|
writeMark(Ion.DOUBLE_ARRAY);
|
||||||
|
writeDoubles((double[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof String[]) {
|
||||||
|
writeMark(Ion.STRING_ARRAY);
|
||||||
|
writeStrings((String[]) obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException("Object " + Log.str(obj) + " could not be be written to stream.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package mightypork.util.ion;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
public class IonSequenceWrapper implements IonBinary {
|
||||||
|
|
||||||
|
private Collection collection = new ArrayList();
|
||||||
|
|
||||||
|
|
||||||
|
public IonSequenceWrapper()
|
||||||
|
{
|
||||||
|
collection = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IonSequenceWrapper(Collection saved)
|
||||||
|
{
|
||||||
|
collection = saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonInput in) throws IOException
|
||||||
|
{
|
||||||
|
collection.clear();
|
||||||
|
in.readSequence(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonOutput out) throws IOException
|
||||||
|
{
|
||||||
|
out.writeSequence(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void fill(Collection o)
|
||||||
|
{
|
||||||
|
o.clear();
|
||||||
|
o.addAll(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getIonMark()
|
||||||
|
{
|
||||||
|
return Ion.SEQUENCE_WRAPPER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user