You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
5.2 KiB
279 lines
5.2 KiB
package mightypork.rogue.world.entity;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Queue;
|
|
|
|
import mightypork.rogue.world.PathStep;
|
|
import mightypork.rogue.world.World;
|
|
import mightypork.rogue.world.WorldPos;
|
|
import mightypork.rogue.world.entity.models.EntityModel;
|
|
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
|
import mightypork.rogue.world.level.Level;
|
|
import mightypork.rogue.world.level.render.EntityRenderContext;
|
|
import mightypork.util.ion.IonBinary;
|
|
import mightypork.util.ion.IonBundle;
|
|
import mightypork.util.ion.IonBundled;
|
|
import mightypork.util.ion.IonInput;
|
|
import mightypork.util.ion.IonOutput;
|
|
|
|
|
|
/**
|
|
* World entity (mob or player)
|
|
*
|
|
* @author MightyPork
|
|
*/
|
|
public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
|
|
|
// binary & bundled - binary stores via a bundle
|
|
|
|
public static final int ION_MARK = 52;
|
|
|
|
private final WorldPos position = new WorldPos(); // saved
|
|
|
|
/** Entity ID */
|
|
private int eid = 0; // saved
|
|
|
|
/** Model ID */
|
|
private int id; // saved
|
|
|
|
private final Queue<PathStep> path = new LinkedList<>(); // saved
|
|
private EntityModel model;
|
|
public final IonBundle metadata = new IonBundle(); // saved
|
|
public final IonBundle tmpdata = new IonBundle(); // NOT saved
|
|
|
|
// used for rendering "facing" sprite
|
|
public int lastXMove = 1;
|
|
public int lastYMove = 1;
|
|
|
|
private final List<EntityMoveListener> moveListeners = new ArrayList<>();
|
|
|
|
private boolean walking = false;
|
|
|
|
|
|
public Entity(int eid, WorldPos pos, EntityModel entityModel)
|
|
{
|
|
this.eid = eid;
|
|
this.position.setTo(pos);
|
|
|
|
setModel(entityModel);
|
|
}
|
|
|
|
|
|
private void setModel(EntityModel entityModel)
|
|
{
|
|
// replace listener
|
|
if (model != null) moveListeners.remove(model);
|
|
moveListeners.add(entityModel);
|
|
|
|
this.id = entityModel.id;
|
|
this.model = entityModel;
|
|
}
|
|
|
|
|
|
public Entity()
|
|
{
|
|
// for ion
|
|
}
|
|
|
|
|
|
@Override
|
|
public short getIonMark()
|
|
{
|
|
return ION_MARK;
|
|
}
|
|
|
|
|
|
@Override
|
|
public void save(IonOutput out) throws IOException
|
|
{
|
|
final IonBundle ib = new IonBundle();
|
|
save(ib);
|
|
out.writeBundle(ib);
|
|
}
|
|
|
|
|
|
@Override
|
|
public void load(IonInput in) throws IOException
|
|
{
|
|
load(in.readBundle());
|
|
}
|
|
|
|
|
|
@Override
|
|
public void save(IonBundle bundle) throws IOException
|
|
{
|
|
bundle.put("id", id);
|
|
bundle.putBundled("pos", position);
|
|
bundle.putSequence("steps", path);
|
|
bundle.put("eid", eid);
|
|
|
|
if (model.hasMetadata()) {
|
|
bundle.put("metadata", metadata);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public void load(IonBundle bundle) throws IOException
|
|
{
|
|
id = bundle.get("id", 0);
|
|
|
|
if (model == null || id != model.id) {
|
|
setModel(Entities.get(id));
|
|
}
|
|
|
|
bundle.loadBundled("pos", position);
|
|
bundle.loadSequence("path", path);
|
|
eid = bundle.get("eid", eid);
|
|
|
|
if (model.hasMetadata()) {
|
|
metadata.clear();
|
|
bundle.loadBundle("metadata", metadata);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @return unique entity id
|
|
*/
|
|
public int getEID()
|
|
{
|
|
return eid;
|
|
}
|
|
|
|
|
|
public WorldPos getPosition()
|
|
{
|
|
return position;
|
|
}
|
|
|
|
|
|
public void setPosition(WorldPos pos)
|
|
{
|
|
position.setTo(pos);
|
|
}
|
|
|
|
|
|
public void setPosition(int x, int y)
|
|
{
|
|
position.setTo(x, y);
|
|
cancelPath(); // discard remaining steps
|
|
}
|
|
|
|
|
|
/**
|
|
* @param world the world
|
|
* @param delta delta time
|
|
*/
|
|
public void update(World world, Level level, double delta)
|
|
{
|
|
if (!position.isFinished()) {
|
|
position.update(delta);
|
|
}
|
|
|
|
if (walking && position.isFinished()) {
|
|
walking = false;
|
|
|
|
onStepFinished(this, world, level);
|
|
|
|
if (path.isEmpty()) {
|
|
onPathFinished(this, world, level);
|
|
}
|
|
}
|
|
|
|
if (!walking && !path.isEmpty()) {
|
|
|
|
walking = true;
|
|
|
|
final PathStep step = path.poll();
|
|
|
|
final int projX = position.x + step.x, projY = position.y + step.y;
|
|
|
|
if (!level.canWalkInto(projX, projY)) {
|
|
cancelPath();
|
|
onPathAborted(this, world, level);
|
|
walking = false;
|
|
} else {
|
|
|
|
// tmp for renderer
|
|
if (step.x != 0) lastXMove = step.x;
|
|
if (step.y != 0) lastYMove = step.y;
|
|
|
|
position.walk(step.x, step.y, getStepTime());
|
|
level.occupyTile(projX, projY);
|
|
level.freeTile(position.x, position.y);
|
|
}
|
|
}
|
|
|
|
if (!walking) {
|
|
model.update(this, level, delta);
|
|
}
|
|
}
|
|
|
|
|
|
public void render(EntityRenderContext context)
|
|
{
|
|
model.renderer.render(this, context);
|
|
}
|
|
|
|
|
|
public boolean isPathFinished()
|
|
{
|
|
return position.isFinished() && path.isEmpty();
|
|
}
|
|
|
|
|
|
public void addStep(PathStep step)
|
|
{
|
|
path.add(step);
|
|
}
|
|
|
|
|
|
public void cancelPath()
|
|
{
|
|
path.clear();
|
|
}
|
|
|
|
|
|
protected double getStepTime()
|
|
{
|
|
return model.getStepTime(this);
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onStepFinished(Entity entity, World world, Level level)
|
|
{
|
|
for (final EntityMoveListener l : moveListeners) {
|
|
l.onStepFinished(entity, world, level);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onPathFinished(Entity entity, World world, Level level)
|
|
{
|
|
for (final EntityMoveListener l : moveListeners) {
|
|
l.onStepFinished(entity, world, level);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onPathAborted(Entity entity, World world, Level level)
|
|
{
|
|
for (final EntityMoveListener l : moveListeners) {
|
|
l.onPathAborted(entity, world, level);
|
|
}
|
|
}
|
|
|
|
|
|
public void addMoveListener(EntityMoveListener listener)
|
|
{
|
|
moveListeners.add(listener);
|
|
}
|
|
}
|
|
|