Merge pull request #1 from valyrie97/beds

Beds
world-object-unification-project
Valerie 2023-01-03 04:00:28 -05:00 committed by GitHub
commit 2e1533d9d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 295 additions and 135 deletions

View File

@ -13,6 +13,7 @@ public class CustomObjectDeserializer extends ObjectInputStream {
super(in);
}
@SuppressWarnings("rawtypes")
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); // initially streams descriptor
Class localClass; // the class in the local JVM that this descriptor represents.

View File

@ -153,14 +153,14 @@ public abstract class SceneGraph implements IScene {
}
private void dump(List<GameObject> objects) {
Map<Class, Integer> count = new HashMap<Class, Integer>();
Map<Class<? extends GameObject>, Integer> count = new HashMap<Class<? extends GameObject>, Integer>();
for(GameObject go : objects) {
Class clazz = go.getClass();
Class<? extends GameObject> clazz = go.getClass();
if(!count.containsKey(clazz))
count.put(clazz, 0);
count.put(clazz, count.get(clazz) + 1);
}
for(Entry<Class, Integer> entry : count.entrySet()) {
for(Entry<Class<? extends GameObject>, Integer> entry : count.entrySet()) {
System.out.println("" + entry.getValue() + "x " + entry.getKey().getSimpleName());
}
}
@ -190,6 +190,7 @@ public abstract class SceneGraph implements IScene {
saveFlag = false;
}
@SuppressWarnings("unchecked")
private void load() {
try {
FileInputStream file = new FileInputStream("SAVE_DATA.TXT");

View File

@ -11,7 +11,6 @@ import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.hadean.scenes.GameScene;
import xyz.valnet.hadean.util.Assets;
public class HadeanGame extends Game {
public static final HadeanGame Hadean = new HadeanGame();

View File

@ -4,11 +4,11 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.hadean.gameobjects.worldobjects.Stockpile;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
import xyz.valnet.hadean.interfaces.IItemReceiver;
import xyz.valnet.hadean.interfaces.IWorkable;
public class Job extends GameObject {
@ -26,9 +26,8 @@ public class Job extends GameObject {
public class PickupItem extends JobStep {
public Item item;
public Vector2f[] locations;
public PickupItem(Item item, Vector2f[] possibleLocations) {
public PickupItem(Item item) {
this.item = item;
}
@ -43,6 +42,28 @@ public class Job extends GameObject {
}
}
public class DropoffAtItemReceiver extends JobStep {
public IItemReceiver receiver;
public Item item;
public DropoffAtItemReceiver(IItemReceiver receiver, Item item) {
this.receiver = receiver;
this.item = item;
}
@Override
public Vector2i[] getLocations() {
return receiver.getItemDropoffLocations();
}
@Override
public boolean isValid() {
return true;
}
}
// TODO find the _best_ place to dropoff, instead of just the top left place.
public class DropoffAtStockpile extends JobStep {
public Item item;
public DropoffAtStockpile(Item item) {
@ -72,8 +93,8 @@ public class Job extends GameObject {
public Vector2i[] getLocations() {
return subject.getWorkablePositions();
}
public boolean doWork() {
return subject.doWork();
public boolean doWork(float dTime) {
return subject.doWork(dTime);
}
@Override

View File

@ -1,7 +1,6 @@
package xyz.valnet.hadean.gameobjects;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

View File

@ -87,8 +87,6 @@ public class Tile extends WorldObject implements IWorkable {
}
thing.onPlaced(this);
if(thing instanceof FarmPlot) {
desiredTill = true;
get(JobBoard.class).postSimpleWorkJob("Till Soil", this);
}
}
@ -140,13 +138,8 @@ public class Tile extends WorldObject implements IWorkable {
return true;
}
private boolean desiredTill = false;
private float tillLevel = 0;
public void setTill(boolean till) {
desiredTill = till;
}
@Override
public Vector2i[] getWorkablePositions() {
return new Vector2i[] {
@ -168,8 +161,8 @@ public class Tile extends WorldObject implements IWorkable {
}
@Override
public boolean doWork() {
tillLevel += 0.005f;
public boolean doWork(float dTime) {
tillLevel += 0.005f * dTime;
tillLevel = Math.min(tillLevel, 1);
return tillLevel >= 1;
}

View File

@ -70,7 +70,6 @@ public class BuildLayer extends GameObject implements IMouseCaptureArea, ITransi
}
private int x, y;
private int screenX, screenY;
private boolean mouseDown = false;
@Override
@ -80,8 +79,6 @@ public class BuildLayer extends GameObject implements IMouseCaptureArea, ITransi
} else if(button == 0 && active && hovered) {
Vector2i worldcoords = camera.screen2world(App.mouseX, App.mouseY).asInt();
mouseDown = true;
screenX = App.mouseX;
screenY = App.mouseY;
x = worldcoords.x;
y = worldcoords.y;
}

View File

@ -49,7 +49,7 @@ public class SelectionLayer extends GameObject implements IMouseCaptureArea, ITr
@Override
public void update(float dTime) {
if(animation < animationMax) animation ++;
if(animation < animationMax) animation += dTime;
if(animation > animationMax) animation = animationMax;
// if(!active) return;

View File

@ -18,7 +18,6 @@ import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.IMouseCaptureArea;
import xyz.valnet.hadean.gameobjects.BottomBar;
import xyz.valnet.hadean.gameobjects.Camera;
import xyz.valnet.hadean.gameobjects.Terrain;
import xyz.valnet.hadean.gameobjects.inputlayer.BuildLayer;
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
import xyz.valnet.hadean.input.Button;
@ -31,7 +30,6 @@ import xyz.valnet.hadean.interfaces.ISelectable;
import xyz.valnet.hadean.interfaces.ISelectionChangeListener;
import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
import xyz.valnet.hadean.util.Pair;
import xyz.valnet.hadean.util.SmartBoolean;
public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCaptureArea, IButtonListener {
@ -39,7 +37,6 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
private SelectionLayer selection;
private BuildLayer buildLayer;
private Camera camera;
private Terrain terrain;
private SmartBoolean opened;
private int width = 200;
@ -51,25 +48,32 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
private String selectedCategory = "";
private transient Constructor<? extends IBuildable> selectedBuildable = null;
private transient Map<String, List<Pair<String, Constructor<? extends IBuildable>>>> buildables = null;
private transient Map<Button, Constructor<? extends IBuildable>> buildableButtons = null;
private transient BuildableRecord selectedBuildable = null;
private transient Map<String, List<BuildableRecord>> buildables = null;
private transient Map<Button, BuildableRecord> buildableButtons = null;
private int height = 0;
private String selectedBuildableName = "";
private record BuildableRecord(
String name,
Constructor<? extends IBuildable> constructor,
int type
) {
}
@SuppressWarnings("unchecked")
private void calculateBuildables() {
try {
Class<? extends IBuildable>[] maybeBuildables = getClasses("xyz.valnet.hadean");
Class<?>[] maybeBuildables = getClasses("xyz.valnet.hadean");
for(Class<? extends IBuildable> clazz : maybeBuildables) {
for(Class<?> clazz : maybeBuildables) {
if(clazz.isAnonymousClass()) continue;
if(!IBuildable.class.isAssignableFrom(clazz)) continue;
if(clazz.isInterface()) continue;
if(Modifier.isAbstract(clazz.getModifiers())) continue;
Constructor<? extends IBuildable> constructor = clazz.getConstructor();
Constructor<? extends IBuildable> constructor = (Constructor<? extends IBuildable>) clazz.getConstructor();
if(constructor.getParameterCount() != 0) {
System.out.println(clazz + " has no default constructor (no params)");
continue;
@ -81,10 +85,11 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
}
String category = annotation.category();
String name = annotation.name();
int type = annotation.type();
if(!buildables.containsKey(category))
buildables.put(category, new ArrayList<Pair<String, Constructor<? extends IBuildable>>>());
buildables.get(category).add(new Pair<String, Constructor<? extends IBuildable>>(name, constructor));
buildables.put(category, new ArrayList<BuildableRecord>());
buildables.get(category).add(new BuildableRecord(name, constructor, type));
System.out.println("Added " + category + " / " + name);
}
@ -107,7 +112,7 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
// draw the currently selected build item
Assets.flat.pushColor(new Vector4f(1f, 1f, 1f, 1.0f));
Vector2i topLeft = camera.world2screen(x, y).asInt();
Assets.font.drawString(selectedBuildableName, topLeft.x, topLeft.y - 20);
Assets.font.drawString(selectedBuildable.name, topLeft.x, topLeft.y - 20);
Assets.flat.swapColor(new Vector4f(1f, 1f, 1f, 0.5f));
for(int i = 0; i < w; i ++) for(int j = 0; j < h; j ++) {{
camera.draw(Layers.BUILD_INTERACTABLE, Assets.checkerBoard, x + i, y + j);
@ -122,7 +127,6 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
buildLayer = get(BuildLayer.class);
selection = get(SelectionLayer.class);
camera = get(Camera.class);
terrain = get(Terrain.class);
opened = new SmartBoolean(false, new SmartBoolean.IListener() {
@ -142,22 +146,23 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
selection.subscribe(this);
}
buildables = new HashMap<String, List<Pair<String, Constructor<? extends IBuildable>>>>();
buildableButtons = new HashMap<Button, Constructor<? extends IBuildable>>();
buildables = new HashMap<String, List<BuildableRecord>>();
buildableButtons = new HashMap<Button, BuildableRecord>();
calculateBuildables();
}
private List<Button> categoryButtons = new ArrayList<Button>();
private void selectBuildable(String name, Constructor<? extends IBuildable> constructor) {
if(selectedBuildable != null && constructor == null) {
buildLayer.deactiveate();
} else if (selectedBuildable == null && constructor != null) {
activateBuildLayer();
private void deselectBuilding() {
if(selectedBuildable != null) buildLayer.deactiveate();
selectedBuildable = null;
}
selectedBuildable = constructor;
selectedBuildableName = name;
private void selectBuildable(BuildableRecord buildableRecord) {
if(buildableRecord == null) deselectBuilding();
if (selectedBuildable == null) activateBuildLayer();
selectedBuildable = buildableRecord;
}
private void activateBuildLayer() {
@ -174,7 +179,7 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
public void build(int x1, int y1, int x2, int y2) {
if(selectedBuildable == null) return;
try {
IBuildable building = selectedBuildable.newInstance();
IBuildable building = selectedBuildable.constructor.newInstance();
if(building instanceof GameObject) {
add((GameObject) building);
}
@ -192,7 +197,7 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
opened.set(false);
buildLayer.deactiveate();
} else {
selectBuildable("", null);
deselectBuilding();
}
}
});
@ -278,7 +283,7 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
if(!opened.value()) return;
List<Pair<String, Constructor<? extends IBuildable>>> categoryBuildables = buildables.get(selectedCategory);
List<BuildableRecord> categoryBuildables = buildables.get(selectedCategory);
if(categoryBuildables == null) return;
int left = width + padding * 2;
@ -286,16 +291,16 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
int buttonWidth = 100;
int top = 576 - BottomBar.bottomBarHeight - padding - buttonHeight;
int i = 0;
for(Pair<String, Constructor<? extends IBuildable>> nameConstructorPair : categoryBuildables) {
for(BuildableRecord buildableRecord : categoryBuildables) {
int x = left + (buttonWidth + padding) * i;
int y = top;
int w = buttonWidth;
int h = buttonHeight;
i ++;
Button btn = new SimpleButton(nameConstructorPair.first(), x, y, w, h, Layers.GENERAL_UI_INTERACTABLE);
Button btn = new SimpleButton(buildableRecord.name, x, y, w, h, Layers.GENERAL_UI_INTERACTABLE);
btn.registerClickListener(this);
add(btn);
buildableButtons.put(btn, nameConstructorPair.second());
buildableButtons.put(btn, buildableRecord);
}
}
@ -303,15 +308,16 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
public void click(Button target) {
if(categoryButtons.contains(target)) {
selectedCategory = target.getText();
selectBuildable("", null);
deselectBuilding();
constructItemButtons();
} else if(buildableButtons.containsKey(target)) {
Constructor<? extends IBuildable> newConstructor = buildableButtons.get(target);
selectBuildable(target.getText(), newConstructor);
BuildableRecord newBuildableRecord = buildableButtons.get(target);
selectBuildable(newBuildableRecord);
}
}
private static Class[] getClasses(String packageName) throws ClassNotFoundException, IOException {
@SuppressWarnings("rawtypes")
private static Class<?>[] getClasses(String packageName) throws ClassNotFoundException, IOException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
assert classLoader != null;
String path = packageName.replace('.', '/');
@ -325,9 +331,10 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
for (File directory : dirs) {
classes.addAll(findClasses(directory, packageName));
}
return classes.toArray(new Class[classes.size()]);
return (Class<?>[]) classes.toArray(new Class[classes.size()]);
}
@SuppressWarnings("rawtypes")
private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
List<Class> classes = new ArrayList<Class>();
if (!directory.exists()) {

View File

@ -0,0 +1,142 @@
package xyz.valnet.hadean.gameobjects.worldobjects;
import static xyz.valnet.engine.util.Math.lerp;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.hadean.gameobjects.Job;
import xyz.valnet.hadean.gameobjects.JobBoard;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Log;
import xyz.valnet.hadean.interfaces.BuildableMetadata;
import xyz.valnet.hadean.interfaces.IBuildable;
import xyz.valnet.hadean.interfaces.IItemReceiver;
import xyz.valnet.hadean.interfaces.ISelectable;
import xyz.valnet.hadean.interfaces.IWorkable;
import xyz.valnet.hadean.util.Action;
import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
import xyz.valnet.hadean.util.detail.BooleanDetail;
import xyz.valnet.hadean.util.detail.Detail;
import xyz.valnet.hadean.util.detail.ObjectDetail;
import xyz.valnet.hadean.util.detail.PercentDetail;
@BuildableMetadata(category = "Furniture", name = "Bed", type = BuildableMetadata.SINGLE)
public class Bed extends WorldObject implements IBuildable, IItemReceiver, IWorkable, ISelectable {
private int logs = 0;
private float work = 0;
private final float maxWork = 500;
private Job job = null;
@Override
protected void create() {
super.create();
// TODO eventually we're going to need a serializable ItemPredicate to select valid items.
// it will be useful for stockpile filters, pickup items, etc. basically a placeholder
// for "any item that matches X" as a data type.
job = add(new Job("Build Bed"));
Log log = get(Log.class);
job.addStep(job.new PickupItem(log));
job.addStep(job.new DropoffAtItemReceiver(this, log));
job.addStep(job.new Work(this));
get(JobBoard.class).postJob(job);
}
@Override
public void render() {
super.render();
if(isBuilt()) {
camera.draw(Layers.GROUND, Assets.bed, (int)x, (int)y, 1, 2);
} else {
Assets.flat.pushColor(Vector4f.opacity(lerp(0.5f, 1.0f, work / maxWork)));
camera.draw(Layers.GROUND, Assets.bed, (int)x, (int)y, 1, 2);
Assets.flat.popColor();
}
}
@Override
public void buildAt(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = 1;
this.h = 2;
}
@Override
public String getName() {
return "Bed";
}
@Override
public Vector4f getWorldBox() {
return new Vector4f(x, y, x+w, y+h);
}
@Override
public boolean receive(Item item) {
remove(item);
logs ++;
return true;
}
private boolean isBuilt() {
return work >= maxWork;
}
@Override
public boolean doWork(float dTime) {
work += dTime;
return isBuilt();
}
private Vector2i[] getBorders() {
return new Vector2i[] {
new Vector2i((int) x, (int) y - 1),
new Vector2i((int) x - 1, (int) y),
new Vector2i((int) x + 1, (int) y),
new Vector2i((int) x - 1, (int) y + 1),
new Vector2i((int) x + 1, (int) y + 1),
new Vector2i((int) x, (int) y + 2),
};
}
@Override
public Vector2i[] getWorkablePositions() {
return getBorders();
}
@Override
public String getJobName() {
return "Build Bed";
}
@Override
public Vector2i[] getItemDropoffLocations() {
return getBorders();
}
@Override
public Action[] getActions() {
return new Action[0];
}
@Override
public void runAction(Action action) {
}
@Override
public Detail[] getDetails() {
return new Detail[] {
new BooleanDetail("Built", isBuilt()),
new PercentDetail("Work", work / maxWork),
new ObjectDetail<Integer>("Logs", logs),
};
}
}

View File

@ -2,39 +2,14 @@ package xyz.valnet.hadean.gameobjects.worldobjects;
import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.hadean.gameobjects.JobBoard;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
import xyz.valnet.hadean.interfaces.ISelectable;
import xyz.valnet.hadean.interfaces.ITileThing;
import xyz.valnet.hadean.util.Action;
import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
import xyz.valnet.hadean.util.detail.Detail;
public class Rice extends Item implements ITileThing, ISelectable {
public class Rice extends Item {
// private SmartBoolean haul;
private JobBoard jobboard;
@Override
public void start() {
super.start();
jobboard = get(JobBoard.class);
Rice that = this;
// haul = new SmartBoolean(false, new IListener() {
// @Override
// public void rise() {
// jobboard.postJob(that);
// }
// @Override
// public void fall() {
// jobboard.rescindJob(that);
// }
// });
}
public Rice(int x, int y) {
this.x = x;

View File

@ -113,7 +113,6 @@ public class Stockpile extends WorldObject implements ISelectable, ITileThing, I
@Override
public String getName() {
// TODO Auto-generated method stub
return "Stockpile";
}

View File

@ -87,8 +87,8 @@ public class Tree extends WorldObject implements ITileThing, ISelectable, IWorka
}
@Override
public boolean doWork() {
choppage ++;
public boolean doWork(float dTime) {
choppage += dTime;
return getProgress() >= 1;
}
@ -135,8 +135,5 @@ public class Tree extends WorldObject implements ITileThing, ISelectable, IWorka
}
@Override
public void onPlaced(Tile tile) {
// TODO Auto-generated method stub
}
public void onPlaced(Tile tile) {}
}

View File

@ -11,6 +11,8 @@ public abstract class WorldObject extends GameObject {
protected float x;
protected float y;
protected float w;
protected float h;
protected Camera camera;
protected Terrain terrain;

View File

@ -27,7 +27,7 @@ import static xyz.valnet.engine.util.Math.lerp;
public abstract class Agent extends WorldObject implements ISelectable {
public abstract String getName();
private int frameCounter = 0;
private float frameCounter = 0;
private int speed = 100 + (int)(Math.random() * 50);
private IPathfinder pathfinder;
@ -58,14 +58,14 @@ public abstract class Agent extends WorldObject implements ISelectable {
@Override
public void update(float dTime) {
think();
act();
act(dTime);
postAct();
}
protected abstract void postAct();
private void move() {
frameCounter++;
private void move(float dTime) {
frameCounter += dTime;
if(frameCounter >= speed) {
Vector2i nextPos = path.pop().getPosition();
this.x = nextPos.x;
@ -75,7 +75,7 @@ public abstract class Agent extends WorldObject implements ISelectable {
nextPath = null;
}
if(path.isComplete()) path = null;
frameCounter = 0;
frameCounter -= speed;
if(stopPathingFlag) {
path = null;
nextPath = null;
@ -112,9 +112,9 @@ public abstract class Agent extends WorldObject implements ISelectable {
correctPath();
}
protected boolean act() {
protected boolean act(float dTime) {
if(path != null) {
move();
move(dTime);
return true;
}
@ -127,7 +127,7 @@ public abstract class Agent extends WorldObject implements ISelectable {
Path newPath = pathfinder.getPath((int)this.x, (int)this.y, x, y);
if(path == null) {
path = newPath;
frameCounter = 0;
frameCounter -= 0;
} else {
nextPath = newPath;
}

View File

@ -1,6 +1,5 @@
package xyz.valnet.hadean.gameobjects.worldobjects.items;
import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.hadean.gameobjects.Job;
import xyz.valnet.hadean.gameobjects.JobBoard;
@ -80,7 +79,7 @@ public abstract class Item extends WorldObject implements ISelectable, ITileThin
private void markForHaul() {
if(haulJob != null) return;
haulJob = add(new Job("Haul " + this.getName()));
haulJob.addStep(haulJob.new PickupItem(this, new Vector2f[] { this.getWorldPosition() }));
haulJob.addStep(haulJob.new PickupItem(this));
haulJob.addStep(haulJob.new DropoffAtStockpile(this));
haulJob.registerClosedListener(() -> {
haulJob = null;

View File

@ -4,6 +4,11 @@ import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
import xyz.valnet.hadean.util.detail.Detail;
// TODO haul on placed in non stockpile. we could have a situation
// where the job gets cancelled, because a pawn has the item
// while it wants to be hauled. thats fine, but what if the pawn then drops
// the item? it should still be hauled. ergo, we should autohaul
// when placed in a non stockpile, not just on create.
public class Log extends Item {
public Log(int x, int y) {

View File

@ -14,7 +14,7 @@ public abstract class Activity implements Serializable {
public abstract boolean isUrgent();
public abstract float getBenefit();
public abstract boolean isValid();
public abstract void act();
public abstract void act(float dTime);
public abstract void begin(ActivityCancellationCallback callback);
public abstract void end();
public abstract String toString();

View File

@ -32,8 +32,8 @@ public class JobActivity extends Activity {
}
@Override
public void act() {
if (doJob()) return;
public void act(float dTime) {
if (doJob(dTime)) return;
}
@ -83,7 +83,7 @@ public class JobActivity extends Activity {
job = null;
}
private boolean doJob() {
private boolean doJob(float dTime) {
if(!jobboard.workerHasJob(worker)) return false;
JobStep step = job.getCurrentStep();
// if we're not at the location of the job...
@ -91,7 +91,7 @@ public class JobActivity extends Activity {
if(step instanceof Job.Work) {
Job.Work workStep = (Job.Work)step;
if(workStep.doWork()) step.next();
if(workStep.doWork(dTime)) step.next();
return true;
} else if(step instanceof Job.PickupItem) {
Job.PickupItem pickupStep = (Job.PickupItem) step;
@ -104,6 +104,10 @@ public class JobActivity extends Activity {
worker.dropoffItem(dropoffStep.item);
step.next();
return true;
} else if(step instanceof Job.DropoffAtItemReceiver) {
Job.DropoffAtItemReceiver dropoffStep = (Job.DropoffAtItemReceiver) step;
worker.dropoffItem(dropoffStep.item, dropoffStep.receiver);
step.next();
}
return false;

View File

@ -14,12 +14,12 @@ public class Needs implements Serializable {
private float decay = 0.000004f;
public void update(float dTime) {
energy = Math.max(energy - decay, 0);
recreation = Math.max(recreation - decay, 0);
energy = Math.max(energy - decay * dTime, 0);
recreation = Math.max(recreation - decay * dTime, 0);
}
public void sleep() {
energy = Math.min(energy + decay * restRatio, 1);
public void sleep(float dTime) {
energy = Math.min(energy + decay * dTime * restRatio, 1);
}
public float getSleepNeed() {

View File

@ -13,6 +13,7 @@ import xyz.valnet.hadean.gameobjects.JobBoard;
import xyz.valnet.hadean.gameobjects.Terrain;
import xyz.valnet.hadean.gameobjects.worldobjects.agents.Agent;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
import xyz.valnet.hadean.interfaces.IItemReceiver;
import xyz.valnet.hadean.util.Action;
import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
@ -52,6 +53,15 @@ public class Pawn extends Agent {
getTile().placeThing(item);
}
public void dropoffItem(Item item, IItemReceiver receiver) {
if(!inventory.contains(item)) {
return;
}
inventory.remove(item);
add(item);
receiver.receive(item);
}
@Override
protected void ready() {
super.ready();
@ -63,7 +73,7 @@ public class Pawn extends Agent {
super.start();
activities.add(new JobActivity(this, get(JobBoard.class)));
activities.add(new SleepActivity(this, needs, get(Clock.class)));
activities.add(new SleepActivity(needs, get(Clock.class)));
}
protected void create() {
@ -162,10 +172,6 @@ public class Pawn extends Agent {
currentActivity.begin(a -> endActivity(a));
}
private void endActivity() {
endActivity(currentActivity);
}
private void endActivity(Activity activity) {
activity.end();
stopPathing();
@ -177,11 +183,11 @@ public class Pawn extends Agent {
// TODO at some point rewrite this to use an actor component array
// where we loop through until something _does_ sometihng.
@Override
protected boolean act() {
if(super.act()) return true;
protected boolean act(float dTime) {
if(super.act(dTime)) return true;
// if(doJob()) return true;
if(currentActivity != null) {
currentActivity.act();
currentActivity.act(dTime);
return true;
}
return false;

View File

@ -3,23 +3,17 @@ package xyz.valnet.hadean.gameobjects.worldobjects.pawn;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.util.Math.WeightedAverage;
import xyz.valnet.hadean.gameobjects.Clock;
import xyz.valnet.hadean.gameobjects.worldobjects.agents.Agent;
import static xyz.valnet.engine.util.Math.lerp;
public class SleepActivity extends Activity {
private Agent agent;
private Needs needs;
private Clock clock;
private float circadianStrength = (float)Math.random() * 5f;
private int stage;
public SleepActivity(Agent agent, Needs needs, Clock clock) {
public SleepActivity(Needs needs, Clock clock) {
this.needs = needs;
this.agent = agent;
this.clock = clock;
}
@ -47,8 +41,8 @@ public class SleepActivity extends Activity {
}
@Override
public void act() {
needs.sleep();
public void act(float dTime) {
needs.sleep(dTime);
if(needs.getSleepNeed() == 0) {
callback.apply(this);
}

View File

@ -3,9 +3,12 @@ package xyz.valnet.hadean.gameobjects.worldobjects.pawn;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.hadean.gameobjects.worldobjects.agents.Agent;
// TODO actually implement this activity.
public class WanderActivity extends Activity {
@SuppressWarnings("unused")
private Agent agent;
@SuppressWarnings("unused")
private Needs needs;
public WanderActivity(Agent agent, Needs needs) {
@ -29,7 +32,7 @@ public class WanderActivity extends Activity {
}
@Override
public void act() {
public void act(float dTime) {
// since wandering is literally just pathing.
}

View File

@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface BuildableMetadata {
public static int AREA = 0;
public static int SINGLE = 1;
public String name();
public String category();
public int type() default AREA;
}

View File

@ -0,0 +1,11 @@
package xyz.valnet.hadean.interfaces;
import java.io.Serializable;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
public interface IItemReceiver extends Serializable {
public boolean receive(Item item);
public Vector2i[] getItemDropoffLocations();
}

View File

@ -3,7 +3,7 @@ package xyz.valnet.hadean.interfaces;
import xyz.valnet.engine.math.Vector2i;
public interface IWorkable {
public boolean doWork();
public boolean doWork(float dTime);
public Vector2i[] getWorkablePositions();
public String getJobName();
}

View File

@ -1,6 +1,5 @@
package xyz.valnet.hadean.scenes;
import xyz.valnet.engine.App;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.IScene;
import xyz.valnet.hadean.input.Button;
@ -10,6 +9,7 @@ import xyz.valnet.hadean.util.Layers;
import static xyz.valnet.hadean.HadeanGame.Hadean;
// TODO convert this to a scenegraph
public class MenuScene implements IScene, IButtonListener {
private Button btnNewGame = new Button(Assets.frame, "New Game", 50, 200, 128, 32, Layers.GENERAL_UI);
@ -44,10 +44,10 @@ public class MenuScene implements IScene, IButtonListener {
@Override
public void update(float dTime) {
btnNewGame.setMouseCoords(App.mouseX, App.mouseY);
btnLoadGame.setMouseCoords(App.mouseX, App.mouseY);
btnOptions.setMouseCoords(App.mouseX, App.mouseY);
btnQuit.setMouseCoords(App.mouseX, App.mouseY);
// btnNewGame.setMouseCoords(App.mouseX, App.mouseY);
// btnLoadGame.setMouseCoords(App.mouseX, App.mouseY);
// btnOptions.setMouseCoords(App.mouseX, App.mouseY);
// btnQuit.setMouseCoords(App.mouseX, App.mouseY);
btnNewGame.update();
btnLoadGame.update();
btnOptions.update();