diff --git a/src/main/java/xyz/valnet/engine/App.java b/src/main/java/xyz/valnet/engine/App.java index 30a9ada..03aeba9 100644 --- a/src/main/java/xyz/valnet/engine/App.java +++ b/src/main/java/xyz/valnet/engine/App.java @@ -123,7 +123,7 @@ public class App { // Get the resolution of the primary monitor long primaryMonitor = glfwGetPrimaryMonitor(); PointerBuffer monitors = glfwGetMonitors(); - primaryMonitor = monitors.get(1); + primaryMonitor = monitors.get(0); GLFWVidMode vidmode = glfwGetVideoMode(primaryMonitor); IntBuffer monitorX = stack.mallocInt(1); // int* IntBuffer monitorY = stack.mallocInt(1); // int* diff --git a/src/main/java/xyz/valnet/engine/math/Vector2i.java b/src/main/java/xyz/valnet/engine/math/Vector2i.java index 78fac4a..f1de131 100644 --- a/src/main/java/xyz/valnet/engine/math/Vector2i.java +++ b/src/main/java/xyz/valnet/engine/math/Vector2i.java @@ -74,4 +74,9 @@ public class Vector2i implements Serializable { return new Vector2i(this.x + b.x, this.y + b.y); } + public Vector2i[] asArray() { + return new Vector2i[] { + this + }; + } } diff --git a/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java b/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java index 4d994c1..48da76d 100644 --- a/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java +++ b/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java @@ -1,13 +1,16 @@ package xyz.valnet.engine.scenegraph; import java.io.Serializable; +import java.util.HashSet; import java.util.List; +import java.util.Set; import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.scenegraph.SceneGraph.GameObjectCallback; +import xyz.valnet.hadean.interfaces.ISceneReferent; import xyz.valnet.hadean.util.Pair; -public class GameObject implements IRenderable, ITickable, Serializable { +public class GameObject implements IRenderable, ITickable, Serializable, ISceneReferent { private transient SceneGraph scene; private boolean created = false; @@ -41,26 +44,6 @@ public class GameObject implements IRenderable, ITickable, Serializable { return obj; } - @Override - public void render() {} - - @Override - public void renderAlpha() {} - - @Override - public void update(float dTime) {} - - // call order goes from top to bottom \/\/\/ - // ready is called before scene linkage, and serves to initialize - // values that may be needed before incoming requests. - protected void ready() {} - // connect is solely for ensuring links to other objects. get() and getAll() - protected void connect() {} - // create is guaranteed to only run once for an object, even after save/load - protected void create() {} - // start is called any time the object is added to a scene - protected void start() {} - public final void addedToScene() { connect(); if(!created) { @@ -94,19 +77,50 @@ public class GameObject implements IRenderable, ITickable, Serializable { return scene.getFPS(); } - protected void onAddGameObject(GameObjectCallback listener) { + protected final void onAddGameObject(GameObjectCallback listener) { scene.registerAddListener(listener); } - protected void onRemoveGameObject(GameObjectCallback listener) { + protected final void onRemoveGameObject(GameObjectCallback listener) { scene.registerRemoveListener(listener); } - protected Vector2i getBufferDimensions() { + protected final Vector2i getBufferDimensions() { return scene.getBufferDimensions(); } - protected void beforeRemoved() {} + private final Set removedListeners = new HashSet<>(); - protected void afterRemoved() {} + @Override + public final void onRemoved(GameObjectCallback listener) { + removedListeners.add(listener); + } + + protected final void finalized() { + for(var listener : removedListeners) { + listener.apply(this); + } + } + + protected void cleanup() {} + + @Override + public void render() {} + + @Override + public void renderAlpha() {} + + @Override + public void update(float dTime) {} + + // call order goes from top to bottom \/\/\/ + // ready is called before scene linkage, and serves to initialize + // values that may be needed before incoming requests. + protected void ready() {} + // connect is solely for ensuring links to other objects. get() and getAll() + protected void connect() {} + // create is guaranteed to only run once for an object, even after save/load + protected void create() {} + // start is called any time the object is added to a scene + protected void start() {} } diff --git a/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java b/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java index f807241..61a6fd2 100644 --- a/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java +++ b/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java @@ -23,9 +23,9 @@ import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab; import xyz.valnet.hadean.util.Pair; public abstract class SceneGraph implements IScene { - protected final List objects = new ArrayList(); - private final List newObjects = new ArrayList(); - private final List removeObjects = new ArrayList(); + private final Set objects = new HashSet(); + private final Set newObjects = new HashSet(); + private final Set removeObjects = new HashSet(); private IMouseCaptureArea hoveredMouseListener = null; @@ -159,7 +159,11 @@ public abstract class SceneGraph implements IScene { @Override public void enable(Game game) { this.game = game; - this.construct(); + Set scene = new HashSet(); + this.construct(scene); + + this.objects.clear(); + this.objects.addAll(scene); for(GameObject obj : objects) { addObjectToCache(obj); @@ -190,7 +194,7 @@ public abstract class SceneGraph implements IScene { } } - protected abstract void construct(); + protected abstract void construct(Set scene); @Override public void disable() { @@ -217,11 +221,11 @@ public abstract class SceneGraph implements IScene { public void remove(GameObject obj) { removeObjects.add(obj); - obj.beforeRemoved(); + obj.cleanup(); for(GameObjectCallback listener : onRemoveListeners) { listener.apply(obj); } - obj.afterRemoved(); + obj.finalized(); } public boolean inScene(GameObject gameObject) { diff --git a/src/main/java/xyz/valnet/engine/util/SceneReference.java b/src/main/java/xyz/valnet/engine/util/SceneReference.java new file mode 100644 index 0000000..aa3ff6c --- /dev/null +++ b/src/main/java/xyz/valnet/engine/util/SceneReference.java @@ -0,0 +1,21 @@ +package xyz.valnet.engine.util; + +import java.lang.ref.WeakReference; + +import xyz.valnet.engine.scenegraph.GameObject; +import xyz.valnet.hadean.interfaces.ISceneReferent; + +public class SceneReference extends WeakReference { + public SceneReference(T ref) { + super(ref); + ref.onRemoved((GameObject obj) -> { + this.clear(); + }); + } + + public String toString() { + var o = this.get(); + if(o == null) return ""; + return "[" + o.toString() + "]"; + } +} diff --git a/src/main/java/xyz/valnet/hadean/enums/WorkType.java b/src/main/java/xyz/valnet/hadean/enums/WorkType.java index ff67d22..e8ef8eb 100644 --- a/src/main/java/xyz/valnet/hadean/enums/WorkType.java +++ b/src/main/java/xyz/valnet/hadean/enums/WorkType.java @@ -1,13 +1,25 @@ package xyz.valnet.hadean.enums; +// TODO skills such as +// upper body strength +// lower body strength +// finess +// plant knowledge +// construction knowledge + +// for now, this isnt meant to be any of that. simply categories for turning work on and off for pawns. + public enum WorkType { - Construct("Construct"), - Farm("Till"), - Chop("Chop"); + Basic("basic", "Work on"), + Construct("building", "Construct"), + Farm("farming", "Till"), + Chop("felling", "Chop"); public final String verb; + public final String idString; - private WorkType(String verb) { + private WorkType(String idString, String verb) { + this.idString = idString; this.verb = verb; } } \ No newline at end of file diff --git a/src/main/java/xyz/valnet/hadean/functions/FCompleted.java b/src/main/java/xyz/valnet/hadean/functions/FCompleted.java new file mode 100644 index 0000000..444a8d3 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/functions/FCompleted.java @@ -0,0 +1,8 @@ +package xyz.valnet.hadean.functions; + +import java.io.Serializable; + +@FunctionalInterface +public interface FCompleted extends Serializable { + public void apply(); +} \ No newline at end of file diff --git a/src/main/java/xyz/valnet/hadean/functions/FGetPositions.java b/src/main/java/xyz/valnet/hadean/functions/FGetPositions.java new file mode 100644 index 0000000..4807e53 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/functions/FGetPositions.java @@ -0,0 +1,10 @@ +package xyz.valnet.hadean.functions; + +import java.io.Serializable; + +import xyz.valnet.engine.math.Vector2i; + +@FunctionalInterface +public interface FGetPositions extends Serializable { + public Vector2i[] get(); +} \ No newline at end of file diff --git a/src/main/java/xyz/valnet/hadean/functions/FProgressEvent.java b/src/main/java/xyz/valnet/hadean/functions/FProgressEvent.java new file mode 100644 index 0000000..eb6e95e --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/functions/FProgressEvent.java @@ -0,0 +1,8 @@ +package xyz.valnet.hadean.functions; + +import java.io.Serializable; + +@FunctionalInterface +public interface FProgressEvent extends Serializable { + public void progress(float progress); +} \ No newline at end of file diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java b/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java index 73a4cf8..fb7a39c 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java @@ -24,7 +24,7 @@ import static xyz.valnet.engine.util.Math.lerp; public class Camera extends GameObject implements ITransient, IMouseCaptureArea { - private int tileWidth = 32; + private int tileWidth = 16; private Vector2f focus = new Vector2f(0, 0); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/Job.java b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/Job.java index f70b4ca..41fa7c6 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/Job.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/Job.java @@ -1,41 +1,79 @@ package xyz.valnet.hadean.gameobjects.jobs; +import xyz.valnet.engine.math.Vector2i; +import xyz.valnet.engine.util.SceneReference; +import xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn.Pawn; import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; -import xyz.valnet.hadean.interfaces.IItemReceiver; +import xyz.valnet.hadean.interfaces.DItemRequest; +import xyz.valnet.hadean.interfaces.IDestination; import xyz.valnet.hadean.interfaces.IWorkable; -// TODO create a subtype of job for jobs with -// locations so pawn can generically path to it - public sealed interface Job { record Work( - IWorkable workable - ) implements Job { + SceneReference workable + ) implements Job, IDestination { @Override public String getShortDescription() { - return workable.getWorkType().verb + " " + workable.getWorkableName(); + return workable.get().getWorkType().verb + " " + workable.get().getWorkableName(); + } + + @Override + public boolean isValidForWorker(Pawn worker) { + var workable = this.workable().get(); + if(workable == null) return false; + if(workable.getWorkablePositions() == null) return false; + return true; + } + + public Vector2i[] getWorkablePositions() { + var workable = this.workable().get(); + if(workable == null) return new Vector2i[] {}; + return workable.getDestinations(); + } + + public void doWork(float dTime) { + var workable = this.workable().get(); + if(workable == null) return; + workable.doWork(dTime); + } + + @Override + public Vector2i[] getDestinations() { + var workable = this.workable().get(); + if(workable == null) return null; + return workable.getDestinations(); } } - record Haul( - Item item, - IItemReceiver rcvr + record ItemRequest( + SceneReference recvr ) implements Job { @Override public String getShortDescription() { - return "Haul " + item.getName() + " to " + rcvr.getName(); + return "Fulfilling " + recvr.get().getName() + " item Request"; + } + + @Override + public boolean isValidForWorker(Pawn worker) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'isValidForWorker'"); + } + } + + record HaulToStockpile( + SceneReference item + ) implements Job { + @Override + public String getShortDescription() { + return "Haul " + item.get().getName() + " to stockpile"; + } + + @Override + public boolean isValidForWorker(Pawn worker) { + return item.get() != null; } } public String getShortDescription(); - - // private JobBoard board; - - // public void connect(JobBoard board) { - // this.board = boaard; - // } - - // public void close() { - // board.close(this); - // } + public boolean isValidForWorker(Pawn worker); } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/JobBoard.java b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/JobBoard.java index f283784..91493cd 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/JobBoard.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/JobBoard.java @@ -1,34 +1,71 @@ package xyz.valnet.hadean.gameobjects.jobs; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import xyz.valnet.engine.scenegraph.GameObject; +import xyz.valnet.engine.util.SceneReference; import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab; import xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn.Pawn; +import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; +import xyz.valnet.hadean.interfaces.DItemRequest; import xyz.valnet.hadean.interfaces.IWorkable; public class JobBoard extends GameObject { private Set availableJobs = new HashSet(); - private List toRemove = new ArrayList(); - private Map allocations = new HashMap(); + // private Set toRemove = new HashSet(); + // private Map allocations = new HashMap(); - public Job postJob(Job job) { + public Job post(Job job) { availableJobs.add(job); return job; } public Job post(IWorkable workable) { - var job = new Job.Work(workable); - return postJob(job); + SceneReference ref = new SceneReference(workable); + var job = new Job.Work(ref); + return post(job); } + public Job post(Item item) { + var job = new Job.HaulToStockpile(item.asRef()); + return post(job); + } + + public Job post(DItemRequest request) { + var job = new Job.ItemRequest(request.asRef()); + return post(job); + } + + public void rescind(Job job) { + if(!availableJobs.contains(job)) return; + availableJobs.remove(job); + } + + + + // === migrate it may be idk + + public Job takeJob(Pawn worker) { + if(availableJobs.isEmpty()) return null; + + Job[] jobs = new Job[availableJobs.size()]; + availableJobs.toArray(jobs); + Job job = jobs[(int) (Math.floor(Math.random() * jobs.length))]; + + DebugTab.log("" + worker.getName() + " took job: " + job.getShortDescription()); + + // allocations.put(worker, job); + availableJobs.remove(job); + + return job; + } + + // ================= lawl old shit @@ -62,40 +99,40 @@ public class JobBoard extends GameObject { @Deprecated public String getTakenJobs() { - String str = ""; - for(Entry allocation : allocations.entrySet()) { - str += " " + allocation.getKey().getName() + ": " + allocation.getValue().getShortDescription() + "\n"; - } + String str = "Unknown for now, as jobboard does not track taken jobs."; + // for(Entry allocation : allocations.entrySet()) { + // str += " " + allocation.getKey().getName() + ": " + allocation.getValue().getShortDescription() + "\n"; + // } return str; } - public void close(Job job) { - if(allocations.values().contains(job)) { - Set workers = new HashSet<>(); - for(var entry : allocations.entrySet()) { - if(entry.getValue() == job) workers.add(entry.getKey()); - } - for(var worker : workers) { - worker.cancelJob(job); - } - } - } + // public void close(Job job) { + // if(allocations.values().contains(job)) { + // Set workers = new HashSet<>(); + // for(var entry : allocations.entrySet()) { + // if(entry.getValue() == job) workers.add(entry.getKey()); + // } + // for(var worker : workers) { + // worker.cancelJob(job); + // } + // } + // } - public class ENoJobsAvailable extends Error {} + // public class ENoJobsAvailable extends Error {} - public Job takeJob(Pawn worker) { - if(availableJobs.size() == 0) return null; + // public Job takeJob(Pawn worker) { + // if(availableJobs.size() == 0) return null; - Job[] jobs = new Job[availableJobs.size()]; - availableJobs.toArray(jobs); - Job job = jobs[(int) (Math.floor(Math.random() * jobs.length))]; + // Job[] jobs = new Job[availableJobs.size()]; + // availableJobs.toArray(jobs); + // Job job = jobs[(int) (Math.floor(Math.random() * jobs.length))]; - DebugTab.log("" + worker.getName() + " took job: " + job.getShortDescription()); + // DebugTab.log("" + worker.getName() + " took job: " + job.getShortDescription()); - allocations.put(worker, job); - availableJobs.remove(job); + // allocations.put(worker, job); + // availableJobs.remove(job); - return job; - } + // return job; + // } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/SimpleWorkable.java b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/SimpleWorkable.java deleted file mode 100644 index 152586a..0000000 --- a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/SimpleWorkable.java +++ /dev/null @@ -1,57 +0,0 @@ -package xyz.valnet.hadean.gameobjects.jobs; - -import java.io.Serializable; - -import xyz.valnet.engine.math.Vector2i; -import xyz.valnet.hadean.interfaces.IWorkable; - -public class SimpleWorkable implements IWorkable { - - private final String name; - private float work = 0; - private float MAX_WORK = 0; - private IProgressUpdateCallback callback; - private IGetPositionsFunction positions; - private final WorkType workType; - - @FunctionalInterface - public interface IGetPositionsFunction extends Serializable { - public Vector2i[] get(); - } - - @FunctionalInterface - public interface IProgressUpdateCallback extends Serializable { - public void progress(float progress); - } - - public SimpleWorkable(String name, float maxWork, WorkType type, IGetPositionsFunction positionsFunction, IProgressUpdateCallback callback) { - this.name = name; - this.MAX_WORK = maxWork; - this.positions = positionsFunction; - this.callback = callback; - this.workType = type; - } - - @Override - public boolean doWork(float dTime) { - work += dTime; - callback.progress(work / MAX_WORK); - return work >= MAX_WORK; - } - - @Override - public Vector2i[] getWorkablePositions() { - return positions.get(); - } - - @Override - public final String getWorkableName() { - return name; - } - - @Override - public WorkType getWorkType() { - return workType; - } - -} diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/WorkOrder.java b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/WorkOrder.java index b06b31e..879ee36 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/WorkOrder.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/WorkOrder.java @@ -7,7 +7,7 @@ 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.DItemRequest; import xyz.valnet.hadean.interfaces.IWorkshop; public class WorkOrder extends GameObject { @@ -72,29 +72,29 @@ public class WorkOrder extends GameObject { } 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 null; + // 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; - } + // 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; + // @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).post(job); + // return job; } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/Workable.java b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/Workable.java new file mode 100644 index 0000000..62d06a6 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/Workable.java @@ -0,0 +1,76 @@ +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.SceneGraph.GameObjectCallback; +import xyz.valnet.hadean.enums.WorkType; +import xyz.valnet.hadean.functions.FGetPositions; +import xyz.valnet.hadean.functions.FProgressEvent; +import xyz.valnet.hadean.functions.FCompleted; +import xyz.valnet.hadean.interfaces.ISceneReferent; +import xyz.valnet.hadean.interfaces.IWorkable; + +public class Workable implements IWorkable { + + private final String name; + private float work = 0; + private float MAX_WORK = 0; + private FProgressEvent progressCallback; + private FGetPositions positions; + private final WorkType workType; + private ISceneReferent linkedSceneObject; + private Set completedCallback = new HashSet<>(); + + public Workable(String name, float maxWork, WorkType type, FGetPositions positionsFunction, FProgressEvent progressCallback, ISceneReferent linkedSceneObject) { + this.name = name; + this.MAX_WORK = maxWork; + this.positions = positionsFunction; + this.progressCallback = progressCallback; + this.workType = type; + this.linkedSceneObject = linkedSceneObject; + } + + public void onCompleted(FCompleted cb) { + completedCallback.add(cb); + } + + private void finished() { + for(var cb : completedCallback) + cb.apply(); + } + + @Override + public boolean doWork(float dTime) { + if (work >= MAX_WORK) return true; + work += dTime; + progressCallback.progress(work / MAX_WORK); + if (work >= MAX_WORK) { + finished(); + return true; + } + return false; + } + + @Override + public Vector2i[] getWorkablePositions() { + return positions.get(); + } + + @Override + public final String getWorkableName() { + return name; + } + + @Override + public WorkType getWorkType() { + return workType; + } + + @Override + public void onRemoved(GameObjectCallback callback) { + linkedSceneObject.onRemoved(callback); + } + +} diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/jobs/WorkableBuilder.java b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/WorkableBuilder.java new file mode 100644 index 0000000..4669b7a --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/gameobjects/jobs/WorkableBuilder.java @@ -0,0 +1,74 @@ +package xyz.valnet.hadean.gameobjects.jobs; + +import xyz.valnet.engine.math.Vector2i; +import xyz.valnet.hadean.enums.WorkType; +import xyz.valnet.hadean.functions.FGetPositions; +import xyz.valnet.hadean.functions.FProgressEvent; +import xyz.valnet.hadean.functions.FCompleted; +import xyz.valnet.hadean.interfaces.ISceneReferent; + +public class WorkableBuilder { + private String name = "work area"; + private float maxWork = 1000; + private WorkType type = WorkType.Basic; + private FGetPositions getPositionsFunction; + private FProgressEvent progressUpdateCallback; + private FCompleted completed; + private ISceneReferent linked; + + public WorkableBuilder(ISceneReferent linked) { + this.linked = linked; + } + + public WorkableBuilder type(WorkType t) { + type = t; + return this; + } + + public WorkableBuilder work(float f) { + maxWork = f; + return this; + } + + public WorkableBuilder progress(FProgressEvent f) { + this.progressUpdateCallback = f; + return this; + } + + public WorkableBuilder name(String n) { + name = n; + return this; + } + + public WorkableBuilder positions(Vector2i[] poss) { + getPositionsFunction = () -> { + return poss; + }; + return this; + } + + public WorkableBuilder position(Vector2i pos) { + var arr = pos.asArray(); + getPositionsFunction = () -> { + return arr; + }; + return this; + } + + public WorkableBuilder positions(FGetPositions f) { + getPositionsFunction = f; + return this; + } + + public WorkableBuilder completed(FCompleted f) { + this.completed = f; + return this; + } + + public Workable build() { + var o = new Workable(name, maxWork, type, getPositionsFunction, progressUpdateCallback, linked); + o.onCompleted(completed); + return o; + } + +} \ No newline at end of file diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Terrain.java b/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Terrain.java index cae7936..fc9bb78 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Terrain.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Terrain.java @@ -11,7 +11,7 @@ import xyz.valnet.hadean.pathfinding.IPathable; public class Terrain extends GameObject implements IPathable, IWorldBoundsAdapter { - public static final int WORLD_SIZE = 24; + public static final int WORLD_SIZE = 48; public static final int TILE_SIZE = 8; // public static int left, top; diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Tile.java b/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Tile.java index 143e21a..71d22b5 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Tile.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/terrain/Tile.java @@ -8,6 +8,7 @@ import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.math.Vector4i; import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.hadean.HadeanGame; +import xyz.valnet.hadean.enums.WorkType; import xyz.valnet.hadean.gameobjects.worldobjects.Tree; import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject; import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder; diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/ui/BottomBar.java b/src/main/java/xyz/valnet/hadean/gameobjects/ui/BottomBar.java index 6d93415..e70956f 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/ui/BottomBar.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/ui/BottomBar.java @@ -8,6 +8,7 @@ import java.util.Map; import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.scenegraph.ITransient; +import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab; import xyz.valnet.hadean.input.Button; import xyz.valnet.hadean.input.IButtonListener; import xyz.valnet.hadean.input.SimpleButton; @@ -16,18 +17,11 @@ import xyz.valnet.hadean.util.Layers; public class BottomBar extends GameObject implements IButtonListener, ITransient { public static final int bottomBarHeight = 32; - private int screenWidth = 1024; private Map btnItemTable = new HashMap(); private List items = new ArrayList(); - @Override - public void start() { - items.clear(); - clearButtons(); - } - public void registerButton(IBottomBarItem newItem) { Vector2i screen = getBufferDimensions(); clearButtons(); @@ -41,6 +35,7 @@ public class BottomBar extends GameObject implements IButtonListener, ITransient int w = r - l; Button btn = new SimpleButton(item.getTabName(), l, screen.y - bottomBarHeight, w, bottomBarHeight, Layers.BOTTOM_BAR); + // Button btn = new SimpleButton(item.getTabName(), 100 * i, 100, 100, 100, Layers.BOTTOM_BAR); if(item.isButtonClickSilent()) btn = btn.setClickSound(false); btn.registerClickListener(this); add(btn); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/ui/SelectionUI.java b/src/main/java/xyz/valnet/hadean/gameobjects/ui/SelectionUI.java index 1a67cec..612ca5d 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/ui/SelectionUI.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/ui/SelectionUI.java @@ -79,7 +79,6 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener updateActionsFlag = false; for(ISelectable selectable : selected) { for(Action action : selectable.getActions()) { - DebugTab.log(action.name); actions.add(action); } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Tree.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Tree.java index f090e7c..2e5e719 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Tree.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Tree.java @@ -58,7 +58,7 @@ public class Tree extends WorldObject implements ISelectable, IWorkable { if(chopJob == null) { chopJob = get(JobBoard.class).post(this); } else { - get(JobBoard.class).close(chopJob); + get(JobBoard.class).rescind(chopJob); chopJob = null; } } @@ -111,8 +111,8 @@ public class Tree extends WorldObject implements ISelectable, IWorkable { } @Override - protected void beforeRemoved() { - super.beforeRemoved(); + protected void cleanup() { + super.cleanup(); Vector2i pos = getWorldPosition().xy(); add(new Log(pos.x, pos.y)); } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java index db7687e..a01a47d 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java @@ -129,7 +129,7 @@ public abstract class WorldObject extends GameObject implements IWorldObject { } @Override - protected void beforeRemoved() { + protected void cleanup() { for(Tile tile : this.getTiles()) { tile.removeThing(this); } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java index 28490c6..815cdcb 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java @@ -16,7 +16,7 @@ import xyz.valnet.engine.shaders.SimpleShader; import xyz.valnet.hadean.HadeanGame; import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab; import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject; -import xyz.valnet.hadean.interfaces.IDestinationProvider; +import xyz.valnet.hadean.interfaces.IDestination; import xyz.valnet.hadean.interfaces.ISelectable; import xyz.valnet.hadean.pathfinding.AStarPathfinder; import xyz.valnet.hadean.pathfinding.IPathfinder; @@ -100,14 +100,14 @@ public abstract class Agent extends WorldObject implements ISelectable { } private Path path; - private IDestinationProvider dsts; + private IDestination dsts; public void stopPathing() { path = null; dsts = null; } - public boolean goTo(IDestinationProvider location) { + public boolean goTo(IDestination location) { if(isAnimating()) { stopPathing(); dsts = location; @@ -133,7 +133,7 @@ public abstract class Agent extends WorldObject implements ISelectable { } while (terrain.isOutOfBounds(random.x, random.y)); - goTo(new IDestinationProvider.SingleDestination(random)); + goTo(new IDestination.Single(random)); } @Override @@ -212,6 +212,10 @@ public abstract class Agent extends WorldObject implements ISelectable { protected abstract void idle(float dTime); + protected boolean isPathing() { + return dsts != null; + } + public Vector2f getCalculatedPosition() { if(!isAnimating()) return getWorldPosition().xy().asFloat(); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/pawn/Pawn.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/pawn/Pawn.java index bda037e..752fe9b 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/pawn/Pawn.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/pawn/Pawn.java @@ -11,14 +11,16 @@ import xyz.valnet.engine.util.Names; import xyz.valnet.hadean.HadeanGame; import xyz.valnet.hadean.gameobjects.jobs.Job; import xyz.valnet.hadean.gameobjects.jobs.JobBoard; -import xyz.valnet.hadean.gameobjects.jobs.JobBoard.ENoJobsAvailable; import xyz.valnet.hadean.gameobjects.terrain.Terrain; import xyz.valnet.hadean.gameobjects.worldobjects.agents.Agent; import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; 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; public class Pawn extends Agent { @@ -29,23 +31,28 @@ public class Pawn extends Agent { private Job currentJob = null; private void doWorkJob(Job.Work workJob, float dTime) { - if(!this.getWorldPosition().xy().isOneOf(workJob.workable().getDestinations())) { - if(goTo(workJob.workable())) { + if(!this.getWorldPosition().xy().isOneOf(workJob.getWorkablePositions())) { + if(goTo(workJob)) { return; } else { cancelJob(currentJob); } } - workJob.workable().doWork(dTime); + workJob.doWork(dTime); } - private void doHaulJob(Job.Haul haulJob, float dTime) { - + private void doHaulToStockpileJob(Job.HaulToStockpile haulJob, float dTime) { + if(inventory.contains(haulJob.item().get())) } private void doJob(float dTime) { - if(currentJob instanceof Job.Haul haul) { - doHaulJob(haul, dTime); + if(!currentJob.isValidForWorker(this)) { + get(JobBoard.class).post(currentJob); + currentJob = null; + return; + } + if(currentJob instanceof Job.HaulToStockpile haul) { + doHaulToStockpileJob(haul, dTime); } else if (currentJob instanceof Job.Work work) { doWorkJob(work, dTime); } @@ -99,7 +106,15 @@ public class Pawn extends Agent { @Override public Detail[] getDetails() { - return new Detail[] {}; + // return needs.getDetails(); + Detail[] details = new Detail[] { + // new ObjectDetail("Activity", currentActivity), + new BooleanDetail("Pathing", isPathing()), + new ObjectDetail("Job", currentJob == null ? "null" : currentJob.toString()), + new ObjectDetail("Inventory", inventory.size()) + }; + + return details; } @Override diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Construction.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Construction.java index cb82c98..e6c1029 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Construction.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Construction.java @@ -6,13 +6,14 @@ import java.util.List; import xyz.valnet.engine.graphics.Color; import xyz.valnet.engine.graphics.Sprite; import xyz.valnet.engine.math.Vector2i; +import xyz.valnet.engine.scenegraph.SceneGraph.GameObjectCallback; import xyz.valnet.hadean.enums.BuildType; import xyz.valnet.hadean.gameobjects.jobs.Job; import xyz.valnet.hadean.gameobjects.jobs.JobBoard; import xyz.valnet.hadean.gameobjects.worldobjects.Buildable; import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; import xyz.valnet.hadean.interfaces.IItemPredicate; -import xyz.valnet.hadean.interfaces.IItemReceiver; +import xyz.valnet.hadean.interfaces.DItemRequest; import xyz.valnet.hadean.interfaces.IWorkable; import xyz.valnet.hadean.util.Action; import xyz.valnet.hadean.util.Assets; @@ -31,32 +32,64 @@ public abstract class Construction extends Buildable { return containedItems.size() >= getBuildingMaterialCount(); } + private void onItem(Item item) { + containedItems.add(item); + postNextJob(); + } + private void postNextJob() { if(!isBuildingMaterialSatisfied()) { - Job job = get(JobBoard.class).postSimpleItemRequirementJob( - "Haul items to building", - getBuildingMaterial(), - 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; - } + var itemRequest = new DItemRequest(this, "Haul items to building") + .accepts(getBuildingMaterial()) + .positions(getSelectionWorldBox().getBorders()) + .handleItem((item) -> onItem(item)); + + var job = get(JobBoard.class).post(itemRequest); + // TODO -> job.onCompleted(postNextJob();) + + // Job job = get(JobBoard.class).postSimpleItemRequirementJob( + // "Haul items to building", + // getBuildingMaterial(), + // new DItemRequest() { + + // @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 getSelectionWorldBox().getBorders(); - } + // @Override + // public Vector2i[] getItemDropoffLocations() { + // return getSelectionWorldBox().getBorders(); + // } + + // @Override + // public void onRemoved(GameObjectCallback callback) { + // // TODO Auto-generated method stub + // throw new UnsupportedOperationException("Unimplemented method 'onRemoved'"); + // } + + // @Override + // public String getName() { + // // TODO Auto-generated method stub + // throw new UnsupportedOperationException("Unimplemented method 'getName'"); + // } + + // @Override + // public IItemPredicate acceptedItems() { + // // TODO Auto-generated method stub + // throw new UnsupportedOperationException("Unimplemented method 'acceptedItems'"); + // } - } - ); - job.registerClosedListener(() -> { - postNextJob(); - }); + // } + // ); + // job.registerClosedListener(() -> { + // postNextJob(); + // }); return; } if(!isBuilt()) { diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Quarry.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Quarry.java index 884d0c8..6d5ce1e 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Quarry.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Quarry.java @@ -4,7 +4,7 @@ import xyz.valnet.engine.graphics.Sprite; import xyz.valnet.engine.math.Vector2i; import xyz.valnet.hadean.gameobjects.jobs.Job; import xyz.valnet.hadean.gameobjects.jobs.JobBoard; -import xyz.valnet.hadean.gameobjects.jobs.SimpleWorkable; +import xyz.valnet.hadean.gameobjects.jobs.WorkableBuilder; import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder; import xyz.valnet.hadean.interfaces.IItemPredicate; import xyz.valnet.hadean.util.Assets; @@ -25,22 +25,39 @@ public class Quarry extends Construction { if (digJob != null) return; if (terrain.getTile(getWorldPosition().xy().south().east()).has(Boulder.class)) return; - digJob = get(JobBoard.class).post(new SimpleWorkable("Mine at Quarry", 5000, () -> { - return new Vector2i[] { - getWorldPosition().xy().south().east() - }; - }, (progress) -> { - digProgress = progress; - })); + var workable = new WorkableBuilder(this) + .name("Quarry") + .position(getWorldPosition().xy().south().east()) + .work(5000) + .progress((p) -> digProgress = p) + .completed(() -> { + digProgress = 0; + Vector2i dropPos = getWorldPosition().xy().south().east(); + Boulder boulder = new Boulder(dropPos.x, dropPos.y); + add(boulder); + boulder.runAction(Boulder.HAUL); + digJob = null; + }) + .build(); - digJob.registerClosedListener(() -> { - digProgress = 0; - Vector2i dropPos = getWorldPosition().xy().south().east(); - Boulder boulder = new Boulder(dropPos.x, dropPos.y); - add(boulder); - boulder.runAction(Boulder.HAUL); - digJob = null; - }); + digJob = get(JobBoard.class).post(workable); + + // digJob = get(JobBoard.class).post(new SimpleWorkable("Mine at Quarry", 5000, () -> { + // return new Vector2i[] { + // getWorldPosition().xy().south().east() + // }; + // }, (progress) -> { + // digProgress = progress; + // })); + + // digJob.registerClosedListener(() -> { + // digProgress = 0; + // Vector2i dropPos = getWorldPosition().xy().south().east(); + // Boulder boulder = new Boulder(dropPos.x, dropPos.y); + // add(boulder); + // boulder.runAction(Boulder.HAUL); + // digJob = null; + // }); } @Override @@ -79,7 +96,7 @@ public class Quarry extends Construction { super.render(); if(!isBuilt()) return; - if(digJob != null && !digJob.isCompleted() && digProgress > 0) { + if(digJob != null && digProgress > 0) { camera.drawProgressBar(digProgress, getSelectionWorldBox()); } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java index 3753029..508d7e6 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java @@ -8,7 +8,17 @@ import xyz.valnet.hadean.util.detail.Detail; public class Boulder extends Item { - public static IItemPredicate BOULDER_PREDICATE = (item) -> (item instanceof Boulder); + public static IItemPredicate BOULDER_PREDICATE = new IItemPredicate() { + @Override + public String getName() { + return "Boulder"; + } + + @Override + public boolean matches(Item item) { + return item instanceof Boulder; + } + }; public Boulder(int x, int y) { setPosition(x, y); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Item.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Item.java index f35540d..283d8a9 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Item.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Item.java @@ -2,20 +2,26 @@ package xyz.valnet.hadean.gameobjects.worldobjects.items; import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.math.Vector4i; +import xyz.valnet.engine.util.SceneReference; import xyz.valnet.hadean.gameobjects.jobs.Job; import xyz.valnet.hadean.gameobjects.jobs.JobBoard; import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject; import xyz.valnet.hadean.interfaces.IItemPredicate; +import xyz.valnet.hadean.interfaces.ISceneReferent; import xyz.valnet.hadean.interfaces.ISelectable; import xyz.valnet.hadean.util.Action; import xyz.valnet.hadean.util.Assets; import xyz.valnet.hadean.util.Layers; -public abstract class Item extends WorldObject implements ISelectable { +public abstract class Item extends WorldObject implements ISelectable, ISceneReferent { protected JobBoard jobboard; private Job haulJob = null; + public final SceneReference asRef() { + return new SceneReference(this); + } + @Override protected void connect() { super.connect(); @@ -67,19 +73,14 @@ public abstract class Item extends WorldObject implements ISelectable { private void cancelHaul() { if(haulJob == null) return; - haulJob.close(); + jobboard.rescind(haulJob); haulJob = null; } private void markForHaul() { if(haulJob != null) return; - haulJob = add(new Job("Haul " + this.getName())); - haulJob.addStep(haulJob.new PickupItem(this)); - haulJob.addStep(haulJob.new DropoffAtStockpile(this)); - haulJob.registerClosedListener(() -> { - haulJob = null; - }); - jobboard.postJob(haulJob); + var j = new Job.HaulToStockpile(asRef()); + jobboard.post(j); } public void destroy() { @@ -105,4 +106,8 @@ public abstract class Item extends WorldObject implements ISelectable { public void setPosition(int x, int y, int w, int h) { super.setPosition(x, y, w, h); } + + public String toString() { + return getGenericName(); + } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Log.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Log.java index e36f4cd..371a6bb 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Log.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Log.java @@ -13,7 +13,19 @@ import xyz.valnet.hadean.util.detail.Detail; // when placed in a non stockpile, not just on create. public class Log extends Item { - public static IItemPredicate LOG_PREDICATE = (item) -> (item instanceof Log); + public static IItemPredicate LOG_PREDICATE = new IItemPredicate() { + + @Override + public boolean matches(Item item) { + return item instanceof Log; + } + + @Override + public String getName() { + return "Any Log"; + } + + }; public Log(int x, int y) { setPosition(x, y); diff --git a/src/main/java/xyz/valnet/hadean/interfaces/DItemRequest.java b/src/main/java/xyz/valnet/hadean/interfaces/DItemRequest.java new file mode 100644 index 0000000..c697f72 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/interfaces/DItemRequest.java @@ -0,0 +1,92 @@ +package xyz.valnet.hadean.interfaces; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +import xyz.valnet.engine.math.Vector2i; +import xyz.valnet.engine.scenegraph.SceneGraph.GameObjectCallback; +import xyz.valnet.engine.util.SceneReference; +import xyz.valnet.hadean.functions.FGetPositions; +import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; + +public class DItemRequest implements ISceneReferent, Serializable { + + @FunctionalInterface + public interface FItemHandler { + public void give(Item item); + } + + private ISceneReferent linked; + private String name = "Default Request Name"; + private IItemPredicate acceptedItems = IItemPredicate.NONE; + private FItemHandler itemHandler; + private FGetPositions positionsFn = () -> new Vector2i[] {}; + + public DItemRequest(ISceneReferent linked, String name) { + this.linked = linked; + } + + // === fluent API + + public DItemRequest accepts(IItemPredicate accepts) { + acceptedItems = accepts; + return this; + } + + public DItemRequest handleItem(FItemHandler handler) { + itemHandler = handler; + return this; + } + + public DItemRequest positions(Vector2i[] poss) { + positionsFn = () -> { + return poss; + }; + return this; + } + + public DItemRequest position(Vector2i pos) { + var arr = pos.asArray(); + positionsFn = () -> { + return arr; + }; + return this; + } + + public DItemRequest positions(FGetPositions f) { + positionsFn = f; + return this; + } + + + + // === public API + + public Vector2i[] getLocations() { + return positionsFn.get(); + } + + public final boolean accepts(Item i) { + return acceptedItems.matches(i); + } + + public void give(Item item) { + if(!accepts(item)) throw new Error("Unaccepted Item given to receiver!"); + itemHandler.give(item); + item.destroy(); + } + + @Override + public void onRemoved(GameObjectCallback callback) { + linked.onRemoved(callback); + } + + public String getName() { + return name; + } + + public SceneReference asRef() { + return new SceneReference(this); + } +} diff --git a/src/main/java/xyz/valnet/hadean/interfaces/IDestination.java b/src/main/java/xyz/valnet/hadean/interfaces/IDestination.java new file mode 100644 index 0000000..38b5131 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/interfaces/IDestination.java @@ -0,0 +1,21 @@ +package xyz.valnet.hadean.interfaces; + +import xyz.valnet.engine.math.Vector2i; + +public interface IDestination { + public Vector2i[] getDestinations(); + + record Single(Vector2i dst) implements IDestination { + @Override + public Vector2i[] getDestinations() { + return new Vector2i[] { dst }; + } + } + + record Many(Vector2i[] dsts) implements IDestination { + @Override + public Vector2i[] getDestinations() { + return dsts; + } + } +} diff --git a/src/main/java/xyz/valnet/hadean/interfaces/IDestinationProvider.java b/src/main/java/xyz/valnet/hadean/interfaces/IDestinationProvider.java deleted file mode 100644 index 58d22f3..0000000 --- a/src/main/java/xyz/valnet/hadean/interfaces/IDestinationProvider.java +++ /dev/null @@ -1,16 +0,0 @@ -package xyz.valnet.hadean.interfaces; - -import xyz.valnet.engine.math.Vector2i; - -public interface IDestinationProvider { - public Vector2i[] getDestinations(); - - record SingleDestination(Vector2i dst) implements IDestinationProvider { - - @Override - public Vector2i[] getDestinations() { - return new Vector2i[] { dst }; - } - - } -} diff --git a/src/main/java/xyz/valnet/hadean/interfaces/IItemPredicate.java b/src/main/java/xyz/valnet/hadean/interfaces/IItemPredicate.java index 985c4b7..07f17bd 100644 --- a/src/main/java/xyz/valnet/hadean/interfaces/IItemPredicate.java +++ b/src/main/java/xyz/valnet/hadean/interfaces/IItemPredicate.java @@ -4,7 +4,20 @@ import java.io.Serializable; import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; -@FunctionalInterface public interface IItemPredicate extends Serializable { public boolean matches(Item item); + public String getName(); + + public static IItemPredicate NONE = new IItemPredicate() { + + @Override + public boolean matches(Item item) { + return false; + } + + @Override + public String getName() { + return "Nothing"; + } + }; } diff --git a/src/main/java/xyz/valnet/hadean/interfaces/IItemReceiver.java b/src/main/java/xyz/valnet/hadean/interfaces/IItemReceiver.java deleted file mode 100644 index 775edc4..0000000 --- a/src/main/java/xyz/valnet/hadean/interfaces/IItemReceiver.java +++ /dev/null @@ -1,20 +0,0 @@ -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(); - public String getName(); - - public default boolean give(Item item) { - if(receive(item)) { - item.destroy(); - return true; - } - return false; - } -} diff --git a/src/main/java/xyz/valnet/hadean/interfaces/ISceneReferent.java b/src/main/java/xyz/valnet/hadean/interfaces/ISceneReferent.java new file mode 100644 index 0000000..c7aadc0 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/interfaces/ISceneReferent.java @@ -0,0 +1,7 @@ +package xyz.valnet.hadean.interfaces; + +import xyz.valnet.engine.scenegraph.SceneGraph.GameObjectCallback; + +public interface ISceneReferent { + public void onRemoved(GameObjectCallback callback); +} diff --git a/src/main/java/xyz/valnet/hadean/interfaces/IWorkable.java b/src/main/java/xyz/valnet/hadean/interfaces/IWorkable.java index 81f3fe6..86a9960 100644 --- a/src/main/java/xyz/valnet/hadean/interfaces/IWorkable.java +++ b/src/main/java/xyz/valnet/hadean/interfaces/IWorkable.java @@ -3,9 +3,10 @@ package xyz.valnet.hadean.interfaces; import java.io.Serializable; import xyz.valnet.engine.math.Vector2i; +import xyz.valnet.engine.util.SceneReference; import xyz.valnet.hadean.enums.WorkType; -public interface IWorkable extends Serializable, IDestinationProvider { +public interface IWorkable extends Serializable, IDestination, ISceneReferent { public WorkType getWorkType(); public boolean doWork(float dTime); public Vector2i[] getWorkablePositions(); @@ -16,4 +17,7 @@ public interface IWorkable extends Serializable, IDestinationProvider { return getWorkablePositions(); } + public default SceneReference asRef() { + return new SceneReference<>(this); + } } diff --git a/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java b/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java index 1c81765..00a8f22 100644 --- a/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java +++ b/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java @@ -7,7 +7,7 @@ import java.util.List; import java.util.Stack; import xyz.valnet.engine.math.Vector2i; -import xyz.valnet.hadean.interfaces.IDestinationProvider; +import xyz.valnet.hadean.interfaces.IDestination; public class AStarPathfinder implements IPathfinder, Serializable { @@ -163,7 +163,7 @@ public class AStarPathfinder implements IPathfinder, Serializable { } @Override - public Path getBestPath(Vector2i src, IDestinationProvider provider) { + public Path getBestPath(Vector2i src, IDestination provider) { var dsts = provider.getDestinations(); diff --git a/src/main/java/xyz/valnet/hadean/pathfinding/IPathfinder.java b/src/main/java/xyz/valnet/hadean/pathfinding/IPathfinder.java index 5707e25..501f158 100644 --- a/src/main/java/xyz/valnet/hadean/pathfinding/IPathfinder.java +++ b/src/main/java/xyz/valnet/hadean/pathfinding/IPathfinder.java @@ -1,7 +1,7 @@ package xyz.valnet.hadean.pathfinding; import xyz.valnet.engine.math.Vector2i; -import xyz.valnet.hadean.interfaces.IDestinationProvider; +import xyz.valnet.hadean.interfaces.IDestination; public interface IPathfinder { public Path getPath(int x1, int y1, int x2, int y2); @@ -14,5 +14,5 @@ public interface IPathfinder { public default Path getPath(Vector2i u, Vector2i v) { return getPath(u.x, u.y, v.x, v.y); } - public Path getBestPath(Vector2i src, IDestinationProvider dsts); + public Path getBestPath(Vector2i src, IDestination dsts); } diff --git a/src/main/java/xyz/valnet/hadean/scenes/GameScene.java b/src/main/java/xyz/valnet/hadean/scenes/GameScene.java index 86b48d4..3ad11e9 100644 --- a/src/main/java/xyz/valnet/hadean/scenes/GameScene.java +++ b/src/main/java/xyz/valnet/hadean/scenes/GameScene.java @@ -1,5 +1,8 @@ package xyz.valnet.hadean.scenes; +import java.util.Set; + +import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.scenegraph.SceneGraph; import xyz.valnet.engine.util.Names; import xyz.valnet.hadean.gameobjects.ui.BottomBar; @@ -32,37 +35,34 @@ import xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn.Pawn; public class GameScene extends SceneGraph { @Override - protected void construct() { + protected void construct(Set scene) { Names.loadNames(); - objects.add(new Terrain()); - objects.add(new Camera()); - objects.add(new JobBoard()); - objects.add(new Clock()); + scene.add(new Terrain()); + scene.add(new Camera()); + scene.add(new JobBoard()); + scene.add(new Clock()); for(int i = 0; i < 1; i ++) { - objects.add(new Pawn()); + scene.add(new Pawn()); } - objects.add(new WorkOrderManager()); - objects.add(new ExclusivityManager()); + scene.add(new WorkOrderManager()); + scene.add(new ExclusivityManager()); - objects.add(new SelectionLayer()); - objects.add(new BuildLayer()); + scene.add(new SelectionLayer()); + scene.add(new BuildLayer()); - objects.add(new WorkshopOrdersUI()); - objects.add(new SelectionUI()); + scene.add(new WorkshopOrdersUI()); + scene.add(new SelectionUI()); - objects.add(new HoverQuery()); + scene.add(new HoverQuery()); - objects.add(new BottomBar()); - objects.add(new BuildTab()); - objects.add(new JobBoardTab()); - objects.add(new DebugTab()); - objects.add(new MenuTab()); - - // objects.add(new Popup()); - + scene.add(new BottomBar()); + scene.add(new BuildTab()); + scene.add(new JobBoardTab()); + scene.add(new DebugTab()); + scene.add(new MenuTab()); } }