Compare commits
8 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
fd64b53d6c | |
|
|
f2f46acbb5 | |
|
|
496ecd9796 | |
|
|
4bf7a092aa | |
|
|
dd775f6d9c | |
|
|
634f48d941 | |
|
|
7afa863ee8 | |
|
|
10d86c45ab |
10
pom.xml
10
pom.xml
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.source>16</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
<maven.compiler.target>16</maven.compiler.target>
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
<lwjgl.version>3.3.1</lwjgl.version>
|
<lwjgl.version>3.3.1</lwjgl.version>
|
||||||
<jar.finalName>${project.name}</jar.finalName>
|
<jar.finalName>${project.name}</jar.finalName>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
@ -143,6 +143,7 @@
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<outputDirectory>output/${platform.name}/raw</outputDirectory>
|
<outputDirectory>output/${platform.name}/raw</outputDirectory>
|
||||||
|
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
<addClasspath>true</addClasspath>
|
<addClasspath>true</addClasspath>
|
||||||
|
|
@ -207,7 +208,10 @@
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.8.0</version>
|
<version>3.10.1</version>
|
||||||
|
<configuration>
|
||||||
|
<enablePreview>true</enablePreview>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-install-plugin</artifactId>
|
<artifactId>maven-install-plugin</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,11 @@ attribute vec2 TexCoord;
|
||||||
//"out" varyings to our fragment shader
|
//"out" varyings to our fragment shader
|
||||||
varying vec4 vColor;
|
varying vec4 vColor;
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
|
varying float vDepth;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vColor = uColor;
|
vColor = uColor;
|
||||||
vTexCoord = TexCoord;
|
vTexCoord = TexCoord;
|
||||||
gl_Position = uProjection * vec4(Position, 1.0);
|
gl_Position = uProjection * vec4(Position, 1.0);
|
||||||
|
vDepth = Position.z;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
//SpriteBatch will use texture unit 0
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
|
||||||
|
//"in" varyings from our vertex shader
|
||||||
|
varying vec4 vColor;
|
||||||
|
varying vec2 vTexCoord;
|
||||||
|
varying float vDepth;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 texColor = texture2D(u_texture, vTexCoord);
|
||||||
|
if(texColor == vec4(1, 0, 1, 1) || texColor == vec4(1, 0, 0, 1) || texColor.w == 0.0) {
|
||||||
|
discard;
|
||||||
|
} else {
|
||||||
|
gl_FragColor = texColor * vColor;
|
||||||
|
gl_FragColor = vec4(vDepth / 20.0, vDepth / 20.0, vDepth / 20.0, gl_FragColor.w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ uniform sampler2D u_texture;
|
||||||
//"in" varyings from our vertex shader
|
//"in" varyings from our vertex shader
|
||||||
varying vec4 vColor;
|
varying vec4 vColor;
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
|
varying float vDepth;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 texColor = texture2D(u_texture, vTexCoord);
|
vec4 texColor = texture2D(u_texture, vTexCoord);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import static org.lwjgl.system.MemoryUtil.*;
|
||||||
|
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.PointerBuffer;
|
||||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||||
import org.lwjgl.glfw.GLFWVidMode;
|
import org.lwjgl.glfw.GLFWVidMode;
|
||||||
import org.lwjgl.openal.AL;
|
import org.lwjgl.openal.AL;
|
||||||
|
|
@ -25,7 +26,8 @@ public class App {
|
||||||
|
|
||||||
// The window handle
|
// The window handle
|
||||||
private long window;
|
private long window;
|
||||||
private int width = 1024, height = 576;
|
// private int width = 1024, height = 576;
|
||||||
|
private int width = 1600, height = 900;
|
||||||
private Matrix4f matrix = Matrix4f.orthographic(0, width, height, 0, 0, 100);
|
private Matrix4f matrix = Matrix4f.orthographic(0, width, height, 0, 0, 100);
|
||||||
public static int mouseX, mouseY;
|
public static int mouseX, mouseY;
|
||||||
|
|
||||||
|
|
@ -69,7 +71,7 @@ public class App {
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // the window will be resizable
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // the window will be resizable
|
||||||
|
|
||||||
// Create the window
|
// Create the window
|
||||||
window = glfwCreateWindow(width, height, "Hello World!", NULL, NULL);
|
window = glfwCreateWindow(width, height, "Val Engine", NULL, NULL);
|
||||||
if ( window == NULL )
|
if ( window == NULL )
|
||||||
throw new RuntimeException("Failed to create the GLFW window");
|
throw new RuntimeException("Failed to create the GLFW window");
|
||||||
|
|
||||||
|
|
@ -94,11 +96,6 @@ public class App {
|
||||||
game.scrollUp();
|
game.scrollUp();
|
||||||
else if(yOffset < 0)
|
else if(yOffset < 0)
|
||||||
game.scrollDown();
|
game.scrollDown();
|
||||||
|
|
||||||
// if(yOffset > 0)
|
|
||||||
// game.scrollLeft();
|
|
||||||
// else if(yOffset < 0)
|
|
||||||
// game.scrollRight();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
glfwSetMouseButtonCallback(window, (long window, int button, int action, int mods) -> {
|
glfwSetMouseButtonCallback(window, (long window, int button, int action, int mods) -> {
|
||||||
|
|
@ -125,6 +122,8 @@ public class App {
|
||||||
|
|
||||||
// Get the resolution of the primary monitor
|
// Get the resolution of the primary monitor
|
||||||
long primaryMonitor = glfwGetPrimaryMonitor();
|
long primaryMonitor = glfwGetPrimaryMonitor();
|
||||||
|
PointerBuffer monitors = glfwGetMonitors();
|
||||||
|
primaryMonitor = monitors.get(0);
|
||||||
GLFWVidMode vidmode = glfwGetVideoMode(primaryMonitor);
|
GLFWVidMode vidmode = glfwGetVideoMode(primaryMonitor);
|
||||||
IntBuffer monitorX = stack.mallocInt(1); // int*
|
IntBuffer monitorX = stack.mallocInt(1); // int*
|
||||||
IntBuffer monitorY = stack.mallocInt(1); // int*
|
IntBuffer monitorY = stack.mallocInt(1); // int*
|
||||||
|
|
@ -179,7 +178,7 @@ public class App {
|
||||||
glDepthMask(true);
|
glDepthMask(true);
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
|
game.resize(width, height);
|
||||||
game.start();
|
game.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ package xyz.valnet.engine;
|
||||||
|
|
||||||
import static xyz.valnet.engine.util.Math.lerp;
|
import static xyz.valnet.engine.util.Math.lerp;
|
||||||
|
|
||||||
|
import xyz.valnet.engine.graphics.Drawing;
|
||||||
import xyz.valnet.engine.math.Matrix4f;
|
import xyz.valnet.engine.math.Matrix4f;
|
||||||
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.scenegraph.IScene;
|
import xyz.valnet.engine.scenegraph.IScene;
|
||||||
|
|
||||||
public abstract class Game {
|
public abstract class Game {
|
||||||
|
|
@ -14,6 +16,8 @@ public abstract class Game {
|
||||||
private int framesSinceKeyframe = 0;
|
private int framesSinceKeyframe = 0;
|
||||||
private long lastFrame = System.nanoTime();
|
private long lastFrame = System.nanoTime();
|
||||||
private long lastKeyframe = System.nanoTime();
|
private long lastKeyframe = System.nanoTime();
|
||||||
|
|
||||||
|
private Vector2i bufferDimensions = new Vector2i(0, 0);
|
||||||
|
|
||||||
public abstract void start();
|
public abstract void start();
|
||||||
|
|
||||||
|
|
@ -26,6 +30,7 @@ public abstract class Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render() {
|
public void render() {
|
||||||
|
Drawing.setLayer(0);
|
||||||
scene.render();
|
scene.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,4 +93,12 @@ public abstract class Game {
|
||||||
public final void keyRepeat(int key) {
|
public final void keyRepeat(int key) {
|
||||||
scene.keyRepeat(key);
|
scene.keyRepeat(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2i getBufferDimensions() {
|
||||||
|
return bufferDimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resize(int width, int height) {
|
||||||
|
bufferDimensions = new Vector2i(width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ public class Drawing {
|
||||||
public static void drawSprite(Sprite sprite, int x, int y, int width, int height) {
|
public static void drawSprite(Sprite sprite, int x, int y, int width, int height) {
|
||||||
// lazy texture binding
|
// lazy texture binding
|
||||||
if(bound != sprite.atlas) {
|
if(bound != sprite.atlas) {
|
||||||
if(bound != null) bound.unbind();
|
if(bound != null) bound.unbind();
|
||||||
sprite.atlas.bind();
|
sprite.atlas.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,9 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
|
||||||
private boolean mouseDown;
|
private boolean mouseDown;
|
||||||
|
|
||||||
public void render() {
|
public void render() {
|
||||||
|
Vector2i screenSize = getBufferDimensions();
|
||||||
begin();
|
begin();
|
||||||
gui();
|
gui(screenSize.x, screenSize.y);
|
||||||
end();
|
end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,7 +56,7 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
|
||||||
return Layers.GENERAL_UI_INTERACTABLE;
|
return Layers.GENERAL_UI_INTERACTABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void gui();
|
protected abstract void gui(int screenWidth, int screenHeight);
|
||||||
|
|
||||||
private record StackingContext(
|
private record StackingContext(
|
||||||
boolean fixedSize,
|
boolean fixedSize,
|
||||||
|
|
@ -403,6 +404,21 @@ public abstract class ImmediateUI extends GameObject implements IMouseCaptureAre
|
||||||
adjustBox(1, space);
|
adjustBox(1, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void space(int space, int space2) {
|
||||||
|
if(context.horizontal) {
|
||||||
|
adjustBox(space, 1);
|
||||||
|
vertical(() -> {
|
||||||
|
space(space2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
adjustBox(1, space);
|
||||||
|
horizontal(() -> {
|
||||||
|
space(space2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void end() {
|
protected void end() {
|
||||||
|
|
||||||
List<String> buttonIdsToRemove = new ArrayList<String>();
|
List<String> buttonIdsToRemove = new ArrayList<String>();
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,10 @@ public class Box implements Serializable {
|
||||||
this(pos.x, pos.y, dim.x, dim.y);
|
this(pos.x, pos.y, dim.x, dim.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Box(Vector4i v) {
|
||||||
|
this(v.x, v.y, v.z, v.w);
|
||||||
|
}
|
||||||
|
|
||||||
public static Box fromPoints(Vector2i a, Vector2i b) {
|
public static Box fromPoints(Vector2i a, Vector2i b) {
|
||||||
return new Box(a.x, a.y, b.x - a.x, b.y - a.y);
|
return new Box(a.x, a.y, b.x - a.x, b.y - a.y);
|
||||||
}
|
}
|
||||||
|
|
@ -152,4 +156,8 @@ public class Box implements Serializable {
|
||||||
(float) Math.ceil(y2)
|
(float) Math.ceil(y2)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TileBox asTileBox() {
|
||||||
|
return new TileBox(pos.asInt(), dim.asInt());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package xyz.valnet.engine.math;
|
package xyz.valnet.engine.math;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class TileBox implements Serializable {
|
public class TileBox implements Serializable {
|
||||||
public final int x, y;
|
public final int x, y;
|
||||||
|
|
@ -49,6 +51,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) {
|
public static TileBox fromPoints(int x, int y, int x2, int y2) {
|
||||||
return new TileBox(
|
return new TileBox(
|
||||||
x <= x2 ? x : x2,
|
x <= x2 ? x : x2,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||||
|
|
||||||
public class Vector2f implements Serializable {
|
public class Vector2f implements Serializable {
|
||||||
|
|
||||||
public float x, y;
|
public final float x, y;
|
||||||
|
|
||||||
public static Vector2f zero = new Vector2f(0, 0);
|
public static Vector2f zero = new Vector2f(0, 0);
|
||||||
public static Vector2f north = new Vector2f(0, -1);
|
public static Vector2f north = new Vector2f(0, -1);
|
||||||
|
|
@ -57,4 +57,16 @@ public class Vector2f implements Serializable {
|
||||||
float y = Math.min(Math.max(this.y, box.y), box.y2);
|
float y = Math.min(Math.max(this.y, box.y), box.y2);
|
||||||
return new Vector2f(x, y);
|
return new Vector2f(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2f toPolar() {
|
||||||
|
float r = (float) Math.sqrt(x * x + y * y);
|
||||||
|
float theta = (float) Math.atan2(y, x);
|
||||||
|
return new Vector2f(r, theta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2f toCartesian() {
|
||||||
|
float x = this.x * (float) Math.cos(this.y);
|
||||||
|
float y = this.x * (float) Math.sin(this.y);
|
||||||
|
return new Vector2f(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||||
|
|
||||||
public class Vector2i implements Serializable {
|
public class Vector2i implements Serializable {
|
||||||
|
|
||||||
public int x, y;
|
public final int x, y;
|
||||||
|
|
||||||
public static Vector2i one = new Vector2i(1, 1);
|
public static Vector2i one = new Vector2i(1, 1);
|
||||||
public static Vector2i zero = new Vector2i(0, 0);
|
public static Vector2i zero = new Vector2i(0, 0);
|
||||||
|
|
@ -70,4 +70,13 @@ public class Vector2i implements Serializable {
|
||||||
return new Vector2i(this.x - b.x, this.y - b.y);
|
return new Vector2i(this.x - b.x, this.y - b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2i add(Vector2i b) {
|
||||||
|
return new Vector2i(this.x + b.x, this.y + b.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2i[] asArray() {
|
||||||
|
return new Vector2i[] {
|
||||||
|
this
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
package xyz.valnet.engine.scenegraph;
|
package xyz.valnet.engine.scenegraph;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.scenegraph.SceneGraph.GameObjectCallback;
|
import xyz.valnet.engine.scenegraph.SceneGraph.GameObjectCallback;
|
||||||
|
import xyz.valnet.hadean.interfaces.ISceneReferent;
|
||||||
import xyz.valnet.hadean.util.Pair;
|
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 transient SceneGraph scene;
|
||||||
|
|
||||||
private boolean created = false;
|
private boolean created = false;
|
||||||
|
|
@ -40,26 +44,6 @@ public class GameObject implements IRenderable, ITickable, Serializable {
|
||||||
return obj;
|
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() {
|
public final void addedToScene() {
|
||||||
connect();
|
connect();
|
||||||
if(!created) {
|
if(!created) {
|
||||||
|
|
@ -93,11 +77,50 @@ public class GameObject implements IRenderable, ITickable, Serializable {
|
||||||
return scene.getFPS();
|
return scene.getFPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onAddGameObject(GameObjectCallback listener) {
|
protected final void onAddGameObject(GameObjectCallback listener) {
|
||||||
scene.registerAddListener(listener);
|
scene.registerAddListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onRemoveGameObject(GameObjectCallback listener) {
|
protected final void onRemoveGameObject(GameObjectCallback listener) {
|
||||||
scene.registerRemoveListener(listener);
|
scene.registerRemoveListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final Vector2i getBufferDimensions() {
|
||||||
|
return scene.getBufferDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Set<GameObjectCallback> removedListeners = new HashSet<>();
|
||||||
|
|
||||||
|
@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() {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,14 @@ import java.util.stream.Collectors;
|
||||||
import xyz.valnet.engine.App;
|
import xyz.valnet.engine.App;
|
||||||
import xyz.valnet.engine.Game;
|
import xyz.valnet.engine.Game;
|
||||||
import xyz.valnet.engine.math.Box;
|
import xyz.valnet.engine.math.Box;
|
||||||
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab;
|
import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab;
|
||||||
import xyz.valnet.hadean.util.Pair;
|
import xyz.valnet.hadean.util.Pair;
|
||||||
|
|
||||||
public abstract class SceneGraph implements IScene {
|
public abstract class SceneGraph implements IScene {
|
||||||
protected final List<GameObject> objects = new ArrayList<GameObject>();
|
private final Set<GameObject> objects = new HashSet<GameObject>();
|
||||||
private final List<GameObject> newObjects = new ArrayList<GameObject>();
|
private final Set<GameObject> newObjects = new HashSet<GameObject>();
|
||||||
private final List<GameObject> removeObjects = new ArrayList<GameObject>();
|
private final Set<GameObject> removeObjects = new HashSet<GameObject>();
|
||||||
|
|
||||||
private IMouseCaptureArea hoveredMouseListener = null;
|
private IMouseCaptureArea hoveredMouseListener = null;
|
||||||
|
|
||||||
|
|
@ -158,7 +159,11 @@ public abstract class SceneGraph implements IScene {
|
||||||
@Override
|
@Override
|
||||||
public void enable(Game game) {
|
public void enable(Game game) {
|
||||||
this.game = game;
|
this.game = game;
|
||||||
this.construct();
|
Set<GameObject> scene = new HashSet<GameObject>();
|
||||||
|
this.construct(scene);
|
||||||
|
|
||||||
|
this.objects.clear();
|
||||||
|
this.objects.addAll(scene);
|
||||||
|
|
||||||
for(GameObject obj : objects) {
|
for(GameObject obj : objects) {
|
||||||
addObjectToCache(obj);
|
addObjectToCache(obj);
|
||||||
|
|
@ -189,7 +194,7 @@ public abstract class SceneGraph implements IScene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void construct();
|
protected abstract void construct(Set<GameObject> scene);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
|
|
@ -216,9 +221,11 @@ public abstract class SceneGraph implements IScene {
|
||||||
|
|
||||||
public void remove(GameObject obj) {
|
public void remove(GameObject obj) {
|
||||||
removeObjects.add(obj);
|
removeObjects.add(obj);
|
||||||
|
obj.cleanup();
|
||||||
for(GameObjectCallback listener : onRemoveListeners) {
|
for(GameObjectCallback listener : onRemoveListeners) {
|
||||||
listener.apply(obj);
|
listener.apply(obj);
|
||||||
}
|
}
|
||||||
|
obj.finalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean inScene(GameObject gameObject) {
|
public boolean inScene(GameObject gameObject) {
|
||||||
|
|
@ -332,7 +339,6 @@ public abstract class SceneGraph implements IScene {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void keyPress(int key) {
|
public final void keyPress(int key) {
|
||||||
DebugTab.log("keyCode: " + key);
|
|
||||||
keys.add(key);
|
keys.add(key);
|
||||||
for(IKeyboardListener ikbl : getAll(IKeyboardListener.class)) {
|
for(IKeyboardListener ikbl : getAll(IKeyboardListener.class)) {
|
||||||
ikbl.keyPress(key);
|
ikbl.keyPress(key);
|
||||||
|
|
@ -373,4 +379,8 @@ public abstract class SceneGraph implements IScene {
|
||||||
public Pair<Float, Integer> getFPS() {
|
public Pair<Float, Integer> getFPS() {
|
||||||
return new Pair<Float, Integer>(game.getAverageFPS(), game.getMeasuredFPS());
|
return new Pair<Float, Integer>(game.getAverageFPS(), game.getMeasuredFPS());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Vector2i getBufferDimensions() {
|
||||||
|
return game.getBufferDimensions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,137 +15,137 @@ import xyz.valnet.engine.math.Vector3f;
|
||||||
import xyz.valnet.engine.math.Vector4f;
|
import xyz.valnet.engine.math.Vector4f;
|
||||||
|
|
||||||
public class Shader {
|
public class Shader {
|
||||||
|
|
||||||
private boolean enabled = false;
|
private boolean enabled = false;
|
||||||
|
|
||||||
public final int handle;
|
public final int handle;
|
||||||
|
|
||||||
public final static int POSITION = 0;
|
public final static int POSITION = 0;
|
||||||
|
|
||||||
private Map<String, Integer> locationCache = new HashMap<String, Integer>();
|
private Map<String, Integer> locationCache = new HashMap<String, Integer>();
|
||||||
|
|
||||||
public Shader(String vertPath, String fragPath) {
|
public Shader(String vertPath, String fragPath) {
|
||||||
handle = load(vertPath, fragPath);
|
handle = load(vertPath, fragPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String loadAsString(String file) {
|
private static String loadAsString(String file) {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
try {
|
try {
|
||||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||||
String buffer = "";
|
String buffer = "";
|
||||||
while ((buffer = reader.readLine()) != null) {
|
while ((buffer = reader.readLine()) != null) {
|
||||||
result.append(buffer + '\n');
|
result.append(buffer + '\n');
|
||||||
}
|
}
|
||||||
reader.close();
|
reader.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int load(String vertPath, String fragPath) {
|
public int load(String vertPath, String fragPath) {
|
||||||
String vert = Shader.loadAsString(vertPath);
|
String vert = Shader.loadAsString(vertPath);
|
||||||
String frag = Shader.loadAsString(fragPath);
|
String frag = Shader.loadAsString(fragPath);
|
||||||
return create(vert, frag);
|
return create(vert, frag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int create(String vert, String frag) {
|
public int create(String vert, String frag) {
|
||||||
int program = glCreateProgram();
|
int program = glCreateProgram();
|
||||||
int vertID = glCreateShader(GL_VERTEX_SHADER);
|
int vertID = glCreateShader(GL_VERTEX_SHADER);
|
||||||
int fragID = glCreateShader(GL_FRAGMENT_SHADER);
|
int fragID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(vertID, vert);
|
glShaderSource(vertID, vert);
|
||||||
glShaderSource(fragID, frag);
|
glShaderSource(fragID, frag);
|
||||||
|
|
||||||
glCompileShader(vertID);
|
glCompileShader(vertID);
|
||||||
if (glGetShaderi(vertID, GL_COMPILE_STATUS) == GL_FALSE) {
|
if (glGetShaderi(vertID, GL_COMPILE_STATUS) == GL_FALSE) {
|
||||||
System.err.println("Failed to compile vertex shader!");
|
System.err.println("Failed to compile vertex shader!");
|
||||||
System.err.println(glGetShaderInfoLog(vertID));
|
System.err.println(glGetShaderInfoLog(vertID));
|
||||||
return -1;
|
throw new Error("Failed to compile vertex shader!");
|
||||||
}
|
}
|
||||||
|
|
||||||
glCompileShader(fragID);
|
glCompileShader(fragID);
|
||||||
if (glGetShaderi(fragID, GL_COMPILE_STATUS) == GL_FALSE) {
|
if (glGetShaderi(fragID, GL_COMPILE_STATUS) == GL_FALSE) {
|
||||||
System.err.println("Failed to compile fragment shader!");
|
System.err.println("Failed to compile fragment shader!");
|
||||||
System.err.println(glGetShaderInfoLog(fragID));
|
System.err.println(glGetShaderInfoLog(fragID));
|
||||||
return -1;
|
throw new Error("Failed to compile fragment shader!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bindAttributes(program);
|
bindAttributes(program);
|
||||||
|
|
||||||
glAttachShader(program, vertID);
|
glAttachShader(program, vertID);
|
||||||
glAttachShader(program, fragID);
|
glAttachShader(program, fragID);
|
||||||
glLinkProgram(program);
|
glLinkProgram(program);
|
||||||
glValidateProgram(program);
|
glValidateProgram(program);
|
||||||
|
|
||||||
glDeleteShader(vertID);
|
glDeleteShader(vertID);
|
||||||
glDeleteShader(fragID);
|
glDeleteShader(fragID);
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void bindAttributes(int program) {
|
protected void bindAttributes(int program) {
|
||||||
glBindAttribLocation(program, POSITION, "Position");
|
glBindAttribLocation(program, POSITION, "Position");
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getUniform(String name) {
|
public int getUniform(String name) {
|
||||||
if (locationCache.containsKey(name))
|
if (locationCache.containsKey(name))
|
||||||
return locationCache.get(name);
|
return locationCache.get(name);
|
||||||
|
|
||||||
int result = glGetUniformLocation(handle, name);
|
int result = glGetUniformLocation(handle, name);
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
System.err.println("Could not find uniform variable '" + name + "'!");
|
System.err.println("Could not find uniform variable '" + name + "'!");
|
||||||
else
|
else
|
||||||
locationCache.put(name, result);
|
locationCache.put(name, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUniform1i(String name, int value) {
|
public void setUniform1i(String name, int value) {
|
||||||
if (!enabled) enable();
|
if (!enabled) enable();
|
||||||
glUniform1i(getUniform(name), value);
|
glUniform1i(getUniform(name), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUniform1f(String name, float value) {
|
public void setUniform1f(String name, float value) {
|
||||||
if (!enabled) enable();
|
if (!enabled) enable();
|
||||||
glUniform1f(getUniform(name), value);
|
glUniform1f(getUniform(name), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUniform2f(String name, float x, float y) {
|
public void setUniform2f(String name, float x, float y) {
|
||||||
if (!enabled) enable();
|
if (!enabled) enable();
|
||||||
glUniform2f(getUniform(name), x, y);
|
glUniform2f(getUniform(name), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUniform3f(String name, Vector3f vector) {
|
public void setUniform3f(String name, Vector3f v) {
|
||||||
if (!enabled) enable();
|
if (!enabled) enable();
|
||||||
glUniform3f(getUniform(name), vector.x, vector.y, vector.z);
|
glUniform3f(getUniform(name), v.x, v.y, v.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUniform4f(String name, Vector4f vector) {
|
public void setUniform4f(String name, Vector4f v) {
|
||||||
if (!enabled) enable();
|
if (!enabled) enable();
|
||||||
glUniform4f(getUniform(name), vector.x, vector.y, vector.z, vector.w);
|
glUniform4f(getUniform(name), v.x, v.y, v.z, v.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUniform4f(String name, Color c) {
|
public void setUniform4f(String name, Color c) {
|
||||||
if (!enabled) enable();
|
if (!enabled) enable();
|
||||||
glUniform4f(getUniform(name), c.r, c.g, c.b, c.a);
|
glUniform4f(getUniform(name), c.r, c.g, c.b, c.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUniformMat4f(String name, Matrix4f matrix) {
|
public void setUniformMat4f(String name, Matrix4f matrix) {
|
||||||
if (!enabled) enable();
|
if (!enabled) enable();
|
||||||
glUniformMatrix4fv(getUniform(name), false, matrix.toFloatBuffer());
|
glUniformMatrix4fv(getUniform(name), false, matrix.toFloatBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMatrices (Matrix4f projection) {
|
public void setMatrices (Matrix4f projection) {
|
||||||
setUniformMat4f("uProjection", projection);
|
setUniformMat4f("uProjection", projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enable() {
|
public void enable() {
|
||||||
glUseProgram(handle);
|
glUseProgram(handle);
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disable() {
|
public void disable() {
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ public class SimpleShader extends Shader {
|
||||||
|
|
||||||
public SimpleShader(String vertPath, String fragPath) {
|
public SimpleShader(String vertPath, String fragPath) {
|
||||||
super(vertPath, fragPath);
|
super(vertPath, fragPath);
|
||||||
|
pushColor(Color.white);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushColor(Color color) {
|
public void pushColor(Color color) {
|
||||||
|
|
|
||||||
|
|
@ -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<T extends ISceneReferent> extends WeakReference<T> {
|
||||||
|
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() + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,38 +2,27 @@ package xyz.valnet.hadean;
|
||||||
|
|
||||||
import xyz.valnet.engine.App;
|
import xyz.valnet.engine.App;
|
||||||
import xyz.valnet.engine.Game;
|
import xyz.valnet.engine.Game;
|
||||||
import xyz.valnet.engine.graphics.Color;
|
|
||||||
import xyz.valnet.engine.graphics.Drawing;
|
|
||||||
import xyz.valnet.engine.math.Matrix4f;
|
import xyz.valnet.engine.math.Matrix4f;
|
||||||
import xyz.valnet.hadean.scenes.GameScene;
|
import xyz.valnet.hadean.scenes.GameScene;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
|
|
||||||
public class HadeanGame extends Game {
|
public class HadeanGame extends Game {
|
||||||
public static final HadeanGame Hadean = new HadeanGame();
|
public static final HadeanGame HADEAN_GAME = new HadeanGame();
|
||||||
|
|
||||||
public static boolean debugView = false;
|
public static boolean debugView = true;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new App(Hadean).run();
|
new App(HADEAN_GAME).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
Assets.flat.pushColor(Color.white);
|
|
||||||
changeScene(new GameScene());
|
changeScene(new GameScene());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render() {
|
|
||||||
Drawing.setLayer(0);
|
|
||||||
super.render();
|
|
||||||
|
|
||||||
if(!debugView) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive the updated matrix every frame for the actual window.
|
// receive the updated matrix every frame for the actual window.
|
||||||
@Override
|
@Override
|
||||||
public void updateViewMatrix(Matrix4f matrix) {
|
public void updateViewMatrix(Matrix4f matrix) {
|
||||||
Assets.flat.setMatrices(matrix);
|
Assets.flat.setMatrices(matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package xyz.valnet.hadean.designation;
|
package xyz.valnet.hadean.designations;
|
||||||
|
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.Tree;
|
import xyz.valnet.hadean.gameobjects.worldobjects.Tree;
|
||||||
|
|
||||||
|
|
@ -16,6 +16,6 @@ public class CutTreesDesignation extends Designation<Tree> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBuildTabName() {
|
public String getBuildTabName() {
|
||||||
return "ChopTrees";
|
return "Chop Trees";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package xyz.valnet.hadean.designation;
|
package xyz.valnet.hadean.designations;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Box;
|
import xyz.valnet.engine.math.Box;
|
||||||
import xyz.valnet.engine.math.TileBox;
|
import xyz.valnet.engine.math.TileBox;
|
||||||
import xyz.valnet.engine.scenegraph.GameObject;
|
import xyz.valnet.engine.scenegraph.GameObject;
|
||||||
import xyz.valnet.hadean.interfaces.BuildType;
|
import xyz.valnet.hadean.enums.BuildType;
|
||||||
import xyz.valnet.hadean.interfaces.IBuildable;
|
import xyz.valnet.hadean.interfaces.IBuildable;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ public abstract class Designation<T extends ISelectable> extends GameObject impl
|
||||||
Class<T> type = getType();
|
Class<T> type = getType();
|
||||||
List<T> things = getAll(type);
|
List<T> things = getAll(type);
|
||||||
for(ISelectable thing : things) {
|
for(ISelectable thing : things) {
|
||||||
Box thingBox = thing.getWorldBox();
|
Box thingBox = thing.getSelectionWorldBox();
|
||||||
if(box.intersects(thingBox))
|
if(box.intersects(thingBox))
|
||||||
designate((T) thing);
|
designate((T) thing);
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package xyz.valnet.hadean.designation;
|
package xyz.valnet.hadean.designations;
|
||||||
|
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package xyz.valnet.hadean.interfaces;
|
package xyz.valnet.hadean.enums;
|
||||||
|
|
||||||
public enum BuildType {
|
public enum BuildType {
|
||||||
AREA,
|
AREA,
|
||||||
|
|
@ -0,0 +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 {
|
||||||
|
Basic("basic", "Work on"),
|
||||||
|
Construct("building", "Construct"),
|
||||||
|
Farm("farming", "Till"),
|
||||||
|
Chop("felling", "Chop");
|
||||||
|
|
||||||
|
public final String verb;
|
||||||
|
public final String idString;
|
||||||
|
|
||||||
|
private WorkType(String idString, String verb) {
|
||||||
|
this.idString = idString;
|
||||||
|
this.verb = verb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package xyz.valnet.hadean.functions;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FCompleted extends Serializable {
|
||||||
|
public void apply();
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package xyz.valnet.hadean.functions;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FProgressEvent extends Serializable {
|
||||||
|
public void progress(float progress);
|
||||||
|
}
|
||||||
|
|
@ -25,8 +25,6 @@ import static xyz.valnet.engine.util.Math.lerp;
|
||||||
public class Camera extends GameObject implements ITransient, IMouseCaptureArea {
|
public class Camera extends GameObject implements ITransient, IMouseCaptureArea {
|
||||||
|
|
||||||
private int tileWidth = 16;
|
private int tileWidth = 16;
|
||||||
// TODO link these in some way to the real resolution. lot of work here.
|
|
||||||
private int screenWidth = 1024, screenHeight = 576;
|
|
||||||
|
|
||||||
private Vector2f focus = new Vector2f(0, 0);
|
private Vector2f focus = new Vector2f(0, 0);
|
||||||
|
|
||||||
|
|
@ -81,8 +79,7 @@ public class Camera extends GameObject implements ITransient, IMouseCaptureArea
|
||||||
}
|
}
|
||||||
|
|
||||||
public void focus(float x, float y) {
|
public void focus(float x, float y) {
|
||||||
this.focus.x = x;
|
this.focus = new Vector2f(x, y);
|
||||||
this.focus.y = y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Box world2screen(Box box) {
|
public final Box world2screen(Box box) {
|
||||||
|
|
@ -90,7 +87,8 @@ public class Camera extends GameObject implements ITransient, IMouseCaptureArea
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Vector2i world2screen(float x, float y) {
|
public final Vector2i world2screen(float x, float y) {
|
||||||
return new Vector2i((int)(x * tileWidth + screenWidth / 2 - focus.x * tileWidth), (int)(y * tileWidth + screenHeight / 2 - focus.y * tileWidth));
|
Vector2i bufferDim = getBufferDimensions();
|
||||||
|
return new Vector2i((int)(x * tileWidth + bufferDim.x / 2 - focus.x * tileWidth), (int)(y * tileWidth + bufferDim.y / 2 - focus.y * tileWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Vector2i world2screen(Vector2f pos) {
|
public final Vector2i world2screen(Vector2f pos) {
|
||||||
|
|
@ -102,7 +100,8 @@ public class Camera extends GameObject implements ITransient, IMouseCaptureArea
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Vector2f screen2world(float x, float y) {
|
public final Vector2f screen2world(float x, float y) {
|
||||||
return new Vector2f((x - screenWidth / 2 + focus.x * tileWidth) / tileWidth, (y - screenHeight / 2 + focus.y * tileWidth) / tileWidth);
|
Vector2i bufferDim = getBufferDimensions();
|
||||||
|
return new Vector2f((x - bufferDim.x / 2 + focus.x * tileWidth) / tileWidth, (y - bufferDim.y / 2 + focus.y * tileWidth) / tileWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Vector2f screen2world(Vector2f pos) {
|
public final Vector2f screen2world(Vector2f pos) {
|
||||||
|
|
@ -111,11 +110,12 @@ public class Camera extends GameObject implements ITransient, IMouseCaptureArea
|
||||||
|
|
||||||
// !! this takes an AABB and returns and AABB
|
// !! this takes an AABB and returns and AABB
|
||||||
public final Vector4f world2screen(Vector4f input) {
|
public final Vector4f world2screen(Vector4f input) {
|
||||||
|
Vector2i bufferDim = getBufferDimensions();
|
||||||
return new Vector4f(
|
return new Vector4f(
|
||||||
input.x * tileWidth + screenWidth / 2 - focus.x * tileWidth,
|
input.x * tileWidth + bufferDim.x / 2 - focus.x * tileWidth,
|
||||||
input.y * tileWidth + screenHeight / 2 - focus.y * tileWidth,
|
input.y * tileWidth + bufferDim.y / 2 - focus.y * tileWidth,
|
||||||
input.z * tileWidth + screenWidth / 2 - focus.x * tileWidth,
|
input.z * tileWidth + bufferDim.x / 2 - focus.x * tileWidth,
|
||||||
input.w * tileWidth + screenHeight / 2 - focus.y * tileWidth
|
input.w * tileWidth + bufferDim.y / 2 - focus.y * tileWidth
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,7 +216,7 @@ public class Camera extends GameObject implements ITransient, IMouseCaptureArea
|
||||||
@Override
|
@Override
|
||||||
public void scrollUp() {
|
public void scrollUp() {
|
||||||
tileWidth *= 2;
|
tileWidth *= 2;
|
||||||
tileWidth = Math.min(tileWidth, 32);
|
tileWidth = Math.min(tileWidth, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ public class Clock extends GameObject {
|
||||||
public void render() {
|
public void render() {
|
||||||
Drawing.setLayer(Layers.GENERAL_UI);
|
Drawing.setLayer(Layers.GENERAL_UI);
|
||||||
String str = toString();
|
String str = toString();
|
||||||
int left = 950;
|
int left = getBufferDimensions().x - (1024 - 950);
|
||||||
Assets.font.drawStringOutlined(str, left, 520);
|
Assets.font.drawStringOutlined(str, left, getBufferDimensions().y - 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getSunlight() {
|
public float getSunlight() {
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.scenegraph.GameObject;
|
import xyz.valnet.engine.scenegraph.GameObject;
|
||||||
import xyz.valnet.engine.scenegraph.IMouseCaptureArea;
|
import xyz.valnet.engine.scenegraph.IMouseCaptureArea;
|
||||||
import xyz.valnet.engine.scenegraph.ITransient;
|
import xyz.valnet.engine.scenegraph.ITransient;
|
||||||
|
import xyz.valnet.hadean.enums.BuildType;
|
||||||
import xyz.valnet.hadean.gameobjects.Camera;
|
import xyz.valnet.hadean.gameobjects.Camera;
|
||||||
import xyz.valnet.hadean.interfaces.BuildType;
|
|
||||||
import xyz.valnet.hadean.interfaces.IBuildLayerListener;
|
import xyz.valnet.hadean.interfaces.IBuildLayerListener;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
import xyz.valnet.hadean.util.Layers;
|
import xyz.valnet.hadean.util.Layers;
|
||||||
|
|
@ -122,7 +122,7 @@ public class BuildLayer extends GameObject implements IMouseCaptureArea, ITransi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Box> getGuiBoxes() {
|
public List<Box> getGuiBoxes() {
|
||||||
return List.of(active ? new Box(0, 0, 1024, 576) : Box.none);
|
return List.of(active ? new Box(0, 0, getBufferDimensions()) : Box.none);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ public class SelectionLayer extends GameObject implements IMouseCaptureArea, ITr
|
||||||
float p = lerp(animationAmplitude, 0, t);
|
float p = lerp(animationAmplitude, 0, t);
|
||||||
|
|
||||||
for(ISelectable thing : selected) {
|
for(ISelectable thing : selected) {
|
||||||
Box box = thing.getWorldBox().outset(p);
|
Box box = thing.getSelectionWorldBox().outset(p);
|
||||||
camera.draw(Layers.SELECTION_IDENTIFIERS, Assets.selectedFrame, box);
|
camera.draw(Layers.SELECTION_IDENTIFIERS, Assets.selectedFrame, box);
|
||||||
thing.selectedRender();
|
thing.selectedRender();
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +100,7 @@ public class SelectionLayer extends GameObject implements IMouseCaptureArea, ITr
|
||||||
int prio = Integer.MIN_VALUE;
|
int prio = Integer.MIN_VALUE;
|
||||||
|
|
||||||
for(ISelectable thing : selectables) {
|
for(ISelectable thing : selectables) {
|
||||||
Box thingBox = thing.getWorldBox();
|
Box thingBox = thing.getSelectionWorldBox();
|
||||||
if(selectionBox.intersects(thingBox)) {
|
if(selectionBox.intersects(thingBox)) {
|
||||||
int thingPrio = thing.getSelectPriority().toValue();
|
int thingPrio = thing.getSelectPriority().toValue();
|
||||||
if(thingPrio > prio) {
|
if(thingPrio > prio) {
|
||||||
|
|
|
||||||
|
|
@ -1,231 +1,79 @@
|
||||||
package xyz.valnet.hadean.gameobjects.jobs;
|
package xyz.valnet.hadean.gameobjects.jobs;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.scenegraph.GameObject;
|
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.gameobjects.worldobjects.items.Item;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.zones.Stockpile;
|
import xyz.valnet.hadean.interfaces.DItemRequest;
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
import xyz.valnet.hadean.interfaces.IDestination;
|
||||||
import xyz.valnet.hadean.interfaces.IItemReceiver;
|
|
||||||
import xyz.valnet.hadean.interfaces.IWorkable;
|
import xyz.valnet.hadean.interfaces.IWorkable;
|
||||||
|
|
||||||
public class Job extends GameObject {
|
public sealed interface Job {
|
||||||
|
record Work(
|
||||||
private Job that = this;
|
SceneReference<IWorkable> workable
|
||||||
private List<Callback> closedListeners = new ArrayList<Callback>();
|
) implements Job, IDestination {
|
||||||
|
@Override
|
||||||
public abstract class JobStep implements Serializable {
|
public String getShortDescription() {
|
||||||
public abstract Vector2i[] getLocations();
|
return workable.get().getWorkType().verb + " " + workable.get().getWorkableName();
|
||||||
public void next() {
|
|
||||||
that.nextStep();
|
|
||||||
}
|
|
||||||
public abstract boolean isValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PickupItem extends JobStep {
|
|
||||||
public Item item;
|
|
||||||
|
|
||||||
public PickupItem(Item item) {
|
|
||||||
this.item = item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2i[] getLocations() {
|
public boolean isValidForWorker(Pawn worker) {
|
||||||
return new Vector2i[] { item.getWorldPosition().xy() };
|
var workable = this.workable().get();
|
||||||
}
|
if(workable == null) return false;
|
||||||
|
if(workable.getWorkablePositions() == null) return false;
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class DropoffPredicateAtItemReceiver extends JobStep {
|
public Vector2i[] getWorkablePositions() {
|
||||||
|
var workable = this.workable().get();
|
||||||
|
if(workable == null) return new Vector2i[] {};
|
||||||
|
return workable.getDestinations();
|
||||||
|
}
|
||||||
|
|
||||||
public IItemReceiver receiver;
|
public void doWork(float dTime) {
|
||||||
public IItemPredicate predicate;
|
var workable = this.workable().get();
|
||||||
|
if(workable == null) return;
|
||||||
public DropoffPredicateAtItemReceiver(IItemReceiver receiver, IItemPredicate predicate) {
|
workable.doWork(dTime);
|
||||||
this.receiver = receiver;
|
|
||||||
this.predicate = predicate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2i[] getLocations() {
|
public Vector2i[] getDestinations() {
|
||||||
return receiver.getItemDropoffLocations();
|
var workable = this.workable().get();
|
||||||
|
if(workable == null) return null;
|
||||||
|
return workable.getDestinations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record ItemRequest(
|
||||||
|
SceneReference<DItemRequest> recvr
|
||||||
|
) implements Job {
|
||||||
|
@Override
|
||||||
|
public String getShortDescription() {
|
||||||
|
return "Fulfilling " + recvr.get().getName() + " item Request";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid() {
|
public boolean isValidForWorker(Pawn worker) {
|
||||||
return true;
|
// TODO Auto-generated method stub
|
||||||
|
throw new UnsupportedOperationException("Unimplemented method 'isValidForWorker'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PickupItemByPredicate extends JobStep {
|
record HaulToStockpile(
|
||||||
public IItemPredicate predicate;
|
SceneReference<Item> item
|
||||||
|
) implements Job {
|
||||||
public PickupItemByPredicate(IItemPredicate predicate) {
|
@Override
|
||||||
this.predicate = predicate;
|
public String getShortDescription() {
|
||||||
|
return "Haul " + item.get().getName() + " to stockpile";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2i[] getLocations() {
|
public boolean isValidForWorker(Pawn worker) {
|
||||||
Set<Vector2i> positionSet = new HashSet<Vector2i>();
|
return item.get() != null;
|
||||||
for(Item item : that.getAll(Item.class)) {
|
|
||||||
if(!item.matches(predicate)) continue;
|
|
||||||
positionSet.add(item.getWorldPosition().xy());
|
|
||||||
}
|
|
||||||
Vector2i[] positions = new Vector2i[positionSet.size()];
|
|
||||||
positionSet.toArray(positions);
|
|
||||||
return positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return getLocations().length > 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DropoffAtItemReceiver extends JobStep {
|
public String getShortDescription();
|
||||||
|
public boolean isValidForWorker(Pawn worker);
|
||||||
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) {
|
|
||||||
this.item = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2i[] getLocations() {
|
|
||||||
List<Stockpile> stockpiles = that.getAll(Stockpile.class);
|
|
||||||
for(Stockpile pile : stockpiles) {
|
|
||||||
Vector2i tile = pile.getFreeTile();
|
|
||||||
if(tile == null) continue;
|
|
||||||
return new Vector2i[] {
|
|
||||||
tile
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return new Vector2i[] {};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return that.get(Stockpile.class) != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Work extends JobStep {
|
|
||||||
public IWorkable subject;
|
|
||||||
public Work(IWorkable subject) {
|
|
||||||
this.subject = subject;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Vector2i[] getLocations() {
|
|
||||||
return subject.getWorkablePositions();
|
|
||||||
}
|
|
||||||
public boolean doWork(float dTime) {
|
|
||||||
return subject.doWork(dTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<JobStep> steps;
|
|
||||||
private String name;
|
|
||||||
private int step;
|
|
||||||
private boolean hasClosed = false;
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
step = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Job(String name) {
|
|
||||||
this.steps = new ArrayList<JobStep>();
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addStep(JobStep step) {
|
|
||||||
steps.add(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2i[] getLocations() {
|
|
||||||
if(steps.size() == 0) throw new Error("Cannot get location of job with no steps");
|
|
||||||
JobStep step = getCurrentStep();
|
|
||||||
return step.getLocations();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void nextStep() {
|
|
||||||
step ++;
|
|
||||||
if(isCompleted()) {
|
|
||||||
close();
|
|
||||||
remove(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCompleted() {
|
|
||||||
return step >= steps.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public JobStep getCurrentStep() {
|
|
||||||
if(step >= steps.size()) return null;
|
|
||||||
return steps.get(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJobName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface Callback extends Serializable {
|
|
||||||
public void apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
if(hasClosed) return;
|
|
||||||
hasClosed = true;
|
|
||||||
for(Callback callback : closedListeners) {
|
|
||||||
callback.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerClosedListener(Callback callback) {
|
|
||||||
closedListeners.add(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unregisterClosedListener(Callback callback) {
|
|
||||||
closedListeners.remove(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isValid() {
|
|
||||||
for(JobStep step : steps) {
|
|
||||||
if(!step.isValid()) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,184 +1,80 @@
|
||||||
package xyz.valnet.hadean.gameobjects.jobs;
|
package xyz.valnet.hadean.gameobjects.jobs;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import xyz.valnet.engine.graphics.Color;
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
|
||||||
import xyz.valnet.engine.scenegraph.GameObject;
|
import xyz.valnet.engine.scenegraph.GameObject;
|
||||||
import xyz.valnet.hadean.HadeanGame;
|
import xyz.valnet.engine.util.SceneReference;
|
||||||
import xyz.valnet.hadean.gameobjects.Camera;
|
import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn.Pawn;
|
import xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn.Pawn;
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
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.IWorkable;
|
import xyz.valnet.hadean.interfaces.IWorkable;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
|
||||||
import xyz.valnet.hadean.util.Layers;
|
|
||||||
import xyz.valnet.hadean.util.Pair;
|
|
||||||
|
|
||||||
public class JobBoard extends GameObject {
|
public class JobBoard extends GameObject {
|
||||||
|
|
||||||
private Set<Job> availableJobs = new HashSet<Job>();
|
private Set<Job> availableJobs = new HashSet<Job>();
|
||||||
private List<Job> toRemove = new ArrayList<Job>();
|
// private Set<Job> toRemove = new HashSet<Job>();
|
||||||
private Map<Pawn, Job> allocations = new HashMap<Pawn, Job>();
|
// private Map<Pawn, Job> allocations = new HashMap<Pawn, Job>();
|
||||||
|
|
||||||
public Job postSimpleWorkJob(IWorkable subject) {
|
public Job post(Job job) {
|
||||||
Job job = add(new Job(subject.getJobName()));
|
availableJobs.add(job);
|
||||||
job.addStep(job.new Work(subject));
|
|
||||||
postJob(job);
|
|
||||||
return job;
|
return job;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Camera camera;
|
public Job post(IWorkable workable) {
|
||||||
|
SceneReference<IWorkable> ref = new SceneReference<IWorkable>(workable);
|
||||||
@Override
|
var job = new Job.Work(ref);
|
||||||
public void connect() {
|
return post(job);
|
||||||
camera = get(Camera.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Job post(Item item) {
|
||||||
public void renderAlpha() {
|
var job = new Job.HaulToStockpile(item.asRef());
|
||||||
super.render();
|
return post(job);
|
||||||
if(HadeanGame.debugView) {
|
|
||||||
float opacity = 0.6f;
|
|
||||||
Assets.flat.pushColor(Color.orange.withAlpha(opacity));
|
|
||||||
for(Job job : availableJobs) {
|
|
||||||
for(Vector2i position : job.getLocations()) {
|
|
||||||
if(job.isValid()) {
|
|
||||||
Assets.flat.swapColor(Color.orange.withAlpha(opacity));
|
|
||||||
} else {
|
|
||||||
Assets.flat.swapColor(Color.red.withAlpha(opacity));
|
|
||||||
}
|
|
||||||
camera.draw(Layers.GROUND_MARKERS, Assets.fillTile, position.asFloat());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Assets.flat.swapColor(Color.lime.withAlpha(opacity));
|
|
||||||
for(Job job : allocations.values()) {
|
|
||||||
for(Vector2i position : job.getLocations()) {
|
|
||||||
camera.draw(Layers.GROUND_MARKERS, Assets.fillTile, position.asFloat());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Assets.flat.popColor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Job postSimpleItemRequirementJob(String name, IItemPredicate predicate, IItemReceiver recv) {
|
public Job post(DItemRequest request) {
|
||||||
Job job = add(new Job(name));
|
var job = new Job.ItemRequest(request.asRef());
|
||||||
job.addStep(job.new PickupItemByPredicate(predicate));
|
return post(job);
|
||||||
job.addStep(job.new DropoffPredicateAtItemReceiver(recv, predicate));
|
}
|
||||||
postJob(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;
|
return job;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postJob(Job job) {
|
|
||||||
job.registerClosedListener(() -> {
|
|
||||||
if(allocations.values().contains(job)) {
|
// ================= lawl old shit
|
||||||
List<Pawn> toFire = new ArrayList<Pawn>();
|
|
||||||
|
|
||||||
for(Pawn worker : allocations.keySet()) {
|
@Deprecated
|
||||||
if(allocations.get(worker) == job) {
|
|
||||||
toFire.add(worker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Pawn worker : toFire) {
|
|
||||||
allocations.remove(worker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(availableJobs.contains(job)) {
|
|
||||||
availableJobs.remove(job);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
availableJobs.add(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean jobsAvailableForWorker(Pawn worker) {
|
|
||||||
return getJobsForWorker(worker).size() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Job> getJobsForWorker(Pawn worker) {
|
|
||||||
Vector2i workerLocation = worker.getWorldPosition().xy();
|
|
||||||
|
|
||||||
List<Job> workables = availableJobs
|
|
||||||
.stream()
|
|
||||||
.filter(job -> job.isValid())
|
|
||||||
.map(job -> new Pair<Job, Float>(
|
|
||||||
job,
|
|
||||||
Stream.of(job.getLocations())
|
|
||||||
.map(v -> v.distanceTo((int) workerLocation.x, (int) workerLocation.y))
|
|
||||||
.reduce(Float.MAX_VALUE, (a, b) -> a < b ? a : b)
|
|
||||||
))
|
|
||||||
// sort the jobs by their distance from the worker
|
|
||||||
.sorted((Pair<Job, Float> a, Pair<Job, Float> b) -> {
|
|
||||||
if(a.second() > b.second()) return 1;
|
|
||||||
if(b.second() > a.second()) return -1;
|
|
||||||
return 0;
|
|
||||||
})
|
|
||||||
// then convert the stream back to just the jobs
|
|
||||||
.map(workerDistanceTuple -> workerDistanceTuple.first())
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
return workables;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Job requestJob(Pawn worker) {
|
|
||||||
|
|
||||||
|
|
||||||
List<Job> workables = getJobsForWorker(worker);
|
|
||||||
|
|
||||||
if(workables.size() > 0) {
|
|
||||||
Job firstJob = workables.get(0);
|
|
||||||
availableJobs.remove(firstJob);
|
|
||||||
allocations.put(worker, firstJob);
|
|
||||||
return firstJob;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void quitJob(Pawn worker, Job job) {
|
|
||||||
if(!allocations.containsKey(worker)) return;
|
|
||||||
Job foundJob = allocations.get(worker);
|
|
||||||
if(foundJob != job) return;
|
|
||||||
availableJobs.add(job);
|
|
||||||
allocations.remove(worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(float dTime) {
|
|
||||||
for(Job job : toRemove) {
|
|
||||||
if(allocations.values().contains(job)) {
|
|
||||||
// I AM NOT SURE THIS WORKS
|
|
||||||
allocations.values().remove(job);
|
|
||||||
}
|
|
||||||
if(availableJobs.contains(job)) {
|
|
||||||
availableJobs.remove(job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
toRemove.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean workerHasJob(Pawn worker) {
|
|
||||||
return allocations.containsKey(worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// public Job getJob(Pawn worker) {
|
|
||||||
// if(allocations.containsKey(worker)) {
|
|
||||||
// return allocations.get(worker);
|
|
||||||
// } else return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public String getValidJobs() {
|
public String getValidJobs() {
|
||||||
Map<String, Integer> jobs = new HashMap<String, Integer>();
|
Map<String, Integer> jobs = new HashMap<String, Integer>();
|
||||||
for(Job job : availableJobs) {
|
for(Job job : availableJobs) {
|
||||||
if(!job.isValid()) continue;
|
// if(!job.isValid()) continue;
|
||||||
String name = job.getJobName();
|
String name = job.getShortDescription();
|
||||||
if(!jobs.containsKey(name)) jobs.put(name, 0);
|
if(!jobs.containsKey(name)) jobs.put(name, 0);
|
||||||
jobs.put(name, jobs.get(name) + 1);
|
jobs.put(name, jobs.get(name) + 1);
|
||||||
}
|
}
|
||||||
|
|
@ -191,49 +87,52 @@ public class JobBoard extends GameObject {
|
||||||
return str.trim();
|
return str.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public String getInvalidJobs() {
|
public String getInvalidJobs() {
|
||||||
String str = "";
|
String str = "";
|
||||||
for(Job job : availableJobs) {
|
// for(Job job : availableJobs) {
|
||||||
if(job.isValid()) continue;
|
// if(job.isValid()) continue;
|
||||||
str += " " + job.getJobName() + "\n";
|
// str += " " + job.getJobName() + "\n";
|
||||||
}
|
// }
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTakenJobs() {
|
|
||||||
String str = "";
|
|
||||||
for(Entry<Pawn, Job> allocation : allocations.entrySet()) {
|
|
||||||
str += " " + allocation.getKey().getName() + ": " + allocation.getValue().getJobName() + "\n";
|
|
||||||
}
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String details() {
|
public String getTakenJobs() {
|
||||||
|
String str = "Unknown for now, as jobboard does not track taken jobs.";
|
||||||
String takenJobsString = "";
|
// for(Entry<Pawn, Job> allocation : allocations.entrySet()) {
|
||||||
String availableJobsString = "";
|
// str += " " + allocation.getKey().getName() + ": " + allocation.getValue().getShortDescription() + "\n";
|
||||||
String impossibleJobsString = "";
|
// }
|
||||||
|
return str;
|
||||||
int possibleJobs = 0;
|
|
||||||
int impossibleJobs = 0;
|
|
||||||
|
|
||||||
for(Entry<Pawn, Job> allocation : allocations.entrySet()) {
|
|
||||||
takenJobsString += " " + allocation.getKey().getName() + ": " + allocation.getValue().getJobName() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Job job : availableJobs) {
|
|
||||||
if(job.isValid()) {
|
|
||||||
availableJobsString += " " + job.getJobName() + "\n";
|
|
||||||
possibleJobs ++;
|
|
||||||
} else {
|
|
||||||
impossibleJobsString += " " + job.getJobName() + "\n";
|
|
||||||
impossibleJobs ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Available Jobs: " + possibleJobs + "\n" + availableJobsString +
|
|
||||||
"Taken Jobs: " + allocations.size() + "\n" + takenJobsString +
|
|
||||||
"Impossible Jobs: " + impossibleJobs + "\n" + impossibleJobsString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public void close(Job job) {
|
||||||
|
// if(allocations.values().contains(job)) {
|
||||||
|
// Set<Pawn> 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 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))];
|
||||||
|
|
||||||
|
// DebugTab.log("" + worker.getName() + " took job: " + job.getShortDescription());
|
||||||
|
|
||||||
|
// allocations.put(worker, job);
|
||||||
|
// availableJobs.remove(job);
|
||||||
|
|
||||||
|
// return job;
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,50 +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;
|
|
||||||
|
|
||||||
@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, IGetPositionsFunction positionsFunction, IProgressUpdateCallback callback) {
|
|
||||||
this.name = name;
|
|
||||||
this.MAX_WORK = maxWork;
|
|
||||||
this.positions = positionsFunction;
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 getJobName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
package xyz.valnet.hadean.gameobjects.jobs;
|
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.engine.scenegraph.GameObject;
|
||||||
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
|
||||||
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||||
|
import xyz.valnet.hadean.interfaces.DItemRequest;
|
||||||
import xyz.valnet.hadean.interfaces.IWorkshop;
|
import xyz.valnet.hadean.interfaces.IWorkshop;
|
||||||
|
|
||||||
public class WorkOrder extends GameObject {
|
public class WorkOrder extends GameObject {
|
||||||
|
|
@ -9,6 +16,9 @@ public class WorkOrder extends GameObject {
|
||||||
private int count = 10;
|
private int count = 10;
|
||||||
private String name = "Cut Stone Blocks";
|
private String name = "Cut Stone Blocks";
|
||||||
private IWorkshop shop = null;
|
private IWorkshop shop = null;
|
||||||
|
private float maxWork = 1000;
|
||||||
|
|
||||||
|
private Set<Job> relatedJobs;
|
||||||
|
|
||||||
public boolean getRecurring() {
|
public boolean getRecurring() {
|
||||||
return recurring;
|
return recurring;
|
||||||
|
|
@ -22,6 +32,10 @@ public class WorkOrder extends GameObject {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getMaxWork() {
|
||||||
|
return maxWork;
|
||||||
|
}
|
||||||
|
|
||||||
public void increaseCount() {
|
public void increaseCount() {
|
||||||
count ++;
|
count ++;
|
||||||
}
|
}
|
||||||
|
|
@ -40,6 +54,47 @@ public class WorkOrder extends GameObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSpecificToShop(IWorkshop shop) {
|
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) {
|
||||||
|
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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<FCompleted> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ import xyz.valnet.hadean.pathfinding.IPathable;
|
||||||
|
|
||||||
public class Terrain extends GameObject implements IPathable, IWorldBoundsAdapter {
|
public class Terrain extends GameObject implements IPathable, IWorldBoundsAdapter {
|
||||||
|
|
||||||
public static final int WORLD_SIZE = 64;
|
public static final int WORLD_SIZE = 48;
|
||||||
public static final int TILE_SIZE = 8;
|
public static final int TILE_SIZE = 8;
|
||||||
// public static int left, top;
|
// public static int left, top;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
package xyz.valnet.hadean.gameobjects.terrain;
|
package xyz.valnet.hadean.gameobjects.terrain;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import xyz.valnet.engine.graphics.Color;
|
import xyz.valnet.engine.graphics.Color;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.math.Vector4i;
|
import xyz.valnet.engine.math.Vector4i;
|
||||||
import xyz.valnet.engine.scenegraph.GameObject;
|
import xyz.valnet.engine.scenegraph.GameObject;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
import xyz.valnet.hadean.HadeanGame;
|
||||||
|
import xyz.valnet.hadean.enums.WorkType;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.Tree;
|
import xyz.valnet.hadean.gameobjects.worldobjects.Tree;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
|
import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
|
||||||
|
|
@ -17,8 +16,8 @@ import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.zones.FarmPlot;
|
import xyz.valnet.hadean.gameobjects.worldobjects.zones.FarmPlot;
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
||||||
import xyz.valnet.hadean.interfaces.IPingable;
|
import xyz.valnet.hadean.interfaces.IPingable;
|
||||||
import xyz.valnet.hadean.interfaces.ITileThing;
|
|
||||||
import xyz.valnet.hadean.interfaces.IWorkable;
|
import xyz.valnet.hadean.interfaces.IWorkable;
|
||||||
|
import xyz.valnet.hadean.interfaces.IWorldObject;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
import xyz.valnet.hadean.util.Layers;
|
import xyz.valnet.hadean.util.Layers;
|
||||||
|
|
||||||
|
|
@ -32,11 +31,7 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
private final int tileSelector = (int)Math.floor(Math.random() * 4);
|
private final int tileSelector = (int)Math.floor(Math.random() * 4);
|
||||||
private boolean rocks = false;
|
private boolean rocks = false;
|
||||||
|
|
||||||
private Set<ITileThing> stuff = new HashSet<ITileThing>();
|
private Set<IWorldObject> stuff = new HashSet<IWorldObject>();
|
||||||
// TODO remove remove queue, cause like, we dont iterate over
|
|
||||||
// things? so why remove queue them? that just leads to unneccesary
|
|
||||||
// timing issues. you dumb fuck.
|
|
||||||
private List<ITileThing> toRemove = new ArrayList<ITileThing>();
|
|
||||||
|
|
||||||
public Tile(int x, int y) {
|
public Tile(int x, int y) {
|
||||||
setPosition(x, y);
|
setPosition(x, y);
|
||||||
|
|
@ -75,14 +70,14 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
|
|
||||||
public boolean isTileFree() {
|
public boolean isTileFree() {
|
||||||
if(!isWalkable()) return false;
|
if(!isWalkable()) return false;
|
||||||
for(ITileThing thing : stuff) {
|
for(var thing : stuff) {
|
||||||
if(thing instanceof Item) return false;
|
if(thing instanceof Item) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item pickupByItemPredicate(IItemPredicate itemPredicate) {
|
public Item pickupByItemPredicate(IItemPredicate itemPredicate) {
|
||||||
for(ITileThing thing : stuff) {
|
for(var thing : stuff) {
|
||||||
if(thing instanceof Item) {
|
if(thing instanceof Item) {
|
||||||
Item item = (Item) thing;
|
Item item = (Item) thing;
|
||||||
if(item.matches(itemPredicate)) {
|
if(item.matches(itemPredicate)) {
|
||||||
|
|
@ -94,7 +89,9 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pingThings() {
|
public void pingThings() {
|
||||||
for(ITileThing thing : stuff) {
|
// this is a quick lil workaround for a concurerncy issue.
|
||||||
|
// just clone the items
|
||||||
|
for(var thing : new HashSet<IWorldObject>(stuff)) {
|
||||||
if(thing instanceof IPingable) {
|
if(thing instanceof IPingable) {
|
||||||
((IPingable)thing).ping();
|
((IPingable)thing).ping();
|
||||||
}
|
}
|
||||||
|
|
@ -113,26 +110,29 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
if(west != null) west.pingThings();
|
if(west != null) west.pingThings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void placeThing(ITileThing thing) {
|
public void placeThing(IWorldObject thing) {
|
||||||
|
if(thing == this) return;
|
||||||
|
|
||||||
stuff.add(thing);
|
stuff.add(thing);
|
||||||
if(thing instanceof GameObject) {
|
if(thing instanceof GameObject) {
|
||||||
add((GameObject)thing);
|
add((GameObject)thing);
|
||||||
}
|
}
|
||||||
thing.onPlaced(this);
|
|
||||||
|
|
||||||
pingThings();
|
pingThings();
|
||||||
pingNeighbors();
|
pingNeighbors();
|
||||||
|
|
||||||
if(thing instanceof FarmPlot) {
|
if(thing instanceof FarmPlot) {
|
||||||
get(JobBoard.class).postSimpleWorkJob(this);
|
throw new Error("Cannot Till Soil Yet");
|
||||||
|
// get(JobBoard.class).postSimpleWorkJob(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends ITileThing> T removeThing(T thing) {
|
public <T extends IWorldObject> T removeThing(T thing) {
|
||||||
if(!(stuff.contains(thing))) return null;
|
if(thing == this) return null;
|
||||||
if(toRemove.contains(thing)) return null;
|
|
||||||
|
|
||||||
toRemove.add(thing);
|
if(!(stuff.contains(thing))) return null;
|
||||||
|
|
||||||
|
stuff.remove(thing);
|
||||||
|
|
||||||
pingThings();
|
pingThings();
|
||||||
pingNeighbors();
|
pingNeighbors();
|
||||||
|
|
@ -141,20 +141,23 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(float dTime) {
|
public void update(float dTime) {}
|
||||||
for(ITileThing thing : stuff) {
|
|
||||||
if(thing.shouldRemove()) {
|
@Override
|
||||||
toRemove.add(thing);
|
public void renderAlpha() {
|
||||||
}
|
if(!HadeanGame.debugView) return;
|
||||||
}
|
// if(!isWalkable()) {
|
||||||
for(ITileThing thing : toRemove) {
|
// Assets.flat.pushColor(new Color(1, 0.3f, 0.3f, 0.5f));
|
||||||
stuff.remove(thing);
|
// camera.draw(
|
||||||
thing.onRemove();
|
// Layers.MARKERS,
|
||||||
if(thing instanceof GameObject) {
|
// Assets.fillColor,
|
||||||
remove((GameObject)thing);
|
// new TileBox(getWorldPosition().xy(), 1, 1));
|
||||||
}
|
// camera.draw(
|
||||||
}
|
// Layers.MARKERS,
|
||||||
toRemove.clear();
|
// Assets.selectionFrame,
|
||||||
|
// new TileBox(getWorldPosition().xy(), 1, 1));
|
||||||
|
// Assets.flat.popColor();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -174,7 +177,7 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWalkable() {
|
public boolean isWalkable() {
|
||||||
for(ITileThing thing : stuff) {
|
for(var thing : stuff) {
|
||||||
if(!thing.isWalkable()) return false;
|
if(!thing.isWalkable()) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -198,11 +201,6 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getJobName() {
|
|
||||||
return "Till Soil";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean doWork(float dTime) {
|
public boolean doWork(float dTime) {
|
||||||
tillLevel += 0.005f * dTime;
|
tillLevel += 0.005f * dTime;
|
||||||
|
|
@ -222,18 +220,28 @@ public class Tile extends WorldObject implements IWorkable {
|
||||||
public String toThingsString() {
|
public String toThingsString() {
|
||||||
if(stuff.size() == 0) return " - Nothing";
|
if(stuff.size() == 0) return " - Nothing";
|
||||||
String str = "";
|
String str = "";
|
||||||
for(ITileThing thing : stuff) {
|
for(var thing : stuff) {
|
||||||
str += " - " + thing + "\n";
|
str += " - " + thing + "\n";
|
||||||
}
|
}
|
||||||
return str.stripTrailing();
|
return str.stripTrailing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> boolean has(Class<T> clazz) {
|
public <T> boolean has(Class<T> clazz) {
|
||||||
for(ITileThing thing : stuff) {
|
for(var thing : stuff) {
|
||||||
if(clazz.isInstance(thing)) {
|
if(clazz.isInstance(thing)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkType getWorkType() {
|
||||||
|
return WorkType.Farm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWorkableName() {
|
||||||
|
return "Soil";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.scenegraph.GameObject;
|
import xyz.valnet.engine.scenegraph.GameObject;
|
||||||
import xyz.valnet.engine.scenegraph.ITransient;
|
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.Button;
|
||||||
import xyz.valnet.hadean.input.IButtonListener;
|
import xyz.valnet.hadean.input.IButtonListener;
|
||||||
import xyz.valnet.hadean.input.SimpleButton;
|
import xyz.valnet.hadean.input.SimpleButton;
|
||||||
|
|
@ -15,30 +17,25 @@ import xyz.valnet.hadean.util.Layers;
|
||||||
|
|
||||||
public class BottomBar extends GameObject implements IButtonListener, ITransient {
|
public class BottomBar extends GameObject implements IButtonListener, ITransient {
|
||||||
public static final int bottomBarHeight = 32;
|
public static final int bottomBarHeight = 32;
|
||||||
private int screenWidth = 1024;
|
|
||||||
|
|
||||||
private Map<Button, IBottomBarItem> btnItemTable = new HashMap<Button, IBottomBarItem>();
|
private Map<Button, IBottomBarItem> btnItemTable = new HashMap<Button, IBottomBarItem>();
|
||||||
|
|
||||||
private List<IBottomBarItem> items = new ArrayList<IBottomBarItem>();
|
private List<IBottomBarItem> items = new ArrayList<IBottomBarItem>();
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() {
|
|
||||||
items.clear();
|
|
||||||
clearButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerButton(IBottomBarItem newItem) {
|
public void registerButton(IBottomBarItem newItem) {
|
||||||
|
Vector2i screen = getBufferDimensions();
|
||||||
clearButtons();
|
clearButtons();
|
||||||
items.add(newItem);
|
items.add(newItem);
|
||||||
int n = items.size();
|
int n = items.size();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(IBottomBarItem item : items) {
|
for(IBottomBarItem item : items) {
|
||||||
int l = (int)((i / (float) n) * screenWidth);
|
int l = (int)((i / (float) n) * screen.x);
|
||||||
int r = (int)(((i + 1) / (float) n) * screenWidth);
|
int r = (int)(((i + 1) / (float) n) * screen.x);
|
||||||
|
|
||||||
int w = r - l;
|
int w = r - l;
|
||||||
Button btn = new SimpleButton(item.getTabName(), l, 576 - bottomBarHeight, w, bottomBarHeight, Layers.BOTTOM_BAR);
|
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);
|
if(item.isButtonClickSilent()) btn = btn.setClickSound(false);
|
||||||
btn.registerClickListener(this);
|
btn.registerClickListener(this);
|
||||||
add(btn);
|
add(btn);
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ public class HoverQuery extends GameObject implements ITransient {
|
||||||
Vector2f position = camera.screen2world(App.mouseX, App.mouseY);
|
Vector2f position = camera.screen2world(App.mouseX, App.mouseY);
|
||||||
thingStrings.clear();
|
thingStrings.clear();
|
||||||
for(WorldObject obj : getAll(WorldObject.class)) {
|
for(WorldObject obj : getAll(WorldObject.class)) {
|
||||||
Box box = obj.getWorldBox();
|
Box box = obj.getSelectionWorldBox();
|
||||||
if(box.contains(position)) {
|
if(box.contains(position)) {
|
||||||
thingStrings.add(obj.getName());
|
thingStrings.add(obj.getName());
|
||||||
if (!HadeanGame.debugView) continue;
|
if (!HadeanGame.debugView) continue;
|
||||||
|
|
@ -58,7 +58,7 @@ public class HoverQuery extends GameObject implements ITransient {
|
||||||
public void render() {
|
public void render() {
|
||||||
if(!visible) return;
|
if(!visible) return;
|
||||||
Drawing.setLayer(Layers.LOW_PRIORITY_UI);
|
Drawing.setLayer(Layers.LOW_PRIORITY_UI);
|
||||||
int i = 576 - BottomBar.bottomBarHeight - 24;
|
int i = getBufferDimensions().y - BottomBar.bottomBarHeight - 24;
|
||||||
for(String thingString : thingStrings) {
|
for(String thingString : thingStrings) {
|
||||||
for(String str : thingString.split("\n")) {
|
for(String str : thingString.split("\n")) {
|
||||||
Assets.font.drawStringOutlined(str, 8, i);
|
Assets.font.drawStringOutlined(str, 8, i);
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,17 @@ import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab;
|
||||||
public class Popup extends ImmediateUI {
|
public class Popup extends ImmediateUI {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void gui() {
|
protected void gui(int screenWidth, int screenHeight) {
|
||||||
|
|
||||||
window(10, 100, 1004, 200, () -> {
|
int desireWidth = 500;
|
||||||
|
int desiredHeight = 300;
|
||||||
|
|
||||||
|
window(
|
||||||
|
screenWidth / 2 - desireWidth / 2,
|
||||||
|
screenHeight / 2 - desiredHeight / 2,
|
||||||
|
desireWidth,
|
||||||
|
desiredHeight,
|
||||||
|
() -> {
|
||||||
header(" Popup Test");
|
header(" Popup Test");
|
||||||
|
|
||||||
horizontal(() -> {
|
horizontal(() -> {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import xyz.valnet.engine.graphics.ImmediateUI;
|
||||||
import xyz.valnet.engine.scenegraph.ITransient;
|
import xyz.valnet.engine.scenegraph.ITransient;
|
||||||
import xyz.valnet.hadean.Constants;
|
import xyz.valnet.hadean.Constants;
|
||||||
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
|
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
|
||||||
|
import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectionChangeListener;
|
import xyz.valnet.hadean.interfaces.ISelectionChangeListener;
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
|
|
@ -63,6 +64,7 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
if(!opened && openness < 0.0001f && selected.size() > 0) {
|
if(!opened && openness < 0.0001f && selected.size() > 0) {
|
||||||
resetCache();
|
resetCache();
|
||||||
}
|
}
|
||||||
|
if(updateActionsFlag) updateActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetCache() {
|
private void resetCache() {
|
||||||
|
|
@ -72,6 +74,16 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
actions.clear();
|
actions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateActions() {
|
||||||
|
actions.clear();
|
||||||
|
updateActionsFlag = false;
|
||||||
|
for(ISelectable selectable : selected) {
|
||||||
|
for(Action action : selectable.getActions()) {
|
||||||
|
actions.add(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectionChanged(List<ISelectable> newSelection) {
|
public void selectionChanged(List<ISelectable> newSelection) {
|
||||||
|
|
||||||
|
|
@ -93,9 +105,6 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
|
|
||||||
properName = selectable.getName();
|
properName = selectable.getName();
|
||||||
genericName = selectable.getGenericName();
|
genericName = selectable.getGenericName();
|
||||||
for(Action action : selectable.getActions()) {
|
|
||||||
actions.add(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!selectedByType.containsKey(clazz)) {
|
if(!selectedByType.containsKey(clazz)) {
|
||||||
selectedByType.put(clazz, new ArrayList<ISelectable>());
|
selectedByType.put(clazz, new ArrayList<ISelectable>());
|
||||||
|
|
@ -104,6 +113,8 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
selectedByType.get(clazz).add(selectable);
|
selectedByType.get(clazz).add(selectable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateActions();
|
||||||
|
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,13 +127,15 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
return (int) Math.round(lerp(a, b, openness));
|
return (int) Math.round(lerp(a, b, openness));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean updateActionsFlag = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void gui() {
|
protected void gui(int screenWidth, int screenHeight) {
|
||||||
// if(selected.isEmpty()) return;
|
// if(selected.isEmpty()) return;
|
||||||
if(!opened && openness <= 0.0001f) return;
|
if(!opened && openness <= 0.0001f) return;
|
||||||
|
|
||||||
// main window
|
// main window
|
||||||
window(animate(-width - 50, 0), 576 - height - BottomBar.bottomBarHeight + 1, width, height, () -> {
|
window(animate(-width - 50, 0), screenHeight - height - BottomBar.bottomBarHeight + 1, width, height, () -> {
|
||||||
if(selectedByType.size() == 1) {
|
if(selectedByType.size() == 1) {
|
||||||
if(selectedCount == 1) {
|
if(selectedCount == 1) {
|
||||||
text(properName);
|
text(properName);
|
||||||
|
|
@ -132,7 +145,7 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
if(details.length == 0) {
|
if(details.length == 0) {
|
||||||
text("No details available.");
|
text("No details available.");
|
||||||
} else for(Detail detail : details) {
|
} else for(Detail detail : details) {
|
||||||
text(detail.toString(30));
|
text(detail.toString(20));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -156,11 +169,12 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
});
|
});
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
window(width - 1, animate(576 + 50, 576 - 48 - BottomBar.bottomBarHeight + 1), 1024 - width + 1, 48, () -> {
|
window(width - 1, animate(screenHeight + 50, screenHeight - 48 - BottomBar.bottomBarHeight + 1), screenWidth - width + 1, 48, () -> {
|
||||||
if(selectedByType.size() == 1) {
|
if(selectedByType.size() == 1) {
|
||||||
horizontal(() -> {
|
horizontal(() -> {
|
||||||
for(Action action : actions) {
|
for(Action action : actions) {
|
||||||
if(button(action.name)) {
|
if(button(action.name)) {
|
||||||
|
updateActionsFlag = true;
|
||||||
for(ISelectable selectable : selected) {
|
for(ISelectable selectable : selected) {
|
||||||
selectable.runAction(action);
|
selectable.runAction(action);
|
||||||
}
|
}
|
||||||
|
|
@ -169,8 +183,8 @@ public class SelectionUI extends ImmediateUI implements ISelectionChangeListener
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
space(8);
|
space(8, 16);
|
||||||
text(" Select an Item Type");
|
text("Select an Item Type");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public class WorkshopOrdersUI extends ImmediateUI implements ITransient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void gui() {
|
protected void gui(int screenWidth, int screenHeight) {
|
||||||
if(shop == null) return;
|
if(shop == null) return;
|
||||||
|
|
||||||
window(0, 0, 200, 300, () -> {
|
window(0, 0, 200, 300, () -> {
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,10 @@ import xyz.valnet.engine.graphics.Drawing;
|
||||||
import xyz.valnet.engine.math.TileBox;
|
import xyz.valnet.engine.math.TileBox;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.scenegraph.GameObject;
|
import xyz.valnet.engine.scenegraph.GameObject;
|
||||||
import xyz.valnet.hadean.designation.CutTreesDesignation;
|
|
||||||
import xyz.valnet.hadean.designation.HaulItemDesignation;
|
|
||||||
import xyz.valnet.hadean.gameobjects.ui.BottomBar;
|
import xyz.valnet.hadean.gameobjects.ui.BottomBar;
|
||||||
|
import xyz.valnet.hadean.designations.CutTreesDesignation;
|
||||||
|
import xyz.valnet.hadean.designations.HaulItemDesignation;
|
||||||
|
import xyz.valnet.hadean.enums.BuildType;
|
||||||
import xyz.valnet.hadean.gameobjects.Camera;
|
import xyz.valnet.hadean.gameobjects.Camera;
|
||||||
import xyz.valnet.hadean.gameobjects.inputlayer.BuildLayer;
|
import xyz.valnet.hadean.gameobjects.inputlayer.BuildLayer;
|
||||||
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
|
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
|
||||||
|
|
@ -23,7 +24,6 @@ import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Bed;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.MasonWorkshop;
|
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.MasonWorkshop;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Quarry;
|
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Quarry;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Wall;
|
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Wall;
|
||||||
import xyz.valnet.hadean.interfaces.BuildType;
|
|
||||||
import xyz.valnet.hadean.interfaces.IBuildLayerListener;
|
import xyz.valnet.hadean.interfaces.IBuildLayerListener;
|
||||||
import xyz.valnet.hadean.interfaces.IBuildable;
|
import xyz.valnet.hadean.interfaces.IBuildable;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||||
|
|
@ -53,7 +53,7 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IBuildLay
|
||||||
BuildTab.registerBuildable(Wall.class);
|
BuildTab.registerBuildable(Wall.class);
|
||||||
|
|
||||||
BuildTab.registerBuildable(Quarry.class);
|
BuildTab.registerBuildable(Quarry.class);
|
||||||
|
|
||||||
BuildTab.registerBuildable(FarmPlot.class);
|
BuildTab.registerBuildable(FarmPlot.class);
|
||||||
BuildTab.registerBuildable(Stockpile.class);
|
BuildTab.registerBuildable(Stockpile.class);
|
||||||
BuildTab.registerBuildable(MasonWorkshop.class);
|
BuildTab.registerBuildable(MasonWorkshop.class);
|
||||||
|
|
@ -186,12 +186,12 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IBuildLay
|
||||||
return "Build";
|
return "Build";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gui() {
|
public void gui(int screenWidth, int screenHeight) {
|
||||||
if(!shouldRender()) return;
|
if(!shouldRender()) return;
|
||||||
|
|
||||||
int height = 8 + 16 + 8 + buildables.size() * (32 + 8);
|
int height = 8 + 16 + 8 + buildables.size() * (32 + 8);
|
||||||
|
|
||||||
window(animate(-180, 0), 576 - BottomBar.bottomBarHeight - height + 1, 150, height, () -> {
|
window(animate(-180, 0), screenHeight - BottomBar.bottomBarHeight - height + 1, 150, height, () -> {
|
||||||
text("Build");
|
text("Build");
|
||||||
|
|
||||||
for(String category : buildables.keySet()) {
|
for(String category : buildables.keySet()) {
|
||||||
|
|
@ -206,7 +206,10 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IBuildLay
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window(149, animate(576 + 50, 576 - BottomBar.bottomBarHeight - 16 - 32 + 1 - 24), 875, 48 + 24, () -> {
|
window(149, animate(screenHeight + 50, screenHeight - BottomBar.bottomBarHeight - 16 - 32 + 1 - 24),
|
||||||
|
screenWidth - (1024 - 875),
|
||||||
|
48 + 24,
|
||||||
|
() -> {
|
||||||
if(selectedCategory == null) {
|
if(selectedCategory == null) {
|
||||||
space(20);
|
space(20);
|
||||||
text(" Select a Category...");
|
text(" Select a Category...");
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ public class DebugTab extends Tab implements IKeyboardListener {
|
||||||
protected void onOpen() {}
|
protected void onOpen() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void gui() {
|
protected void gui(int screenWidth, int screenHeight) {
|
||||||
if(!shouldRender()) return;
|
if(!shouldRender()) return;
|
||||||
|
|
||||||
window(0, animate(-200, 0), 1024 - width + 1, 176, () -> {
|
window(0, animate(-200, 0), screenWidth - width + 1, 176, () -> {
|
||||||
for(int i = 10; i > logs.size(); i --) {
|
for(int i = 10; i > logs.size(); i --) {
|
||||||
text(" ");
|
text(" ");
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +36,7 @@ public class DebugTab extends Tab implements IKeyboardListener {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window(animate(1050, 1024 - width), 0, width, 576 - BottomBar.bottomBarHeight + 1, () -> {
|
window(animate(screenWidth + 30, screenWidth - width), 0, width, screenHeight - BottomBar.bottomBarHeight + 1, () -> {
|
||||||
text("Debug");
|
text("Debug");
|
||||||
space(8);
|
space(8);
|
||||||
|
|
||||||
|
|
@ -59,7 +59,6 @@ public class DebugTab extends Tab implements IKeyboardListener {
|
||||||
HadeanGame.debugView = !HadeanGame.debugView;
|
HadeanGame.debugView = !HadeanGame.debugView;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> logs = new LinkedList<String>();
|
private static List<String> logs = new LinkedList<String>();
|
||||||
|
|
@ -76,10 +75,20 @@ public class DebugTab extends Tab implements IKeyboardListener {
|
||||||
log(obj.toString());
|
log(obj.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean keyTest = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyPress(int code) {
|
public void keyPress(int code) {
|
||||||
|
if(keyTest) {
|
||||||
|
DebugTab.log("Key Code:" + code);
|
||||||
|
keyTest = false;
|
||||||
|
}
|
||||||
if(code == 96) { // tilde
|
if(code == 96) { // tilde
|
||||||
evoke();
|
evoke();
|
||||||
|
} else if(code == 281) { // insert? top row second to last
|
||||||
|
keyTest = true;
|
||||||
|
} else if(code == 301) { // f12
|
||||||
|
HadeanGame.debugView = !HadeanGame.debugView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@ public class JobBoardTab extends Tab {
|
||||||
private int height = 200;
|
private int height = 200;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void gui() {
|
protected void gui(int screenWidth, int screenHeight) {
|
||||||
if(!shouldRender()) return;
|
if(!shouldRender()) return;
|
||||||
|
|
||||||
window(0, animate(576 + 50, 576 - BottomBar.bottomBarHeight - height + 1), 1024, height, () -> {
|
window(0, animate(screenHeight + 50, screenHeight - BottomBar.bottomBarHeight - height + 1), screenWidth, height, () -> {
|
||||||
horizontal(() -> {
|
horizontal(() -> {
|
||||||
vertical(() -> {
|
vertical(() -> {
|
||||||
text("Valid");
|
text("Valid");
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ public class MenuTab extends Tab implements IPauser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void gui() {
|
protected void gui(int screenWidth, int screenHeight) {
|
||||||
if(!shouldRender()) return;
|
if(!shouldRender()) return;
|
||||||
|
|
||||||
window(1024 / 2 - width / 2, animate(-height - 50, 576 / 2 - height / 2), width, height, () -> {
|
window(screenWidth / 2 - width / 2, animate(-height - 50, screenHeight / 2 - height / 2), width, height, () -> {
|
||||||
text(" === Paused ===");
|
text(" === Paused ===");
|
||||||
space(8);
|
space(8);
|
||||||
if(button("Resume")) {
|
if(button("Resume")) {
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,34 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects;
|
package xyz.valnet.hadean.gameobjects.worldobjects;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.TileBox;
|
import xyz.valnet.engine.math.TileBox;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
import xyz.valnet.hadean.gameobjects.ui.Popup;
|
||||||
import xyz.valnet.hadean.interfaces.IBuildable;
|
import xyz.valnet.hadean.interfaces.IBuildable;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||||
import xyz.valnet.hadean.interfaces.ITileThing;
|
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
import xyz.valnet.hadean.util.detail.Detail;
|
import xyz.valnet.hadean.util.detail.Detail;
|
||||||
|
|
||||||
public abstract class Buildable extends WorldObject implements IBuildable, ITileThing, ISelectable {
|
// Buildable, means its in the build menu
|
||||||
|
public abstract class Buildable extends WorldObject implements IBuildable, ISelectable {
|
||||||
|
|
||||||
|
public static Action CANCEL = new Action("Cancel");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildAt(TileBox box) {
|
public void buildAt(TileBox box) {
|
||||||
setPosition(box.asBox());
|
setPosition(box.asBox());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlaced(Tile tile) {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action[] getActions() {
|
public Action[] getActions() {
|
||||||
return new Action[] {};
|
return new Action[] {
|
||||||
|
CANCEL
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAction(Action action) {
|
public void runAction(Action action) {
|
||||||
|
if(action == CANCEL) {
|
||||||
|
add(new Popup());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ package xyz.valnet.hadean.gameobjects.worldobjects;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Box;
|
import xyz.valnet.engine.math.Box;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
|
import xyz.valnet.hadean.enums.WorkType;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.Job;
|
import xyz.valnet.hadean.gameobjects.jobs.Job;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Log;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Log;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||||
import xyz.valnet.hadean.interfaces.ITileThing;
|
|
||||||
import xyz.valnet.hadean.interfaces.IWorkable;
|
import xyz.valnet.hadean.interfaces.IWorkable;
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
|
|
@ -16,7 +16,7 @@ import xyz.valnet.hadean.util.detail.BooleanDetail;
|
||||||
import xyz.valnet.hadean.util.detail.Detail;
|
import xyz.valnet.hadean.util.detail.Detail;
|
||||||
import xyz.valnet.hadean.util.detail.PercentDetail;
|
import xyz.valnet.hadean.util.detail.PercentDetail;
|
||||||
|
|
||||||
public class Tree extends WorldObject implements ITileThing, ISelectable, IWorkable {
|
public class Tree extends WorldObject implements ISelectable, IWorkable {
|
||||||
|
|
||||||
private Job chopJob = null;
|
private Job chopJob = null;
|
||||||
|
|
||||||
|
|
@ -56,9 +56,9 @@ public class Tree extends WorldObject implements ITileThing, ISelectable, IWorka
|
||||||
public void runAction(Action action) {
|
public void runAction(Action action) {
|
||||||
if(action == ACTION_CHOP) {
|
if(action == ACTION_CHOP) {
|
||||||
if(chopJob == null) {
|
if(chopJob == null) {
|
||||||
chopJob = get(JobBoard.class).postSimpleWorkJob(this);
|
chopJob = get(JobBoard.class).post(this);
|
||||||
} else {
|
} else {
|
||||||
chopJob.close();
|
get(JobBoard.class).rescind(chopJob);
|
||||||
chopJob = null;
|
chopJob = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -85,6 +85,7 @@ public class Tree extends WorldObject implements ITileThing, ISelectable, IWorka
|
||||||
@Override
|
@Override
|
||||||
public boolean doWork(float dTime) {
|
public boolean doWork(float dTime) {
|
||||||
choppage += dTime;
|
choppage += dTime;
|
||||||
|
if(getProgress() >= 1.0) remove(this);
|
||||||
return getProgress() >= 1;
|
return getProgress() >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,26 +111,24 @@ public class Tree extends WorldObject implements ITileThing, ISelectable, IWorka
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldRemove() {
|
protected void cleanup() {
|
||||||
return getProgress() >= 1.0;
|
super.cleanup();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {
|
|
||||||
Vector2i pos = getWorldPosition().xy();
|
Vector2i pos = getWorldPosition().xy();
|
||||||
add(new Log(pos.x, pos.y));
|
add(new Log(pos.x, pos.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getJobName() {
|
|
||||||
return "Chop Tree";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Tree";
|
return "Tree";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlaced(Tile tile) {}
|
public WorkType getWorkType() {
|
||||||
|
return WorkType.Chop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWorkableName() {
|
||||||
|
return "Tree";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@ import xyz.valnet.engine.scenegraph.GameObject;
|
||||||
import xyz.valnet.hadean.gameobjects.Camera;
|
import xyz.valnet.hadean.gameobjects.Camera;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
|
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
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 implements IWorldObject {
|
||||||
|
|
||||||
public abstract class WorldObject extends GameObject {
|
|
||||||
|
|
||||||
// TODO make it just a box lawl
|
// TODO make it just a box lawl
|
||||||
private int x;
|
private int x;
|
||||||
private int y;
|
private int y;
|
||||||
|
|
@ -39,11 +39,11 @@ public abstract class WorldObject extends GameObject {
|
||||||
@Override
|
@Override
|
||||||
protected void start() {
|
protected void start() {
|
||||||
setPosition(x, y, w, h);
|
setPosition(x, y, w, h);
|
||||||
|
getTile().placeThing(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTileLinks(Set<Tile> tiles) {
|
private void updateTileLinks(Set<Tile> tiles) {
|
||||||
if(tiles == null || tiles.size() == 0) return;
|
if(tiles == null || tiles.size() == 0) return;
|
||||||
if(!(this instanceof ITileThing)) return;
|
|
||||||
|
|
||||||
Set<Tile> removeTiles = new HashSet<Tile>();
|
Set<Tile> removeTiles = new HashSet<Tile>();
|
||||||
Set<Tile> addTiles = new HashSet<Tile>();
|
Set<Tile> addTiles = new HashSet<Tile>();
|
||||||
|
|
@ -60,26 +60,13 @@ public abstract class WorldObject extends GameObject {
|
||||||
|
|
||||||
for(Tile tile : removeTiles) {
|
for(Tile tile : removeTiles) {
|
||||||
linkedTiles.remove(tile);
|
linkedTiles.remove(tile);
|
||||||
if(this instanceof ITileThing) {
|
tile.removeThing(this);
|
||||||
tile.removeThing((ITileThing) this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Tile tile : addTiles) {
|
for(Tile tile : addTiles) {
|
||||||
linkedTiles.add(tile);
|
linkedTiles.add(tile);
|
||||||
if(this instanceof ITileThing) {
|
tile.placeThing(this);
|
||||||
tile.placeThing((ITileThing) this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(linkedTiles.size() == 0 && inScene()) {
|
|
||||||
remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(linkedTiles.size() != 0 && !inScene()) {
|
|
||||||
add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setPosition(Vector4i vector) {
|
protected void setPosition(Vector4i vector) {
|
||||||
|
|
@ -119,6 +106,14 @@ public abstract class WorldObject extends GameObject {
|
||||||
return terrain.getTile(x, y);
|
return terrain.getTile(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tile getTile(int x, int y) {
|
||||||
|
return terrain.getTile(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tile getTile(Vector2i location) {
|
||||||
|
return terrain.getTile(location.x, location.y);
|
||||||
|
}
|
||||||
|
|
||||||
public Set<Tile> getTiles() {
|
public Set<Tile> getTiles() {
|
||||||
return linkedTiles;
|
return linkedTiles;
|
||||||
}
|
}
|
||||||
|
|
@ -129,8 +124,15 @@ public abstract class WorldObject extends GameObject {
|
||||||
|
|
||||||
public abstract String getName();
|
public abstract String getName();
|
||||||
|
|
||||||
public Box getWorldBox() {
|
public Box getSelectionWorldBox() {
|
||||||
return new Box(x, y, w, h);
|
return new Box(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cleanup() {
|
||||||
|
for(Tile tile : this.getTiles()) {
|
||||||
|
tile.removeThing(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,18 @@ import static org.lwjgl.opengl.GL20.glVertexAttrib2f;
|
||||||
|
|
||||||
import xyz.valnet.engine.graphics.Color;
|
import xyz.valnet.engine.graphics.Color;
|
||||||
import xyz.valnet.engine.graphics.Drawing;
|
import xyz.valnet.engine.graphics.Drawing;
|
||||||
|
import xyz.valnet.engine.math.Box;
|
||||||
|
import xyz.valnet.engine.math.TileBox;
|
||||||
import xyz.valnet.engine.math.Vector2f;
|
import xyz.valnet.engine.math.Vector2f;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.shaders.SimpleShader;
|
import xyz.valnet.engine.shaders.SimpleShader;
|
||||||
import xyz.valnet.hadean.HadeanGame;
|
import xyz.valnet.hadean.HadeanGame;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
|
import xyz.valnet.hadean.gameobjects.ui.tabs.DebugTab;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
|
import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
|
||||||
|
import xyz.valnet.hadean.interfaces.IDestination;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||||
import xyz.valnet.hadean.pathfinding.AStarPathfinder;
|
import xyz.valnet.hadean.pathfinding.AStarPathfinder;
|
||||||
import xyz.valnet.hadean.pathfinding.IPathfinder;
|
import xyz.valnet.hadean.pathfinding.IPathfinder;
|
||||||
import xyz.valnet.hadean.pathfinding.Node;
|
|
||||||
import xyz.valnet.hadean.pathfinding.Path;
|
import xyz.valnet.hadean.pathfinding.Path;
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
|
|
@ -27,147 +28,135 @@ import static xyz.valnet.engine.util.Math.lerp;
|
||||||
|
|
||||||
public abstract class Agent extends WorldObject implements ISelectable {
|
public abstract class Agent extends WorldObject implements ISelectable {
|
||||||
public abstract String getName();
|
public abstract String getName();
|
||||||
private float frameCounter = 0;
|
|
||||||
private int speed = 100 + (int)(Math.random() * 50);
|
private int speed = 100 + (int)(Math.random() * 50);
|
||||||
|
private float frameCounter = speed;
|
||||||
|
|
||||||
private IPathfinder pathfinder;
|
private IPathfinder pathfinder;
|
||||||
private Path path = null;
|
|
||||||
|
|
||||||
private boolean stopPathingFlag = false;
|
private boolean isAnimating() {
|
||||||
|
return frameCounter < speed;
|
||||||
public boolean isPathing() {
|
|
||||||
return path != null && !path.isComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2f getCalculatedPosition() {
|
|
||||||
if(path == null || path.isComplete()) return getWorldPosition().xy().asFloat();
|
|
||||||
Vector2i pos = getWorldPosition().xy();
|
|
||||||
Vector2f nextPos = path.peek().getPosition().asFloat();
|
|
||||||
return new Vector2f(
|
|
||||||
lerp(pos.x, nextPos.x, frameCounter / (float)speed),
|
|
||||||
lerp(pos.y, nextPos.y, frameCounter / (float)speed)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
super.start();
|
super.start();
|
||||||
frameCounter = 0;
|
frameCounter = speed;
|
||||||
pathfinder = new AStarPathfinder(terrain);
|
pathfinder = new AStarPathfinder(terrain);
|
||||||
|
previousPosition = getWorldPosition().xy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(float dTime) {
|
public void update(float dTime) {
|
||||||
think();
|
|
||||||
act(dTime);
|
|
||||||
postAct();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void postAct();
|
|
||||||
|
|
||||||
private void move(float dTime) {
|
|
||||||
frameCounter += dTime;
|
frameCounter += dTime;
|
||||||
if(frameCounter >= speed) {
|
|
||||||
Vector2i nextPos = path.pop().getPosition();
|
// if we're already doing something, let it happen
|
||||||
setPosition(nextPos.x, nextPos.y);
|
if(isAnimating()) return;
|
||||||
if(nextPath != null) {
|
|
||||||
path = nextPath;
|
// if we're not doing anything and we have a path,
|
||||||
nextPath = null;
|
// try to take a step
|
||||||
}
|
if(path != null) takeStep();
|
||||||
if(path.isComplete()) path = null;
|
if(isAnimating()) return;
|
||||||
frameCounter -= speed;
|
|
||||||
if(stopPathingFlag) {
|
// if we're STILL doing jack, but we have a destination
|
||||||
path = null;
|
// try to path to that place
|
||||||
nextPath = null;
|
if(dsts != null) goTo(dsts);
|
||||||
stopPathingFlag = false;
|
if(isAnimating()) return;
|
||||||
|
|
||||||
|
// if all fails, tell the agent we're idle
|
||||||
|
idle(dTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void goTo(int x, int y) {
|
||||||
|
// Vector2i pos = getWorldPosition().xy();
|
||||||
|
// Path newPath = pathfinder.getPath(pos.x, pos.y, x, y);
|
||||||
|
// path = newPath;
|
||||||
|
// }
|
||||||
|
|
||||||
|
private Vector2i previousPosition;
|
||||||
|
|
||||||
|
private void takeStep() {
|
||||||
|
path.pop();
|
||||||
|
if(path.isComplete()) {
|
||||||
|
DebugTab.log("Finished Pathing");
|
||||||
|
if(path.getDestination().getPosition().equals(dsts)) {
|
||||||
|
dsts = null;
|
||||||
}
|
}
|
||||||
|
path = null;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
if(!getTile(path.peek().getPosition()).isWalkable()) {
|
||||||
|
goTo(dsts);
|
||||||
protected void stopPathing() {
|
return;
|
||||||
stopPathingFlag = true;
|
|
||||||
nextPath = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void correctPath() {
|
|
||||||
if(path != null && path.isComplete()) path = null;
|
|
||||||
if(path == null) return;
|
|
||||||
if(path.peek().getPosition().equals(this.getWorldPosition().xy())) {
|
|
||||||
path.pop();
|
|
||||||
}
|
|
||||||
if(path != null && path.isComplete()) path = null;
|
|
||||||
if(path == null) return;
|
|
||||||
Tile nextTile = terrain.getTile(path.peek().getPosition());
|
|
||||||
if(!nextTile.isWalkable()) {
|
|
||||||
Vector2i pos = getWorldPosition().xy();
|
|
||||||
path = pathfinder.getPath(
|
|
||||||
pos.x,
|
|
||||||
pos.y,
|
|
||||||
path.dst.x,
|
|
||||||
path.dst.y
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
updatePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void think() {
|
private void updatePath() {
|
||||||
correctPath();
|
frameCounter = 0;
|
||||||
|
Vector2i nextPos = path.peek().getPosition();
|
||||||
|
if(path.isComplete()) path = null;
|
||||||
|
previousPosition = getWorldPosition().xy();
|
||||||
|
setPosition(nextPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean act(float dTime) {
|
private Path path;
|
||||||
if(path != null) {
|
private IDestination dsts;
|
||||||
move(dTime);
|
|
||||||
|
public void stopPathing() {
|
||||||
|
path = null;
|
||||||
|
dsts = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean goTo(IDestination location) {
|
||||||
|
if(isAnimating()) {
|
||||||
|
stopPathing();
|
||||||
|
dsts = location;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Path newPath = pathfinder.getBestPath(getWorldPosition().xy(), location);
|
||||||
return false;
|
path = newPath;
|
||||||
}
|
if(path == null) return false;
|
||||||
|
dsts = location;
|
||||||
private Path nextPath = null;
|
updatePath();
|
||||||
|
return true;
|
||||||
public void goTo(int x, int y) {
|
|
||||||
Vector2i pos = getWorldPosition().xy();
|
|
||||||
Path newPath = pathfinder.getPath(pos.x, pos.y, x, y);
|
|
||||||
if(path == null) {
|
|
||||||
path = newPath;
|
|
||||||
frameCounter -= 0;
|
|
||||||
} else {
|
|
||||||
nextPath = newPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goToClosest(Vector2i[] destinations) {
|
|
||||||
Path newPath = pathfinder.getBestPath(getWorldPosition().xy(), destinations);
|
|
||||||
if(path == null) {
|
|
||||||
path = newPath;
|
|
||||||
frameCounter = 0;
|
|
||||||
} else {
|
|
||||||
nextPath = newPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goTo(Vector2i location) {
|
|
||||||
goTo(location.x, location.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void wander() {
|
public void wander() {
|
||||||
Vector2i pos = getWorldPosition().xy();
|
Vector2i pos;
|
||||||
int randomX = (int)Math.floor(Math.random() * Terrain.WORLD_SIZE);
|
Vector2i random;
|
||||||
int randomY = (int)Math.floor(Math.random() * Terrain.WORLD_SIZE);
|
do {
|
||||||
path = pathfinder.getPath(pos.x, pos.y, randomX, randomY);
|
pos = getWorldPosition().xy();
|
||||||
|
random = new Vector2f(
|
||||||
|
2 + (float) Math.random() * 10,
|
||||||
|
(float) Math.random() * (float) Math.PI * 2
|
||||||
|
).toCartesian().asInt().add(pos);
|
||||||
|
|
||||||
|
} while (terrain.isOutOfBounds(random.x, random.y));
|
||||||
|
|
||||||
|
goTo(new IDestination.Single(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderAlpha() {
|
public void renderAlpha() {
|
||||||
if(!HadeanGame.debugView) return;
|
if(!HadeanGame.debugView) return;
|
||||||
|
camera.drawProgressBar(frameCounter / speed, new Box(getWorldPosition()));
|
||||||
|
|
||||||
Drawing.setLayer(Layers.GROUND_MARKERS);
|
Drawing.setLayer(Layers.GROUND_MARKERS);
|
||||||
Assets.flat.pushColor(Color.white.withAlpha(0.6f));
|
Assets.flat.pushColor(new Color(0.1f, 0.7f, 1.0f, 0.6f));
|
||||||
|
|
||||||
if(path != null) {
|
if(path != null) {
|
||||||
|
Assets.flat.swapColor(Color.white.withAlpha(0.6f));
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(Node node : path) {
|
for(var node : path) {
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
Vector2i u, v;
|
Vector2i u, v;
|
||||||
|
|
||||||
Vector2i pos = getWorldPosition().xy();
|
Vector2i pos = getWorldPosition().xy();
|
||||||
|
|
||||||
if(node.from == null) u = camera.world2screen(pos.x, pos.y);
|
if(node.from == null) u = camera.world2screen(pos.x, pos.y);
|
||||||
else u = camera.world2screen(node.from.x + 0.5f, node.from.y + 0.5f);
|
else u = camera.world2screen(node.from.x + 0.5f, node.from.y + 0.5f);
|
||||||
|
|
||||||
|
|
@ -177,15 +166,24 @@ public abstract class Agent extends WorldObject implements ISelectable {
|
||||||
u = camera.world2screen(getCalculatedPosition().add(new Vector2f(0.5f, 0.5f)));
|
u = camera.world2screen(getCalculatedPosition().add(new Vector2f(0.5f, 0.5f)));
|
||||||
}
|
}
|
||||||
glVertexAttrib2f(SimpleShader.TEX_COORD, 0, 88 / 256f);
|
glVertexAttrib2f(SimpleShader.TEX_COORD, 0, 88 / 256f);
|
||||||
glVertex3f(u.x, u.y, 3f);
|
glVertex3f(u.x, u.y, Layers.GROUND_MARKERS);
|
||||||
glVertexAttrib2f(SimpleShader.TEX_COORD, 0, 88 / 255f);
|
glVertexAttrib2f(SimpleShader.TEX_COORD, 0, 88 / 255f);
|
||||||
glVertex3f(v.x, v.y, 3f);
|
glVertex3f(v.x, v.y, Layers.GROUND_MARKERS);
|
||||||
glEnd();
|
glEnd();
|
||||||
count ++;
|
count ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
camera.draw(Layers.GROUND_MARKERS, Assets.selectionFrame, path.getDestination().getPosition().getTileBox());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assets.flat.swapColor(Color.yellow);
|
||||||
|
if(dsts != null) {
|
||||||
|
for(Vector2i dst : dsts.getDestinations())
|
||||||
|
camera.draw(
|
||||||
|
Layers.GROUND_MARKERS,
|
||||||
|
Assets.selectionFrame,
|
||||||
|
new TileBox(dst, 1, 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Assets.flat.popColor();
|
Assets.flat.popColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,9 +197,38 @@ public abstract class Agent extends WorldObject implements ISelectable {
|
||||||
return ISelectable.Priority.HIGH;
|
return ISelectable.Priority.HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2i getDestination() {
|
@Override
|
||||||
if(nextPath != null) return nextPath.getDestination().getPosition();
|
public void runAction(Action action) {}
|
||||||
if(path == null) return null;
|
|
||||||
return path.getDestination().getPosition();
|
@Override
|
||||||
|
public boolean isWalkable() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public Box getSelectionWorldBox() {
|
||||||
|
return new Box(getCalculatedPosition(), 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void idle(float dTime);
|
||||||
|
|
||||||
|
protected boolean isPathing() {
|
||||||
|
return dsts != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2f getCalculatedPosition() {
|
||||||
|
if(!isAnimating())
|
||||||
|
return getWorldPosition().xy().asFloat();
|
||||||
|
return new Vector2f(
|
||||||
|
lerp(previousPosition.x, getWorldPosition().x, frameCounter / speed),
|
||||||
|
lerp(previousPosition.y, getWorldPosition().y, frameCounter / speed)
|
||||||
|
);
|
||||||
|
// if(path == null || path.isComplete()) return getWorldPosition().xy().asFloat();
|
||||||
|
// Vector2i pos = getWorldPosition().xy();
|
||||||
|
// Vector2f nextPos = path.peek().getPosition().asFloat();
|
||||||
|
// return new Vector2f(
|
||||||
|
// lerp(pos.x, nextPos.x, frameCounter / (float)speed),
|
||||||
|
// lerp(pos.y, nextPos.y, frameCounter / (float)speed)
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
|
||||||
|
|
||||||
public abstract class Activity implements Serializable {
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface ActivityCancellationCallback extends Serializable {
|
|
||||||
public void apply(Activity activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean isUrgent();
|
|
||||||
public abstract float getBenefit();
|
|
||||||
public abstract boolean isValid();
|
|
||||||
public abstract void act(float dTime);
|
|
||||||
public abstract void begin(ActivityCancellationCallback callback);
|
|
||||||
public abstract void end();
|
|
||||||
public abstract String toString();
|
|
||||||
public abstract Vector2i[] getTargetLocations();
|
|
||||||
}
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn;
|
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.Job;
|
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.Job.JobStep;
|
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
|
||||||
|
|
||||||
public class JobActivity extends Activity {
|
|
||||||
|
|
||||||
private JobBoard jobboard;
|
|
||||||
private Pawn worker;
|
|
||||||
private Job job;
|
|
||||||
|
|
||||||
public JobActivity(Pawn worker, JobBoard jobboard) {
|
|
||||||
this.worker = worker;
|
|
||||||
this.jobboard = jobboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUrgent() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return jobboard.jobsAvailableForWorker(worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getBenefit() {
|
|
||||||
return 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void act(float dTime) {
|
|
||||||
if (doJob(dTime)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean isPathingToJobLocation() {
|
|
||||||
if(!worker.isPathing()) return false;
|
|
||||||
return worker.getDestination().isOneOf(job.getCurrentStep().getLocations());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAtJobStepLocation() {
|
|
||||||
return worker.getWorldPosition().xy().isOneOf(job.getCurrentStep().getLocations());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void goToJobStepLocation() {
|
|
||||||
worker.goToClosest(job
|
|
||||||
.getCurrentStep()
|
|
||||||
.getLocations()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ActivityCancellationCallback callback;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(ActivityCancellationCallback callback) {
|
|
||||||
|
|
||||||
this.callback = callback;
|
|
||||||
job = jobboard.requestJob(worker);
|
|
||||||
if(job == null) callback.apply(this);
|
|
||||||
job.registerClosedListener(() -> {
|
|
||||||
callback.apply(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
// if we dont have a job
|
|
||||||
if(!jobboard.workerHasJob(worker)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have a job and need to go to it and we're not pathing to it
|
|
||||||
if(jobboard.workerHasJob(worker) && !isAtJobStepLocation() && !isPathingToJobLocation()) {
|
|
||||||
goToJobStepLocation(); // start pathing there.
|
|
||||||
return; // and dont think about anything else.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void end() {
|
|
||||||
jobboard.quitJob(worker, job);
|
|
||||||
job = null;
|
|
||||||
}
|
|
||||||
// TODO pawns should keep tabs of what job step an item is picked up from
|
|
||||||
// so dropoff steps can reference the pickup step.
|
|
||||||
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...
|
|
||||||
if(!isAtJobStepLocation()) return false;
|
|
||||||
|
|
||||||
if(step instanceof Job.Work) {
|
|
||||||
Job.Work workStep = (Job.Work)step;
|
|
||||||
if(workStep.doWork(dTime)) step.next();
|
|
||||||
return true;
|
|
||||||
} else if(step instanceof Job.PickupItem) {
|
|
||||||
Job.PickupItem pickupStep = (Job.PickupItem) step;
|
|
||||||
worker.pickupItem(pickupStep.item);
|
|
||||||
step.next();
|
|
||||||
return true;
|
|
||||||
} else if(step instanceof Job.DropoffAtStockpile) {
|
|
||||||
if(!worker.getTile().isTileFree()) return false;
|
|
||||||
Job.DropoffAtStockpile dropoffStep = (Job.DropoffAtStockpile) step;
|
|
||||||
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 true;
|
|
||||||
} else if(step instanceof Job.DropoffPredicateAtItemReceiver) {
|
|
||||||
Job.DropoffPredicateAtItemReceiver dropoffStep = (Job.DropoffPredicateAtItemReceiver) step;
|
|
||||||
worker.dropoffPredicate(dropoffStep.predicate, dropoffStep.receiver);
|
|
||||||
step.next();
|
|
||||||
return true;
|
|
||||||
} else if(step instanceof Job.PickupItemByPredicate) {
|
|
||||||
Job.PickupItemByPredicate pickupStep = (Job.PickupItemByPredicate) step;
|
|
||||||
worker.pickupItemByPredicate(pickupStep.predicate);
|
|
||||||
step.next();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
if(job == null) return "No Work";
|
|
||||||
return job.getJobName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Vector2i[] getTargetLocations() {
|
|
||||||
return job.getCurrentStep().getLocations();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import xyz.valnet.hadean.HadeanGame;
|
|
||||||
import xyz.valnet.hadean.util.detail.Detail;
|
|
||||||
import xyz.valnet.hadean.util.detail.PercentDetail;
|
|
||||||
|
|
||||||
public class Needs implements Serializable {
|
|
||||||
|
|
||||||
private float energy = 0.7f + (float)Math.random() * 0.3f;
|
|
||||||
private float recreation = 0.5f + (float)Math.random() * 0.5f;
|
|
||||||
|
|
||||||
private float restRatio = 3;
|
|
||||||
private float decay = 0.000004f;
|
|
||||||
|
|
||||||
public void update(float dTime) {
|
|
||||||
energy = Math.max(energy - decay * dTime, 0);
|
|
||||||
recreation = Math.max(recreation - decay * dTime, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sleep(float dTime) {
|
|
||||||
energy = Math.min(energy + decay * dTime * restRatio, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getSleepNeed() {
|
|
||||||
if(HadeanGame.debugView) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1 - energy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public
|
|
||||||
|
|
||||||
public Detail[] getDetails() {
|
|
||||||
return new Detail[] {
|
|
||||||
new PercentDetail("Energy", energy, 1),
|
|
||||||
new PercentDetail("Fun", recreation, 1)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -2,26 +2,21 @@ package xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn;
|
||||||
|
|
||||||
import static xyz.valnet.hadean.util.detail.Detail.*;
|
import static xyz.valnet.hadean.util.detail.Detail.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
import xyz.valnet.engine.graphics.Color;
|
import xyz.valnet.engine.graphics.Color;
|
||||||
import xyz.valnet.engine.math.Box;
|
|
||||||
import xyz.valnet.engine.math.Vector2f;
|
import xyz.valnet.engine.math.Vector2f;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
|
||||||
import xyz.valnet.engine.util.Names;
|
import xyz.valnet.engine.util.Names;
|
||||||
import xyz.valnet.hadean.HadeanGame;
|
import xyz.valnet.hadean.HadeanGame;
|
||||||
import xyz.valnet.hadean.gameobjects.Clock;
|
import xyz.valnet.hadean.gameobjects.jobs.Job;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
|
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.agents.Agent;
|
import xyz.valnet.hadean.gameobjects.worldobjects.agents.Agent;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
|
||||||
import xyz.valnet.hadean.interfaces.IItemReceiver;
|
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
import xyz.valnet.hadean.util.Layers;
|
import xyz.valnet.hadean.util.Layers;
|
||||||
import xyz.valnet.hadean.util.Pair;
|
|
||||||
import xyz.valnet.hadean.util.detail.BooleanDetail;
|
import xyz.valnet.hadean.util.detail.BooleanDetail;
|
||||||
import xyz.valnet.hadean.util.detail.Detail;
|
import xyz.valnet.hadean.util.detail.Detail;
|
||||||
import xyz.valnet.hadean.util.detail.ObjectDetail;
|
import xyz.valnet.hadean.util.detail.ObjectDetail;
|
||||||
|
|
@ -30,75 +25,59 @@ import xyz.valnet.hadean.util.detail.PercentDetail;
|
||||||
public class Pawn extends Agent {
|
public class Pawn extends Agent {
|
||||||
|
|
||||||
private String name = Names.getRandomName();
|
private String name = Names.getRandomName();
|
||||||
private Needs needs = new Needs();
|
|
||||||
|
|
||||||
// private int meaningless = 0;
|
private Set<Item> inventory = new HashSet<>();
|
||||||
|
|
||||||
// private float workEthic = (float) Math.random();
|
private Job currentJob = null;
|
||||||
// private float selfWorth = (float) Math.random();
|
|
||||||
|
|
||||||
private transient List<Activity> activities = new ArrayList<Activity>();
|
private void doWorkJob(Job.Work workJob, float dTime) {
|
||||||
private Activity currentActivity = null;
|
if(!this.getWorldPosition().xy().isOneOf(workJob.getWorkablePositions())) {
|
||||||
|
if(goTo(workJob)) {
|
||||||
public void pickupItemByPredicate(IItemPredicate itemPredicate) {
|
return;
|
||||||
Item item = getTile().pickupByItemPredicate(itemPredicate);
|
} else {
|
||||||
inventory.add(item);
|
cancelJob(currentJob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
workJob.doWork(dTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pickupItem(Item i) {
|
private void doHaulToStockpileJob(Job.HaulToStockpile haulJob, float dTime) {
|
||||||
Item item = getTile().removeThing(i);
|
if(inventory.contains(haulJob.item().get()))
|
||||||
if(item == null) return;
|
|
||||||
remove(item);
|
|
||||||
inventory.add(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dropoffItem(Item item) {
|
private void doJob(float dTime) {
|
||||||
if(!inventory.contains(item)) {
|
if(!currentJob.isValidForWorker(this)) {
|
||||||
|
get(JobBoard.class).post(currentJob);
|
||||||
|
currentJob = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inventory.remove(add(item));
|
if(currentJob instanceof Job.HaulToStockpile haul) {
|
||||||
item.setPosition(getWorldPosition().xy());
|
doHaulToStockpileJob(haul, dTime);
|
||||||
getTile().placeThing(item);
|
} else if (currentJob instanceof Job.Work work) {
|
||||||
}
|
doWorkJob(work, dTime);
|
||||||
|
|
||||||
public void dropoffItem(Item item, IItemReceiver receiver) {
|
|
||||||
if(!inventory.contains(item)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
inventory.remove(item);
|
|
||||||
add(item);
|
|
||||||
receiver.receive(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Item getInventoryItemByPredicate(IItemPredicate predicate) {
|
|
||||||
for(Item item : inventory) {
|
|
||||||
if(!item.matches(predicate)) continue;
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dropoffPredicate(IItemPredicate predicate, IItemReceiver receiver) {
|
|
||||||
Item item = getInventoryItemByPredicate(predicate);
|
|
||||||
if(!inventory.contains(item)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dropoffItem(item, receiver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void ready() {
|
public void idle(float dTime) {
|
||||||
super.ready();
|
if(currentJob != null) {
|
||||||
activities = new ArrayList<Activity>();
|
doJob(dTime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO implement some sort of negotiating pattern between pawn and jobboard
|
||||||
|
// such that a pawn can decide if its capable of a job (imagine a pawn stuck
|
||||||
|
// in a place where it cant reach the job location. or in future, where it
|
||||||
|
// may lack a skill)
|
||||||
|
|
||||||
|
if((currentJob = get(JobBoard.class).takeJob(this)) != null) {
|
||||||
|
doJob(dTime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void cancelJob(Job job) {
|
||||||
public void start() {
|
currentJob = null;
|
||||||
super.start();
|
|
||||||
|
|
||||||
activities.add(new JobActivity(this, get(JobBoard.class)));
|
|
||||||
activities.add(new SleepActivity(needs, get(Clock.class)));
|
|
||||||
activities.add(new WanderActivity(get(Terrain.class)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void create() {
|
protected void create() {
|
||||||
|
|
@ -111,34 +90,29 @@ public class Pawn extends Agent {
|
||||||
@Override
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
super.render();
|
super.render();
|
||||||
if(currentActivity instanceof SleepActivity) {
|
Assets.flat.pushColor(Color.white);
|
||||||
Assets.flat.pushColor(Color.grey(0.5f));
|
|
||||||
} else {
|
float shake = 0.0f;
|
||||||
Assets.flat.pushColor(Color.white);
|
camera.draw(
|
||||||
}
|
Layers.PAWNS,
|
||||||
camera.draw(Layers.PAWNS, Assets.pawn, getCalculatedPosition());
|
Assets.pawn,
|
||||||
|
getCalculatedPosition().add(new Vector2f(
|
||||||
|
(float) Math.random() * shake - shake / 2,
|
||||||
|
(float) Math.random() * shake - shake / 2
|
||||||
|
))
|
||||||
|
);
|
||||||
Assets.flat.popColor();
|
Assets.flat.popColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void runAction(Action action) {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Detail[] getDetails() {
|
public Detail[] getDetails() {
|
||||||
// return needs.getDetails();
|
// return needs.getDetails();
|
||||||
Detail[] details = mergeDetails(needs.getDetails(), new Detail[] {
|
Detail[] details = new Detail[] {
|
||||||
new ObjectDetail<Activity>("Activity", currentActivity),
|
// new ObjectDetail<Activity>("Activity", currentActivity),
|
||||||
new BooleanDetail("Pathing", isPathing()),
|
new BooleanDetail("Pathing", isPathing()),
|
||||||
|
new ObjectDetail<String>("Job", currentJob == null ? "null" : currentJob.toString()),
|
||||||
new ObjectDetail<Integer>("Inventory", inventory.size())
|
new ObjectDetail<Integer>("Inventory", inventory.size())
|
||||||
});
|
};
|
||||||
|
|
||||||
if(HadeanGame.debugView) {
|
|
||||||
for(Activity activity : activities) {
|
|
||||||
details = mergeDetails(details, new Detail[] {
|
|
||||||
new PercentDetail(activity.toString(), activity.getBenefit())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
|
|
@ -154,81 +128,12 @@ public class Pawn extends Agent {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Box getWorldBox() {
|
public Action[] getActions() {
|
||||||
Vector2f pos = getCalculatedPosition();
|
return new Action[] {};
|
||||||
return new Box(pos, 1, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void think() {
|
public void runAction(Action action) {
|
||||||
super.think();
|
|
||||||
decideActivity();
|
|
||||||
pathToActivity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pathToActivity() {
|
|
||||||
if(currentActivity == null) return;
|
|
||||||
Vector2i[] locations = currentActivity.getTargetLocations();
|
|
||||||
if(locations == null || locations.length == 0) return;
|
|
||||||
if(isPathing() && getDestination().isOneOf(locations)) return;
|
|
||||||
goToClosest(locations);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void decideActivity() {
|
|
||||||
|
|
||||||
List<Activity> urgentActivities = activities.stream()
|
|
||||||
.filter(a -> a.isValid() && a.isUrgent())
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if(urgentActivities.size() > 0) {
|
|
||||||
switchActivity(urgentActivities.get(0));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(currentActivity != null) return;
|
|
||||||
|
|
||||||
List<Activity> valueSortedActivities = activities.stream()
|
|
||||||
.filter(a -> a.isValid())
|
|
||||||
.map(a -> new Pair<Activity, Float>(a, a.getBenefit()))
|
|
||||||
.filter(a -> a.second() >= 0)
|
|
||||||
.sorted((a, b) -> a.second() > b.second() ? -1 : 1)
|
|
||||||
.map(p -> p.first())
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if(valueSortedActivities.size() == 0) return;
|
|
||||||
|
|
||||||
switchActivity(valueSortedActivities.get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void switchActivity(Activity activity) {
|
|
||||||
if(activity == currentActivity) return;
|
|
||||||
if(currentActivity != null) currentActivity.end();
|
|
||||||
currentActivity = activity;
|
|
||||||
stopPathing();
|
|
||||||
currentActivity.begin(a -> endActivity(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void endActivity(Activity activity) {
|
|
||||||
activity.end();
|
|
||||||
stopPathing();
|
|
||||||
if(currentActivity == activity) {
|
|
||||||
currentActivity = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean act(float dTime) {
|
|
||||||
if(super.act(dTime)) return true;
|
|
||||||
if(currentActivity != null) {
|
|
||||||
currentActivity.act(dTime);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void postAct() {
|
|
||||||
needs.update(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Item> inventory = new ArrayList<Item>();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn;
|
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
|
||||||
import xyz.valnet.engine.util.Math.WeightedAverage;
|
|
||||||
import xyz.valnet.hadean.gameobjects.Clock;
|
|
||||||
|
|
||||||
public class SleepActivity extends Activity {
|
|
||||||
|
|
||||||
private Needs needs;
|
|
||||||
private Clock clock;
|
|
||||||
|
|
||||||
private float circadianStrength = (float)Math.random() * 5f;
|
|
||||||
|
|
||||||
|
|
||||||
public SleepActivity(Needs needs, Clock clock) {
|
|
||||||
this.needs = needs;
|
|
||||||
this.clock = clock;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUrgent() {
|
|
||||||
return needs.getSleepNeed() >= 0.97f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getBenefit() {
|
|
||||||
// subtract because sleeping for only 5 minutes when
|
|
||||||
// you're not that tired to hit 100% is undesireable.
|
|
||||||
// as it will induce oversleep
|
|
||||||
WeightedAverage average = new WeightedAverage();
|
|
||||||
average.add(needs.getSleepNeed(), 1);
|
|
||||||
|
|
||||||
average.add(1 - 2 * clock.getSunlight(), circadianStrength);
|
|
||||||
return average.calculate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// isValid vs canBeStarted? idk, maybe thats not important.
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return needs.getSleepNeed() > 0.2f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void act(float dTime) {
|
|
||||||
needs.sleep(dTime);
|
|
||||||
if(needs.getSleepNeed() == 0) {
|
|
||||||
callback.apply(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ActivityCancellationCallback callback;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(ActivityCancellationCallback callback) {
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void end() { }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Sleeping";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Vector2i[] getTargetLocations() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects.agents.pawn;
|
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Terrain;
|
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
|
||||||
|
|
||||||
// TODO actually implement this activity.
|
|
||||||
public class WanderActivity extends Activity {
|
|
||||||
|
|
||||||
// TODO implement fun?
|
|
||||||
// private Needs needs;
|
|
||||||
|
|
||||||
private Terrain terrain;
|
|
||||||
|
|
||||||
public WanderActivity(Terrain terrain) {
|
|
||||||
this.terrain = terrain;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUrgent() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getBenefit() {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void act(float dTime) {
|
|
||||||
callback.apply(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ActivityCancellationCallback callback;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(ActivityCancellationCallback callback) {
|
|
||||||
this.callback = callback;
|
|
||||||
|
|
||||||
Tile tile = terrain.getRandomWalkableTile();
|
|
||||||
if(tile == null) {
|
|
||||||
callback.apply(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
target = tile.getCoords();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void end() { }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Wandering";
|
|
||||||
}
|
|
||||||
|
|
||||||
private Vector2i target = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Vector2i[] getTargetLocations() {
|
|
||||||
if(target == null) return null;
|
|
||||||
return new Vector2i[] { target };
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -23,16 +23,6 @@ public class Bed extends Construction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IItemPredicate getBuildingMaterial() {
|
protected IItemPredicate getBuildingMaterial() {
|
||||||
return Log.LOG_PREDICATE;
|
return Log.LOG_PREDICATE;
|
||||||
|
|
|
||||||
|
|
@ -6,19 +6,20 @@ import java.util.List;
|
||||||
import xyz.valnet.engine.graphics.Color;
|
import xyz.valnet.engine.graphics.Color;
|
||||||
import xyz.valnet.engine.graphics.Sprite;
|
import xyz.valnet.engine.graphics.Sprite;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
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.Job;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.Buildable;
|
import xyz.valnet.hadean.gameobjects.worldobjects.Buildable;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||||
import xyz.valnet.hadean.interfaces.BuildType;
|
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
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.interfaces.IWorkable;
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
import xyz.valnet.hadean.util.Layers;
|
import xyz.valnet.hadean.util.Layers;
|
||||||
|
|
||||||
public abstract class Construction extends Buildable implements IItemReceiver {
|
public abstract class Construction extends Buildable {
|
||||||
|
|
||||||
private float work = 0;
|
private float work = 0;
|
||||||
|
|
||||||
|
|
@ -31,16 +32,64 @@ public abstract class Construction extends Buildable implements IItemReceiver {
|
||||||
return containedItems.size() >= getBuildingMaterialCount();
|
return containedItems.size() >= getBuildingMaterialCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onItem(Item item) {
|
||||||
|
containedItems.add(item);
|
||||||
|
postNextJob();
|
||||||
|
}
|
||||||
|
|
||||||
private void postNextJob() {
|
private void postNextJob() {
|
||||||
if(!isBuildingMaterialSatisfied()) {
|
if(!isBuildingMaterialSatisfied()) {
|
||||||
Job job = get(JobBoard.class).postSimpleItemRequirementJob(
|
|
||||||
"Haul items to building",
|
var itemRequest = new DItemRequest(this, "Haul items to building")
|
||||||
getBuildingMaterial(),
|
.accepts(getBuildingMaterial())
|
||||||
this
|
.positions(getSelectionWorldBox().getBorders())
|
||||||
);
|
.handleItem((item) -> onItem(item));
|
||||||
job.registerClosedListener(() -> {
|
|
||||||
postNextJob();
|
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 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();
|
||||||
|
// });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!isBuilt()) {
|
if(!isBuilt()) {
|
||||||
|
|
@ -54,7 +103,7 @@ public abstract class Construction extends Buildable implements IItemReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2i[] getWorkablePositions() {
|
public Vector2i[] getWorkablePositions() {
|
||||||
return getWorldBox().getBorders();
|
return getSelectionWorldBox().getBorders();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -87,16 +136,6 @@ public abstract class Construction extends Buildable implements IItemReceiver {
|
||||||
@Override
|
@Override
|
||||||
public abstract boolean isWalkable();
|
public abstract boolean isWalkable();
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract String getName();
|
public abstract String getName();
|
||||||
|
|
||||||
|
|
@ -108,20 +147,6 @@ public abstract class Construction extends Buildable implements IItemReceiver {
|
||||||
return work / getMaxWork();
|
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
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
Sprite sprite = getDefaultSprite();
|
Sprite sprite = getDefaultSprite();
|
||||||
|
|
@ -135,7 +160,7 @@ public abstract class Construction extends Buildable implements IItemReceiver {
|
||||||
Assets.flat.popColor();
|
Assets.flat.popColor();
|
||||||
|
|
||||||
if(getBuildProgress() > 0) {
|
if(getBuildProgress() > 0) {
|
||||||
camera.drawProgressBar(getBuildProgress(), getWorldBox());
|
camera.drawProgressBar(getBuildProgress(), getSelectionWorldBox());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,9 +182,6 @@ public abstract class Construction extends Buildable implements IItemReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action[] getActions() {
|
public Action[] getActions() {
|
||||||
return new Action[0];
|
return super.getActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void runAction(Action action) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects.constructions;
|
package xyz.valnet.hadean.gameobjects.worldobjects.constructions;
|
||||||
|
|
||||||
import xyz.valnet.engine.graphics.Sprite;
|
import xyz.valnet.engine.graphics.Sprite;
|
||||||
|
import xyz.valnet.engine.math.TileBox;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
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.ui.WorkshopOrdersUI;
|
||||||
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Log;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Log;
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
||||||
import xyz.valnet.hadean.interfaces.IWorkshop;
|
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 static Action OPEN_ORDERS = new Action("Orders");
|
||||||
private transient WorkshopOrdersUI ordersWindow;
|
private transient WorkshopOrdersUI ordersWindow;
|
||||||
|
private WorkOrderManager manager;
|
||||||
|
|
||||||
|
// TODO the job itself should have the work amount...
|
||||||
|
private float workDone = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IItemPredicate getBuildingMaterial() {
|
protected IItemPredicate getBuildingMaterial() {
|
||||||
|
|
@ -62,6 +71,7 @@ public class MasonWorkshop extends Construction implements IWorkshop {
|
||||||
protected void connect() {
|
protected void connect() {
|
||||||
super.connect();
|
super.connect();
|
||||||
ordersWindow = get(WorkshopOrdersUI.class);
|
ordersWindow = get(WorkshopOrdersUI.class);
|
||||||
|
manager = get(WorkOrderManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -73,5 +83,52 @@ public class MasonWorkshop extends Construction implements IWorkshop {
|
||||||
public String getBuildTabCategory() {
|
public String getBuildTabCategory() {
|
||||||
return "Workshops";
|
return "Workshops";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doWork(float dTime) {
|
||||||
|
workDone += dTime;
|
||||||
|
return workDone > order.getMaxWork();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector2i[] getWorkablePositions() {
|
||||||
|
return getSelectionWorldBox().getBorders();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJobName() {
|
||||||
|
return "Do Work as Workshop";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileBox getSpawnableArea() {
|
||||||
|
return getSelectionWorldBox().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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import xyz.valnet.engine.graphics.Sprite;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.Job;
|
import xyz.valnet.hadean.gameobjects.jobs.Job;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
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.gameobjects.worldobjects.items.Boulder;
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
|
|
@ -21,26 +21,43 @@ public class Quarry extends Construction {
|
||||||
private float digProgress = 0;
|
private float digProgress = 0;
|
||||||
|
|
||||||
private void tryCreateDigJob() {
|
private void tryCreateDigJob() {
|
||||||
if(!isBuilt()) return;
|
if (!isBuilt()) return;
|
||||||
if (digJob != null) return;
|
if (digJob != null) return;
|
||||||
if (terrain.getTile(getWorldPosition().xy().south().east()).has(Boulder.class)) return;
|
if (terrain.getTile(getWorldPosition().xy().south().east()).has(Boulder.class)) return;
|
||||||
|
|
||||||
digJob = get(JobBoard.class).postSimpleWorkJob(new SimpleWorkable("Mine at Quarry", 5000, () -> {
|
var workable = new WorkableBuilder(this)
|
||||||
return new Vector2i[] {
|
.name("Quarry")
|
||||||
getWorldPosition().xy().south().east()
|
.position(getWorldPosition().xy().south().east())
|
||||||
};
|
.work(5000)
|
||||||
}, (progress) -> {
|
.progress((p) -> digProgress = p)
|
||||||
digProgress = progress;
|
.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(() -> {
|
digJob = get(JobBoard.class).post(workable);
|
||||||
digProgress = 0;
|
|
||||||
Vector2i dropPos = getWorldPosition().xy().south().east();
|
// digJob = get(JobBoard.class).post(new SimpleWorkable("Mine at Quarry", 5000, () -> {
|
||||||
Boulder boulder = new Boulder(dropPos.x, dropPos.y);
|
// return new Vector2i[] {
|
||||||
add(boulder);
|
// getWorldPosition().xy().south().east()
|
||||||
boulder.runAction(Boulder.HAUL);
|
// };
|
||||||
digJob = null;
|
// }, (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
|
@Override
|
||||||
|
|
@ -54,15 +71,6 @@ public class Quarry extends Construction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Quarry";
|
return "Quarry";
|
||||||
|
|
@ -88,8 +96,8 @@ public class Quarry extends Construction {
|
||||||
super.render();
|
super.render();
|
||||||
if(!isBuilt()) return;
|
if(!isBuilt()) return;
|
||||||
|
|
||||||
if(digJob != null && !digJob.isCompleted() && digProgress > 0) {
|
if(digJob != null && digProgress > 0) {
|
||||||
camera.drawProgressBar(digProgress, getWorldBox());
|
camera.drawProgressBar(digProgress, getSelectionWorldBox());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import java.util.EnumSet;
|
||||||
import xyz.valnet.engine.graphics.Sprite;
|
import xyz.valnet.engine.graphics.Sprite;
|
||||||
import xyz.valnet.engine.graphics.Tile16.Direction;
|
import xyz.valnet.engine.graphics.Tile16.Direction;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
|
import xyz.valnet.hadean.enums.BuildType;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
|
||||||
import xyz.valnet.hadean.interfaces.BuildType;
|
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
||||||
import xyz.valnet.hadean.interfaces.IPingable;
|
import xyz.valnet.hadean.interfaces.IPingable;
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
|
|
@ -41,21 +41,11 @@ public class Wall extends Construction implements IPingable {
|
||||||
return !isBuilt();
|
return !isBuilt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnumSet<Direction> wallSides = EnumSet.noneOf(Direction.class);
|
private EnumSet<Direction> wallSides = EnumSet.noneOf(Direction.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ping() {
|
public void ping() {
|
||||||
Vector2i pos = getWorldBox().a.asInt();
|
Vector2i pos = getSelectionWorldBox().a.asInt();
|
||||||
wallSides = EnumSet.noneOf(Direction.class);
|
wallSides = EnumSet.noneOf(Direction.class);
|
||||||
|
|
||||||
Tile north = terrain.getTile(pos.x, pos.y - 1);
|
Tile north = terrain.getTile(pos.x, pos.y - 1);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,17 @@ import xyz.valnet.hadean.util.detail.Detail;
|
||||||
|
|
||||||
public class Boulder extends Item {
|
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) {
|
public Boulder(int x, int y) {
|
||||||
setPosition(x, y);
|
setPosition(x, y);
|
||||||
|
|
@ -30,14 +40,6 @@ public class Boulder extends Item {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Detail[] getDetails() {
|
public Detail[] getDetails() {
|
||||||
return new Detail[] {};
|
return new Detail[] {};
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,26 @@ package xyz.valnet.hadean.gameobjects.worldobjects.items;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
import xyz.valnet.engine.math.Vector4i;
|
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.Job;
|
||||||
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
import xyz.valnet.hadean.gameobjects.jobs.JobBoard;
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
|
import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
|
||||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
||||||
|
import xyz.valnet.hadean.interfaces.ISceneReferent;
|
||||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||||
import xyz.valnet.hadean.interfaces.ITileThing;
|
|
||||||
import xyz.valnet.hadean.util.Action;
|
import xyz.valnet.hadean.util.Action;
|
||||||
import xyz.valnet.hadean.util.Assets;
|
import xyz.valnet.hadean.util.Assets;
|
||||||
import xyz.valnet.hadean.util.Layers;
|
import xyz.valnet.hadean.util.Layers;
|
||||||
|
|
||||||
public abstract class Item extends WorldObject implements ISelectable, ITileThing {
|
public abstract class Item extends WorldObject implements ISelectable, ISceneReferent {
|
||||||
protected JobBoard jobboard;
|
protected JobBoard jobboard;
|
||||||
|
|
||||||
private Job haulJob = null;
|
private Job haulJob = null;
|
||||||
|
|
||||||
|
public final SceneReference<Item> asRef() {
|
||||||
|
return new SceneReference<Item>(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void connect() {
|
protected void connect() {
|
||||||
super.connect();
|
super.connect();
|
||||||
|
|
@ -69,32 +73,24 @@ public abstract class Item extends WorldObject implements ISelectable, ITileThin
|
||||||
|
|
||||||
private void cancelHaul() {
|
private void cancelHaul() {
|
||||||
if(haulJob == null) return;
|
if(haulJob == null) return;
|
||||||
haulJob.close();
|
jobboard.rescind(haulJob);
|
||||||
haulJob = null;
|
haulJob = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markForHaul() {
|
private void markForHaul() {
|
||||||
if(haulJob != null) return;
|
if(haulJob != null) return;
|
||||||
haulJob = add(new Job("Haul " + this.getName()));
|
var j = new Job.HaulToStockpile(asRef());
|
||||||
haulJob.addStep(haulJob.new PickupItem(this));
|
jobboard.post(j);
|
||||||
haulJob.addStep(haulJob.new DropoffAtStockpile(this));
|
|
||||||
haulJob.registerClosedListener(() -> {
|
|
||||||
haulJob = null;
|
|
||||||
});
|
|
||||||
jobboard.postJob(haulJob);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void destroy() {
|
||||||
public void onPlaced(Tile tile) {
|
remove(this);
|
||||||
setPosition(tile.getWorldPosition());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(IItemPredicate itemPredicate) {
|
public boolean matches(IItemPredicate itemPredicate) {
|
||||||
return itemPredicate.matches(this);
|
return itemPredicate.matches(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void setPosition(Vector4i vector) {
|
public void setPosition(Vector4i vector) {
|
||||||
super.setPosition(vector);
|
super.setPosition(vector);
|
||||||
}
|
}
|
||||||
|
|
@ -110,4 +106,8 @@ public abstract class Item extends WorldObject implements ISelectable, ITileThin
|
||||||
public void setPosition(int x, int y, int w, int h) {
|
public void setPosition(int x, int y, int w, int h) {
|
||||||
super.setPosition(x, y, w, h);
|
super.setPosition(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getGenericName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,19 @@ import xyz.valnet.hadean.util.detail.Detail;
|
||||||
// when placed in a non stockpile, not just on create.
|
// when placed in a non stockpile, not just on create.
|
||||||
public class Log extends Item {
|
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) {
|
public Log(int x, int y) {
|
||||||
setPosition(x, y);
|
setPosition(x, y);
|
||||||
|
|
@ -30,14 +42,6 @@ public class Log extends Item {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Detail[] getDetails() {
|
public Detail[] getDetails() {
|
||||||
return new Detail[] {};
|
return new Detail[] {};
|
||||||
|
|
|
||||||
|
|
@ -46,24 +46,11 @@ public class FarmPlot extends Zone {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Farm Plot";
|
return "Farm Plot";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlaced(Tile tile) {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ISelectable.Priority getSelectPriority() {
|
public ISelectable.Priority getSelectPriority() {
|
||||||
return ISelectable.Priority.LOW;
|
return ISelectable.Priority.LOW;
|
||||||
|
|
|
||||||
|
|
@ -61,24 +61,11 @@ public class Stockpile extends Zone {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Stockpile";
|
return "Stockpile";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlaced(Tile tile) {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ISelectable.Priority getSelectPriority() {
|
public ISelectable.Priority getSelectPriority() {
|
||||||
return ISelectable.Priority.LOW;
|
return ISelectable.Priority.LOW;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package xyz.valnet.hadean.gameobjects.worldobjects.zones;
|
package xyz.valnet.hadean.gameobjects.worldobjects.zones;
|
||||||
|
|
||||||
|
import xyz.valnet.hadean.enums.BuildType;
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.Buildable;
|
import xyz.valnet.hadean.gameobjects.worldobjects.Buildable;
|
||||||
import xyz.valnet.hadean.interfaces.BuildType;
|
|
||||||
|
|
||||||
public abstract class Zone extends Buildable {
|
public abstract class Zone extends Buildable {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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<DItemRequest> asRef() {
|
||||||
|
return new SceneReference<DItemRequest>(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package xyz.valnet.hadean.interfaces;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.TileBox;
|
import xyz.valnet.engine.math.TileBox;
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
|
import xyz.valnet.hadean.enums.BuildType;
|
||||||
|
|
||||||
public interface IBuildable {
|
public interface IBuildable {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,20 @@ import java.io.Serializable;
|
||||||
|
|
||||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface IItemPredicate extends Serializable {
|
public interface IItemPredicate extends Serializable {
|
||||||
public boolean matches(Item item);
|
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";
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +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();
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package xyz.valnet.hadean.interfaces;
|
||||||
|
|
||||||
|
import xyz.valnet.engine.scenegraph.SceneGraph.GameObjectCallback;
|
||||||
|
|
||||||
|
public interface ISceneReferent {
|
||||||
|
public void onRemoved(GameObjectCallback callback);
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ public interface ISelectable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Box getWorldBox();
|
public Box getSelectionWorldBox();
|
||||||
public Action[] getActions();
|
public Action[] getActions();
|
||||||
public void runAction(Action action);
|
public void runAction(Action action);
|
||||||
public Detail[] getDetails();
|
public Detail[] getDetails();
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,21 @@ package xyz.valnet.hadean.interfaces;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
|
import xyz.valnet.engine.util.SceneReference;
|
||||||
|
import xyz.valnet.hadean.enums.WorkType;
|
||||||
|
|
||||||
public interface IWorkable extends Serializable {
|
public interface IWorkable extends Serializable, IDestination, ISceneReferent {
|
||||||
|
public WorkType getWorkType();
|
||||||
public boolean doWork(float dTime);
|
public boolean doWork(float dTime);
|
||||||
public Vector2i[] getWorkablePositions();
|
public Vector2i[] getWorkablePositions();
|
||||||
public String getJobName();
|
public String getWorkableName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public default Vector2i[] getDestinations() {
|
||||||
|
return getWorkablePositions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public default SceneReference<IWorkable> asRef() {
|
||||||
|
return new SceneReference<>(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package xyz.valnet.hadean.interfaces;
|
package xyz.valnet.hadean.interfaces;
|
||||||
|
|
||||||
public interface IWorkshop extends ISelectable {
|
public interface IWorkshop extends ISelectable,
|
||||||
|
IWorkable,
|
||||||
|
IItemSpawner {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@ package xyz.valnet.hadean.interfaces;
|
||||||
|
|
||||||
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
import xyz.valnet.hadean.gameobjects.terrain.Tile;
|
||||||
|
|
||||||
public interface ITileThing {
|
public interface IWorldObject {
|
||||||
|
public Tile getTile(int x, int y);
|
||||||
public boolean isWalkable();
|
public boolean isWalkable();
|
||||||
public boolean shouldRemove();
|
|
||||||
public void onRemove();
|
|
||||||
public void onPlaced(Tile tile);
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import java.util.List;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
|
import xyz.valnet.hadean.interfaces.IDestination;
|
||||||
|
|
||||||
public class AStarPathfinder implements IPathfinder, Serializable {
|
public class AStarPathfinder implements IPathfinder, Serializable {
|
||||||
|
|
||||||
|
|
@ -162,7 +163,9 @@ public class AStarPathfinder implements IPathfinder, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path getBestPath(Vector2i src, Vector2i[] dsts) {
|
public Path getBestPath(Vector2i src, IDestination provider) {
|
||||||
|
|
||||||
|
var dsts = provider.getDestinations();
|
||||||
|
|
||||||
if(src.isOneOf(dsts)) return null;
|
if(src.isOneOf(dsts)) return null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,18 @@
|
||||||
package xyz.valnet.hadean.pathfinding;
|
package xyz.valnet.hadean.pathfinding;
|
||||||
|
|
||||||
import xyz.valnet.engine.math.Vector2i;
|
import xyz.valnet.engine.math.Vector2i;
|
||||||
|
import xyz.valnet.hadean.interfaces.IDestination;
|
||||||
|
|
||||||
public interface IPathfinder {
|
public interface IPathfinder {
|
||||||
public Path getPath(int x1, int y1, int x2, int y2);
|
public Path getPath(int x1, int y1, int x2, int y2);
|
||||||
public Path getBestPath(Vector2i src, Vector2i[] dsts);
|
public default Path getPath(Vector2i u, int x2, int y2) {
|
||||||
|
return getPath(u.x, u.y, x2, y2);
|
||||||
|
}
|
||||||
|
public default Path getPath(int x1, int y1, Vector2i v) {
|
||||||
|
return getPath(x1, y1, v.x, v.y);
|
||||||
|
}
|
||||||
|
public default Path getPath(Vector2i u, Vector2i v) {
|
||||||
|
return getPath(u.x, u.y, v.x, v.y);
|
||||||
|
}
|
||||||
|
public Path getBestPath(Vector2i src, IDestination dsts);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public class Path implements Iterable<Node>, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node getDestination() {
|
public Node getDestination() {
|
||||||
return nodes.firstElement();
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isComplete() {
|
public boolean isComplete() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
package xyz.valnet.hadean.scenes;
|
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.scenegraph.SceneGraph;
|
||||||
import xyz.valnet.engine.util.Names;
|
import xyz.valnet.engine.util.Names;
|
||||||
import xyz.valnet.hadean.gameobjects.ui.BottomBar;
|
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 {
|
public class GameScene extends SceneGraph {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void construct() {
|
protected void construct(Set<GameObject> scene) {
|
||||||
|
|
||||||
Names.loadNames();
|
Names.loadNames();
|
||||||
|
|
||||||
objects.add(new Terrain());
|
scene.add(new Terrain());
|
||||||
objects.add(new Camera());
|
scene.add(new Camera());
|
||||||
objects.add(new JobBoard());
|
scene.add(new JobBoard());
|
||||||
objects.add(new Clock());
|
scene.add(new Clock());
|
||||||
|
|
||||||
for(int i = 0; i < 5; i ++) {
|
for(int i = 0; i < 1; i ++) {
|
||||||
objects.add(new Pawn());
|
scene.add(new Pawn());
|
||||||
}
|
}
|
||||||
|
|
||||||
objects.add(new WorkOrderManager());
|
scene.add(new WorkOrderManager());
|
||||||
objects.add(new ExclusivityManager());
|
scene.add(new ExclusivityManager());
|
||||||
|
|
||||||
objects.add(new SelectionLayer());
|
scene.add(new SelectionLayer());
|
||||||
objects.add(new BuildLayer());
|
scene.add(new BuildLayer());
|
||||||
|
|
||||||
objects.add(new WorkshopOrdersUI());
|
scene.add(new WorkshopOrdersUI());
|
||||||
objects.add(new SelectionUI());
|
scene.add(new SelectionUI());
|
||||||
|
|
||||||
objects.add(new HoverQuery());
|
scene.add(new HoverQuery());
|
||||||
|
|
||||||
objects.add(new BottomBar());
|
scene.add(new BottomBar());
|
||||||
objects.add(new BuildTab());
|
scene.add(new BuildTab());
|
||||||
objects.add(new JobBoardTab());
|
scene.add(new JobBoardTab());
|
||||||
objects.add(new DebugTab());
|
scene.add(new DebugTab());
|
||||||
objects.add(new MenuTab());
|
scene.add(new MenuTab());
|
||||||
|
|
||||||
// objects.add(new Popup());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package xyz.valnet.hadean.util;
|
package xyz.valnet.hadean.util;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO consider making this an enum?
|
||||||
public class Action {
|
public class Action {
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
|
|
@ -37,4 +39,8 @@ public class Action {
|
||||||
Action[] merged = mergeActions(rest);
|
Action[] merged = mergeActions(rest);
|
||||||
return mergeActions(first, merged);
|
return mergeActions(first, merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,14 @@ public class Assets {
|
||||||
|
|
||||||
|
|
||||||
public static final SimpleShader flat;
|
public static final SimpleShader flat;
|
||||||
|
public static final SimpleShader depth;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
DebugTab.log("=== [ LOADING ASSETS ] ===");
|
DebugTab.log("=== [ LOADING ASSETS ] ===");
|
||||||
flat = new SimpleShader("res/shaders/flat.vert", "res/shaders/flat.frag");
|
flat = new SimpleShader("res/shaders/base.vert", "res/shaders/flat.frag");
|
||||||
|
depth = new SimpleShader("res/shaders/base.vert", "res/shaders/depth.frag");
|
||||||
|
|
||||||
|
flat.enable();
|
||||||
|
|
||||||
atlas = new Texture("res/textures.png");
|
atlas = new Texture("res/textures.png");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue