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_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.WorldProvider;
|
||||||
import mightypork.rogue.world.entity.Entity;
|
import mightypork.rogue.world.entity.Entity;
|
||||||
import mightypork.rogue.world.item.Item;
|
import mightypork.rogue.world.item.Item;
|
||||||
import mightypork.rogue.world.level.Level;
|
import mightypork.rogue.world.level.Level;
|
||||||
@@ -73,6 +74,9 @@ public final class App extends BaseApp {
|
|||||||
@Override
|
@Override
|
||||||
protected void initScreens(ScreenRegistry screens)
|
protected void initScreens(ScreenRegistry screens)
|
||||||
{
|
{
|
||||||
|
// world provider instance is referenced by screens
|
||||||
|
WorldProvider.init(this);
|
||||||
|
|
||||||
screens.addScreen(new ScreenTestBouncy(this));
|
screens.addScreen(new ScreenTestBouncy(this));
|
||||||
screens.addScreen(new ScreenTestCat(this));
|
screens.addScreen(new ScreenTestCat(this));
|
||||||
screens.addScreen(new ScreenTestRender(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(Item.ION_MARK, Item.class);
|
||||||
Ion.registerBinary(Level.ION_MARK, Level.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
|
// sprites
|
||||||
texture = textures.loadTexture("mob", "/res/img/dudes-b.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
texture = textures.loadTexture("mob", "/res/img/dudes-b.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||||
tiles = texture.grid(8, 8);
|
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
|
// small sheet
|
||||||
texture = textures.loadTexture("tiles16", "/res/img/tiles16.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
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 class HudLayer extends ScreenLayer {
|
||||||
|
|
||||||
public HudLayer(Screen screen, World world)
|
public HudLayer(Screen screen)
|
||||||
{
|
{
|
||||||
super(screen);
|
super(screen);
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ public class HudLayer extends ScreenLayer {
|
|||||||
root.add(experience);
|
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)));
|
mm.setRect(root.shrink(root.width().perc(5), root.height().perc(15)));
|
||||||
root.add(mm);
|
root.add(mm);
|
||||||
|
|
||||||
|
|||||||
@@ -10,57 +10,19 @@ import mightypork.gamecore.gui.screens.LayeredScreen;
|
|||||||
import mightypork.rogue.Paths;
|
import mightypork.rogue.Paths;
|
||||||
import mightypork.rogue.world.World;
|
import mightypork.rogue.world.World;
|
||||||
import mightypork.rogue.world.WorldCreator;
|
import mightypork.rogue.world.WorldCreator;
|
||||||
|
import mightypork.rogue.world.WorldProvider;
|
||||||
import mightypork.util.files.ion.Ion;
|
import mightypork.util.files.ion.Ion;
|
||||||
|
|
||||||
|
|
||||||
public class ScreenGame extends LayeredScreen {
|
public class ScreenGame extends LayeredScreen {
|
||||||
|
|
||||||
private final World world;
|
|
||||||
|
|
||||||
|
|
||||||
public ScreenGame(AppAccess app)
|
public ScreenGame(AppAccess app)
|
||||||
{
|
{
|
||||||
super(app);
|
super(app);
|
||||||
|
|
||||||
this.world = obtainWorld();
|
addLayer(new HudLayer(this));
|
||||||
|
addLayer(new WorldLayer(this));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,4 +32,18 @@ public class ScreenGame extends LayeredScreen {
|
|||||||
return "game_screen";
|
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;
|
private final MapView worldView;
|
||||||
|
|
||||||
|
|
||||||
public WorldLayer(Screen screen, World world)
|
public WorldLayer(Screen screen)
|
||||||
{
|
{
|
||||||
super(screen);
|
super(screen);
|
||||||
|
|
||||||
// render component
|
// render component
|
||||||
|
|
||||||
worldView = new MapView(world);
|
worldView = new MapView();
|
||||||
|
|
||||||
// map input plugins
|
// map input plugins
|
||||||
worldView.addPlugin(new MIPKeyWalk());
|
worldView.addPlugin(new MIPKeyWalk());
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ import mightypork.gamecore.input.Keys;
|
|||||||
import mightypork.rogue.world.Coord;
|
import mightypork.rogue.world.Coord;
|
||||||
import mightypork.rogue.world.PlayerControl;
|
import mightypork.rogue.world.PlayerControl;
|
||||||
import mightypork.rogue.world.World;
|
import mightypork.rogue.world.World;
|
||||||
|
import mightypork.rogue.world.WorldProvider;
|
||||||
import mightypork.rogue.world.WorldRenderer;
|
import mightypork.rogue.world.WorldRenderer;
|
||||||
import mightypork.rogue.world.entity.Entity;
|
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.Easing;
|
||||||
import mightypork.util.math.constraints.num.Num;
|
import mightypork.util.math.constraints.num.Num;
|
||||||
import mightypork.util.math.constraints.num.mutable.NumAnimated;
|
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 {
|
public class MapView extends InputComponent implements KeyListener, MouseButtonListener, EntityMoveListener, Updateable {
|
||||||
|
|
||||||
protected final WorldRenderer worldRenderer;
|
protected final WorldRenderer worldRenderer;
|
||||||
protected final World world;
|
|
||||||
private final PlayerControl pc;
|
private final PlayerControl pc;
|
||||||
|
|
||||||
private final Set<MapInteractionPlugin> plugins = new HashSet<>();
|
private final Set<MapInteractionPlugin> plugins = new HashSet<>();
|
||||||
private Num tileSize;
|
|
||||||
private final NumAnimated zoom = new NumAnimated(0, Easing.SINE_BOTH);
|
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.tileSize = height().min(width()).div(8).max(32).mul(Num.make(1).sub(zoom.mul(0.66)));
|
||||||
this.worldRenderer = new WorldRenderer(world, this, tileSize);
|
this.worldRenderer = new WorldRenderer(this, tileSize);
|
||||||
pc = world.getPlayerControl();
|
pc = WorldProvider.get().getPlayerControl();
|
||||||
pc.addMoveListener(this);
|
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
|
* Get tile coord at a screen position
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import mightypork.gamecore.gui.components.InputComponent;
|
|||||||
import mightypork.gamecore.render.Render;
|
import mightypork.gamecore.render.Render;
|
||||||
import mightypork.rogue.world.Coord;
|
import mightypork.rogue.world.Coord;
|
||||||
import mightypork.rogue.world.World;
|
import mightypork.rogue.world.World;
|
||||||
|
import mightypork.rogue.world.WorldProvider;
|
||||||
import mightypork.rogue.world.entity.Entity;
|
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.Level;
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.util.math.color.Color;
|
import mightypork.util.math.color.Color;
|
||||||
@@ -23,29 +24,24 @@ import org.lwjgl.opengl.GL11;
|
|||||||
|
|
||||||
public class Minimap extends InputComponent implements MouseButtonListener {
|
public class Minimap extends InputComponent implements MouseButtonListener {
|
||||||
|
|
||||||
private final World world;
|
|
||||||
private final RectMutable bounds = Rect.makeVar();
|
private final RectMutable bounds = Rect.makeVar();
|
||||||
private int unit = 0;
|
private int unit = 0;
|
||||||
private final Num translucency = Num.make(0.8);
|
private final Num translucency = Num.make(0.8);
|
||||||
private final Color playerColor = RGB.RED;
|
private final Color playerColor = RGB.RED;
|
||||||
|
|
||||||
|
|
||||||
public Minimap(World w) {
|
|
||||||
this.world = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderComponent()
|
protected void renderComponent()
|
||||||
{
|
{
|
||||||
Color.pushAlpha(translucency);
|
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);
|
unit = (int) Math.min(Math.max(2, Math.ceil((height().value()/2) / (lvl.getHeight() + 2))), 6);
|
||||||
|
|
||||||
final World w = lvl.getWorld();
|
final World w = lvl.getWorld();
|
||||||
final Entity e = w.getPlayerEntity();
|
final Entity e = w.getPlayerEntity();
|
||||||
final EntityPos plCoord = e.getPosition();
|
final Vect plCoord = e.pos.getVisualPos();
|
||||||
|
|
||||||
final int lw = lvl.getWidth();
|
final int lw = lvl.getWidth();
|
||||||
final int lh = lvl.getHeight();
|
final int lh = lvl.getHeight();
|
||||||
@@ -80,8 +76,8 @@ public class Minimap extends InputComponent implements MouseButtonListener {
|
|||||||
// player
|
// player
|
||||||
Render.setColor(playerColor);
|
Render.setColor(playerColor);
|
||||||
|
|
||||||
final double plx = tl.xi() + plCoord.visualX() * unit;
|
final double plx = tl.xi() + plCoord.x() * unit;
|
||||||
final double ply = tl.yi() + plCoord.visualY() * unit;
|
final double ply = tl.yi() + plCoord.y() * unit;
|
||||||
|
|
||||||
GL11.glVertex2d(plx, ply);
|
GL11.glVertex2d(plx, ply);
|
||||||
GL11.glVertex2d(plx + unit, ply);
|
GL11.glVertex2d(plx + unit, ply);
|
||||||
@@ -101,10 +97,10 @@ public class Minimap extends InputComponent implements MouseButtonListener {
|
|||||||
if (event.isUp()) {
|
if (event.isUp()) {
|
||||||
final Vect relative = event.getPos().sub(bounds.origin());
|
final Vect relative = event.getPos().sub(bounds.origin());
|
||||||
final Coord actual = Coord.make(relative.xi() / unit, relative.yi() / unit);
|
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()) {
|
if (player.getLevel().getTile(actual).isExplored()) {
|
||||||
player.navigateTo(actual);
|
player.pos.navigateTo(actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,90 +1,102 @@
|
|||||||
package mightypork.rogue.world;
|
package mightypork.rogue.world;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import mightypork.rogue.world.entity.Entity;
|
import mightypork.rogue.world.entity.Entity;
|
||||||
import mightypork.rogue.world.entity.EntityPos;
|
|
||||||
import mightypork.rogue.world.entity.PathStep;
|
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;
|
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;
|
if(getWorld2() == null) return null;
|
||||||
}
|
|
||||||
|
return getWorld2().getPlayerEntity();
|
||||||
|
|
||||||
public Entity getEntity()
|
|
||||||
{
|
|
||||||
return world.getPlayerEntity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void goNorth()
|
public void goNorth()
|
||||||
{
|
{
|
||||||
getEntity().cancelPath();
|
getPlayerEntity().pos.cancelPath();
|
||||||
getEntity().addStep(PathStep.NORTH);
|
getPlayerEntity().pos.addStep(PathStep.NORTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void goSouth()
|
public void goSouth()
|
||||||
{
|
{
|
||||||
getEntity().cancelPath();
|
getPlayerEntity().pos.cancelPath();
|
||||||
getEntity().addStep(PathStep.SOUTH);
|
getPlayerEntity().pos.addStep(PathStep.SOUTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void goEast()
|
public void goEast()
|
||||||
{
|
{
|
||||||
getEntity().cancelPath();
|
getPlayerEntity().pos.cancelPath();
|
||||||
getEntity().addStep(PathStep.EAST);
|
getPlayerEntity().pos.addStep(PathStep.EAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void goWest()
|
public void goWest()
|
||||||
{
|
{
|
||||||
getEntity().cancelPath();
|
getPlayerEntity().pos.cancelPath();
|
||||||
getEntity().addStep(PathStep.WEST);
|
getPlayerEntity().pos.addStep(PathStep.WEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void navigateTo(Coord pos)
|
public void navigateTo(Coord pos)
|
||||||
{
|
{
|
||||||
getEntity().navigateTo(pos);
|
getPlayerEntity().pos.navigateTo(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addMoveListener(EntityMoveListener eml)
|
public void addMoveListener(EntityMoveListener eml)
|
||||||
{
|
{
|
||||||
getEntity().addMoveListener(eml);
|
playerMoveListeners.add(eml);
|
||||||
}
|
if(getPlayerEntity() != null) {
|
||||||
|
getPlayerEntity().pos.addMoveListener(eml);
|
||||||
|
}
|
||||||
public EntityPos getPos()
|
|
||||||
{
|
|
||||||
return getEntity().getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public World getWorld()
|
|
||||||
{
|
|
||||||
return world;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Level getLevel()
|
public Level getLevel()
|
||||||
{
|
{
|
||||||
return world.getCurrentLevel();
|
return getWorld2().getCurrentLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Coord getCoord()
|
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 final PlayerInfo playerInfo = new PlayerInfo();
|
||||||
private Entity playerEntity;
|
private Entity playerEntity;
|
||||||
|
|
||||||
private final PlayerControl control = new PlayerControl(this);
|
|
||||||
|
|
||||||
/** World seed */
|
/** World seed */
|
||||||
private long seed;
|
private long seed;
|
||||||
|
|
||||||
@@ -48,6 +46,7 @@ public class World implements IonBundled, Updateable {
|
|||||||
in.loadBundled("player", playerInfo);
|
in.loadBundled("player", playerInfo);
|
||||||
|
|
||||||
playerEntity = levels.get(playerInfo.getLevel()).getEntity(playerInfo.getEID());
|
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();
|
final int playerEid = getNewEID();
|
||||||
|
|
||||||
playerEntity = Entities.PLAYER.createEntity(playerEid);
|
playerEntity = Entities.PLAYER.createEntity(playerEid);
|
||||||
playerEntity.setPosition(levels.get(level).getEnterPoint());
|
playerEntity.pos.setPosition(levels.get(level).getEnterPoint());
|
||||||
levels.get(level).addEntity(playerEntity);
|
levels.get(level).addEntity(playerEntity);
|
||||||
|
|
||||||
playerInfo.setLevel(level);
|
playerInfo.setLevel(level);
|
||||||
@@ -118,12 +117,6 @@ public class World implements IonBundled, Updateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public PlayerControl getPlayerControl()
|
|
||||||
{
|
|
||||||
return control;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Entity getPlayerEntity()
|
public Entity getPlayerEntity()
|
||||||
{
|
{
|
||||||
return playerEntity;
|
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.gamecore.render.Render;
|
||||||
import mightypork.rogue.Res;
|
import mightypork.rogue.Res;
|
||||||
import mightypork.rogue.world.entity.Entity;
|
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.Level;
|
||||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||||
import mightypork.util.math.color.RGB;
|
import mightypork.util.math.color.RGB;
|
||||||
@@ -22,15 +22,12 @@ import mightypork.util.math.constraints.vect.VectConst;
|
|||||||
*
|
*
|
||||||
* @author MightyPork
|
* @author MightyPork
|
||||||
*/
|
*/
|
||||||
public class WorldRenderer extends RectProxy implements Pollable {
|
public class WorldRenderer extends RectProxy {
|
||||||
|
|
||||||
private static final boolean USE_BATCH_RENDERING = true;
|
private static final boolean USE_BATCH_RENDERING = true;
|
||||||
|
|
||||||
private final Num tileSize;
|
private final Num tileSize;
|
||||||
|
|
||||||
private final World world;
|
|
||||||
private final Entity player;
|
|
||||||
|
|
||||||
// can be changed
|
// can be changed
|
||||||
private RectConst mapRect;
|
private RectConst mapRect;
|
||||||
private Level activeLevel;
|
private Level activeLevel;
|
||||||
@@ -43,12 +40,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
|||||||
private TileRenderContext trc;
|
private TileRenderContext trc;
|
||||||
|
|
||||||
|
|
||||||
public WorldRenderer(World world, Rect viewport, Num tileSize) {
|
public WorldRenderer(Rect viewport, Num tileSize) {
|
||||||
super(viewport);
|
super(viewport);
|
||||||
|
|
||||||
this.world = world;
|
|
||||||
this.player = world.getPlayerEntity();
|
|
||||||
|
|
||||||
this.tileSize = tileSize;
|
this.tileSize = tileSize;
|
||||||
|
|
||||||
final Num grX = width().perc(30);
|
final Num grX = width().perc(30);
|
||||||
@@ -58,16 +52,15 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
|||||||
final Num grY = height().perc(20);
|
final Num grY = height().perc(20);
|
||||||
topShadow = topEdge().growDown(grY);
|
topShadow = topEdge().growDown(grY);
|
||||||
bottomShadow = bottomEdge().growUp(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;
|
if (activeLevel == level) return;
|
||||||
|
|
||||||
activeLevel = level;
|
activeLevel = level;
|
||||||
|
|
||||||
mapRect = Rect.make(0, 0, level.getWidth(), level.getHeight());
|
mapRect = Rect.make(0, 0, level.getWidth(), level.getHeight());
|
||||||
@@ -78,24 +71,25 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
|||||||
|
|
||||||
private VectConst getOffset()
|
private VectConst getOffset()
|
||||||
{
|
{
|
||||||
final EntityPos pos = player.getPosition();
|
Entity ent = WorldProvider.get().getPlayerEntity();
|
||||||
final double playerX = pos.visualX();
|
return Vect.make(ent.pos.getVisualPos().neg().add(0.5, 0.5)).freeze();
|
||||||
final double playerY = pos.visualY();
|
|
||||||
return Vect.make(-playerX-0.5, -playerY-0.5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void render()
|
public void render()
|
||||||
{
|
{
|
||||||
|
prepareRenderContextIfNeeded();
|
||||||
|
|
||||||
Render.pushMatrix();
|
Render.pushMatrix();
|
||||||
Render.setColor(RGB.WHITE);
|
Render.setColor(RGB.WHITE);
|
||||||
Render.translate(center());
|
Render.translate(center());
|
||||||
Render.scaleXY(tileSize.value());
|
Render.scaleXY(tileSize.value());
|
||||||
Render.translate(getOffset());
|
Render.translate(getOffset());
|
||||||
|
|
||||||
|
|
||||||
// tiles to render
|
// 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 w = width().value();
|
||||||
final double h = height().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 xtilesh = (int) (w / (ts * 2)) + 1;
|
||||||
final int ytilesh = (int) (h / (ts * 2)) + 1;
|
final int ytilesh = (int) (h / (ts * 2)) + 1;
|
||||||
|
|
||||||
final int x1 = pos.x() - xtilesh;
|
final int x1 = pos.x - xtilesh;
|
||||||
final int y1 = pos.y() - ytilesh;
|
final int y1 = pos.y - ytilesh;
|
||||||
final int x2 = pos.x() + xtilesh;
|
final int x2 = pos.x + xtilesh;
|
||||||
final int y2 = pos.y() + ytilesh;
|
final int y2 = pos.y + ytilesh;
|
||||||
|
|
||||||
// === TILES ===
|
// === TILES ===
|
||||||
|
|
||||||
@@ -139,8 +133,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
|||||||
for (final Entity e : activeLevel.getEntities()) {
|
for (final Entity e : activeLevel.getEntities()) {
|
||||||
|
|
||||||
// avoid entities out of view rect
|
// avoid entities out of view rect
|
||||||
final int x = (int) Math.round(e.getPosition().visualX());
|
Vect entPos = e.pos.getVisualPos();
|
||||||
final int y = (int) Math.round(e.getPosition().visualY());
|
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 (x < x1 - ts || x > x2 + ts) continue;
|
||||||
if (y < y1 - ts || y > y2 + 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);
|
return new Coord(v.xi() / ts, v.yi() / ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void poll()
|
|
||||||
{
|
|
||||||
rebuildTiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package mightypork.rogue.world.entity;
|
package mightypork.rogue.world.entity;
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.entity.models.EntityModel;
|
import java.io.IOException;
|
||||||
import mightypork.rogue.world.entity.models.PlayerModel;
|
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];
|
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)
|
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;
|
entities[id] = model;
|
||||||
}
|
}
|
||||||
@@ -31,8 +39,49 @@ public final class Entities {
|
|||||||
{
|
{
|
||||||
final EntityModel e = entities[id];
|
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;
|
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.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
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.World;
|
||||||
import mightypork.rogue.world.entity.models.EntityModel;
|
import mightypork.rogue.world.entity.modules.EntityHealthModule;
|
||||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
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.Level;
|
||||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
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.rogue.world.pathfinding.PathFindingContext;
|
||||||
import mightypork.util.files.ion.IonBinary;
|
import mightypork.util.annotations.DefaultImpl;
|
||||||
import mightypork.util.files.ion.IonBundle;
|
import mightypork.util.error.IllegalValueException;
|
||||||
import mightypork.util.files.ion.IonInput;
|
import mightypork.util.files.ion.*;
|
||||||
import mightypork.util.files.ion.IonOutput;
|
import mightypork.util.timing.Updateable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,135 +24,51 @@ import mightypork.util.files.ion.IonOutput;
|
|||||||
*
|
*
|
||||||
* @author MightyPork
|
* @author MightyPork
|
||||||
*/
|
*/
|
||||||
public final class Entity implements IonBinary {
|
public abstract class Entity implements IonBundled, Updateable {
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
private Level level;
|
private Level level;
|
||||||
private EntityModel model;
|
private final EntityModel model;
|
||||||
|
|
||||||
/** Entity ID */
|
/** Entity ID */
|
||||||
private int entityId = -1;
|
private int entityId;
|
||||||
|
|
||||||
/** Model ID */
|
private final Map<String, EntityModule> modules = new HashMap<>();
|
||||||
private int modelId = -1;
|
|
||||||
|
|
||||||
/** Entity data holder */
|
// default modules
|
||||||
private final EntityData data = new EntityData();
|
public final EntityPosModule pos = new EntityPosModule(this);
|
||||||
|
public final EntityHealthModule health = new EntityHealthModule(this);
|
||||||
/** 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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public Entity(int eid, EntityModel entityModel)
|
public Entity(EntityModel model, int eid) {
|
||||||
{
|
|
||||||
this.entityId = eid;
|
this.entityId = eid;
|
||||||
setModel(entityModel);
|
this.model = model;
|
||||||
|
|
||||||
model.initMetadata(data);
|
// register modules
|
||||||
}
|
modules.put("pos", pos);
|
||||||
|
modules.put("health", health);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
public void save(IonOutput out) throws IOException
|
public void load(IonBundle bundle) throws IOException
|
||||||
{
|
{
|
||||||
final IonBundle bundle = new IonBundle();
|
entityId = bundle.get("eid", -1);
|
||||||
bundle.put("model", modelId);
|
if (entityId < 0) throw new IllegalValueException("Bad entity id: " + entityId);
|
||||||
bundle.put("id", entityId);
|
|
||||||
bundle.putBundled("data", data);
|
|
||||||
|
|
||||||
out.writeBundle(bundle);
|
for (Entry<String, EntityModule> entry : modules.entrySet()) {
|
||||||
}
|
bundle.loadBundled(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
@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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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)
|
public void setLevel(Level level)
|
||||||
{
|
{
|
||||||
this.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;
|
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;
|
import mightypork.rogue.world.entity.Entity;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface EntityMoveListener {
|
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 java.io.IOException;
|
||||||
|
|
||||||
import mightypork.rogue.world.Coord;
|
import mightypork.rogue.world.Coord;
|
||||||
|
import mightypork.rogue.world.entity.PathStep;
|
||||||
import mightypork.util.files.ion.IonBundle;
|
import mightypork.util.files.ion.IonBundle;
|
||||||
import mightypork.util.files.ion.IonBundled;
|
import mightypork.util.files.ion.IonBundled;
|
||||||
import mightypork.util.math.Easing;
|
import mightypork.util.math.Easing;
|
||||||
import mightypork.util.math.constraints.vect.Vect;
|
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.math.constraints.vect.mutable.VectAnimated;
|
||||||
import mightypork.util.timing.Updateable;
|
import mightypork.util.timing.Updateable;
|
||||||
|
|
||||||
@@ -175,5 +177,10 @@ public class EntityPos implements IonBundled, Updateable {
|
|||||||
} else if (!coord.equals(other.coord)) return false;
|
} else if (!coord.equals(other.coord)) return false;
|
||||||
return true;
|
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 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.gamecore.render.textures.TxSheet;
|
||||||
import mightypork.rogue.Res;
|
import mightypork.rogue.Res;
|
||||||
import mightypork.rogue.world.entity.Entity;
|
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.rogue.world.level.render.MapRenderContext;
|
||||||
import mightypork.util.math.Calc;
|
import mightypork.util.math.Calc;
|
||||||
import mightypork.util.math.constraints.rect.Rect;
|
import mightypork.util.math.constraints.rect.Rect;
|
||||||
|
|
||||||
|
|
||||||
public class PlayerRenderer extends EntityRenderer {
|
public class SimpleLeftRightMobRenderer extends EntityRenderer {
|
||||||
|
|
||||||
TxSheet sheet;
|
private final TxSheet sheet;
|
||||||
|
|
||||||
|
public SimpleLeftRightMobRenderer(Entity entity, String sheetKey) {
|
||||||
public PlayerRenderer(String sheetKey)
|
super(entity);
|
||||||
{
|
|
||||||
this.sheet = Res.getTxSheet(sheetKey);
|
this.sheet = Res.getTxSheet(sheetKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@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(entity.pos.getCoord());
|
||||||
|
|
||||||
final Rect tileRect = context.getRectForTile(pos.getCoord());
|
|
||||||
final double w = tileRect.width().value();
|
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);
|
spriteRect = spriteRect.shrink(w * 0.1);
|
||||||
|
|
||||||
Render.quadTextured(spriteRect, q);
|
Render.quadTextured(spriteRect, q);
|
||||||
@@ -11,6 +11,7 @@ import java.util.Set;
|
|||||||
import mightypork.rogue.world.Coord;
|
import mightypork.rogue.world.Coord;
|
||||||
import mightypork.rogue.world.Sides;
|
import mightypork.rogue.world.Sides;
|
||||||
import mightypork.rogue.world.World;
|
import mightypork.rogue.world.World;
|
||||||
|
import mightypork.rogue.world.entity.Entities;
|
||||||
import mightypork.rogue.world.entity.Entity;
|
import mightypork.rogue.world.entity.Entity;
|
||||||
import mightypork.rogue.world.pathfinding.FillContext;
|
import mightypork.rogue.world.pathfinding.FillContext;
|
||||||
import mightypork.rogue.world.pathfinding.FloodFill;
|
import mightypork.rogue.world.pathfinding.FloodFill;
|
||||||
@@ -146,31 +147,33 @@ public class Level implements MapAccess, IonBinary {
|
|||||||
@Override
|
@Override
|
||||||
public void load(IonInput in) throws IOException
|
public void load(IonInput in) throws IOException
|
||||||
{
|
{
|
||||||
// metadata
|
// -- metadata --
|
||||||
final IonBundle ib = in.readBundle();
|
final IonBundle ib = in.readBundle();
|
||||||
seed = ib.get("seed", 0L);
|
seed = ib.get("seed", 0L);
|
||||||
ib.loadBundled("size", size);
|
ib.loadBundled("size", size);
|
||||||
ib.loadBundled("enter_point", enterPoint);
|
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
|
// -- binary data --
|
||||||
buildArray();
|
|
||||||
|
|
||||||
// load tiles
|
// load tiles
|
||||||
|
buildArray();
|
||||||
|
|
||||||
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||||
for (c.y = 0; c.y < size.y; c.y++) {
|
for (c.y = 0; c.y < size.y; c.y++) {
|
||||||
setTile(c, Tiles.loadTile(in));
|
setTile(c, Tiles.loadTile(in));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// mark tiles as occupied
|
// load entities
|
||||||
for (final Entity e : entitySet) {
|
Entities.loadEntities(in, entitySet);
|
||||||
occupyTile(e.getPosition().getCoord());
|
|
||||||
|
// 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
|
@Override
|
||||||
public void save(IonOutput out) throws IOException
|
public void save(IonOutput out) throws IOException
|
||||||
{
|
{
|
||||||
// metadata
|
// -- metadata --
|
||||||
final IonBundle ib = new IonBundle();
|
final IonBundle ib = new IonBundle();
|
||||||
ib.put("seed", seed);
|
ib.put("seed", seed);
|
||||||
ib.putBundled("size", size);
|
ib.putBundled("size", size);
|
||||||
ib.putBundled("enter_point", enterPoint);
|
ib.putBundled("enter_point", enterPoint);
|
||||||
ib.putSequence("entities", entitySet);
|
|
||||||
out.writeBundle(ib);
|
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 (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||||
for (c.y = 0; c.y < size.y; c.y++) {
|
for (c.y = 0; c.y < size.y; c.y++) {
|
||||||
Tiles.saveTile(out, getTile(c));
|
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);
|
final Tile t = getTile(pos);
|
||||||
|
|
||||||
@@ -362,8 +367,10 @@ public class Level implements MapAccess, IonBinary {
|
|||||||
return !t.isNull();
|
return !t.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean forceSpreadStart() {
|
public boolean forceSpreadStart()
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public final class TileModel {
|
|||||||
public Tile createTile()
|
public Tile createTile()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return tileClass.getConstructor(int.class, TileRenderer.class).newInstance(id, renderer);
|
return tileClass.getConstructor(TileModel.class, TileRenderer.class).newInstance(this, renderer);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Could not instantiate a tile.", 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
|
public <T> void writeSequence(Collection<T> sequence) throws IOException
|
||||||
{
|
{
|
||||||
for (final T element : sequence) {
|
for (final T element : sequence) {
|
||||||
writeMark(Ion.ENTRY);
|
startEntry();
|
||||||
writeObject(element);
|
writeObject(element);
|
||||||
}
|
}
|
||||||
writeMark(Ion.END);
|
endSequence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -223,12 +223,24 @@ public class IonOutput {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeMark(Ion.ENTRY);
|
startEntry();
|
||||||
writeObject(e.getKey());
|
writeObject(e.getKey());
|
||||||
writeObject(e.getValue());
|
writeObject(e.getValue());
|
||||||
}
|
}
|
||||||
|
endSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void endSequence() throws IOException
|
||||||
|
{
|
||||||
writeMark(Ion.END);
|
writeMark(Ion.END);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void startEntry() throws IOException
|
||||||
|
{
|
||||||
|
writeMark(Ion.ENTRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void writeMark(int mark) throws IOException
|
private void writeMark(int mark) throws IOException
|
||||||
|
|||||||
Reference in New Issue
Block a user