mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-12-13 14:49:03 +00:00
Fixed some debug commands. Added blueprint item deserialization, Added inventory SCAN and SEEK actions
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package net.simon987.constructionplugin;
|
||||
|
||||
import net.simon987.server.game.item.Item;
|
||||
import net.simon987.server.game.objects.GameObject;
|
||||
import net.simon987.server.game.objects.InventoryHolder;
|
||||
import net.simon987.server.io.JSONSerializable;
|
||||
import net.simon987.server.io.MongoSerializable;
|
||||
import org.bson.Document;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class BluePrint implements InventoryHolder, JSONSerializable, MongoSerializable {
|
||||
|
||||
/**
|
||||
* Map of items id and required amount
|
||||
* <br>The amount is decremented as the items are added
|
||||
*/
|
||||
protected Map<Integer, Integer> requiredItems;
|
||||
|
||||
/**
|
||||
* This object will be instantiated when completed
|
||||
*/
|
||||
protected Class<? extends GameObject> targetObject;
|
||||
|
||||
/**
|
||||
* Set to true when all the requirements are met
|
||||
*/
|
||||
private boolean completed;
|
||||
|
||||
public BluePrint() {
|
||||
requiredItems = new HashMap<>();
|
||||
}
|
||||
|
||||
public BluePrint(Document document) {
|
||||
requiredItems = (Map<Integer, Integer>) document.get("required_items");
|
||||
completed = document.getBoolean("completed");
|
||||
try {
|
||||
targetObject = Class.forName(document.getString("target")).asSubclass(GameObject.class);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCompleted() {
|
||||
|
||||
for (Integer remaining : requiredItems.values()) {
|
||||
if (remaining > 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
completed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeItem(Item item) {
|
||||
|
||||
if (requiredItems.containsKey(item.getId()) && requiredItems.get(item.getId()) > 0) {
|
||||
requiredItems.put(item.getId(), requiredItems.get(item.getId()) - 1);
|
||||
checkCompleted();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void takeItem(int itemId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTakeItem(int itemId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
public Class<? extends GameObject> getTargetObject() {
|
||||
return targetObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject debugJsonSerialise() {
|
||||
return jsonSerialise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject jsonSerialise() {
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.put("target", targetObject);
|
||||
json.put("required_items", requiredItems);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
Document document = new Document();
|
||||
|
||||
document.put("completed", completed);
|
||||
document.put("target", targetObject);
|
||||
document.put("required_items", requiredItems);
|
||||
|
||||
return document;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package net.simon987.constructionplugin;
|
||||
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BluePrintRegistry {
|
||||
|
||||
public static final BluePrintRegistry INSTANCE = new BluePrintRegistry();
|
||||
|
||||
private Map<String, Class<? extends BluePrint>> blueprints;
|
||||
private Map<String, String> digitizedBlueprints;
|
||||
|
||||
private BluePrintRegistry() {
|
||||
blueprints = new HashMap<>();
|
||||
digitizedBlueprints = new HashMap<>();
|
||||
}
|
||||
|
||||
public void registerBluePrint(Class<? extends BluePrint> clazz) {
|
||||
blueprints.put(clazz.getCanonicalName(), clazz);
|
||||
String bpData = new String(BluePrintUtil.bluePrintData(clazz));
|
||||
digitizedBlueprints.put(bpData, clazz.getCanonicalName());
|
||||
}
|
||||
|
||||
public BluePrint deserializeBlueprint(Document document) {
|
||||
|
||||
String type = document.getString("type");
|
||||
|
||||
if (blueprints.containsKey(type)) {
|
||||
|
||||
try {
|
||||
return blueprints.get(type).getConstructor(Document.class).newInstance(document);
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (InvocationTargetException e) {
|
||||
LogManager.LOGGER.severe("(Construction Plugin) Error while trying to deserialize object of type " + type + ": " + e.getTargetException().getMessage());
|
||||
LogManager.LOGGER.severe(document.toJson());
|
||||
e.getTargetException().printStackTrace();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
LogManager.LOGGER.severe("(Construction Plugin) Trying to deserialize unknown BluePrint type: " + type);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public BluePrint deserializeBluePrint(char[] chars) {
|
||||
|
||||
String bpData = new String(chars);
|
||||
|
||||
if (digitizedBlueprints.containsKey(bpData)) {
|
||||
return deserializeBlueprint(new Document("type", digitizedBlueprints.get(bpData)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package net.simon987.constructionplugin;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
class BluePrintUtil {
|
||||
|
||||
private static byte[] secretKey;
|
||||
private static final String SHA512 = "SHA-512";
|
||||
|
||||
//We need 1024 chars = 2048 bytes = 32 values
|
||||
private static final char[] ARBITRARY_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456".toCharArray();
|
||||
|
||||
static void setSecretKey(String secretKey) {
|
||||
BluePrintUtil.secretKey = secretKey.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a message using SHA512 with the server secret key as the sal
|
||||
*
|
||||
* @return 128-bit char array
|
||||
*/
|
||||
private static char[] hashMessage(String message) {
|
||||
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance(SHA512);
|
||||
md.update(secretKey);
|
||||
md.update(message.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
byte[] digest = md.digest();
|
||||
char[] chars = new char[digest.length / 2];
|
||||
ByteBuffer.wrap(digest).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(chars);
|
||||
|
||||
return chars;
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a char array representation of a blueprint. It is obtained by hashing the blueprint
|
||||
* properties with the server secret key. Some arbitrary values are added to make a 1024-char
|
||||
* array. The same blueprint and secret key always gives the same result.
|
||||
*/
|
||||
static char[] bluePrintData(Class<? extends BluePrint> blueprint) {
|
||||
|
||||
char[] result = new char[ARBITRARY_STRING.length * 32];
|
||||
|
||||
for (int i = ARBITRARY_STRING.length - 1; i > 0; --i) {
|
||||
char[] hashedBlueprint = hashMessage(ARBITRARY_STRING[i] + blueprint.getName());
|
||||
if (hashedBlueprint != null) {
|
||||
System.arraycopy(hashedBlueprint, 0, result,
|
||||
i * hashedBlueprint.length, hashedBlueprint.length);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,24 @@
|
||||
package net.simon987.constructionplugin;
|
||||
|
||||
import net.simon987.server.ServerConfiguration;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.objects.GameRegistry;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
|
||||
public class ConstructionPlugin extends ServerPlugin {
|
||||
@Override
|
||||
public void init(ServerConfiguration config, GameRegistry gameRegistry) {
|
||||
|
||||
@Override
|
||||
public void init(GameServer gameServer) {
|
||||
|
||||
BluePrintUtil.setSecretKey(gameServer.getSecretKey());
|
||||
GameRegistry gameRegistry = gameServer.getRegistry();
|
||||
|
||||
gameRegistry.registerItem(ItemBluePrint.ID, ItemBluePrint.class);
|
||||
gameRegistry.registerGameObject(Obstacle.class);
|
||||
gameRegistry.registerGameObject(ConstructionSite.class);
|
||||
|
||||
BluePrintRegistry.INSTANCE.registerBluePrint(ObstacleBlueprint.class);
|
||||
|
||||
LogManager.LOGGER.info("(Construction Plugin) Initialized construction plugin");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,33 @@ package net.simon987.constructionplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.item.Item;
|
||||
import net.simon987.server.game.objects.GameObject;
|
||||
import net.simon987.server.game.objects.InventoryHolder;
|
||||
import net.simon987.server.game.objects.Structure;
|
||||
import net.simon987.server.game.objects.Updatable;
|
||||
import org.bson.Document;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ConstructionSite extends GameObject implements Updatable, InventoryHolder {
|
||||
public class ConstructionSite extends Structure implements Updatable, InventoryHolder {
|
||||
|
||||
public static final int MAP_INFO = 0xFFFF; //TODO: determine
|
||||
public static final int LIFETIME = GameServer.INSTANCE.getConfig().getInt("construction_site_ttl");
|
||||
|
||||
private int age;
|
||||
private BluePrint bluePrint;
|
||||
|
||||
public ConstructionSite(BluePrint bluePrint) {
|
||||
super(1, 1);
|
||||
|
||||
this.bluePrint = bluePrint;
|
||||
this.age = 0;
|
||||
}
|
||||
|
||||
public ConstructionSite(Document document) {
|
||||
super(document, 1, 1);
|
||||
|
||||
age = document.getInteger("age");
|
||||
bluePrint = BluePrintRegistry.INSTANCE.deserializeBlueprint((Document) document.get("blueprint"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getMapInfo() {
|
||||
@@ -30,11 +47,7 @@ public class ConstructionSite extends GameObject implements Updatable, Inventory
|
||||
|
||||
@Override
|
||||
public boolean placeItem(Item item) {
|
||||
|
||||
//todo: add mats here
|
||||
//todo: inv digitize
|
||||
|
||||
return false;
|
||||
return bluePrint.placeItem(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,4 +59,24 @@ public class ConstructionSite extends GameObject implements Updatable, Inventory
|
||||
public boolean canTakeItem(int itemId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject jsonSerialise() {
|
||||
JSONObject json = super.jsonSerialise();
|
||||
|
||||
json.put("blueprint", bluePrint.jsonSerialise());
|
||||
json.put("age", age);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
Document document = super.mongoSerialise();
|
||||
|
||||
document.put("blueprint", bluePrint.mongoSerialise());
|
||||
document.put("age", age);
|
||||
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.simon987.constructionplugin;
|
||||
|
||||
import net.simon987.server.assembly.Memory;
|
||||
import net.simon987.server.game.item.Item;
|
||||
import org.bson.Document;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ItemBluePrint extends Item {
|
||||
|
||||
public static final int ID = 0x0005;
|
||||
private Class<? extends BluePrint> bluePrint;
|
||||
|
||||
public ItemBluePrint() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public ItemBluePrint(Document document) {
|
||||
super(document);
|
||||
try {
|
||||
bluePrint = Class.forName(document.getString("blueprint")).asSubclass(BluePrint.class);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void digitize(Memory memory, int offset) {
|
||||
char[] data = BluePrintUtil.bluePrintData(bluePrint);
|
||||
memory.write(offset, data, 0, data.length);
|
||||
|
||||
System.out.println("DEBUG: blueprint digitize " + data.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char poll() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject debugJsonSerialise() {
|
||||
JSONObject json = super.debugJsonSerialise();
|
||||
json.put("blueprint", bluePrint.getCanonicalName());
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
Document document = super.mongoSerialise();
|
||||
|
||||
document.put("blueprint", bluePrint.getCanonicalName());
|
||||
return document;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package net.simon987.constructionplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.objects.Attackable;
|
||||
import net.simon987.server.game.objects.Structure;
|
||||
import net.simon987.server.game.objects.Updatable;
|
||||
import org.bson.Document;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class Obstacle extends Structure implements Attackable, Updatable {
|
||||
|
||||
public static final int MAP_INFO = 0x0601;
|
||||
private static final int HEAL_RATE = GameServer.INSTANCE.getConfig().getInt("obstacle_regen");
|
||||
private static final int MAX_HP = GameServer.INSTANCE.getConfig().getInt("obstacle_hp");
|
||||
|
||||
private int hp;
|
||||
private int color;
|
||||
|
||||
public Obstacle() {
|
||||
super(1, 1);
|
||||
}
|
||||
|
||||
public Obstacle(Document document) {
|
||||
super(document, 1, 1);
|
||||
|
||||
hp = document.getInteger(hp);
|
||||
color = document.getInteger(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
heal(HEAL_RATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHealRate(int hp) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHp() {
|
||||
return hp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHp(int hp) {
|
||||
this.hp = hp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHp() {
|
||||
return MAX_HP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxHp(int hp) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void heal(int amount) {
|
||||
hp = Math.min(getMaxHp(), hp + amount);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void damage(int amount) {
|
||||
hp -= amount;
|
||||
|
||||
if (hp < 0) {
|
||||
setDead(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
Document document = super.mongoSerialise();
|
||||
|
||||
document.put("hp", hp);
|
||||
document.put("color", hp);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject debugJsonSerialise() {
|
||||
return jsonSerialise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject jsonSerialise() {
|
||||
JSONObject json = super.jsonSerialise();
|
||||
|
||||
json.put("hp", hp);
|
||||
json.put("color", hp);
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.simon987.constructionplugin;
|
||||
|
||||
import net.simon987.server.game.item.ItemIron;
|
||||
import org.bson.Document;
|
||||
|
||||
public class ObstacleBlueprint extends BluePrint {
|
||||
|
||||
public ObstacleBlueprint() {
|
||||
super();
|
||||
|
||||
this.requiredItems.put(ItemIron.ID, 2); //TODO: load from config?
|
||||
this.targetObject = Obstacle.class;
|
||||
}
|
||||
|
||||
public ObstacleBlueprint(Document document) {
|
||||
this.requiredItems.put(ItemIron.ID, 2); //TODO: load from config?
|
||||
this.targetObject = Obstacle.class;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user