workorder stuff

shops
Ivory 2023-03-06 19:37:29 -05:00
parent c4bfd44cc9
commit 10d86c45ab
14 changed files with 220 additions and 23 deletions

View File

@ -152,4 +152,8 @@ public class Box implements Serializable {
(float) Math.ceil(y2)
);
}
public TileBox asTileBox() {
return new TileBox(pos.asInt(), dim.asInt());
}
}

View File

@ -1,6 +1,10 @@
package xyz.valnet.engine.math;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class TileBox implements Serializable {
public final int x, y;
@ -49,6 +53,16 @@ public class TileBox implements Serializable {
}
}
public List<Vector2i> getTiles() {
List<Vector2i> tiles = new ArrayList<>();
for(int i = 0; i < w; i ++) {
for(int j = 0; j < h; j ++) {
tiles.add(new Vector2i(x + i, y + j));
}
}
return tiles;
}
public static TileBox fromPoints(int x, int y, int x2, int y2) {
return new TileBox(
x <= x2 ? x : x2,

View File

@ -16,6 +16,6 @@ public class CutTreesDesignation extends Designation<Tree> {
@Override
public String getBuildTabName() {
return "ChopTrees";
return "Chop Trees";
}
}

View File

@ -18,6 +18,7 @@ public class Job extends GameObject {
private Job that = this;
private List<Callback> closedListeners = new ArrayList<Callback>();
private List<Callback> completedListeners = new ArrayList<Callback>();
public abstract class JobStep implements Serializable {
public abstract Vector2i[] getLocations();
@ -27,6 +28,10 @@ public class Job extends GameObject {
public abstract boolean isValid();
}
// pickup and dropoff should be all in one step, as each step should
// only need state tracked for the job, not the worker.
// workers can change between steps.
@Deprecated
public class PickupItem extends JobStep {
public Item item;
@ -66,6 +71,10 @@ public class Job extends GameObject {
}
}
// pickup and dropoff should be all in one step, as each step should
// only need state tracked for the job, not the worker.
// workers can change between steps.
@Deprecated
public class PickupItemByPredicate extends JobStep {
public IItemPredicate predicate;
@ -156,6 +165,7 @@ public class Job extends GameObject {
private String name;
private int step;
private boolean hasClosed = false;
private boolean hasCompleted = false;
public void reset() {
step = 0;
@ -179,7 +189,7 @@ public class Job extends GameObject {
public void nextStep() {
step ++;
if(isCompleted()) {
close();
completed();
remove(this);
}
}
@ -202,6 +212,15 @@ public class Job extends GameObject {
public void apply();
}
private final void completed() {
if(hasCompleted) return;
hasCompleted = true;
for(Callback callback : completedListeners) {
callback.apply();
}
close();
}
public void close() {
if(hasClosed) return;
hasClosed = true;
@ -218,6 +237,14 @@ public class Job extends GameObject {
closedListeners.remove(callback);
}
public void registerCompletedListener(Callback callback) {
completedListeners.add(callback);
}
public void unregisterCompletedListener(Callback callback) {
completedListeners.remove(callback);
}
public boolean isValid() {
for(JobStep step : steps) {
if(!step.isValid()) return false;

View File

@ -77,6 +77,7 @@ public class JobBoard extends GameObject {
}
public void postJob(Job job) {
if(!job.inScene()) add(job);
job.registerClosedListener(() -> {
if(allocations.values().contains(job)) {
List<Pawn> toFire = new ArrayList<Pawn>();

View File

@ -1,6 +1,13 @@
package xyz.valnet.hadean.gameobjects.jobs;
import java.util.HashSet;
import java.util.Set;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
import xyz.valnet.hadean.interfaces.IItemReceiver;
import xyz.valnet.hadean.interfaces.IWorkshop;
public class WorkOrder extends GameObject {
@ -9,6 +16,9 @@ public class WorkOrder extends GameObject {
private int count = 10;
private String name = "Cut Stone Blocks";
private IWorkshop shop = null;
private float maxWork = 1000;
private Set<Job> relatedJobs;
public boolean getRecurring() {
return recurring;
@ -22,6 +32,10 @@ public class WorkOrder extends GameObject {
return name;
}
public float getMaxWork() {
return maxWork;
}
public void increaseCount() {
count ++;
}
@ -40,6 +54,47 @@ public class WorkOrder extends GameObject {
}
public boolean isSpecificToShop(IWorkshop shop) {
return this.shop != null && shop == this.shop;
return this.shop != null && this.shop == shop;
}
@Override
protected void create() {
super.create();
relatedJobs = new HashSet<>();
}
public boolean isBeingWorkedOn() {
return relatedJobs.size() > 0;
}
public boolean canCreateJob() {
return count > relatedJobs.size();
}
public Job createNextJob(IWorkshop shop) {
Job job = new Job("Cut brickies");
job.addStep(job.new PickupItemByPredicate(Boulder.BOULDER_PREDICATE));
job.addStep(job.new DropoffPredicateAtItemReceiver(new IItemReceiver() {
@Override
public boolean receive(Item item) {
return false;
}
@Override
public Vector2i[] getItemDropoffLocations() {
return shop.getWorkablePositions();
}
}, Boulder.BOULDER_PREDICATE));
job.addStep(job.new Work(shop));
job.registerCompletedListener(() -> {
decreaseCount();
});
job.registerClosedListener(() -> {
relatedJobs.remove(job);
});
get(JobBoard.class).postJob(job);
return job;
}
}

View File

@ -11,8 +11,9 @@ import xyz.valnet.hadean.gameobjects.Camera;
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
import xyz.valnet.hadean.gameobjects.terrain.Tile;
import xyz.valnet.hadean.interfaces.ITileThing;
import xyz.valnet.hadean.interfaces.IWorldObject;
public abstract class WorldObject extends GameObject {
public abstract class WorldObject extends GameObject implements IWorldObject {
// TODO make it just a box lawl
private int x;
@ -119,6 +120,10 @@ public abstract class WorldObject extends GameObject {
return terrain.getTile(x, y);
}
public Tile getTile(int x, int y) {
return terrain.getTile(x, y);
}
public Set<Tile> getTiles() {
return linkedTiles;
}

View File

@ -14,6 +14,7 @@ import xyz.valnet.hadean.HadeanGame;
import xyz.valnet.hadean.gameobjects.Clock;
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab;
import xyz.valnet.hadean.gameobjects.worldobjects.agents.Agent;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
import xyz.valnet.hadean.interfaces.IItemPredicate;
@ -42,6 +43,9 @@ public class Pawn extends Agent {
public void pickupItemByPredicate(IItemPredicate itemPredicate) {
Item item = getTile().pickupByItemPredicate(itemPredicate);
if(item == null) {
DebugTab.log("This is an issue");
}
inventory.add(item);
}
@ -66,7 +70,8 @@ public class Pawn extends Agent {
return;
}
inventory.remove(item);
add(item);
// TODO this might need to exist at some point
// add(item);
receiver.receive(item);
}

View File

@ -18,7 +18,7 @@ import xyz.valnet.hadean.util.Action;
import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
public abstract class Construction extends Buildable implements IItemReceiver {
public abstract class Construction extends Buildable {
private float work = 0;
@ -36,7 +36,23 @@ public abstract class Construction extends Buildable implements IItemReceiver {
Job job = get(JobBoard.class).postSimpleItemRequirementJob(
"Haul items to building",
getBuildingMaterial(),
this
new IItemReceiver() {
@Override
public final boolean receive(Item item) {
if(item == null) return false;
if(!item.matches(getBuildingMaterial())) return false;
remove(item);
containedItems.add(item);
return true;
}
@Override
public Vector2i[] getItemDropoffLocations() {
return getWorldBox().getBorders();
}
}
);
job.registerClosedListener(() -> {
postNextJob();
@ -108,20 +124,6 @@ public abstract class Construction extends Buildable implements IItemReceiver {
return work / getMaxWork();
}
@Override
public final boolean receive(Item item) {
if(item == null) return false;
if(!item.matches(getBuildingMaterial())) return false;
remove(item);
containedItems.add(item);
return true;
}
@Override
public Vector2i[] getItemDropoffLocations() {
return getWorldBox().getBorders();
}
@Override
public void render() {
Sprite sprite = getDefaultSprite();

View File

@ -1,8 +1,13 @@
package xyz.valnet.hadean.gameobjects.worldobjects.constructions;
import xyz.valnet.engine.graphics.Sprite;
import xyz.valnet.engine.math.TileBox;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.hadean.gameobjects.jobs.Job;
import xyz.valnet.hadean.gameobjects.jobs.WorkOrder;
import xyz.valnet.hadean.gameobjects.jobs.WorkOrderManager;
import xyz.valnet.hadean.gameobjects.ui.WorkshopOrdersUI;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Log;
import xyz.valnet.hadean.interfaces.IItemPredicate;
import xyz.valnet.hadean.interfaces.IWorkshop;
@ -13,6 +18,10 @@ public class MasonWorkshop extends Construction implements IWorkshop {
private static Action OPEN_ORDERS = new Action("Orders");
private transient WorkshopOrdersUI ordersWindow;
private WorkOrderManager manager;
// TODO the job itself should have the work amount...
private float workDone = 0;
@Override
protected IItemPredicate getBuildingMaterial() {
@ -62,6 +71,7 @@ public class MasonWorkshop extends Construction implements IWorkshop {
protected void connect() {
super.connect();
ordersWindow = get(WorkshopOrdersUI.class);
manager = get(WorkOrderManager.class);
}
@Override
@ -73,5 +83,52 @@ public class MasonWorkshop extends Construction implements IWorkshop {
public String getBuildTabCategory() {
return "Workshops";
}
@Override
public boolean doWork(float dTime) {
workDone += dTime;
return workDone > order.getMaxWork();
}
@Override
public Vector2i[] getWorkablePositions() {
return getWorldBox().getBorders();
}
@Override
public String getJobName() {
return "Do Work as Workshop";
}
@Override
public TileBox getSpawnableArea() {
return getWorldBox().asTileBox();
}
private Job job = null;
private WorkOrder order = null;
@Override
public void update(float dTime) {
super.update(dTime);
if(job == null) {
tryGetJob();
}
}
private final void tryGetJob() {
for(WorkOrder order : manager.getOrders(this)) {
if(order.canCreateJob()) {
this.order = order;
job = order.createNextJob(this);
job.registerClosedListener(() -> {
workDone = 0;
job = null;
this.order = null;
});
return;
}
}
}
}

View File

@ -0,0 +1,17 @@
package xyz.valnet.hadean.interfaces;
import xyz.valnet.engine.math.TileBox;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
public interface IItemSpawner extends IWorldObject {
public abstract TileBox getSpawnableArea();
public default void spawn(Item item) {
var tiles = getSpawnableArea().getTiles();
while(tiles.size() > 0) {
int idx = (int) Math.floor(Math.random() * tiles.size());
var pos = tiles.get(idx);
getTile(pos.x, pos.y);
}
}
}

View File

@ -7,5 +7,7 @@ import xyz.valnet.engine.math.Vector2i;
public interface IWorkable extends Serializable {
public boolean doWork(float dTime);
public Vector2i[] getWorkablePositions();
// we should honestly switch to only have names of jobs not steps...
@Deprecated
public String getJobName();
}

View File

@ -1,5 +1,6 @@
package xyz.valnet.hadean.interfaces;
public interface IWorkshop extends ISelectable {
public interface IWorkshop extends ISelectable,
IWorkable,
IItemSpawner {
}

View File

@ -0,0 +1,7 @@
package xyz.valnet.hadean.interfaces;
import xyz.valnet.hadean.gameobjects.terrain.Tile;
public interface IWorldObject {
public Tile getTile(int x, int y);
}