entity & world rewrite. rendering broken atm.
This commit is contained in:
@@ -22,6 +22,7 @@ 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.WorldProvider;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.item.Item;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
@@ -73,6 +74,9 @@ public final class App extends BaseApp {
|
||||
@Override
|
||||
protected void initScreens(ScreenRegistry screens)
|
||||
{
|
||||
// world provider instance is referenced by screens
|
||||
WorldProvider.init(this);
|
||||
|
||||
screens.addScreen(new ScreenTestBouncy(this));
|
||||
screens.addScreen(new ScreenTestCat(this));
|
||||
screens.addScreen(new ScreenTestRender(this));
|
||||
@@ -108,7 +112,13 @@ public final class App extends BaseApp {
|
||||
{
|
||||
Ion.registerBinary(Item.ION_MARK, Item.class);
|
||||
Ion.registerBinary(Level.ION_MARK, Level.class);
|
||||
Ion.registerBinary(Entity.ION_MARK, Entity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postInit()
|
||||
{
|
||||
// TODO tmp
|
||||
WorldProvider.get().createWorld(37);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public final class Res {
|
||||
// sprites
|
||||
texture = textures.loadTexture("mob", "/res/img/dudes-b.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
tiles = texture.grid(8, 8);
|
||||
textures.addSheet("player", tiles.makeSheet(0, 0, 4, 1));
|
||||
textures.addSheet("sprite.player", tiles.makeSheet(0, 0, 4, 1));
|
||||
|
||||
// small sheet
|
||||
texture = textures.loadTexture("tiles16", "/res/img/tiles16.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
|
||||
@@ -19,7 +19,7 @@ import mightypork.util.math.constraints.rect.Rect;
|
||||
|
||||
public class HudLayer extends ScreenLayer {
|
||||
|
||||
public HudLayer(Screen screen, World world)
|
||||
public HudLayer(Screen screen)
|
||||
{
|
||||
super(screen);
|
||||
|
||||
@@ -52,7 +52,7 @@ public class HudLayer extends ScreenLayer {
|
||||
root.add(experience);
|
||||
|
||||
|
||||
final Minimap mm = new Minimap(world);
|
||||
final Minimap mm = new Minimap();
|
||||
mm.setRect(root.shrink(root.width().perc(5), root.height().perc(15)));
|
||||
root.add(mm);
|
||||
|
||||
|
||||
@@ -10,57 +10,19 @@ import mightypork.gamecore.gui.screens.LayeredScreen;
|
||||
import mightypork.rogue.Paths;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldCreator;
|
||||
import mightypork.rogue.world.WorldProvider;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
|
||||
|
||||
public class ScreenGame extends LayeredScreen {
|
||||
|
||||
private final World world;
|
||||
|
||||
|
||||
public ScreenGame(AppAccess app)
|
||||
{
|
||||
super(app);
|
||||
|
||||
this.world = obtainWorld();
|
||||
|
||||
addLayer(new HudLayer(this, world));
|
||||
addLayer(new WorldLayer(this, world));
|
||||
}
|
||||
|
||||
|
||||
private World obtainWorld()
|
||||
{
|
||||
|
||||
// FIXME just temporary test here
|
||||
|
||||
final Random rand = new Random();
|
||||
final File f = new File(Paths.WORKDIR, "test-world.ion");
|
||||
|
||||
// SAVE
|
||||
|
||||
final World world = WorldCreator.createWorld(rand.nextLong());
|
||||
addChildClient(world);
|
||||
|
||||
try {
|
||||
Ion.toFile(f, world);
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// LOAD
|
||||
|
||||
// final World w;
|
||||
//
|
||||
// try {
|
||||
// world = Ion.fromFile(f, World.class);
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// System.exit(1);
|
||||
// return;
|
||||
// }
|
||||
|
||||
return world;
|
||||
addLayer(new HudLayer(this));
|
||||
addLayer(new WorldLayer(this));
|
||||
}
|
||||
|
||||
|
||||
@@ -70,4 +32,18 @@ public class ScreenGame extends LayeredScreen {
|
||||
return "game_screen";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onScreenEnter()
|
||||
{
|
||||
super.onScreenEnter();
|
||||
WorldProvider.get().setListening(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScreenLeave()
|
||||
{
|
||||
super.onScreenLeave();
|
||||
WorldProvider.get().setListening(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@ public class WorldLayer extends ScreenLayer {
|
||||
private final MapView worldView;
|
||||
|
||||
|
||||
public WorldLayer(Screen screen, World world)
|
||||
public WorldLayer(Screen screen)
|
||||
{
|
||||
super(screen);
|
||||
|
||||
// render component
|
||||
|
||||
worldView = new MapView(world);
|
||||
worldView = new MapView();
|
||||
|
||||
// map input plugins
|
||||
worldView.addPlugin(new MIPKeyWalk());
|
||||
|
||||
@@ -13,9 +13,10 @@ import mightypork.gamecore.input.Keys;
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.PlayerControl;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldProvider;
|
||||
import mightypork.rogue.world.WorldRenderer;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.entity.modules.EntityMoveListener;
|
||||
import mightypork.util.math.Easing;
|
||||
import mightypork.util.math.constraints.num.Num;
|
||||
import mightypork.util.math.constraints.num.mutable.NumAnimated;
|
||||
@@ -26,20 +27,19 @@ import mightypork.util.timing.Updateable;
|
||||
public class MapView extends InputComponent implements KeyListener, MouseButtonListener, EntityMoveListener, Updateable {
|
||||
|
||||
protected final WorldRenderer worldRenderer;
|
||||
protected final World world;
|
||||
private final PlayerControl pc;
|
||||
|
||||
private final Set<MapInteractionPlugin> plugins = new HashSet<>();
|
||||
private Num tileSize;
|
||||
private final NumAnimated zoom = new NumAnimated(0, Easing.SINE_BOTH);
|
||||
|
||||
private final Num tileSize;
|
||||
|
||||
public MapView(World world)
|
||||
|
||||
public MapView()
|
||||
{
|
||||
this.world = world;
|
||||
this.tileSize = height().min(width()).div(8).max(32).mul(Num.make(1).sub(zoom.mul(0.66)));
|
||||
this.worldRenderer = new WorldRenderer(world, this, tileSize);
|
||||
pc = world.getPlayerControl();
|
||||
this.worldRenderer = new WorldRenderer(this, tileSize);
|
||||
pc = WorldProvider.get().getPlayerControl();
|
||||
pc.addMoveListener(this);
|
||||
}
|
||||
|
||||
@@ -51,13 +51,6 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateLayout()
|
||||
{
|
||||
worldRenderer.poll(); // update sizing
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get tile coord at a screen position
|
||||
*
|
||||
|
||||
@@ -7,8 +7,9 @@ import mightypork.gamecore.gui.components.InputComponent;
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldProvider;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityPos;
|
||||
import mightypork.rogue.world.entity.modules.EntityPos;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.math.color.Color;
|
||||
@@ -23,29 +24,24 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class Minimap extends InputComponent implements MouseButtonListener {
|
||||
|
||||
private final World world;
|
||||
private final RectMutable bounds = Rect.makeVar();
|
||||
private int unit = 0;
|
||||
private final Num translucency = Num.make(0.8);
|
||||
private final Color playerColor = RGB.RED;
|
||||
|
||||
|
||||
public Minimap(World w) {
|
||||
this.world = w;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderComponent()
|
||||
{
|
||||
Color.pushAlpha(translucency);
|
||||
|
||||
final Level lvl = world.getCurrentLevel();
|
||||
final Level lvl = WorldProvider.get().getCurrentLevel();
|
||||
unit = (int) Math.min(Math.max(2, Math.ceil((height().value()/2) / (lvl.getHeight() + 2))), 6);
|
||||
|
||||
final World w = lvl.getWorld();
|
||||
final Entity e = w.getPlayerEntity();
|
||||
final EntityPos plCoord = e.getPosition();
|
||||
final Vect plCoord = e.pos.getVisualPos();
|
||||
|
||||
final int lw = lvl.getWidth();
|
||||
final int lh = lvl.getHeight();
|
||||
@@ -80,8 +76,8 @@ public class Minimap extends InputComponent implements MouseButtonListener {
|
||||
// player
|
||||
Render.setColor(playerColor);
|
||||
|
||||
final double plx = tl.xi() + plCoord.visualX() * unit;
|
||||
final double ply = tl.yi() + plCoord.visualY() * unit;
|
||||
final double plx = tl.xi() + plCoord.x() * unit;
|
||||
final double ply = tl.yi() + plCoord.y() * unit;
|
||||
|
||||
GL11.glVertex2d(plx, ply);
|
||||
GL11.glVertex2d(plx + unit, ply);
|
||||
@@ -101,10 +97,10 @@ public class Minimap extends InputComponent implements MouseButtonListener {
|
||||
if (event.isUp()) {
|
||||
final Vect relative = event.getPos().sub(bounds.origin());
|
||||
final Coord actual = Coord.make(relative.xi() / unit, relative.yi() / unit);
|
||||
final Entity player = world.getPlayerEntity();
|
||||
final Entity player = WorldProvider.get().getPlayerEntity();
|
||||
|
||||
if (player.getLevel().getTile(actual).isExplored()) {
|
||||
player.navigateTo(actual);
|
||||
player.pos.navigateTo(actual);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,90 +1,102 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityPos;
|
||||
import mightypork.rogue.world.entity.PathStep;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.entity.modules.EntityMoveListener;
|
||||
import mightypork.rogue.world.entity.modules.EntityPos;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
|
||||
|
||||
public class PlayerControl {
|
||||
public abstract class PlayerControl {
|
||||
|
||||
private final World world;
|
||||
protected Set<EntityMoveListener> playerMoveListeners = new HashSet<>();
|
||||
|
||||
private World lastWorld;
|
||||
|
||||
|
||||
public PlayerControl(World w)
|
||||
protected abstract World getWorld();
|
||||
|
||||
|
||||
private World getWorld2()
|
||||
{
|
||||
World newWorld = getWorld();
|
||||
|
||||
if (newWorld != lastWorld) {
|
||||
for (EntityMoveListener eml : playerMoveListeners) {
|
||||
newWorld.getPlayerEntity().pos.addMoveListener(eml);
|
||||
}
|
||||
}
|
||||
|
||||
lastWorld = newWorld;
|
||||
|
||||
return newWorld;
|
||||
|
||||
};
|
||||
|
||||
|
||||
private Entity getPlayerEntity()
|
||||
{
|
||||
this.world = w;
|
||||
}
|
||||
|
||||
|
||||
public Entity getEntity()
|
||||
{
|
||||
return world.getPlayerEntity();
|
||||
if(getWorld2() == null) return null;
|
||||
|
||||
return getWorld2().getPlayerEntity();
|
||||
}
|
||||
|
||||
|
||||
public void goNorth()
|
||||
{
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.NORTH);
|
||||
getPlayerEntity().pos.cancelPath();
|
||||
getPlayerEntity().pos.addStep(PathStep.NORTH);
|
||||
}
|
||||
|
||||
|
||||
public void goSouth()
|
||||
{
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.SOUTH);
|
||||
getPlayerEntity().pos.cancelPath();
|
||||
getPlayerEntity().pos.addStep(PathStep.SOUTH);
|
||||
}
|
||||
|
||||
|
||||
public void goEast()
|
||||
{
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.EAST);
|
||||
getPlayerEntity().pos.cancelPath();
|
||||
getPlayerEntity().pos.addStep(PathStep.EAST);
|
||||
}
|
||||
|
||||
|
||||
public void goWest()
|
||||
{
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.WEST);
|
||||
getPlayerEntity().pos.cancelPath();
|
||||
getPlayerEntity().pos.addStep(PathStep.WEST);
|
||||
}
|
||||
|
||||
|
||||
public void navigateTo(Coord pos)
|
||||
{
|
||||
getEntity().navigateTo(pos);
|
||||
getPlayerEntity().pos.navigateTo(pos);
|
||||
}
|
||||
|
||||
|
||||
public void addMoveListener(EntityMoveListener eml)
|
||||
{
|
||||
getEntity().addMoveListener(eml);
|
||||
}
|
||||
|
||||
|
||||
public EntityPos getPos()
|
||||
{
|
||||
return getEntity().getPosition();
|
||||
}
|
||||
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
playerMoveListeners.add(eml);
|
||||
if(getPlayerEntity() != null) {
|
||||
getPlayerEntity().pos.addMoveListener(eml);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Level getLevel()
|
||||
{
|
||||
return world.getCurrentLevel();
|
||||
return getWorld2().getCurrentLevel();
|
||||
}
|
||||
|
||||
|
||||
public Coord getCoord()
|
||||
{
|
||||
return getEntity().getCoord();
|
||||
return getPlayerEntity().pos.getCoord();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ public class World implements IonBundled, Updateable {
|
||||
private final PlayerInfo playerInfo = new PlayerInfo();
|
||||
private Entity playerEntity;
|
||||
|
||||
private final PlayerControl control = new PlayerControl(this);
|
||||
|
||||
/** World seed */
|
||||
private long seed;
|
||||
|
||||
@@ -48,6 +46,7 @@ public class World implements IonBundled, Updateable {
|
||||
in.loadBundled("player", playerInfo);
|
||||
|
||||
playerEntity = levels.get(playerInfo.getLevel()).getEntity(playerInfo.getEID());
|
||||
if(playerEntity == null) throw new RuntimeException("Player entity not found in the world.");
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +103,7 @@ public class World implements IonBundled, Updateable {
|
||||
final int playerEid = getNewEID();
|
||||
|
||||
playerEntity = Entities.PLAYER.createEntity(playerEid);
|
||||
playerEntity.setPosition(levels.get(level).getEnterPoint());
|
||||
playerEntity.pos.setPosition(levels.get(level).getEnterPoint());
|
||||
levels.get(level).addEntity(playerEntity);
|
||||
|
||||
playerInfo.setLevel(level);
|
||||
@@ -118,12 +117,6 @@ public class World implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
public PlayerControl getPlayerControl()
|
||||
{
|
||||
return control;
|
||||
}
|
||||
|
||||
|
||||
public Entity getPlayerEntity()
|
||||
{
|
||||
return playerEntity;
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.modules.EntityMoveListener;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.util.control.eventbus.BusAccess;
|
||||
import mightypork.util.control.eventbus.clients.BusNode;
|
||||
import mightypork.util.control.eventbus.clients.RootBusNode;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.timing.Updateable;
|
||||
|
||||
|
||||
public class WorldProvider extends RootBusNode implements Updateable {
|
||||
|
||||
public static synchronized void init(BusAccess busAccess)
|
||||
{
|
||||
if (inst == null) {
|
||||
inst = new WorldProvider(busAccess);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public WorldProvider(BusAccess busAccess) {
|
||||
super(busAccess);
|
||||
setListening(false);
|
||||
}
|
||||
|
||||
private static WorldProvider inst;
|
||||
|
||||
|
||||
public static WorldProvider get()
|
||||
{
|
||||
if (inst == null) {
|
||||
throw new IllegalStateException("World provider not initialized.");
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
private World world;
|
||||
private final PlayerControl playerControl = new PlayerControl() {
|
||||
|
||||
@Override
|
||||
protected World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public void createWorld(long seed)
|
||||
{
|
||||
if (world != null) removeChildClient(world);
|
||||
world = WorldCreator.createWorld(seed);
|
||||
addChildClient(world);
|
||||
}
|
||||
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
|
||||
public void loadWorld(File file) throws IOException
|
||||
{
|
||||
world = Ion.fromFile(file, World.class);
|
||||
}
|
||||
|
||||
|
||||
public void saveWorld(File file) throws IOException
|
||||
{
|
||||
if (world == null) throw new IllegalStateException("Trying to save a NULL world.");
|
||||
Ion.toFile(file, world);
|
||||
}
|
||||
|
||||
|
||||
public Level getCurrentLevel()
|
||||
{
|
||||
return getWorld().getCurrentLevel();
|
||||
}
|
||||
|
||||
|
||||
public Entity getPlayerEntity()
|
||||
{
|
||||
return getWorld().getPlayerEntity();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return constant player control (world independent)
|
||||
*/
|
||||
public PlayerControl getPlayerControl()
|
||||
{
|
||||
return playerControl;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
world.update(delta);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void deinit()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ package mightypork.rogue.world;
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityPos;
|
||||
import mightypork.rogue.world.entity.modules.EntityPos;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.util.math.color.RGB;
|
||||
@@ -22,15 +22,12 @@ import mightypork.util.math.constraints.vect.VectConst;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class WorldRenderer extends RectProxy implements Pollable {
|
||||
public class WorldRenderer extends RectProxy {
|
||||
|
||||
private static final boolean USE_BATCH_RENDERING = true;
|
||||
|
||||
private final Num tileSize;
|
||||
|
||||
private final World world;
|
||||
private final Entity player;
|
||||
|
||||
// can be changed
|
||||
private RectConst mapRect;
|
||||
private Level activeLevel;
|
||||
@@ -43,12 +40,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
private TileRenderContext trc;
|
||||
|
||||
|
||||
public WorldRenderer(World world, Rect viewport, Num tileSize) {
|
||||
public WorldRenderer(Rect viewport, Num tileSize) {
|
||||
super(viewport);
|
||||
|
||||
this.world = world;
|
||||
this.player = world.getPlayerEntity();
|
||||
|
||||
this.tileSize = tileSize;
|
||||
|
||||
final Num grX = width().perc(30);
|
||||
@@ -58,16 +52,15 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
final Num grY = height().perc(20);
|
||||
topShadow = topEdge().growDown(grY);
|
||||
bottomShadow = bottomEdge().growUp(grY);
|
||||
|
||||
rebuildTiles();
|
||||
}
|
||||
|
||||
|
||||
private void rebuildTiles()
|
||||
private void prepareRenderContextIfNeeded()
|
||||
{
|
||||
final Level level = world.getCurrentLevel();
|
||||
final Level level = WorldProvider.get().getCurrentLevel();
|
||||
|
||||
if (activeLevel == level) return;
|
||||
|
||||
activeLevel = level;
|
||||
|
||||
mapRect = Rect.make(0, 0, level.getWidth(), level.getHeight());
|
||||
@@ -78,24 +71,25 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
|
||||
private VectConst getOffset()
|
||||
{
|
||||
final EntityPos pos = player.getPosition();
|
||||
final double playerX = pos.visualX();
|
||||
final double playerY = pos.visualY();
|
||||
return Vect.make(-playerX-0.5, -playerY-0.5);
|
||||
Entity ent = WorldProvider.get().getPlayerEntity();
|
||||
return Vect.make(ent.pos.getVisualPos().neg().add(0.5, 0.5)).freeze();
|
||||
}
|
||||
|
||||
|
||||
public void render()
|
||||
{
|
||||
prepareRenderContextIfNeeded();
|
||||
|
||||
Render.pushMatrix();
|
||||
Render.setColor(RGB.WHITE);
|
||||
Render.translate(center());
|
||||
Render.scaleXY(tileSize.value());
|
||||
Render.translate(getOffset());
|
||||
|
||||
|
||||
// tiles to render
|
||||
final EntityPos pos = player.getPosition();
|
||||
Entity ent = WorldProvider.get().getPlayerEntity();
|
||||
|
||||
final Coord pos = ent.pos.getCoord();
|
||||
final double w = width().value();
|
||||
final double h = height().value();
|
||||
|
||||
@@ -104,10 +98,10 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
final int xtilesh = (int) (w / (ts * 2)) + 1;
|
||||
final int ytilesh = (int) (h / (ts * 2)) + 1;
|
||||
|
||||
final int x1 = pos.x() - xtilesh;
|
||||
final int y1 = pos.y() - ytilesh;
|
||||
final int x2 = pos.x() + xtilesh;
|
||||
final int y2 = pos.y() + ytilesh;
|
||||
final int x1 = pos.x - xtilesh;
|
||||
final int y1 = pos.y - ytilesh;
|
||||
final int x2 = pos.x + xtilesh;
|
||||
final int y2 = pos.y + ytilesh;
|
||||
|
||||
// === TILES ===
|
||||
|
||||
@@ -139,8 +133,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
for (final Entity e : activeLevel.getEntities()) {
|
||||
|
||||
// avoid entities out of view rect
|
||||
final int x = (int) Math.round(e.getPosition().visualX());
|
||||
final int y = (int) Math.round(e.getPosition().visualY());
|
||||
Vect entPos = e.pos.getVisualPos();
|
||||
final int x = (int) Math.round(entPos.x());
|
||||
final int y = (int) Math.round(entPos.y());
|
||||
|
||||
if (x < x1 - ts || x > x2 + ts) continue;
|
||||
if (y < y1 - ts || y > y2 + ts) continue;
|
||||
@@ -167,11 +162,4 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
return new Coord(v.xi() / ts, v.yi() / ts);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void poll()
|
||||
{
|
||||
rebuildTiles();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import mightypork.rogue.world.entity.models.EntityModel;
|
||||
import mightypork.rogue.world.entity.models.PlayerModel;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import mightypork.rogue.world.entity.entities.PlayerEntity;
|
||||
import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,14 +18,18 @@ public final class Entities {
|
||||
|
||||
private static final EntityModel[] entities = new EntityModel[256];
|
||||
|
||||
public static final EntityModel PLAYER = new PlayerModel(0);
|
||||
public static final EntityModel PLAYER = new EntityModel(1, PlayerEntity.class);
|
||||
|
||||
|
||||
public static void register(int id, EntityModel model)
|
||||
{
|
||||
if (id < 0 || id >= entities.length) { throw new IllegalArgumentException("Entity model ID " + id + " is out of range."); }
|
||||
if (id < 0 || id >= entities.length) {
|
||||
throw new IllegalArgumentException("Entity model ID " + id + " is out of range.");
|
||||
}
|
||||
|
||||
if (entities[id] != null) { throw new IllegalArgumentException("Entity model ID " + id + " already in use."); }
|
||||
if (entities[id] != null) {
|
||||
throw new IllegalArgumentException("Entity model ID " + id + " already in use.");
|
||||
}
|
||||
|
||||
entities[id] = model;
|
||||
}
|
||||
@@ -31,8 +39,49 @@ public final class Entities {
|
||||
{
|
||||
final EntityModel e = entities[id];
|
||||
|
||||
if (e == null) { throw new IllegalArgumentException("No entity model with ID " + id + "."); }
|
||||
if (e == null) {
|
||||
throw new IllegalArgumentException("No entity model with ID " + id + ".");
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
public static void loadEntities(IonInput in, Collection<Entity> entities) throws IOException
|
||||
{
|
||||
entities.clear();
|
||||
while (in.hasNextEntry()) {
|
||||
entities.add(loadEntity(in));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void saveEntities(IonOutput out, Collection<Entity> entities) throws IOException
|
||||
{
|
||||
for (Entity entity : entities) {
|
||||
out.startEntry();
|
||||
saveEntity(out, entity);
|
||||
}
|
||||
|
||||
out.endSequence();
|
||||
}
|
||||
|
||||
|
||||
public static Entity loadEntity(IonInput in) throws IOException
|
||||
{
|
||||
int id = in.readIntByte();
|
||||
|
||||
EntityModel model = get(id);
|
||||
return model.loadEntity(in);
|
||||
}
|
||||
|
||||
|
||||
public static void saveEntity(IonOutput out, Entity entity) throws IOException
|
||||
{
|
||||
EntityModel model = entity.getModel();
|
||||
|
||||
out.writeIntByte(model.id);
|
||||
|
||||
model.saveEntity(out, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,21 @@ package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.Sides;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.entity.models.EntityModel;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.entity.modules.EntityHealthModule;
|
||||
import mightypork.rogue.world.entity.modules.EntityModule;
|
||||
import mightypork.rogue.world.entity.modules.EntityPosModule;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
import mightypork.rogue.world.pathfinding.Heuristic;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
import mightypork.rogue.world.pathfinding.PathFindingContext;
|
||||
import mightypork.util.files.ion.IonBinary;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
import mightypork.util.annotations.DefaultImpl;
|
||||
import mightypork.util.error.IllegalValueException;
|
||||
import mightypork.util.files.ion.*;
|
||||
import mightypork.util.timing.Updateable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,135 +24,51 @@ import mightypork.util.files.ion.IonOutput;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public final class Entity implements IonBinary {
|
||||
|
||||
public static final int ION_MARK = 52;
|
||||
|
||||
/** Last pos, will be freed upon finishing move */
|
||||
private final EntityPos lastPosition = new EntityPos();
|
||||
private boolean walking = false;
|
||||
public abstract class Entity implements IonBundled, Updateable {
|
||||
|
||||
private Level level;
|
||||
private EntityModel model;
|
||||
private final EntityModel model;
|
||||
|
||||
/** Entity ID */
|
||||
private int entityId = -1;
|
||||
private int entityId;
|
||||
|
||||
/** Model ID */
|
||||
private int modelId = -1;
|
||||
private final Map<String, EntityModule> modules = new HashMap<>();
|
||||
|
||||
/** Entity data holder */
|
||||
private final EntityData data = new EntityData();
|
||||
|
||||
/** Temporary renderer's data */
|
||||
public final EntityRenderData renderData = new EntityRenderData();
|
||||
|
||||
private final List<EntityMoveListener> moveListeners = new ArrayList<>();
|
||||
|
||||
private final PathFindingContext pfc = new PathFindingContext() {
|
||||
|
||||
@Override
|
||||
public boolean isAccessible(Coord pos)
|
||||
{
|
||||
return model.canWalkInto(Entity.this, pos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinCost()
|
||||
{
|
||||
return model.getPathMinCost();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Heuristic getHeuristic()
|
||||
{
|
||||
return model.getPathHeuristic();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getCost(Coord from, Coord to)
|
||||
{
|
||||
return model.getPathCost(Entity.this, from, to);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Coord[] getWalkSides() {
|
||||
return Sides.cardinalSides;
|
||||
}
|
||||
};
|
||||
// default modules
|
||||
public final EntityPosModule pos = new EntityPosModule(this);
|
||||
public final EntityHealthModule health = new EntityHealthModule(this);
|
||||
|
||||
|
||||
public Entity(int eid, EntityModel entityModel)
|
||||
{
|
||||
public Entity(EntityModel model, int eid) {
|
||||
|
||||
this.entityId = eid;
|
||||
setModel(entityModel);
|
||||
this.model = model;
|
||||
|
||||
model.initMetadata(data);
|
||||
}
|
||||
|
||||
|
||||
public Entity()
|
||||
{
|
||||
// for ion
|
||||
}
|
||||
|
||||
|
||||
private void setModel(EntityModel entityModel)
|
||||
{
|
||||
// replace listener
|
||||
if (model != null) moveListeners.remove(model);
|
||||
moveListeners.add(entityModel);
|
||||
|
||||
this.modelId = entityModel.id;
|
||||
this.model = entityModel;
|
||||
}
|
||||
|
||||
|
||||
public Level getLevel()
|
||||
{
|
||||
if (level == null) throw new IllegalStateException("Entity has no level assigned.");
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return getLevel().getWorld();
|
||||
// register modules
|
||||
modules.put("pos", pos);
|
||||
modules.put("health", health);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
return ION_MARK;
|
||||
bundle.put("eid", entityId);
|
||||
for (Entry<String, EntityModule> entry : modules.entrySet()) {
|
||||
bundle.putBundled(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
final IonBundle bundle = new IonBundle();
|
||||
bundle.put("model", modelId);
|
||||
bundle.put("id", entityId);
|
||||
bundle.putBundled("data", data);
|
||||
entityId = bundle.get("eid", -1);
|
||||
if (entityId < 0) throw new IllegalValueException("Bad entity id: " + entityId);
|
||||
|
||||
out.writeBundle(bundle);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
final IonBundle bundle = in.readBundle();
|
||||
modelId = bundle.get("model", 0);
|
||||
entityId = bundle.get("id", entityId);
|
||||
bundle.loadBundled("data", data);
|
||||
|
||||
setModel(Entities.get(modelId));
|
||||
for (Entry<String, EntityModule> entry : modules.entrySet()) {
|
||||
bundle.loadBundled(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,138 +81,21 @@ public final class Entity implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public EntityPos getPosition()
|
||||
{
|
||||
return data.position;
|
||||
}
|
||||
|
||||
|
||||
public void setPosition(Coord coord)
|
||||
{
|
||||
data.position.setTo(coord);
|
||||
lastPosition.setTo(coord);
|
||||
cancelPath(); // discard remaining steps
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param delta delta time
|
||||
*/
|
||||
public void update(double delta)
|
||||
{
|
||||
if (!data.position.isFinished()) {
|
||||
data.position.update(delta);
|
||||
}
|
||||
|
||||
if (walking && data.position.isFinished()) {
|
||||
walking = false;
|
||||
level.freeTile(lastPosition.getCoord());
|
||||
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onStepFinished(this);
|
||||
}
|
||||
|
||||
if (data.path.isEmpty()) {
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onPathFinished(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!walking && !data.path.isEmpty()) {
|
||||
|
||||
walking = true;
|
||||
|
||||
final PathStep step = data.path.poll();
|
||||
|
||||
final Coord planned = data.position.getCoord().add(step.toCoord());
|
||||
|
||||
if (!level.canWalkInto(planned)) {
|
||||
cancelPath();
|
||||
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onPathInterrupted(this);
|
||||
}
|
||||
|
||||
walking = false;
|
||||
} else {
|
||||
|
||||
// tmp for renderer
|
||||
if (step.x != 0) renderData.lastXDir = step.x;
|
||||
if (step.y != 0) renderData.lastYDir = step.y;
|
||||
|
||||
lastPosition.setTo(data.position);
|
||||
data.position.walk(step, model.getStepTime(this));
|
||||
level.occupyTile(planned);
|
||||
}
|
||||
}
|
||||
|
||||
if (!walking) {
|
||||
model.update(this, delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void render(MapRenderContext context)
|
||||
{
|
||||
model.renderer.render(this, context);
|
||||
}
|
||||
|
||||
|
||||
public boolean isPathFinished()
|
||||
{
|
||||
return data.position.isFinished() && data.path.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public void addStep(PathStep step)
|
||||
{
|
||||
data.path.add(step);
|
||||
}
|
||||
|
||||
|
||||
public void cancelPath()
|
||||
{
|
||||
data.path.clear();
|
||||
}
|
||||
|
||||
|
||||
public boolean navigateTo(Coord pos)
|
||||
{
|
||||
if(pos.equals(getCoord())) return true;
|
||||
|
||||
final List<PathStep> path = PathFinder.findPathRelative(pfc, getPosition().getCoord(), pos);
|
||||
|
||||
if (path == null) return false;
|
||||
|
||||
this.cancelPath();
|
||||
this.addSteps(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void addMoveListener(EntityMoveListener listener)
|
||||
{
|
||||
moveListeners.add(listener);
|
||||
}
|
||||
|
||||
|
||||
public void addSteps(List<PathStep> path)
|
||||
{
|
||||
data.path.addAll(path);
|
||||
}
|
||||
|
||||
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
this.level = level;
|
||||
model.onEnteredLevel(this);
|
||||
}
|
||||
|
||||
|
||||
public Coord getCoord()
|
||||
public Level getLevel()
|
||||
{
|
||||
return data.position.getCoord();
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return getLevel().getWorld();
|
||||
}
|
||||
|
||||
|
||||
@@ -306,4 +103,25 @@ public final class Entity implements IonBinary {
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
public abstract PathFindingContext getPathfindingContext();
|
||||
|
||||
|
||||
public abstract void render(MapRenderContext context);
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
for (Entry<String, EntityModule> entry : modules.entrySet()) {
|
||||
entry.getValue().update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@DefaultImpl
|
||||
public void onKilled()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonBundled;
|
||||
|
||||
|
||||
public class EntityData implements IonBundled {
|
||||
|
||||
public int health = 1;
|
||||
public int maxHealth = 1;
|
||||
public boolean dead = false;
|
||||
|
||||
public final IonBundle extra = new IonBundle();
|
||||
public final Queue<PathStep> path = new LinkedList<>();
|
||||
public final EntityPos position = new EntityPos();
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.put("health", health);
|
||||
bundle.put("max_health", maxHealth);
|
||||
bundle.put("dead", dead);
|
||||
bundle.putSequence("steps", path);
|
||||
bundle.putBundled("pos", position);
|
||||
|
||||
bundle.put("extra", extra);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
health = bundle.get("health", health);
|
||||
maxHealth = bundle.get("max_health", maxHealth);
|
||||
dead = bundle.get("dead", dead);
|
||||
bundle.loadSequence("path", path);
|
||||
bundle.loadBundled("pos", position);
|
||||
|
||||
bundle.loadBundle("extra", extra);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
|
||||
|
||||
/**
|
||||
* Entity model
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public final class EntityModel {
|
||||
|
||||
/** Model ID */
|
||||
public final int id;
|
||||
public final Class<? extends Entity> tileClass;
|
||||
|
||||
|
||||
public EntityModel(int id, Class<? extends Entity> entity)
|
||||
{
|
||||
Entities.register(id, this);
|
||||
this.id = id;
|
||||
this.tileClass = entity;
|
||||
}
|
||||
|
||||
public Entity createEntity(int eid)
|
||||
{
|
||||
try {
|
||||
return tileClass.getConstructor(EntityModel.class, int.class).newInstance(this, eid);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not instantiate a tile.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Entity loadEntity(IonInput in) throws IOException
|
||||
{
|
||||
IonBundle bundle = in.readBundle();
|
||||
Entity ent = createEntity(-1);
|
||||
ent.load(bundle);
|
||||
return ent;
|
||||
}
|
||||
|
||||
|
||||
public void saveEntity(IonOutput out, Entity entity) throws IOException
|
||||
{
|
||||
IonBundle bundle = new IonBundle();
|
||||
entity.save(bundle);
|
||||
out.writeBundle(bundle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.Sides;
|
||||
import mightypork.rogue.world.pathfinding.Heuristic;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
import mightypork.rogue.world.pathfinding.PathFindingContext;
|
||||
|
||||
|
||||
public abstract class EntityPathfindingContext implements PathFindingContext {
|
||||
|
||||
protected final Entity entity;
|
||||
|
||||
|
||||
public EntityPathfindingContext(Entity entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAccessible(Coord pos)
|
||||
{
|
||||
return entity.getLevel().isWalkable(pos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public abstract int getCost(Coord from, Coord to);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract int getMinCost();
|
||||
|
||||
|
||||
@Override
|
||||
public Heuristic getHeuristic()
|
||||
{
|
||||
return PathFinder.DIAGONAL_HEURISTIC;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Coord[] getWalkSides()
|
||||
{
|
||||
return Sides.cardinalSides;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
/**
|
||||
* Data storage for renderer / entity.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class EntityRenderData {
|
||||
|
||||
public int lastXDir = 1;
|
||||
public int lastYDir = 1;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
|
||||
|
||||
public class SimpleEntityPathFindingContext extends EntityPathfindingContext {
|
||||
|
||||
public SimpleEntityPathFindingContext(Entity entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCost(Coord from, Coord to)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinCost()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package mightypork.rogue.world.entity.entities;
|
||||
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityModel;
|
||||
import mightypork.rogue.world.entity.EntityPathfindingContext;
|
||||
import mightypork.rogue.world.entity.SimpleEntityPathFindingContext;
|
||||
import mightypork.rogue.world.entity.renderers.EntityRenderer;
|
||||
import mightypork.rogue.world.entity.renderers.SimpleLeftRightMobRenderer;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
import mightypork.rogue.world.pathfinding.PathFindingContext;
|
||||
|
||||
|
||||
public class PlayerEntity extends Entity {
|
||||
|
||||
private final EntityPathfindingContext pathfc = new SimpleEntityPathFindingContext(this) {
|
||||
|
||||
@Override
|
||||
public int getCost(Coord from, Coord to)
|
||||
{
|
||||
|
||||
if (!getLevel().getTile(pos.getCoord()).isExplored()) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
return super.getCost(from, to);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
private final EntityRenderer renderer = new SimpleLeftRightMobRenderer(this, "sprite.player");
|
||||
|
||||
|
||||
public PlayerEntity(EntityModel model, int eid) {
|
||||
super(model, eid);
|
||||
|
||||
// init default values
|
||||
pos.setStepTime(0.25);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PathFindingContext getPathfindingContext()
|
||||
{
|
||||
return pathfc;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render(MapRenderContext context)
|
||||
{
|
||||
renderer.render(context);
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.entity.Entities;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityData;
|
||||
import mightypork.rogue.world.entity.renderers.EntityRenderer;
|
||||
import mightypork.rogue.world.pathfinding.Heuristic;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
import mightypork.util.annotations.DefaultImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Entity model
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class EntityModel implements EntityMoveListener {
|
||||
|
||||
/** Model ID */
|
||||
public final int id;
|
||||
public EntityRenderer renderer = EntityRenderer.NONE;
|
||||
|
||||
|
||||
public EntityModel(int id) {
|
||||
Entities.register(id, this);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
public EntityModel setRenderer(EntityRenderer renderer)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return new tile of this type; if 100% invariant, can return cached one.
|
||||
*/
|
||||
public Entity createEntity(int eid)
|
||||
{
|
||||
return new Entity(eid, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Entity is idle, waiting for action.
|
||||
*/
|
||||
public abstract void update(Entity entity, double delta);
|
||||
|
||||
|
||||
/**
|
||||
* Get one path step duration (in seconds)
|
||||
*/
|
||||
public abstract double getStepTime(Entity entity);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onStepFinished(Entity entity);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onPathFinished(Entity entity);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onPathInterrupted(Entity entity);
|
||||
|
||||
|
||||
@DefaultImpl
|
||||
public boolean canWalkInto(Entity entity, Coord pos)
|
||||
{
|
||||
return entity.getLevel().canWalkInto(pos);
|
||||
}
|
||||
|
||||
|
||||
@DefaultImpl
|
||||
public int getPathMinCost()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
@DefaultImpl
|
||||
public Heuristic getPathHeuristic()
|
||||
{
|
||||
return PathFinder.DIAGONAL_HEURISTIC;
|
||||
}
|
||||
|
||||
|
||||
@DefaultImpl
|
||||
public int getPathCost(Entity entity, Coord from, Coord to)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
public abstract void initMetadata(EntityData metadata);
|
||||
|
||||
|
||||
@DefaultImpl
|
||||
public void onEnteredLevel(Entity entity)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityData;
|
||||
import mightypork.rogue.world.entity.renderers.PlayerRenderer;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
|
||||
|
||||
/**
|
||||
* Player info
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class PlayerModel extends EntityModel {
|
||||
|
||||
private static final double STEP_TIME = 0.25;
|
||||
|
||||
|
||||
public PlayerModel(int id) {
|
||||
super(id);
|
||||
setRenderer(new PlayerRenderer("player"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(Entity entity, double delta)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getStepTime(Entity entity)
|
||||
{
|
||||
return STEP_TIME;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepFinished(Entity entity)
|
||||
{
|
||||
exploreSurroundings(entity);
|
||||
}
|
||||
|
||||
|
||||
private void exploreSurroundings(Entity entity)
|
||||
{
|
||||
entity.getLevel().explore(entity.getCoord());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnteredLevel(Entity entity)
|
||||
{
|
||||
exploreSurroundings(entity);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathFinished(Entity entity)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathInterrupted(Entity entity)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initMetadata(EntityData metadata)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canWalkInto(Entity entity, Coord pos)
|
||||
{
|
||||
final Tile t = entity.getLevel().getTile(pos);
|
||||
return t.isWalkable();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPathCost(Entity entity, Coord from, Coord to)
|
||||
{
|
||||
if (!entity.getLevel().getTile(entity.getCoord()).isExplored()) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
return super.getPathCost(entity, from, to);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package mightypork.rogue.world.entity.modules;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.util.error.IllegalValueException;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonBundled;
|
||||
import mightypork.util.math.Calc;
|
||||
|
||||
|
||||
public class EntityHealthModule implements EntityModule {
|
||||
|
||||
public EntityHealthModule(Entity entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
private final Entity entity;
|
||||
|
||||
protected int health = 1;
|
||||
protected int maxHealth = 1;
|
||||
protected boolean dead = false;
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
health = bundle.get("health", health);
|
||||
maxHealth = bundle.get("max_health", maxHealth);
|
||||
dead = bundle.get("dead", dead);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.put("health", health);
|
||||
bundle.put("max_health", maxHealth);
|
||||
bundle.put("dead", dead);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public int getHealth()
|
||||
{
|
||||
return health;
|
||||
}
|
||||
|
||||
|
||||
public void setHealth(int health)
|
||||
{
|
||||
|
||||
this.health = Calc.clamp(health, 0, maxHealth);
|
||||
|
||||
if (health <= 0) {
|
||||
setDead(true);
|
||||
entity.onKilled();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getMaxHealth()
|
||||
{
|
||||
return maxHealth;
|
||||
}
|
||||
|
||||
|
||||
public void setMaxHealth(int maxHealth)
|
||||
{
|
||||
if (maxHealth <= 0) throw new IllegalValueException("Max health out of allowed range: " + maxHealth);
|
||||
this.maxHealth = maxHealth;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDead()
|
||||
{
|
||||
return dead;
|
||||
}
|
||||
|
||||
|
||||
public void setDead(boolean dead)
|
||||
{
|
||||
this.dead = dead;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package mightypork.rogue.world.entity.modules;
|
||||
|
||||
import mightypork.util.files.ion.IonBundled;
|
||||
import mightypork.util.timing.Updateable;
|
||||
|
||||
|
||||
public interface EntityModule extends IonBundled, Updateable {
|
||||
|
||||
|
||||
}
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
package mightypork.rogue.world.entity.modules;
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
|
||||
|
||||
|
||||
|
||||
public interface EntityMoveListener {
|
||||
|
||||
/**
|
||||
+9
-2
@@ -1,13 +1,15 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
package mightypork.rogue.world.entity.modules;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.entity.PathStep;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonBundled;
|
||||
import mightypork.util.math.Easing;
|
||||
import mightypork.util.math.constraints.vect.Vect;
|
||||
import mightypork.util.math.constraints.vect.VectConst;
|
||||
import mightypork.util.math.constraints.vect.mutable.VectAnimated;
|
||||
import mightypork.util.timing.Updateable;
|
||||
|
||||
@@ -175,5 +177,10 @@ public class EntityPos implements IonBundled, Updateable {
|
||||
} else if (!coord.equals(other.coord)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public VectConst getVisualPos()
|
||||
{
|
||||
return Vect.make(walkOffset.x()+coord.x, walkOffset.y()+coord.y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package mightypork.rogue.world.entity.modules;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.PathStep;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
import mightypork.rogue.world.pathfinding.PathFindingContext;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.math.constraints.vect.VectConst;
|
||||
|
||||
|
||||
public class EntityPosModule implements EntityModule {
|
||||
|
||||
private final Entity entity;
|
||||
|
||||
/** Last pos, will be freed upon finishing move */
|
||||
private final Coord lastPos = new Coord(0, 0);
|
||||
private boolean walking = false;
|
||||
|
||||
private final Queue<PathStep> path = new LinkedList<>();
|
||||
private final EntityPos entityPos = new EntityPos();
|
||||
private double stepTime = 0.5;
|
||||
|
||||
// marks for simple renderers
|
||||
public int lastXDir = 1;
|
||||
public int lastYDir = 1;
|
||||
|
||||
private final Set<EntityMoveListener> moveListeners = new LinkedHashSet<>();
|
||||
|
||||
|
||||
public EntityPosModule(Entity entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.putSequence("path", path);
|
||||
bundle.putBundled("pos", entityPos);
|
||||
bundle.put("step_time", stepTime);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.loadSequence("path", path);
|
||||
bundle.loadBundled("pos", entityPos);
|
||||
|
||||
stepTime = bundle.get("step_time", stepTime);
|
||||
}
|
||||
|
||||
|
||||
public void setPosition(Coord coord)
|
||||
{
|
||||
entityPos.setTo(coord);
|
||||
lastPos.setTo(coord);
|
||||
cancelPath(); // discard remaining steps
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param delta delta time
|
||||
*/
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
if (!entityPos.isFinished()) {
|
||||
entityPos.update(delta);
|
||||
}
|
||||
|
||||
if (walking && entityPos.isFinished()) {
|
||||
walking = false;
|
||||
entity.getLevel().freeTile(lastPos);
|
||||
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onStepFinished(entity);
|
||||
}
|
||||
|
||||
if (path.isEmpty()) {
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onPathFinished(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!walking && !path.isEmpty()) {
|
||||
|
||||
walking = true;
|
||||
|
||||
final PathStep step = path.poll();
|
||||
|
||||
final Coord planned = entityPos.getCoord().add(step.toCoord());
|
||||
|
||||
if (!entity.getLevel().isWalkable(planned)) {
|
||||
cancelPath();
|
||||
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onPathInterrupted(entity);
|
||||
}
|
||||
|
||||
walking = false;
|
||||
} else {
|
||||
|
||||
// tmp for renderer
|
||||
if (step.x != 0) this.lastXDir = step.x;
|
||||
if (step.y != 0) this.lastYDir = step.y;
|
||||
|
||||
lastPos.setTo(entityPos.getCoord());
|
||||
entityPos.walk(step, stepTime);
|
||||
entity.getLevel().occupyTile(planned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isPathFinished()
|
||||
{
|
||||
return entityPos.isFinished() && path.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public void addStep(PathStep step)
|
||||
{
|
||||
path.add(step);
|
||||
}
|
||||
|
||||
|
||||
public void cancelPath()
|
||||
{
|
||||
path.clear();
|
||||
}
|
||||
|
||||
|
||||
public boolean navigateTo(Coord target)
|
||||
{
|
||||
if (target.equals(getCoord())) return true;
|
||||
|
||||
PathFindingContext pfc = entity.getPathfindingContext();
|
||||
final List<PathStep> path = PathFinder.findPathRelative(pfc, entityPos.getCoord(), target);
|
||||
|
||||
if (path == null) return false;
|
||||
|
||||
this.cancelPath();
|
||||
this.addSteps(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a move listener. If already present, do nothing.
|
||||
*/
|
||||
public void addMoveListener(EntityMoveListener listener)
|
||||
{
|
||||
moveListeners.add(listener);
|
||||
}
|
||||
|
||||
|
||||
public void addSteps(List<PathStep> path)
|
||||
{
|
||||
path.addAll(path);
|
||||
}
|
||||
|
||||
|
||||
public Coord getCoord()
|
||||
{
|
||||
return entityPos.getCoord();
|
||||
}
|
||||
|
||||
|
||||
public double getStepTime()
|
||||
{
|
||||
return stepTime;
|
||||
}
|
||||
|
||||
|
||||
public void setStepTime(double stepTime)
|
||||
{
|
||||
this.stepTime = stepTime;
|
||||
}
|
||||
|
||||
|
||||
public double getProgress()
|
||||
{
|
||||
return entityPos.getProgress();
|
||||
}
|
||||
|
||||
|
||||
public VectConst getVisualPos()
|
||||
{
|
||||
return entityPos.getVisualPos();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,9 +7,14 @@ import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
|
||||
public abstract class EntityRenderer {
|
||||
|
||||
public static final EntityRenderer NONE = new NullEntityRenderer();
|
||||
protected final Entity entity;
|
||||
|
||||
|
||||
public abstract void render(Entity entity, MapRenderContext context);
|
||||
public EntityRenderer(Entity entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
|
||||
public abstract void render(MapRenderContext context);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
|
||||
|
||||
public class NullEntityRenderer extends EntityRenderer {
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, MapRenderContext context)
|
||||
{
|
||||
// hell no
|
||||
}
|
||||
|
||||
}
|
||||
+10
-14
@@ -6,36 +6,32 @@ import mightypork.gamecore.render.textures.TxQuad;
|
||||
import mightypork.gamecore.render.textures.TxSheet;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityPos;
|
||||
import mightypork.rogue.world.entity.modules.EntityPos;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
import mightypork.util.math.Calc;
|
||||
import mightypork.util.math.constraints.rect.Rect;
|
||||
|
||||
|
||||
public class PlayerRenderer extends EntityRenderer {
|
||||
public class SimpleLeftRightMobRenderer extends EntityRenderer {
|
||||
|
||||
TxSheet sheet;
|
||||
private final TxSheet sheet;
|
||||
|
||||
|
||||
public PlayerRenderer(String sheetKey)
|
||||
{
|
||||
public SimpleLeftRightMobRenderer(Entity entity, String sheetKey) {
|
||||
super(entity);
|
||||
this.sheet = Res.getTxSheet(sheetKey);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, MapRenderContext context)
|
||||
public void render(MapRenderContext context)
|
||||
{
|
||||
TxQuad q = sheet.getQuad(Calc.frag(entity.getPosition().getProgress()));
|
||||
TxQuad q = sheet.getQuad(Calc.frag(entity.pos.getProgress()));
|
||||
|
||||
if (entity.renderData.lastXDir == -1) q = q.flipX();
|
||||
if (entity.pos.lastXDir == -1) q = q.flipX();
|
||||
|
||||
final EntityPos pos = entity.getPosition();
|
||||
|
||||
final Rect tileRect = context.getRectForTile(pos.getCoord());
|
||||
final Rect tileRect = context.getRectForTile(entity.pos.getCoord());
|
||||
final double w = tileRect.width().value();
|
||||
|
||||
Rect spriteRect = tileRect.move(pos.visualXOffset() * w, pos.visualYOffset() * w);
|
||||
Rect spriteRect = tileRect.move(entity.pos.getVisualPos().mul(w));
|
||||
spriteRect = spriteRect.shrink(w * 0.1);
|
||||
|
||||
Render.quadTextured(spriteRect, q);
|
||||
@@ -11,6 +11,7 @@ import java.util.Set;
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.Sides;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.entity.Entities;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.pathfinding.FillContext;
|
||||
import mightypork.rogue.world.pathfinding.FloodFill;
|
||||
@@ -146,31 +147,33 @@ public class Level implements MapAccess, IonBinary {
|
||||
@Override
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
// metadata
|
||||
// -- metadata --
|
||||
final IonBundle ib = in.readBundle();
|
||||
seed = ib.get("seed", 0L);
|
||||
ib.loadBundled("size", size);
|
||||
ib.loadBundled("enter_point", enterPoint);
|
||||
|
||||
ib.loadSequence("entities", entitySet);
|
||||
for (final Entity ent : entitySet) {
|
||||
ent.setLevel(this);
|
||||
entityMap.put(ent.getEntityId(), ent);
|
||||
}
|
||||
|
||||
// init array of size
|
||||
buildArray();
|
||||
// -- binary data --
|
||||
|
||||
// load tiles
|
||||
buildArray();
|
||||
|
||||
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||
for (c.y = 0; c.y < size.y; c.y++) {
|
||||
setTile(c, Tiles.loadTile(in));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mark tiles as occupied
|
||||
for (final Entity e : entitySet) {
|
||||
occupyTile(e.getPosition().getCoord());
|
||||
// load entities
|
||||
Entities.loadEntities(in, entitySet);
|
||||
|
||||
// prepare entities
|
||||
for (final Entity ent : entitySet) {
|
||||
ent.setLevel(this);
|
||||
occupyTile(ent.pos.getCoord());
|
||||
entityMap.put(ent.getEntityId(), ent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,21 +181,23 @@ public class Level implements MapAccess, IonBinary {
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
// metadata
|
||||
// -- metadata --
|
||||
final IonBundle ib = new IonBundle();
|
||||
ib.put("seed", seed);
|
||||
ib.putBundled("size", size);
|
||||
ib.putBundled("enter_point", enterPoint);
|
||||
ib.putSequence("entities", entitySet);
|
||||
out.writeBundle(ib);
|
||||
|
||||
// tiles (writing this way to save space)
|
||||
// -- binary data --
|
||||
|
||||
// tiles
|
||||
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||
for (c.y = 0; c.y < size.y; c.y++) {
|
||||
Tiles.saveTile(out, getTile(c));
|
||||
}
|
||||
}
|
||||
|
||||
Entities.saveEntities(out, entitySet);
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +269,7 @@ public class Level implements MapAccess, IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public boolean canWalkInto(Coord pos)
|
||||
public boolean isWalkable(Coord pos)
|
||||
{
|
||||
final Tile t = getTile(pos);
|
||||
|
||||
@@ -362,8 +367,10 @@ public class Level implements MapAccess, IonBinary {
|
||||
return !t.isNull();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean forceSpreadStart() {
|
||||
public boolean forceSpreadStart()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class TileModel {
|
||||
public Tile createTile()
|
||||
{
|
||||
try {
|
||||
return tileClass.getConstructor(int.class, TileRenderer.class).newInstance(id, renderer);
|
||||
return tileClass.getConstructor(TileModel.class, TileRenderer.class).newInstance(this, renderer);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not instantiate a tile.", e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package mightypork.util.error;
|
||||
|
||||
|
||||
public class IllegalValueException extends RuntimeException {
|
||||
|
||||
public IllegalValueException() {
|
||||
}
|
||||
|
||||
|
||||
public IllegalValueException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public IllegalValueException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
|
||||
public IllegalValueException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
public IllegalValueException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package mightypork.util.error;
|
||||
|
||||
|
||||
public class YouFuckedUpException extends RuntimeException {
|
||||
|
||||
public YouFuckedUpException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public YouFuckedUpException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
public YouFuckedUpException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public YouFuckedUpException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -209,10 +209,10 @@ public class IonOutput {
|
||||
public <T> void writeSequence(Collection<T> sequence) throws IOException
|
||||
{
|
||||
for (final T element : sequence) {
|
||||
writeMark(Ion.ENTRY);
|
||||
startEntry();
|
||||
writeObject(element);
|
||||
}
|
||||
writeMark(Ion.END);
|
||||
endSequence();
|
||||
}
|
||||
|
||||
|
||||
@@ -223,12 +223,24 @@ public class IonOutput {
|
||||
continue;
|
||||
}
|
||||
|
||||
writeMark(Ion.ENTRY);
|
||||
startEntry();
|
||||
writeObject(e.getKey());
|
||||
writeObject(e.getValue());
|
||||
}
|
||||
endSequence();
|
||||
}
|
||||
|
||||
|
||||
public void endSequence() throws IOException
|
||||
{
|
||||
writeMark(Ion.END);
|
||||
}
|
||||
|
||||
|
||||
public void startEntry() throws IOException
|
||||
{
|
||||
writeMark(Ion.ENTRY);
|
||||
}
|
||||
|
||||
|
||||
private void writeMark(int mark) throws IOException
|
||||
|
||||
Reference in New Issue
Block a user