beginnings of savedata

pull/1/head
valyrie97 2023-01-02 00:26:39 -05:00
parent fa654bac35
commit e8be8b4089
31 changed files with 264 additions and 63 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
target
out
bin
SAVE_DATA.TXT

View File

@ -1,6 +1,8 @@
package xyz.valnet.engine.math;
public class Vector2f {
import java.io.Serializable;
public class Vector2f implements Serializable {
public float x, y;

View File

@ -1,6 +1,8 @@
package xyz.valnet.engine.math;
public class Vector2i {
import java.io.Serializable;
public class Vector2i implements Serializable {
public int x, y;

View File

@ -1,6 +1,8 @@
package xyz.valnet.engine.math;
public class Vector4f {
import java.io.Serializable;
public class Vector4f implements Serializable {
public float x, y, z, w;

View File

@ -1,6 +1,8 @@
package xyz.valnet.engine.math;
public class Vector4i {
import java.io.Serializable;
public class Vector4i implements Serializable {
public int x, y, z, w;

View File

@ -0,0 +1,42 @@
package xyz.valnet.engine.scenegraph;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
public class CustomObjectDeserializer extends ObjectInputStream {
public CustomObjectDeserializer(InputStream in) throws IOException {
super(in);
}
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); // initially streams descriptor
Class localClass; // the class in the local JVM that this descriptor represents.
try {
localClass = Class.forName(resultClassDescriptor.getName());
} catch (ClassNotFoundException e) {
System.out.println("No local class for " + resultClassDescriptor.getName());
System.out.println(e);
return resultClassDescriptor;
}
ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
if (localClassDescriptor != null) { // only if class implements serializable
final long localSUID = localClassDescriptor.getSerialVersionUID();
final long streamSUID = resultClassDescriptor.getSerialVersionUID();
if (streamSUID != localSUID) { // check for serialVersionUID mismatch.
final StringBuffer s = new StringBuffer("Overriding serialized class version mismatch: ");
s.append("local serialVersionUID = ").append(localSUID);
s.append(" stream serialVersionUID = ").append(streamSUID);
Exception e = new InvalidClassException(s.toString());
System.out.println("Potentially Fatal Deserialization Operation.");
System.out.println(e);
resultClassDescriptor = localClassDescriptor; // Use local class descriptor for deserialization
}
}
return resultClassDescriptor;
}
}

View File

@ -1,9 +1,10 @@
package xyz.valnet.engine.scenegraph;
import java.io.Serializable;
import java.util.List;
public class GameObject implements IRenderable, ITickable {
private SceneGraph scene;
public class GameObject implements IRenderable, ITickable, Serializable {
private transient SceneGraph scene;
public void link(SceneGraph scene) {
this.scene = scene;
@ -47,4 +48,12 @@ public class GameObject implements IRenderable, ITickable {
protected void remove(GameObject obj) {
scene.remove(obj);
}
protected void save() {
scene.queueSave();
}
protected void load() {
scene.queueLoad();
}
}

View File

@ -0,0 +1,3 @@
package xyz.valnet.engine.scenegraph;
public interface ITransient {}

View File

@ -1,8 +1,17 @@
package xyz.valnet.engine.scenegraph;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import xyz.valnet.engine.App;
@ -12,7 +21,10 @@ public abstract class SceneGraph implements IScene {
private final List<GameObject> removeObjects = new ArrayList<GameObject>();
private IMouseCaptureArea hoveredMouseListener = null;
private boolean loadFlag = false;
private boolean saveFlag = false;
public <T> T get(Class<T> clazz) {
for(GameObject obj : objects) {
if(clazz.isInstance(obj)) {
@ -53,6 +65,9 @@ public abstract class SceneGraph implements IScene {
removeObjects.clear();
}
if(saveFlag) save();
if(loadFlag) load();
// TICK OBJECTS
for(GameObject obj : objects) {
obj.update(dTime);
@ -113,7 +128,6 @@ public abstract class SceneGraph implements IScene {
protected abstract void construct();
@Override
public void disable() {
objects.clear();
@ -138,6 +152,76 @@ public abstract class SceneGraph implements IScene {
System.out.println(go);
}
private void dump(List<GameObject> objects) {
Map<Class, Integer> count = new HashMap<Class, Integer>();
for(GameObject go : objects) {
Class clazz = go.getClass();
if(!count.containsKey(clazz))
count.put(clazz, 0);
count.put(clazz, count.get(clazz) + 1);
}
for(Entry<Class, Integer> entry : count.entrySet()) {
System.out.println("" + entry.getValue() + "x " + entry.getKey().getSimpleName());
}
}
private ArrayList<GameObject> getNonTransientObjects() {
return new ArrayList<GameObject>(objects.stream()
.filter(go -> !(go instanceof ITransient))
.collect(Collectors.toList()));
}
private void save() {
try {
FileOutputStream file = new FileOutputStream("SAVE_DATA.TXT");
ObjectOutputStream out = new ObjectOutputStream(file);
ArrayList<GameObject> toSave = getNonTransientObjects();
dump(toSave);
out.writeObject(toSave);
out.close();
file.close();
} catch (NotSerializableException e) {
System.out.println("HEY");
e.printStackTrace();
} catch (Exception e) {
System.out.println(e);
}
saveFlag = false;
}
private void load() {
try {
FileInputStream file = new FileInputStream("SAVE_DATA.TXT");
ObjectInputStream input = new CustomObjectDeserializer(file);
List<GameObject> newObjects = (List<GameObject>) input.readObject();
input.close();
file.close();
System.out.println("imported " + newObjects.size() + " objects");
ArrayList<GameObject> toRemove = getNonTransientObjects();
for(GameObject obj : toRemove) {
objects.remove(obj);
}
objects.addAll(newObjects);
for(GameObject obj : objects) obj.link(this);
for(GameObject obj : objects) obj.start();
} catch (Exception e) {
e.printStackTrace();
}
loadFlag = false;
}
protected void queueSave() {
saveFlag = true;
}
protected void queueLoad() {
loadFlag = true;
}
@Override
public void mouseDown(int button) {
for(IMouseCaptureArea iml : getAll(IMouseCaptureArea.class)) {

View File

@ -6,13 +6,14 @@ import java.util.List;
import java.util.Map;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.ITransient;
import xyz.valnet.hadean.input.Button;
import xyz.valnet.hadean.input.IButtonListener;
import xyz.valnet.hadean.input.SimpleButton;
import xyz.valnet.hadean.interfaces.IBottomBarItem;
import xyz.valnet.hadean.util.Layers;
public class BottomBar extends GameObject implements IButtonListener {
public class BottomBar extends GameObject implements IButtonListener, ITransient {
public static final int bottomBarHeight = 32;
private int screenWidth = 1024;

View File

@ -1,13 +1,11 @@
package xyz.valnet.hadean.gameobjects;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.hadean.gameobjects.worldobjects.Stockpile;
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
@ -18,7 +16,7 @@ public class Job extends GameObject {
private Job that = this;
private List<Callback> closedListeners = new ArrayList<Callback>();
public abstract class JobStep {
public abstract class JobStep implements Serializable {
public abstract Vector2i[] getLocations();
public void next() {
that.nextStep();
@ -132,7 +130,7 @@ public class Job extends GameObject {
}
@FunctionalInterface
public interface Callback {
public interface Callback extends Serializable {
public void apply();
}

View File

@ -56,10 +56,10 @@ public class JobBoard extends GameObject {
}
public boolean jobsAvailableForWorker(Pawn worker) {
return availableJobs.size() != 0;
return getJobsForWorker(worker).size() != 0;
}
public Job requestJob(Pawn worker) {
private List<Job> getJobsForWorker(Pawn worker) {
Vector2f workerLocation = worker.getWorldPosition();
List<Job> workables = availableJobs
@ -72,18 +72,22 @@ public class JobBoard extends GameObject {
.reduce(Float.MAX_VALUE, (a, b) -> a < b ? a : b)
))
// sort the jobs by their distance from the worker
.sorted(new Comparator<Pair<Job, Float>>() {
@Override
public int compare(Pair<Job, Float> a, Pair<Job, Float> b) {
if(a.second() > b.second()) return 1;
if(b.second() > a.second()) return -1;
return 0;
}
.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);

View File

@ -7,6 +7,7 @@ import java.util.List;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.IMouseCaptureArea;
import xyz.valnet.engine.scenegraph.ITransient;
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
import xyz.valnet.hadean.input.Button;
import xyz.valnet.hadean.input.IButtonListener;
@ -18,7 +19,7 @@ import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
import xyz.valnet.hadean.util.detail.Detail;
public class SelectionUI extends GameObject implements ISelectionChangeListener, IButtonListener, IMouseCaptureArea {
public class SelectionUI extends GameObject implements ISelectionChangeListener, IButtonListener, IMouseCaptureArea, ITransient {
private String name = "";
private int count = 0;

View File

@ -26,8 +26,7 @@ public class Tile extends WorldObject implements IWorkable {
// private final int x, y;
private Vector4f color;
private final Sprite sprite = Assets.defaultTerrain[(int)Math.floor(Math.random() * Assets.defaultTerrain.length)];
private final Sprite farmSprite = Assets.farmPlot[(int)Math.floor(Math.random() * Assets.farmPlot.length)];
private final int tileSelector = (int)Math.floor(Math.random() * 4);
private List<ITileThing> stuff = new ArrayList<ITileThing>();
// TODO remove remove queue, cause like, we dont iterate over
@ -46,11 +45,11 @@ public class Tile extends WorldObject implements IWorkable {
public void start() {
super.start();
if(Math.random() > 0.97) {
Tree tree = new Tree((int)x, (int)y);
stuff.add(tree);
add(tree);
}
// if(Math.random() > 0.97) {
// Tree tree = new Tree((int)x, (int)y);
// stuff.add(tree);
// add(tree);
// }
float scale = 1;
@ -58,7 +57,7 @@ public class Tile extends WorldObject implements IWorkable {
float green = (float) terrain.getNoise(greenSeed, x * scale, y * scale);
float blue = (float) terrain.getNoise(blueSeed, x * scale, y * scale);
color = new Vector4f(red * 0.1f, 0.4f + green * 0.15f, blue * 0.05f, 1f);
if(color == null) color = new Vector4f(red * 0.1f, 0.4f + green * 0.15f, blue * 0.05f, 1f);
// color = new Vector4f(red, green, blue, 1.0f);
}
@ -112,12 +111,12 @@ public class Tile extends WorldObject implements IWorkable {
public void render() {
if(tillLevel < 1f) {
Assets.flat.pushColor(color);
camera.draw(Layers.TILES, sprite, x, y);
camera.draw(Layers.TILES, Assets.defaultTerrain[tileSelector], x, y);
Assets.flat.popColor();
}
if(tillLevel > 0f) {
Assets.flat.pushColor(Vector4f.opacity(tillLevel));
camera.draw(Layers.TILES, farmSprite, x, y);
camera.draw(Layers.TILES, Assets.farmPlot[tileSelector], x, y);
Assets.flat.popColor();
}
}

View File

@ -5,11 +5,12 @@ import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.IMouseCaptureArea;
import xyz.valnet.engine.scenegraph.ITransient;
import xyz.valnet.hadean.gameobjects.Camera;
import xyz.valnet.hadean.interfaces.IBuildLayerListener;
import xyz.valnet.hadean.util.Layers;
public class BuildLayer extends GameObject implements IMouseCaptureArea {
public class BuildLayer extends GameObject implements IMouseCaptureArea, ITransient {
private boolean hovered = false;

View File

@ -9,6 +9,7 @@ import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.IMouseCaptureArea;
import xyz.valnet.engine.scenegraph.ITransient;
import xyz.valnet.hadean.gameobjects.Camera;
import xyz.valnet.hadean.gameobjects.ui.tabs.BuildTab;
import xyz.valnet.hadean.interfaces.ISelectable;
@ -18,7 +19,7 @@ import xyz.valnet.hadean.util.Layers;
import static xyz.valnet.engine.util.Math.lerp;
public class SelectionLayer extends GameObject implements IMouseCaptureArea {
public class SelectionLayer extends GameObject implements IMouseCaptureArea, ITransient {
public Vector2f initialCoords;
private Camera camera;

View File

@ -7,13 +7,14 @@ import xyz.valnet.engine.App;
import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.ITransient;
import xyz.valnet.hadean.HadeanGame;
import xyz.valnet.hadean.gameobjects.Camera;
import xyz.valnet.hadean.gameobjects.Tile;
import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
import xyz.valnet.hadean.util.Assets;
public class HoverQuery extends GameObject {
public class HoverQuery extends GameObject implements ITransient {
private Camera camera;

View File

@ -1,21 +1,17 @@
package xyz.valnet.hadean.gameobjects.ui.tabs;
import static xyz.valnet.engine.util.Math.lerp;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import xyz.valnet.engine.graphics.Drawing;
import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject;
@ -25,7 +21,6 @@ import xyz.valnet.hadean.gameobjects.Camera;
import xyz.valnet.hadean.gameobjects.Terrain;
import xyz.valnet.hadean.gameobjects.inputlayer.BuildLayer;
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
import xyz.valnet.hadean.gameobjects.worldobjects.FarmPlot;
import xyz.valnet.hadean.input.Button;
import xyz.valnet.hadean.input.IButtonListener;
import xyz.valnet.hadean.input.SimpleButton;
@ -34,7 +29,6 @@ import xyz.valnet.hadean.interfaces.IBuildLayerListener;
import xyz.valnet.hadean.interfaces.IBuildable;
import xyz.valnet.hadean.interfaces.ISelectable;
import xyz.valnet.hadean.interfaces.ISelectionChangeListener;
import xyz.valnet.hadean.interfaces.ITileThing;
import xyz.valnet.hadean.util.Assets;
import xyz.valnet.hadean.util.Layers;
import xyz.valnet.hadean.util.Pair;
@ -55,14 +49,12 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
private int x, y;
private int w, h;
// private List<String> categories = new ArrayList<String>();
private String selectedCategory = "";
private String selectedCategory = "Zones";
private transient Constructor<? extends IBuildable> selectedBuildable = null;
private transient Map<String, List<Pair<String, Constructor<? extends IBuildable>>>> buildables = null;
private transient Map<Button, Constructor<? extends IBuildable>> buildableButtons = null;
private List<Class<ITileThing>> things = new ArrayList<Class<ITileThing>>();
private Constructor<? extends IBuildable> selectedBuildable = null;
private Map<String, List<Pair<String, Constructor<? extends IBuildable>>>> buildables = new HashMap<String, List<Pair<String, Constructor<? extends IBuildable>>>>();
private int height = 0;
private String selectedBuildableName = "";
@ -150,6 +142,9 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
selection.subscribe(this);
}
buildables = new HashMap<String, List<Pair<String, Constructor<? extends IBuildable>>>>();
buildableButtons = new HashMap<Button, Constructor<? extends IBuildable>>();
calculateBuildables();
}
@ -274,8 +269,6 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
return Layers.GENERAL_UI;
}
private Map<Button, Constructor<? extends IBuildable>> buildableButtons = new HashMap<Button, Constructor<? extends IBuildable>>();
private void constructItemButtons() {
for(Button btn : buildableButtons.keySet()) {
remove(btn);
@ -286,6 +279,8 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
if(!opened.value()) return;
List<Pair<String, Constructor<? extends IBuildable>>> categoryBuildables = buildables.get(selectedCategory);
if(categoryBuildables == null) return;
int left = width + padding * 2;
int buttonHeight = 24;
int buttonWidth = 100;

View File

@ -0,0 +1,15 @@
package xyz.valnet.hadean.gameobjects.ui.tabs;
public class LoadTab extends Tab {
@Override
public void evoke() {
load();
}
@Override
public String getTabName() {
return "Load";
}
}

View File

@ -0,0 +1,15 @@
package xyz.valnet.hadean.gameobjects.ui.tabs;
public class SaveTab extends Tab {
@Override
public void evoke() {
save();
}
@Override
public String getTabName() {
return "Save";
}
}

View File

@ -1,10 +1,11 @@
package xyz.valnet.hadean.gameobjects.ui.tabs;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.ITransient;
import xyz.valnet.hadean.gameobjects.BottomBar;
import xyz.valnet.hadean.interfaces.IBottomBarItem;
public abstract class Tab extends GameObject implements IBottomBarItem {
public abstract class Tab extends GameObject implements IBottomBarItem, ITransient {
private BottomBar bottombar;

View File

@ -1,11 +1,13 @@
package xyz.valnet.hadean.gameobjects.worldobjects.pawn;
import java.io.Serializable;
import xyz.valnet.engine.math.Vector2i;
public abstract class Activity {
public abstract class Activity implements Serializable {
@FunctionalInterface
public interface ActivityCancellationCallback {
public interface ActivityCancellationCallback extends Serializable {
public void apply(Activity activity);
}

View File

@ -1,9 +1,11 @@
package xyz.valnet.hadean.gameobjects.worldobjects.pawn;
import java.io.Serializable;
import xyz.valnet.hadean.util.detail.Detail;
import xyz.valnet.hadean.util.detail.PercentDetail;
public class Needs {
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;

View File

@ -28,6 +28,8 @@ public class Pawn extends Agent {
private String name = "Pawn " + (++ pawnCount);
private Needs needs = new Needs();
// private int meaningless = 0;
// private float workEthic = (float) Math.random();
// private float selfWorth = (float) Math.random();

View File

@ -8,9 +8,10 @@ import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.math.Vector4i;
import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.scenegraph.IMouseCaptureArea;
import xyz.valnet.engine.scenegraph.ITransient;
import xyz.valnet.hadean.util.Assets;
public class Button extends GameObject implements IMouseCaptureArea {
public class Button extends GameObject implements IMouseCaptureArea, ITransient {
private int x, y, width, height;
private String text;

View File

@ -1,5 +1,6 @@
package xyz.valnet.hadean.pathfinding;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@ -7,7 +8,7 @@ import java.util.Stack;
import xyz.valnet.engine.math.Vector2i;
public class AStarPathfinder implements IPathfinder {
public class AStarPathfinder implements IPathfinder, Serializable {
private IPathable pathable;

View File

@ -1,8 +1,10 @@
package xyz.valnet.hadean.pathfinding;
import java.io.Serializable;
import xyz.valnet.engine.math.Vector2i;
public class Node {
public class Node implements Serializable {
public int x, y, g, h;
public Node from;

View File

@ -1,9 +1,10 @@
package xyz.valnet.hadean.pathfinding;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Stack;
public class Path implements Iterable<Node> {
public class Path implements Iterable<Node>, Serializable {
private Stack<Node> nodes;
public final int cost;
public final Node dst;

View File

@ -12,7 +12,9 @@ import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
import xyz.valnet.hadean.gameobjects.ui.HoverQuery;
import xyz.valnet.hadean.gameobjects.ui.tabs.BuildTab;
import xyz.valnet.hadean.gameobjects.ui.tabs.JobBoardTab;
import xyz.valnet.hadean.gameobjects.ui.tabs.LoadTab;
import xyz.valnet.hadean.gameobjects.ui.tabs.MenuTab;
import xyz.valnet.hadean.gameobjects.ui.tabs.SaveTab;
import xyz.valnet.hadean.gameobjects.worldobjects.pawn.Pawn;
// TODO BIG IDEAS
@ -43,11 +45,15 @@ public class GameScene extends SceneGraph {
objects.add(new BuildLayer());
objects.add(new HoverQuery());
objects.add(new BottomBar());
objects.add(new BuildTab());
objects.add(new JobBoardTab());
objects.add(new MenuTab());
objects.add(new HoverQuery());
objects.add(new SaveTab());
objects.add(new LoadTab());
}
}

View File

@ -1,6 +1,8 @@
package xyz.valnet.hadean.util;
public class Pair<T, U> {
import java.io.Serializable;
public class Pair<T, U> implements Serializable {
private final T t;
private final U u;
public Pair(T t, U u) {

View File

@ -1,9 +1,11 @@
package xyz.valnet.hadean.util;
public class SmartBoolean {
import java.io.Serializable;
public class SmartBoolean implements Serializable {
private boolean value;
public interface IListener {
public interface IListener extends Serializable {
public default void rise() {}
public default void fall() {}
public default void changed() {}