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 { | 
				
			||||
	 | 
				
			||||
	protected Set<EntityMoveListener> playerMoveListeners = new HashSet<>(); | 
				
			||||
	 | 
				
			||||
	private World lastWorld; | 
				
			||||
	 | 
				
			||||
	private final World world; | 
				
			||||
	 | 
				
			||||
	protected abstract World getWorld(); | 
				
			||||
	 | 
				
			||||
	public PlayerControl(World w) | 
				
			||||
	 | 
				
			||||
	private World getWorld2() | 
				
			||||
	{		 | 
				
			||||
		this.world = w; | 
				
			||||
		World newWorld = getWorld(); | 
				
			||||
		 | 
				
			||||
		if (newWorld != lastWorld) { | 
				
			||||
			for (EntityMoveListener eml : playerMoveListeners) { | 
				
			||||
				newWorld.getPlayerEntity().pos.addMoveListener(eml); | 
				
			||||
			} | 
				
			||||
		} | 
				
			||||
		 | 
				
			||||
		lastWorld = newWorld; | 
				
			||||
		 | 
				
			||||
		return newWorld; | 
				
			||||
		 | 
				
			||||
	}; | 
				
			||||
	 | 
				
			||||
	 | 
				
			||||
	public Entity getEntity() | 
				
			||||
	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(); | 
				
			||||
		playerMoveListeners.add(eml); | 
				
			||||
		if(getPlayerEntity() != null) { | 
				
			||||
			getPlayerEntity().pos.addMoveListener(eml); | 
				
			||||
		} | 
				
			||||
	 | 
				
			||||
	 | 
				
			||||
	public World getWorld() | 
				
			||||
	{ | 
				
			||||
		return world; | 
				
			||||
	} | 
				
			||||
	 | 
				
			||||
	 | 
				
			||||
	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