Removed test classes, improved ION error handling & performance.

This commit is contained in:
Ondřej Hruška
2014-04-19 01:45:38 +02:00
parent 7eb390d915
commit 4721351ed9
37 changed files with 1298 additions and 793 deletions
+11 -2
View File
@@ -6,7 +6,6 @@ import java.util.Locale;
import mightypork.gamecore.control.BaseApp;
import mightypork.gamecore.control.GameLoop;
import mightypork.gamecore.control.events.ScreenRequestEvent;
import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.KeyStroke;
@@ -23,8 +22,11 @@ import mightypork.rogue.screens.main_menu.ScreenMainMenu;
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
import mightypork.rogue.screens.test_render.ScreenTestRender;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.tile.Tile;
import mightypork.util.control.eventbus.EventBus;
import mightypork.util.control.eventbus.events.Event;
import mightypork.util.files.ion.Ion;
import mightypork.util.logging.Log;
import mightypork.util.logging.writers.LogWriter;
@@ -34,7 +36,7 @@ import mightypork.util.logging.writers.LogWriter;
*
* @author MightyPork
*/
public class App extends BaseApp {
public final class App extends BaseApp {
/**
* Launcher
@@ -100,6 +102,13 @@ public class App extends BaseApp {
}
@Override
protected void preInit()
{
Ion.registerIonizable(Tile.ION_MARK, Tile.class);
Ion.registerIonizable(Item.ION_MARK, Item.class);
}
@Override
protected File getLockFile()
{
+1 -1
View File
@@ -10,7 +10,7 @@ import mightypork.util.logging.Log;
*
* @author MightyPork
*/
public class Config {
public final class Config {
private static PropertyManager mgr;
+1 -1
View File
@@ -6,7 +6,7 @@ package mightypork.rogue;
*
* @author MightyPork
*/
public class Const {
public final class Const {
// STRINGS
public static final int VERSION = 1;
+1 -1
View File
@@ -17,7 +17,7 @@ import mightypork.util.control.Action;
import mightypork.util.logging.Log;
public class MainLoop extends GameLoop implements ActionRequest.Listener {
public final class MainLoop extends GameLoop implements ActionRequest.Listener {
public MainLoop(BaseApp app) {
super(app);
+1 -1
View File
@@ -6,7 +6,7 @@ import java.io.File;
import mightypork.util.files.OsUtils;
public class Paths {
public final class Paths {
private static final String APPDIR_NAME = "rogue";
+1 -1
View File
@@ -25,7 +25,7 @@ import org.newdawn.slick.opengl.Texture;
*
* @author MightyPork
*/
public class Res {
public final class Res {
private static TextureBank textures;
private static SoundBank sounds;
+1 -1
View File
@@ -6,7 +6,7 @@ package mightypork.rogue.util;
*
* @author MightyPork
*/
public class Utils {
public final class Utils {
public static Thread runAsThread(Runnable r)
{
+121
View File
@@ -0,0 +1,121 @@
package mightypork.rogue.world;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import mightypork.util.constraints.rect.proxy.RectBound;
import mightypork.util.control.timing.Updateable;
import mightypork.util.files.ion.Ion;
import mightypork.util.files.ion.Ionizable;
/**
* Abstract entity
*
* @author MightyPork
* @param <D> Data object class
* @param <M> Model class
* @param <R> Render context class
*/
public abstract class Entity<D, M extends EntityModel<D, R>, R extends RectBound> implements Ionizable, Updateable {
protected M model;
protected D data;
/**
* Used by Ion for loading.
*/
public Entity() {
}
/**
* Create from model
*
* @param model model
*/
public Entity(M model) {
setModel(model);
}
@Override
public final void loadFrom(InputStream in) throws IOException
{
final int id = Ion.readInt(in);
setModel(id);
model.load(data, in); // load saved data
}
private void initData()
{
data = model.createData();
}
/**
* @return entity model
*/
public final M getModel()
{
return model;
}
/**
* Assign a model.
*
* @param id model id
*/
public final void setModel(int id)
{
setModel(getModelForId(id));
}
/**
* Assign a model.
*
* @param model model
*/
public final void setModel(M model)
{
this.model = model;
initData();
}
@Override
public final void saveTo(OutputStream out) throws IOException
{
Ion.writeInt(out, model.getId());
model.save(data, out);
}
public void render(R context)
{
model.render(data, context);
}
@Override
public void update(double delta)
{
model.update(data, delta);
}
/**
* Get model for ID
*
* @param id id
* @return model for the ID
*/
protected abstract M getModelForId(int id);
}
@@ -0,0 +1,92 @@
package mightypork.rogue.world;
import java.io.InputStream;
import java.io.OutputStream;
import mightypork.util.annotations.DefaultImpl;
import mightypork.util.constraints.rect.proxy.RectBound;
/**
* Entity model. Provides concrete implementation to an entity, working with
* it's data object.
*
* @author MightyPork
* @param <D> Data object class
* @param <R> Render context class
*/
public abstract class EntityModel<D, R extends RectBound> {
/** Model id */
private final int id;
/**
* Create a model. The caller must then register this instance in a Model
* registry for the particular entity type.
*
* @param id model id
*/
public EntityModel(int id) {
this.id = id;
}
/**
* Get the model id.
*
* @return id
*/
public final int getId()
{
return id;
}
/**
* Create a data object and populate it with default values.
*
* @return data object
*/
public abstract D createData();
/**
* Load an entity from ION input stream.
*
* @param data data to load
* @param in input stream
*/
public abstract void load(D data, InputStream in);
/**
* Save an entity to ION output stream.
*
* @param data data to save
* @param out output stream
*/
@DefaultImpl
public abstract void save(D data, OutputStream out);
/**
* Render the item according to given context.
*
* @param data rendered item
* @param context rendering context
*/
public abstract void render(D data, R context);
/**
* Update the item (animation, decay etc)
*
* @param item item to update
* @param delta delta time
*/
@DefaultImpl
public abstract void update(D item, double delta);
}
-89
View File
@@ -1,89 +0,0 @@
package mightypork.rogue.world;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import mightypork.util.constraints.rect.proxy.RectBound;
import mightypork.util.control.timing.Updateable;
import mightypork.util.files.ion.BinaryUtils;
import mightypork.util.files.ion.Ionizable;
public class ItemData implements Ionizable, Updateable {
public static final short ION_MARK = 701;
private Model<ItemData, RectBound> model;
// data fields for models to use
public Object data;
public boolean[] flags;
public int[] ints;
/**
* Create from model id
*
* @param id model id
*/
public ItemData(int id) {
this(Items.get(id));
}
/**
* Create from model
*
* @param model model
*/
public ItemData(Model<ItemData, RectBound> model) {
this.model = model;
model.create(this);
}
/**
* Create without model. Model will be read from ION input stream.
*/
public ItemData() {
}
@Override
public void loadFrom(InputStream in) throws IOException
{
final int id = BinaryUtils.readInt(in);
model = Items.get(id);
model.load(this, in);
}
@Override
public void saveTo(OutputStream out) throws IOException
{
BinaryUtils.writeInt(out, model.getId());
model.save(this, out);
}
@Override
public short getIonMark()
{
return ION_MARK;
}
public void render(RectBound context)
{
model.render(this, context);
}
@Override
public void update(double delta)
{
model.update(this, delta);
}
}
-84
View File
@@ -1,84 +0,0 @@
package mightypork.rogue.world;
import java.io.InputStream;
import java.io.OutputStream;
import mightypork.util.annotations.DefaultImpl;
import mightypork.util.constraints.rect.proxy.RectBound;
/**
* An item model
*
* @author MightyPork
*/
public abstract class ItemModel implements Model<ItemData, RectBound> {
public final int id;
public ItemModel(int id) {
this.id = id;
Items.register(id, this);
}
@Override
public final int getId()
{
return id;
}
@Override
@DefaultImpl
public void create(ItemData item)
{
}
/**
* On search performed (reveal hidden door etc)
*
* @param item item in world
*/
@DefaultImpl
public void search(TileData item)
{
}
/**
* Check if an entity can walk this item. If the item is not potentially
* walkable, then this method must always return false.
*
* @param item item in world
*/
public abstract void isWalkable(TileData item);
@Override
@DefaultImpl
public void load(ItemData item, InputStream in)
{
}
@Override
@DefaultImpl
public void save(ItemData item, OutputStream out)
{
}
@Override
public abstract void render(ItemData item, RectBound context);
@Override
@DefaultImpl
public void update(ItemData item, double delta)
{
}
}
-63
View File
@@ -1,63 +0,0 @@
package mightypork.rogue.world;
import java.io.InputStream;
import java.io.OutputStream;
import mightypork.util.constraints.rect.proxy.RectBound;
public interface Model<DATA, RCTX> {
/**
* Get the id.
*
* @return id
*/
int getId();
/**
* Populate an entity with data for this model
*
* @param entity entity in world
*/
void create(DATA entity);
/**
* Load entity data from a binary stream.
*
* @param entity item to load
* @param in input stream
*/
void load(DATA entity, InputStream in);
/**
* Save entity data to a binary stream.
*
* @param entity entity to save
* @param out output stream
*/
void save(DATA entity, OutputStream out);
/**
* Render according to given context.
*
* @param entity data object
* @param context rendering context
*/
void render(DATA entity, RCTX context);
/**
* Update the entity (animation, decay etc)
*
* @param entity data object
* @param delta delta time
*/
void update(DATA entity, double delta);
}
-102
View File
@@ -1,102 +0,0 @@
package mightypork.rogue.world;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Stack;
import mightypork.util.control.timing.Updateable;
import mightypork.util.files.ion.BinaryUtils;
import mightypork.util.files.ion.Ionizable;
/**
* Concrete tile in the world.
*
* @author MightyPork
*/
public class TileData implements Ionizable, Updateable {
public static final short ION_MARK = 700;
/** Items dropped onto this tile */
public final Stack<ItemData> items = new Stack<>();
/** Whether the tile is occupied by an entity */
public boolean occupied;
private TileModel model;
// data fields for models to use
public Object data;
public boolean[] flags;
public int[] ints;
/**
* Create from model id
*
* @param id model id
*/
public TileData(int id) {
this(Tiles.get(id));
}
/**
* Create from model
*
* @param model model
*/
public TileData(TileModel model) {
this.model = model;
model.create(this);
}
/**
* Create without model. Model will be read from ION input stream.
*/
public TileData() {
}
@Override
public void loadFrom(InputStream in) throws IOException
{
final int id = BinaryUtils.readInt(in);
model = Tiles.get(id);
model.load(this, in);
}
@Override
public void saveTo(OutputStream out) throws IOException
{
BinaryUtils.writeInt(out, model.getId());
model.save(this, out);
}
@Override
public short getIonMark()
{
return ION_MARK;
}
public void render(TileRenderContext context)
{
model.render(this, context);
if (!items.isEmpty()) items.peek().render(context);
}
@Override
public void update(double delta)
{
model.update(this, delta);
if (!items.isEmpty()) items.peek().update(delta);
}
}
-106
View File
@@ -1,106 +0,0 @@
package mightypork.rogue.world;
import java.io.InputStream;
import java.io.OutputStream;
import mightypork.util.annotations.DefaultImpl;
public abstract class TileModel {
public final int id;
public TileModel(int id) {
this.id = id;
Tiles.register(id, this);
}
/**
* Get the id.
*
* @return id
*/
public final int getId()
{
return id;
}
/**
* @return can be walked through (if discovered / open)
*/
public abstract boolean isPotentiallyWalkable();
/**
* Populate a tile holder with data for this tile model
*
* @param tile tile in world
*/
@DefaultImpl
public void create(TileData tile)
{
}
/**
* On search performed (reveal hidden door etc)
*
* @param tile tile in world
*/
@DefaultImpl
public void search(TileData tile)
{
}
/**
* Check if an entity can walk this tile. If the tile is not potentially
* walkable, then this method must always return false.
*
* @param tile tile in world
*/
public abstract void isWalkable(TileData tile);
/**
* Load a tile from binary stream.
*
* @param tile tile to load
* @param in input stream
*/
@DefaultImpl
public void load(TileData tile, InputStream in)
{
}
/**
* Save a tile to binary stream.
*
* @param tile tile to save
* @param out output stream
*/
@DefaultImpl
public void save(TileData tile, OutputStream out)
{
}
public abstract void render(TileData tile, TileRenderContext context);
/**
* Update the tile (animation, item spawning etc)
*
* @param tile tile to update
* @param delta delta time
*/
@DefaultImpl
public void update(TileData tile, double delta)
{
}
}
+89
View File
@@ -0,0 +1,89 @@
package mightypork.rogue.world;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileHolder;
import mightypork.util.files.ion.Ion;
import mightypork.util.files.ion.Ionizable;
public class WorldMap implements TileHolder, Ionizable {
private int width, height;
/** Array of tiles [y][x] */
private Tile[][] tiles;
public WorldMap(int width, int height) {
this.width = width;
this.height = height;
buildArray();
}
private void buildArray()
{
this.tiles = new Tile[height][width];
}
@Override
public Tile getTile(int x, int y)
{
return tiles[y][x];
}
public void setTile(Tile tile, int x, int y)
{
tiles[y][x] = tile;
}
@Override
public int getWidth()
{
return width;
}
@Override
public int getHeight()
{
return height;
}
@Override
public void loadFrom(InputStream in) throws IOException
{
width = Ion.readInt(in);
height = Ion.readInt(in);
buildArray();
short mark;
mark = Ion.readMark(in);
if(mark == Ion.START);
}
@Override
public void saveTo(OutputStream out) throws IOException
{
}
@Override
public short getIonMark()
{
return 0;
}
}
+41
View File
@@ -0,0 +1,41 @@
package mightypork.rogue.world.item;
import mightypork.rogue.world.Entity;
import mightypork.util.constraints.rect.proxy.RectBound;
public final class Item extends Entity<ItemData, ItemModel, RectBound> {
public static final short ION_MARK = 701;
public Item() {
super();
}
public Item(ItemModel model) {
super(model);
}
public Item(int id) {
super(Items.get(id));
}
@Override
protected ItemModel getModelForId(int id)
{
return Items.get(id);
}
@Override
public short getIonMark()
{
return ION_MARK;
}
}
@@ -0,0 +1,11 @@
package mightypork.rogue.world.item;
/**
* Item data object. Can be extended for particular models' needs.
*
* @author MightyPork
*/
public abstract class ItemData {
}
@@ -0,0 +1,19 @@
package mightypork.rogue.world.item;
import mightypork.rogue.world.EntityModel;
import mightypork.util.constraints.rect.proxy.RectBound;
/**
* An item model
*
* @author MightyPork
*/
public abstract class ItemModel extends EntityModel<ItemData, RectBound> {
public ItemModel(int id) {
super(id);
Items.register(id, this);
}
}
@@ -1,11 +1,11 @@
package mightypork.rogue.world;
package mightypork.rogue.world.item;
import java.util.HashMap;
import java.util.Map;
public class Items {
public final class Items {
private static final Map<Integer, ItemModel> registered = new HashMap<>();
+98
View File
@@ -0,0 +1,98 @@
package mightypork.rogue.world.tile;
import java.util.Stack;
import mightypork.rogue.world.Entity;
import mightypork.rogue.world.item.Item;
/**
* Concrete tile in the world.
*
* @author MightyPork
*/
public final class Tile extends Entity<TileData, TileModel, TileRenderContext> {
public static final short ION_MARK = 700;
/** Items dropped onto this tile */
public final Stack<Item> items = new Stack<>();
/** Whether the tile is occupied by an entity */
public boolean occupied;
public Tile() {
super();
}
public Tile(TileModel model) {
super(model);
}
public Tile(int id) {
super(Tiles.get(id));
}
@Override
protected TileModel getModelForId(int id)
{
return Tiles.get(id);
}
@Override
public short getIonMark()
{
return ION_MARK;
}
@Override
public void render(TileRenderContext context)
{
super.render(context);
// render laying-on-top item
if (!items.isEmpty()) {
Item item = items.peek();
item.render(context.getRect());
}
}
@Override
public void update(double delta)
{
super.update(delta);
// update laying-on-top item
if (!items.isEmpty()) {
Item item = items.peek();
item.update(delta);
}
}
/**
* Try to reveal secrets of this tile
*/
public void search()
{
model.search(data);
}
/**
* @return true if a mob can walk through
*/
public boolean isWalkable()
{
return model.isWalkable(data);
}
}
@@ -0,0 +1,18 @@
package mightypork.rogue.world.tile;
import java.util.Stack;
import mightypork.rogue.world.item.Item;
/**
* Tile data object. Can be extended for particular models' needs.
*
* @author MightyPork
*/
public abstract class TileData {
/** Items dropped onto this tile */
public final Stack<Item> items = new Stack<>();
}
@@ -1,9 +1,9 @@
package mightypork.rogue.world;
package mightypork.rogue.world.tile;
public interface TileHolder {
TileData getTile(int x, int y);
Tile getTile(int x, int y);
int getWidth();
@@ -0,0 +1,45 @@
package mightypork.rogue.world.tile;
import mightypork.rogue.world.EntityModel;
import mightypork.util.annotations.DefaultImpl;
public abstract class TileModel extends EntityModel<TileData, TileRenderContext> {
public TileModel(int id) {
super(id);
Tiles.register(id, this);
}
/**
* Test if this tile type is potentially walkable. Used during world
* generation.
*
* @return can be walked through (if discovered / open)
*/
public abstract boolean isPotentiallyWalkable();
/**
* Try to reveal a secret.
*
* @param data tile data
*/
@DefaultImpl
public void search(TileData data)
{
// do nothing.
}
/**
* Check if a mob can walk through.
*
* @param data tile data
* @return is walkable
*/
public abstract boolean isWalkable(TileData data);
}
@@ -1,4 +1,4 @@
package mightypork.rogue.world;
package mightypork.rogue.world.tile;
import mightypork.util.constraints.rect.Rect;
@@ -6,7 +6,7 @@ import mightypork.util.constraints.rect.builders.TiledRect;
import mightypork.util.constraints.rect.proxy.RectBound;
public class TileRenderContext implements RectBound {
public final class TileRenderContext implements RectBound {
private final TileHolder map;
private final TiledRect tiler;
@@ -19,13 +19,13 @@ public class TileRenderContext implements RectBound {
}
public TileData getTile()
public Tile getTile()
{
return map.getTile(x, y);
}
public TileData getAdjacentTile(int offsetX, int offsetY)
public Tile getAdjacentTile(int offsetX, int offsetY)
{
return map.getTile(x + offsetX, y + offsetY);
}
@@ -1,11 +1,11 @@
package mightypork.rogue.world;
package mightypork.rogue.world.tile;
import java.util.HashMap;
import java.util.Map;
public class Tiles {
public final class Tiles {
private static final Map<Integer, TileModel> registered = new HashMap<>();