parent
ab1c3b3a74
commit
19d13c7903
@ -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) |
||||
{ |
||||
this.world = w; |
||||
} |
||||
|
||||
protected abstract World getWorld(); |
||||
|
||||
|
||||
public Entity getEntity() |
||||
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() |
||||
{ |
||||
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(); |
||||
} |
||||
} |
||||
|
@ -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() |
||||
{ |
||||
} |
||||
|
||||
} |
@ -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 { |
||||
|
||||
|
||||
} |
@ -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 { |
||||
|
||||
/** |
@ -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(); |
||||
} |
||||
|
||||
} |
@ -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
|
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue