From ecf0a96f6ded370a5650cd5f99176f19e118d1ad Mon Sep 17 00:00:00 2001 From: notzed Date: Sat, 22 Feb 2014 01:23:56 +0000 Subject: [PATCH] checkpoint db work. git-svn-id: file:///home/notzed/svn/duskz/trunk@23 b8b59bfb-1aa4-4687-8f88-a62eeb14c21e --- .../src/duskz/server/entityz/Ability.java | 13 +- .../src/duskz/server/entityz/Active.java | 262 ++++++++++-------- .../src/duskz/server/entityz/Battle.java | 4 +- .../src/duskz/server/entityz/Condition.java | 2 + .../duskz/server/entityz/ConditionList.java | 4 + .../src/duskz/server/entityz/Container.java | 4 +- .../src/duskz/server/entityz/Converter.java | 4 +- .../src/duskz/server/entityz/DBTest.java | 134 +++++++++ .../src/duskz/server/entityz/Equipment.java | 12 +- .../src/duskz/server/entityz/Faction.java | 49 +++- DuskServer/src/duskz/server/entityz/Game.java | 26 +- .../src/duskz/server/entityz/GameShop.java | 28 +- DuskServer/src/duskz/server/entityz/Held.java | 68 +++++ .../src/duskz/server/entityz/Holdable.java | 61 +++- .../src/duskz/server/entityz/Inventory.java | 8 +- .../src/duskz/server/entityz/Inventory2.java | 227 +++++++++++++++ .../src/duskz/server/entityz/Mobile.java | 14 +- DuskServer/src/duskz/server/entityz/Pack.java | 14 +- DuskServer/src/duskz/server/entityz/Pet.java | 17 +- .../src/duskz/server/entityz/Player.java | 88 ++++-- .../server/entityz/PlayerConnection.java | 4 +- .../src/duskz/server/entityz/PlayerShop.java | 18 +- .../src/duskz/server/entityz/PlayerState.java | 10 +- DuskServer/src/duskz/server/entityz/Race.java | 45 ++- DuskServer/src/duskz/server/entityz/Shop.java | 18 +- DuskServer/src/duskz/server/entityz/Sign.java | 5 + .../src/duskz/server/entityz/Thing.java | 55 +++- .../src/duskz/server/entityz/ThingTable.java | 10 +- .../src/duskz/server/entityz/TileMap.java | 60 ++++ .../src/duskz/server/entityz/Training.java | 4 + .../duskz/server/entityz/VariableList.java | 2 + .../src/duskz/server/entityz/Weapon.java | 2 +- .../src/duskz/server/entityz/Wearable.java | 6 +- 33 files changed, 1007 insertions(+), 271 deletions(-) create mode 100644 DuskServer/src/duskz/server/entityz/DBTest.java create mode 100644 DuskServer/src/duskz/server/entityz/Held.java create mode 100644 DuskServer/src/duskz/server/entityz/Inventory2.java diff --git a/DuskServer/src/duskz/server/entityz/Ability.java b/DuskServer/src/duskz/server/entityz/Ability.java index 3b70c3e..ec3b729 100644 --- a/DuskServer/src/duskz/server/entityz/Ability.java +++ b/DuskServer/src/duskz/server/entityz/Ability.java @@ -19,15 +19,26 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Persistent; + /** * * @author Michael Zucchi */ +@Persistent public class Ability { - public final String name; + public String name; private int level; + public Ability() { + } + + public Ability(String name, int level) { + this.name = name; + this.level = level; + } + public Ability(String name) { this.name = name; } diff --git a/DuskServer/src/duskz/server/entityz/Active.java b/DuskServer/src/duskz/server/entityz/Active.java index e3e8af1..edb26f5 100644 --- a/DuskServer/src/duskz/server/entityz/Active.java +++ b/DuskServer/src/duskz/server/entityz/Active.java @@ -21,6 +21,10 @@ // fixme copyrihgts package duskz.server.entityz; +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Persistent; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; import duskz.protocol.DuskMessage; import duskz.protocol.Wearing; import java.io.BufferedWriter; @@ -43,6 +47,7 @@ import java.util.List; * * @author Michael Zucchi */ +@Persistent public abstract class Active extends Thing { /** @@ -84,13 +89,14 @@ public abstract class Active extends Thing { // object? player? // I don' think mobs can have clans - factions are used instead, clan/race // candiates for class beteen active and player/pet - String clan; /** * Race, mobs can't have races. */ + @SecondaryKey(relate = Relationship.ONE_TO_ONE, relatedEntity = Race.class) + long raceid; + @NotPersistent Race race; - Equipment wornItems = new Equipment(); - Inventory inventory = new Inventory(); + Inventory2 inventory = new Inventory2(); /** * Sleeping state */ @@ -98,19 +104,24 @@ public abstract class Active extends Thing { /** * Tracks actives following in a pack */ - protected Pack pack; + // FIXME: it is persistent + @NotPersistent + volatile protected Pack pack; /** * Does this leader allow following at the moment. */ - boolean canLead = true; + @NotPersistent + volatile boolean canLead = true; /** * Allowed to move */ - protected boolean moveable = true; + @NotPersistent + volatile protected boolean moveable = true; /** * "step" of image: basically last direction moved. */ - protected int imageStep; + @NotPersistent + volatile protected int imageStep; /** * Live conditions */ @@ -122,12 +133,14 @@ public abstract class Active extends Thing { /** * If fighting, current battle */ - protected Battle battle; + @NotPersistent + volatile protected Battle battle; /** * Damage done, accumulates until you lose, where it is used to give * bonus experience to your the winners */ - int damageDone; + @NotPersistent + volatile int damageDone; // private final HashMap skills = new HashMap<>(); // FIXME: SpellAbility subclasses Ability @@ -135,25 +148,32 @@ public abstract class Active extends Thing { /** * Pending moves, processed one at a time during movement tick */ + @NotPersistent final private LinkedList moveQueue = new LinkedList<>(); /** * Pending commands, this is only used during battle */ + @NotPersistent final private LinkedList battleCommands = new LinkedList<>(); /** * Tick of last state change, such as sleeping, etc. */ - int flagsChanged; + @NotPersistent + volatile int flagsChanged; /** * Tick of last condition change */ - int conditionsChanged; + @NotPersistent + volatile int conditionsChanged; + + protected Active() { + } Active(Game game) { super(game); } - Wearable parseWearable(String value) { + Held parseWearable(int where, String value) { // format is name,durability,uses System.out.println("parse wearable: " + value); @@ -165,15 +185,18 @@ public abstract class Active extends Thing { Wearable w = (Wearable) game.createItem(args[0].toLowerCase()); + Held h = null; + if (w != null) { - w.durability = Long.valueOf(args[1]); - w.uses = Integer.valueOf(args[2]); + h = new Held(w); + h.wear = Long.valueOf(args[1]); + h.used = Integer.valueOf(args[2]); } - return w; + return h; } // TODO: this probably needs some 'exporter' on Thing - Holdable parseHoldable(String value) { + Held parseHoldable(String value) { // format is name,durability,uses ... but durability is only used on Wearables // FIXME: fix exporter ... not so easy, everything is an item, even weapons. @@ -186,13 +209,15 @@ public abstract class Active extends Thing { Holdable h = (Holdable) game.createItem(args[0].toLowerCase()); + Held he = new Held(h); + // blah ... nice eh? if (h instanceof Wearable) { - ((Wearable) h).durability = Long.valueOf(args[1]); + (he).wear = Long.valueOf(args[1]); } - h.uses = Integer.valueOf(args[2]); + he.used = Integer.valueOf(args[2]); - return h; + return he; } /* * @@ -268,35 +293,35 @@ public abstract class Active extends Thing { case "race": race = game.getRace(value); break; - case "clan": - clan = value; + case "privs": + privs = Integer.valueOf(value); break; case "wield": - wornItems.wear(Wearing.WIELD, parseWearable(value)); + inventory.add(parseWearable(Wearing.WIELD, value)); break; case "arms": - wornItems.wear(Wearing.ARMS, parseWearable(value)); + inventory.wear(parseWearable(Wearing.ARMS, value)); break; case "legs": - wornItems.wear(Wearing.LEGS, parseWearable(value)); + inventory.wear(parseWearable(Wearing.LEGS, value)); break; case "torso": - wornItems.wear(Wearing.TORSO, parseWearable(value)); + inventory.wear(parseWearable(Wearing.TORSO, value)); break; case "waist": - wornItems.wear(Wearing.WAIST, parseWearable(value)); + inventory.wear(parseWearable(Wearing.WAIST, value)); break; case "neck": - wornItems.wear(Wearing.NECK, parseWearable(value)); + inventory.wear(parseWearable(Wearing.NECK, value)); break; case "skull": - wornItems.wear(Wearing.SKULL, parseWearable(value)); + inventory.wear(parseWearable(Wearing.SKULL, value)); break; case "eyes": - wornItems.wear(Wearing.EYES, parseWearable(value)); + inventory.wear(parseWearable(Wearing.EYES, value)); break; case "hands": - wornItems.wear(Wearing.HANDS, parseWearable(value)); + inventory.wear(parseWearable(Wearing.HANDS, value)); break; // FIXME: should it specify the item type? case "item": @@ -323,20 +348,24 @@ public abstract class Active extends Thing { } writeProperty(out, "exp", exp); writeProperty(out, "gold", gold); - writeProperty(out, "clan", clan); + writeProperty(out, "privs", privs); // FIXME: hack for mobile, race doesn't apply - for (int i = 0; i < Wearing.WEARING_COUNT; i++) { - Wearable w = wornItems.getWorn(i); - if (w != null) { - writeProperty(out, Wearing.wornNames[i], w.name + "," + w.durability + "," + w.uses); - } - } + // for (int i = 0; i < Wearing.WEARING_COUNT; i++) { + // Wearable w = wornItems.getWorn(i); + // if (w != null) { + // writeProperty(out, Wearing.wornNames[i], w.name + "," + w.durability + "," + w.uses); + // } + // } if (race != null) writeProperty(out, "race", race.name); variables.writeProperties(out); conditions.writeProperties(out); } + public int getPrivs() { + return privs; + } + public int getStat(int key) { return stats[key] + race.stats[key] + bonus[key]; } @@ -349,7 +378,7 @@ public abstract class Active extends Thing { public void addStat(int key, int value) { setStat(key, stats[key] + value); } - + public int getBonus(int key) { return bonus[key]; } @@ -391,9 +420,9 @@ public abstract class Active extends Thing { } public int getRange() { - Weapon item = (Weapon) wornItems.getWorn(Wearing.WIELD); + Held h = inventory.getWorn(Wearing.WIELD); - return item != null ? item.range : 1; + return h != null ? ((Weapon) h.holdable).range : 1; } public int getRangeWithBonus() { @@ -434,6 +463,15 @@ public abstract class Active extends Thing { return true; } + public void addSkill(String name, int level) { + Ability a = skills.get(name); + + if (a != null) { + level += a.getLevel(); + } + skills.put(name, new Ability(name, level)); + } + public boolean isMoveable() { return moveable; } @@ -508,9 +546,9 @@ public abstract class Active extends Thing { * @param amount */ public void weaponDamage(int amount) { - Wearable item = wornItems.damageItem(Wearing.WIELD, amount); + Held item = inventory.damageItem(Wearing.WIELD, amount); if (item != null) { - chatMessage("Your " + item.name + " breaks."); + chatMessage("Your " + item.getName() + " breaks."); // FIXME: onUnwear(item); //if (isPlayer()) { // updateEquipment(); @@ -525,15 +563,15 @@ public abstract class Active extends Thing { } public void armourDamage(int damage) { - int total = wornItems.armourCount(); + int total = inventory.armourCount(); if (total == 0) { return; } for (int i = Wearing.ARMS; i < Wearing.WEARING_COUNT; i++) { - Wearable item = wornItems.damageItem(i, damage / total); + Held item = inventory.damageItem(i, damage / total); if (item != null) { - chatMessage("Your " + item.name + " breaks."); + chatMessage("Your " + item.getName() + " breaks."); //FIXME: onUnwear(item); //updateStats(); //updateEquipment(); @@ -554,7 +592,7 @@ public abstract class Active extends Thing { dir = moveQueue.removeFirst(); } - System.out.println("move " + name + " tick: " + dir); + System.out.println("move " + getName() + " tick: " + dir); switch (dir.charAt(0)) { case 'n': @@ -884,8 +922,8 @@ public abstract class Active extends Thing { if ((x == leader.x) && (y == leader.y)) { return false; } else if (Math.abs(x - oldx) + Math.abs(y - oldy) > 1) { - leader.chatMessage(name + " is no longer following you."); - chatMessage("You are no longer following " + leader.name + "."); + leader.chatMessage(getName() + " is no longer following you."); + chatMessage("You are no longer following " + leader.getName() + "."); pack.removeFollower(this); return false; @@ -928,7 +966,7 @@ public abstract class Active extends Thing { // search by name for (TileMap.MapData md : map.range(x, y, game.viewRange)) { for (Thing t : md.entities) { - if (t.name.equalsIgnoreCase(name)) { + if (t.getName().equalsIgnoreCase(name)) { boolean see = true; if (t instanceof Active) { @@ -962,7 +1000,7 @@ public abstract class Active extends Thing { } else if (enemy.getType() == TYPE_PET) { msg = ("You can't attack pets."); } else if (distanceL1(enemy) > getRangeWithBonus()) { - System.out.println("attack enemy =" + enemy.name + " distance =" + distanceL1(enemy) + " range = " + getRangeWithBonus()); + System.out.println("attack enemy =" + enemy.getName() + " distance =" + distanceL1(enemy) + " range = " + getRangeWithBonus()); msg = ("They're too far away."); } else if (!game.onCanAttack(this, enemy)) { msg = ("You can't attack them."); @@ -992,7 +1030,7 @@ public abstract class Active extends Thing { } public int getArmourMod() { - return wornItems.armourMod(); + return inventory.armourMod(); } public int getArmourModWithBonus() { @@ -1000,9 +1038,9 @@ public abstract class Active extends Thing { } public int getDamageMod() { - Wearable item = wornItems.getWorn(Wearing.WIELD); + Held item = inventory.getWorn(Wearing.WIELD); if (item != null) - return item.mod; + return ((Wearable) item.holdable).mod; return 100; } @@ -1092,10 +1130,10 @@ public abstract class Active extends Thing { r2 = this.getSkillLevel("close combat"); } if (r2 < 0) { - s.append(this.name).append(" missed."); + s.append(this.getName()).append(" missed."); battle.hitMessage(this, target, 0, "Missed!"); } else if (dodgeRoll(target, r2)) { - s.append(target.name).append(" dodged ").append(this.name).append("'s attack"); + s.append(target.getName()).append(" dodged ").append(this.getName()).append("'s attack"); battle.hitMessage(this, target, 0, "Dodged!"); } else { // FIXME: audio @@ -1106,7 +1144,7 @@ public abstract class Active extends Thing { if (i < 0) { i = 0; } - s.append(this.name + " did " + i + " to " + target.name); + s.append(this.getName()).append(" did ").append(i).append(" to ").append(target.getName()); target.receivedDamage(i); this.causedDamage(i); @@ -1227,7 +1265,7 @@ public abstract class Active extends Thing { public void attack(Battle battle, Active target, int range) { if (range > getRangeWithBonus()) { // out of range - battle.chatMessage(name + " is out of range"); + battle.chatMessage(getName() + " is out of range"); } else { StringBuilder msg = new StringBuilder(); @@ -1501,8 +1539,8 @@ public abstract class Active extends Thing { @Override public void look(Active viewer) { - chatMessage(viewer.name + " is looking at you."); - viewer.chatMessage(name + " has " + getCP() + "cp and " + getHP() + "/" + getHPMax() + "hp."); + chatMessage(viewer.getName() + " is looking at you."); + viewer.chatMessage(getName() + " has " + getCP() + "cp and " + getHP() + "/" + getHPMax() + "hp."); if (description != null) { viewer.chatMessage("Their description is: " + description); } @@ -1518,9 +1556,9 @@ public abstract class Active extends Thing { "They are wearing %s on their hands." }; for (int i = 0; i < formats.length; i++) { - Wearable item = wornItems.getWorn(i); + Held item = inventory.getWorn(i); if (item != null) - viewer.chatMessage(String.format(formats[i], item.description)); + viewer.chatMessage(String.format(formats[i], item.getDescription())); } } @@ -1529,31 +1567,24 @@ public abstract class Active extends Thing { * * The item will be worn at the correct location. * + * This is here to provide hooks for subclasses + * * @param w */ - public void wearItem(Wearable w) { - // FIXME: threads. - if (inventory.contains(w)) { - Wearable old = wornItems.wear(w.getWearing(), w); - - if (old != null) { - inventory.add(old); - } - inventory.remove(w); - } + public boolean wearItem(Held what) { + return inventory.wear(what); } public void wearCommand(String what) { - Holdable h = inventory.get(what); + Held h = inventory.get(what); String msg = null; + if (h != null) { - if (h instanceof Wearable) { - wearItem((Wearable) h); - } else { + if (!wearItem(h)) msg = "You'd look pretty stupid trying to wear that!"; - } - } else + } else { msg = "You don't have that"; + } chatMessage(msg); } @@ -1565,11 +1596,7 @@ public abstract class Active extends Thing { * @param index */ public void unwearAt(int index) { - Wearable w = wornItems.unwear(index); - - // fIXME: onunwear/etc. - if (w != null) - inventory.add(w); + inventory.unwear(index); } /** @@ -1583,12 +1610,16 @@ public abstract class Active extends Thing { unwearAt(i); } } else { - int index = Equipment.toIndex(what); + int index = Inventory2.toIndex(what); + + if (index == -1) { + Held h = inventory.get(what); - if (index == -1) - index = wornItems.getWornIndex(what); + if (h != null) + index = h.where; + } - if (index != -1) { + if (index != Wearing.INVENTORY) { unwearAt(index); } else { chatMessage("You're not wearing that."); @@ -1610,7 +1641,12 @@ public abstract class Active extends Thing { Holdable item = (Holdable) thing; game.removeThing(thing); - inventory.add(item); + + Held h = new Held(); + h.holdable = item; + h.holdableID = item.ID; + + inventory.add(h); game.onItem(this, item, "get"); } @@ -1619,23 +1655,21 @@ public abstract class Active extends Thing { } public void dropCommand(String what) { - Holdable h = inventory.get(what); + Held h = inventory.get(what); String msg = null; if (h == null) { - if (wornItems.isWearing(what)) { - msg = ("You're wearing that, you cannot drop it."); - } else { - msg = ("You don't have that"); - } - } else if (game.haveOnItem(h, "drop")) { - game.onItem(this, h, "drop"); + msg = ("You don't have that"); + } else if (h.where != Wearing.INVENTORY) { + msg = ("You're wearing that, you cannot drop it."); + } else if (game.haveOnItem(h.holdable, "drop")) { + game.onItem(this, h.holdable, "drop"); } else { inventory.remove(h); - if (h.cost == 0) { - msg = h.name + " vanishes into thin air."; + if (h.holdable.cost == 0) { + msg = h.getName() + " vanishes into thin air."; } else { - game.addThing(h, map, x, y); + game.addThing(h.holdable, map, x, y); } } @@ -1643,39 +1677,38 @@ public abstract class Active extends Thing { } public void useCommand(String what) { - Holdable item = inventory.get(what); + Held item = inventory.get(what); String msg = null; // TODO: check type? if (item == null) msg = "You don't have that."; - else if (!game.haveOnItem(item, "use")) + else if (!game.haveOnItem(item.holdable, "use")) msg = "That cannot be used."; - else if (item.uses == 0) + else if (item.holdable.uses != -1 && item.used >= item.holdable.uses) msg = "That is used up."; else { - if (item.uses != -1) - item.uses--; - game.onItem(this, item, "use"); + item.used += 1; + game.onItem(this, item.holdable, "use"); } chatMessage(msg); } public void drinkCommand(String what) { - Holdable item = inventory.get(what); + Held item = inventory.get(what); - if (item != null && item.getType() != TYPE_DRINK) { + if (item != null && item.holdable.getType() != TYPE_DRINK) { chatMessage("You can't drink that."); } else useCommand(what); } public void eatCommand(String what) { - Holdable item = inventory.get(what); + Held item = inventory.get(what); - if (item != null && item.getType() != TYPE_FOOD) { + if (item != null && item.holdable.getType() != TYPE_FOOD) { chatMessage("You can't eat that."); } else useCommand(what); @@ -1739,14 +1772,14 @@ public abstract class Active extends Thing { addStat(STAT_STR, inc); } - public List getAllItems(String name) { + public List getAllItems(String name) { return inventory.getAll(name, Integer.MAX_VALUE); } - public void addItem(Holdable item) { + public void addItem(Held item) { if (item != null) { inventory.add(item); - game.onItem(this, item, "get"); + game.onItem(this, item.holdable, "get"); } } @@ -1756,7 +1789,7 @@ public abstract class Active extends Thing { * @param item * @return true if the item was in the inventory and could be removed. */ - public boolean removeItem(Holdable item) { + public boolean removeItem(Held item) { // FIXME: what if worn? if (item != null) { return inventory.remove(item); @@ -1783,11 +1816,10 @@ public abstract class Active extends Thing { * @return */ public boolean isOwner(String key) { - return inventory.get(key) != null - || wornItems.isWearing(key); + return inventory.get(key) != null; } public boolean isWearing(String key) { - return wornItems.isWearing(key); + return inventory.isWearing(key); } } diff --git a/DuskServer/src/duskz/server/entityz/Battle.java b/DuskServer/src/duskz/server/entityz/Battle.java index 1637f06..c2f0ff7 100644 --- a/DuskServer/src/duskz/server/entityz/Battle.java +++ b/DuskServer/src/duskz/server/entityz/Battle.java @@ -66,7 +66,7 @@ public class Battle implements DuskProtocol { playerInSide1 = addToBattle(1, side1, side2, a, playerInSide1, playerInSide2); } - inpla1.localisedChat("-" + inpla1.name + " has attacked " + inpla2.name); + inpla1.localisedChat("-" + inpla1.getName() + " has attacked " + inpla2.getName()); // FIXME: inpla1.startBattle(inpla2); // inpla2.startBattle(inpla1); } catch (Exception e) { @@ -135,7 +135,7 @@ public class Battle implements DuskProtocol { // added.playMusic(1); //} } - chatMessage(added.name + " has joined the battle."); + chatMessage(added.getName() + " has joined the battle."); side.add(added); added.enterBattle(this); diff --git a/DuskServer/src/duskz/server/entityz/Condition.java b/DuskServer/src/duskz/server/entityz/Condition.java index 55bd81b..dddfc7b 100644 --- a/DuskServer/src/duskz/server/entityz/Condition.java +++ b/DuskServer/src/duskz/server/entityz/Condition.java @@ -19,6 +19,7 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Persistent; import java.util.Objects; /** @@ -31,6 +32,7 @@ import java.util.Objects; * * @author Michael Zucchi */ +@Persistent public class Condition { /** diff --git a/DuskServer/src/duskz/server/entityz/ConditionList.java b/DuskServer/src/duskz/server/entityz/ConditionList.java index 2ed0916..39dd2cd 100644 --- a/DuskServer/src/duskz/server/entityz/ConditionList.java +++ b/DuskServer/src/duskz/server/entityz/ConditionList.java @@ -19,6 +19,8 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Persistent; import java.io.BufferedWriter; import java.io.IOException; import java.util.ArrayList; @@ -29,9 +31,11 @@ import java.util.List; * * @author Michael Zucchi */ +@Persistent public class ConditionList { private final HashMap conditions = new HashMap<>(); + @NotPersistent private final List endedConditions = new ArrayList<>(); /* *************** diff --git a/DuskServer/src/duskz/server/entityz/Container.java b/DuskServer/src/duskz/server/entityz/Container.java index ddabc4d..ebc649a 100644 --- a/DuskServer/src/duskz/server/entityz/Container.java +++ b/DuskServer/src/duskz/server/entityz/Container.java @@ -31,8 +31,8 @@ public class Container extends Holdable { public Container(Game game) { super(game); } - int volumeLimit; - int weightLimit; + public int volumeLimit; + public int weightLimit; @Override public int getType() { diff --git a/DuskServer/src/duskz/server/entityz/Converter.java b/DuskServer/src/duskz/server/entityz/Converter.java index e367e40..182c7ca 100644 --- a/DuskServer/src/duskz/server/entityz/Converter.java +++ b/DuskServer/src/duskz/server/entityz/Converter.java @@ -485,7 +485,7 @@ public class Converter { BufferedWriter out = new BufferedWriter(new FileWriter(dst))) { String line; - item.name = src.getName(); + item.setName(src.getName()); while ((line = in.readLine()) != null) { line = line.trim(); @@ -503,7 +503,7 @@ public class Converter { out.append("type."); out.append(item.getClass().getSimpleName()); out.append("="); - out.append(item.name); + out.append(item.getName()); out.append('\n'); item.writeProperties(out); diff --git a/DuskServer/src/duskz/server/entityz/DBTest.java b/DuskServer/src/duskz/server/entityz/DBTest.java new file mode 100644 index 0000000..ce3f906 --- /dev/null +++ b/DuskServer/src/duskz/server/entityz/DBTest.java @@ -0,0 +1,134 @@ +/* + * This file is part of DuskZ, a graphical mud engine. + * + * Copyright (C) 2013 Michael Zucchi + * + * DuskZ is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * DuskZ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DuskZ; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package duskz.server.entityz; + +import com.sleepycat.je.DatabaseException; +import com.sleepycat.je.Environment; +import com.sleepycat.je.EnvironmentConfig; +import com.sleepycat.persist.EntityCursor; +import com.sleepycat.persist.EntityStore; +import com.sleepycat.persist.PrimaryIndex; +import com.sleepycat.persist.SecondaryIndex; +import com.sleepycat.persist.StoreConfig; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; + +/** + * + * @author Michael Zucchi + */ +public class DBTest { + + public static void main(String[] args) throws IOException { + new File("/tmp/foo").mkdirs(); + + EnvironmentConfig envConfig = new EnvironmentConfig(); + envConfig.setAllowCreate(true); + envConfig.setTransactional(true); + Environment env = new Environment(new File("/tmp/foo"), envConfig); + +// Open a transactional entity store. +// + StoreConfig storeConfig = new StoreConfig(); + storeConfig.setAllowCreate(true); + storeConfig.setTransactional(true); + + // Persistent read-only data like mobs? + EntityStore gstore = new EntityStore(env, "GameStore", storeConfig); + + storeConfig = new StoreConfig(); + storeConfig.setAllowCreate(true); + storeConfig.setTransactional(true); + + EntityStore store = new EntityStore(env, "LiveStore", storeConfig); + + PrimaryIndex playerByID = store.getPrimaryIndex(Long.class, Player.class); + SecondaryIndex playerByName = store.getSecondaryIndex(playerByID, String.class, "name"); + PrimaryIndex raceByID = store.getPrimaryIndex(Long.class, Race.class); + SecondaryIndex raceByName = store.getSecondaryIndex(raceByID, String.class, "name"); + + PrimaryIndex itemsByID = store.getPrimaryIndex(Long.class, Holdable.class); + + File g = new File("/home/notzed/dusk/game"); + + Game game = new Game(); + game.init(g); + + if (raceByName.get("human") == null) { + System.out.println("Create races\n"); + for (Race r : game.races.values()) { + r.ID = 0; + raceByID.put(r); + } + } + + if (playerByName.get("z") == null) { + Player p = new Player(); + p.game = game; + p.load(new File(g, "players/z")); + + p.race = raceByName.get(p.race.name); + p.raceid = p.race.ID; + + playerByID.put(p); + } + + // Load items + File items = new File(game.getRoot(), "defItems"); + for (String n : items.list()) { + try { + Holdable h = game.createItem(n); + System.out.printf("item %s = %s %d\n", n, h, h.ID); + } catch (Exception ex) { + System.out.printf("error with item %s: %s\n", n, ex); + } + } + + // Shops + for (GameShop s : game.gameShops.values()) { + System.out.println("game shop: " + s); + } + + PrimaryIndex signByID = store.getPrimaryIndex(Long.class, Sign.class); + for (Sign s : game.signs.values()) { + s.ID = 0; + try { + System.out.printf("writing %s %s\n", s.getName(), s.description); + signByID.put(s); + } catch (DatabaseException ex) { + System.out.println("error writing: " + ex); + } + } + + try (EntityCursor ec = signByID.entities()) { + Sign s; + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + while ((s = ec.next()) != null) { + s.writeState(bw); + } + bw.close(); + } + + store.sync(); + + } +} diff --git a/DuskServer/src/duskz/server/entityz/Equipment.java b/DuskServer/src/duskz/server/entityz/Equipment.java index 81986b5..4640e02 100644 --- a/DuskServer/src/duskz/server/entityz/Equipment.java +++ b/DuskServer/src/duskz/server/entityz/Equipment.java @@ -57,7 +57,7 @@ public class Equipment { for (int i = 0; i < worn.length; i++) { Wearable item = worn[i]; if (item != null) - sb.append(item.name).append('\n'); + sb.append(item.getName()).append('\n'); else sb.append("none\n"); } @@ -70,7 +70,7 @@ public class Equipment { for (int i = 0; i < worn.length; i++) { Wearable item = worn[i]; if (item != null) - msg.add(i, item.name); + msg.add(i, item.getName()); } return msg; @@ -84,7 +84,7 @@ public class Equipment { for (int i=0;i relations = new HashMap<>(); - private Game game; + @NotPersistent + volatile private Game game; private boolean changed = false; + public Faction() { + } + public Faction(String name, Game game) { this.name = name; this.game = game; @@ -115,10 +129,13 @@ public class Faction { if (game.isPreference(Game.PREF_AI)) { int delta = killer.getCP() - died.getCP(); - changed |= updateRelation(killer.name, delta); + changed |= updateRelation(killer.getName(), delta); - if (killer.clan != null && !killer.clan.equals("none")) { - changed |= updateRelation(killer.clan, delta); + if (killer instanceof Player) { + Player kp = (Player) killer; + if (kp.clan != null && !kp.clan.equals("none")) { + changed |= updateRelation(kp.clan, delta); + } } } } @@ -148,26 +165,27 @@ public class Faction { if (mob.onCanSeeActive(lt) && mob.canSee(lt.x, lt.y)) { if (o.getType() == Thing.TYPE_PLAYER) { + Player p = (Player) o; visiblePlayer = true; - double relation = getRelationValue(lt.name); - if (!(lt.clan == null || lt.clan.equals("none"))) { - relation = (relation + getRelationValue(lt.clan)) / 2; + double relation = getRelationValue(lt.getName()); + if (!(p.clan == null || p.clan.equals("none"))) { + relation = (relation + getRelationValue(p.clan)) / 2; } if (relation < 0 && (enemy == null || enemyrelation < relation)) { enemy = lt; enemyrelation = relation; } intConfidence += relation * lt.getTP(); - System.out.printf("mob '%s' can see player '%s' relation %f confidence=%d\n", mob.name, lt.name, relation, intConfidence); + System.out.printf("mob '%s' can see player '%s' relation %f confidence=%d\n", mob.getName(), lt.getName(), relation, intConfidence); System.out.printf(" player points total = %d armour %d damage %d cmponent %f\n", lt.getTP(), lt.getArmourMod(), lt.getDamageMod(), relation * lt.getTP()); } else { double relation; Mobile m = (Mobile) lt; - if (m.name.equals(mob.name)) { + if (m.getName().equals(mob.getName())) { relation = m.groupRelation; } else { - relation = getRelationValue(m.name); + relation = getRelationValue(m.getName()); } intConfidence += relation * m.getTP(); if (relation < 0 && (enemy == null || enemyrelation > relation)) { @@ -175,7 +193,7 @@ public class Faction { enemyrelation = relation; } intConfidence += relation * lt.getTP(); - System.out.printf("mob '%s' can see mob '%s' relation %f confidence=%d\n", mob.name, lt.name, relation, intConfidence); + System.out.printf("mob '%s' can see mob '%s' relation %f confidence=%d\n", mob.getName(), lt.getName(), relation, intConfidence); System.out.printf(" player points total = %d armour %d damage %d component %f\n", lt.getTP(), lt.getArmourMod(), lt.getDamageMod(), relation * lt.getTP()); } } @@ -196,7 +214,7 @@ public class Faction { } //Fight if (enemy.distanceL1(mob) <= mob.getRangeWithBonus()) { - System.out.println(mob.name + " close enough, going into battle distance: " + enemy.distanceL1(mob) + " range: " + mob.getRangeWithBonus()); + System.out.println(mob.getName() + " close enough, going into battle distance: " + enemy.distanceL1(mob) + " range: " + mob.getRangeWithBonus()); // close enough to attack, so stop moving mob.clearMoveQueue(); mob.createBattle(enemy); @@ -208,7 +226,7 @@ public class Faction { game.log.printError("runAI():" + mob.name + " had an error attacking " + enemy.name, e); }*/ } else { - System.out.println("Mob ai: move to enemy " + enemy.name + " " + enemy.x + "," + enemy.y); + System.out.println("Mob ai: move to enemy " + enemy.getName() + " " + enemy.x + "," + enemy.y); mob.travelTo(enemy.x, enemy.y, false); } } else { @@ -218,7 +236,7 @@ public class Faction { //Flee int destX = mob.x + Integer.signum(mob.x - enemy.x) * game.viewRange; int destY = mob.y + Integer.signum(mob.y - enemy.y) * game.viewRange; - System.out.println("Mob ai: flee from " + enemy.name + " " + destX + "," + destY); + System.out.println("Mob ai: flee from " + enemy.getName() + " " + destX + "," + destY); mob.travelTo(destX, destY, true); } } @@ -247,6 +265,7 @@ public class Faction { * * @author Tom Weingarten */ + @Persistent static class Relation { String name; diff --git a/DuskServer/src/duskz/server/entityz/Game.java b/DuskServer/src/duskz/server/entityz/Game.java index d7860aa..8f4dff3 100644 --- a/DuskServer/src/duskz/server/entityz/Game.java +++ b/DuskServer/src/duskz/server/entityz/Game.java @@ -243,7 +243,7 @@ public class Game { try { Mobile mob = new Mobile(this); mob.load(file); - allMobs.put(mob.name, mob); + allMobs.put(mob.getName(), mob); //log.printf(Log.VERBOSE, "Mob class: %s", mob.name); } catch (Exception ex) { log.printf(ex, "Loading mob %s failed", file.getName()); @@ -261,15 +261,15 @@ public class Game { // HACK: just copy to indices now for (Mobile m : mobs.values()) { - System.out.println("add mob " + m.name + " on " + m.map.name); + System.out.println("add mob " + m.getName() + " on " + m.map.name); addThing(m); } for (Sign s : signs.values()) { - System.out.println("add sign: " + s.name + " at " + s.x + ", " + s.y + " on map " + s.map.name); + System.out.println("add sign: " + s.getName() + " at " + s.x + ", " + s.y + " on map " + s.map.name); addThing(s); } for (Shop s : gameShops.values()) { - System.out.println("add shop: " + s.name + " at " + s.x + ", " + s.y + " on map " + s.map.name); + System.out.println("add shop: " + s.getName() + " at " + s.x + ", " + s.y + " on map " + s.map.name); addThing(s); } @@ -375,7 +375,7 @@ public class Game { switch (thing.getType()) { case Thing.TYPE_PLAYER: - players.remove(((Player) thing).name); + players.remove(((Player) thing).getName()); actives.remove(thing.ID); break; case Thing.TYPE_MOBILE: @@ -398,7 +398,7 @@ public class Game { switch (t.getType()) { case Thing.TYPE_PLAYER: { Player player = (Player) t; - players.put(player.name, player); + players.put(player.getName(), player); actives.put(player.ID, player); break; } @@ -641,7 +641,7 @@ public class Game { } public boolean haveOnItem(Holdable trigger, String what) { - return new File(onScriptDir, trigger.name + "." + what).exists(); + return new File(onScriptDir, trigger.getName() + "." + what).exists(); } /** @@ -652,14 +652,14 @@ public class Game { * @param what "get" or "drop", etc. */ public void onItem(Active owner, Holdable item, String what) { - runScript(onScriptDir, item.name + "." + what, + runScript(onScriptDir, item.getName() + "." + what, "game", this, "owner", owner, "item", item); } public boolean haveOnCondition(Holdable trigger, String what) { - return new File(onConditionDir, trigger.name + "." + what).exists(); + return new File(onConditionDir, trigger.getName() + "." + what).exists(); } /** @@ -816,16 +816,16 @@ public class Game { * @throws BlockedIPException */ void registerPlayer(Player player) { - logPasswordSuccess(player.name, player.getAddress()); + logPasswordSuccess(player.getName(), player.getAddress()); - Player old = players.get(player.name); + Player old = players.get(player.getName()); if (old != null) { old.chatMessage("Logged in again from: " + player.getAddress()); old.logout(); } //throw new UnsupportedOperationException("Not supported yet."); - players.put(player.name, player); + players.put(player.getName(), player); things.put(player.ID, player); actives.put(player.ID, player); player.map.addEntity(player); @@ -844,7 +844,7 @@ public class Game { void unregisterPlayer(Player player) { // TODO threading player.map.removeEntity(player); - players.remove(player.name); + players.remove(player.getName()); things.remove(player.ID); actives.remove(player.ID); } diff --git a/DuskServer/src/duskz/server/entityz/GameShop.java b/DuskServer/src/duskz/server/entityz/GameShop.java index fab7450..ffe35b2 100644 --- a/DuskServer/src/duskz/server/entityz/GameShop.java +++ b/DuskServer/src/duskz/server/entityz/GameShop.java @@ -49,15 +49,15 @@ public class GameShop extends Shop { @Override public void buy(Active buyer, String what, int quantity) { - Holdable h = items.get(what); + Held h = items.get(what); if (h == null) { - buyer.chatMessage(name + " doesn't sell those."); + buyer.chatMessage(getName() + " doesn't sell those."); return; } - if (h instanceof Training) { - Training t = (Training) h; - if (!buyer.addExp(-h.cost * quantity)) { + if (h.holdable instanceof Training) { + Training t = (Training) h.holdable; + if (!buyer.addExp(-t.cost * quantity)) { buyer.chatMessage("You can't afford that many."); } else { switch (t.skill) { @@ -91,19 +91,21 @@ public class GameShop extends Shop { break; default: buyer.chatMessage("BUG: I don't know how to train " + t.skill); - buyer.addExp(h.cost * quantity); + buyer.addExp(t.cost * quantity); break; } } } else { - if (buyer.getGold() < h.cost * quantity) { + if (buyer.getGold() < h.holdable.cost * quantity) { buyer.chatMessage("You can't afford that many."); } else { while (quantity > 0) { - Holdable s = game.createItem(what); - if (buyer.addGold(-h.cost)) { - buyer.addItem(s); + // FIXME: db stuff + + if (buyer.addGold(-h.holdable.cost)) { + Holdable s = game.createItem(what); + buyer.addItem(new Held(s)); } quantity -= 1; } @@ -112,13 +114,13 @@ public class GameShop extends Shop { } @Override - public void sell(Active customer, List items) { + public void sell(Active customer, List items) { // TODO: I really want to look up the item somewhere to see what // this shop will buy the items for ...? - for (Holdable h : items) { + for (Held h : items) { if (customer.removeItem(h)) { - customer.addGold(h.cost / 2); + customer.addGold(h.holdable.cost / 2); } } } diff --git a/DuskServer/src/duskz/server/entityz/Held.java b/DuskServer/src/duskz/server/entityz/Held.java new file mode 100644 index 0000000..abe95a7 --- /dev/null +++ b/DuskServer/src/duskz/server/entityz/Held.java @@ -0,0 +1,68 @@ +/* + * This file is part of DuskZ, a graphical mud engine. + * + * Copyright (C) 2013 Michael Zucchi + * + * DuskZ is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * DuskZ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DuskZ; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package duskz.server.entityz; + +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Persistent; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; +import duskz.protocol.Wearing; + +/** + * Volatile parts of a 'holdable' item. + * + * @author Michael Zucchi + */ +@Persistent +public class Held { + + @SecondaryKey(relate = Relationship.MANY_TO_ONE, relatedEntity = Holdable.class) + public long holdableID; + @NotPersistent + public Holdable holdable; + /** + * Where it is, Wearing constants + */ + public int where = Wearing.INVENTORY; + /** + * How many times it's been consumed + */ + public int used; + /** + * For weapons, wear and tear + */ + public long wear; + + public Held() { + } + + public Held(Holdable holdable) { + this.holdableID = holdable.ID; + this.holdable = holdable; + } + + public String getName() { + return holdable.getName(); + } + + public String getDescription() { + return holdable.description; + } +} diff --git a/DuskServer/src/duskz/server/entityz/Holdable.java b/DuskServer/src/duskz/server/entityz/Holdable.java index ddc6689..0f8c71a 100644 --- a/DuskServer/src/duskz/server/entityz/Holdable.java +++ b/DuskServer/src/duskz/server/entityz/Holdable.java @@ -20,6 +20,8 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Entity; +import duskz.protocol.Wearing; import java.io.BufferedWriter; import java.io.IOException; @@ -28,24 +30,63 @@ import java.io.IOException; * * @author Michael Zucchi */ -public abstract class Holdable extends Thing { +@Entity +public class Holdable extends Thing { - int cost; + // FIXME: these shouldn't be public + public int cost; //int image; - int volume; - int weight; - String onGet, onDrop; - int uses = -1; - String onUse; + public int volume; + public int weight; + public String onGet, onDrop, onUse; + public int uses = -1; + // new stuff + public int wearing = Wearing.INVENTORY; + /** + * TODO: move the readonly stuff into a different object + * then have two objects to wrap it, depending on context: + * + * Held when held + * MapItem when stored on a map + */ + public Holdable() { + } Holdable(Game game) { super(game); } - abstract public int getWearing(); + public int getWearing() { + return wearing; + } + + @Override + public int getType() { + switch (wearing) { + case Wearing.TRAINING: + return TYPE_TRAINING; + case Wearing.DRINK: + return TYPE_DRINK; + case Wearing.FOOD: + return TYPE_FOOD; + case Wearing.CONTAINER: + return TYPE_CONTAINER; + case Wearing.INVENTORY: + return TYPE_ITEM; + case Wearing.WIELD: + return TYPE_WEAPON; + default: + return TYPE_ARMOUR; + } + } public String getUnits() { - return "gp"; + switch (wearing) { + case Wearing.TRAINING: + return "exp"; + default: + return "gp"; + } } @Override @@ -84,7 +125,7 @@ public abstract class Holdable extends Thing { @Override protected void writeProperties(BufferedWriter out) throws IOException { - writeProperty(out, "name", name); + writeProperty(out, "name", getName()); writeProperty(out, "description", description); //writeProperty(out, "map", map.name); //writeProperty(out, "x", x); diff --git a/DuskServer/src/duskz/server/entityz/Inventory.java b/DuskServer/src/duskz/server/entityz/Inventory.java index 0e6c185..574203e 100644 --- a/DuskServer/src/duskz/server/entityz/Inventory.java +++ b/DuskServer/src/duskz/server/entityz/Inventory.java @@ -49,7 +49,7 @@ public class Inventory { int cost = (int) (h.cost * scale); - msg.add(h.getWearing(), h.name, 1, cost, h.getUnits()); + msg.add(h.getWearing(), h.getName(), 1, cost, h.getUnits()); } return msg; @@ -61,7 +61,7 @@ public class Inventory { else { // hack: shopping list for (Holdable h : items) { - viewer.chatMessage(String.format("%-20s %s", h.name, h.description)); + viewer.chatMessage(String.format("%-20s %s", h.getName(), h.description)); } } } @@ -73,7 +73,7 @@ public class Inventory { */ public Holdable get(String key) { for (Holdable h : items) { - if (key.equalsIgnoreCase(h.name)) + if (key.equalsIgnoreCase(h.getName())) return h; } return null; @@ -90,7 +90,7 @@ public class Inventory { public List getAll(String key, int maximum) { ArrayList list = new ArrayList<>(); for (Holdable h : items) { - if (h.name.equalsIgnoreCase(key)) { + if (h.getName().equalsIgnoreCase(key)) { list.add(h); if (list.size() >= maximum) break; diff --git a/DuskServer/src/duskz/server/entityz/Inventory2.java b/DuskServer/src/duskz/server/entityz/Inventory2.java new file mode 100644 index 0000000..88ab0ed --- /dev/null +++ b/DuskServer/src/duskz/server/entityz/Inventory2.java @@ -0,0 +1,227 @@ +/* + * This file is part of DuskZ, a graphical mud engine. + * + * Copyright (C) 2000 Tom Weingarten + * Copyright (C) 2013 Michael Zucchi + * + * DuskZ is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * DuskZ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DuskZ; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package duskz.server.entityz; + +import com.sleepycat.persist.model.Persistent; +import duskz.protocol.DuskMessage; +import duskz.protocol.ListMessage; +import duskz.protocol.TransactionMessage; +import duskz.protocol.Wearing; +import static duskz.protocol.Wearing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * A list of holdables. + * + * Original game had table by type, but that seems somewhat pointless overhead. + * + * This is a bit of a mis-mash right now just trying to get the code working + * + * + * @author Michael Zucchi + */ +@Persistent +public class Inventory2 { + + final private ArrayList items = new ArrayList<>(); + + public TransactionMessage createTransactionMessage(Game game, int name, float scale) { + TransactionMessage msg = new TransactionMessage(name); + + // TODO: count occurances here for player inventory? + + for (Held held : items) { + // FIXME: how to represent skills + + if (held.where == Wearing.INVENTORY) { + Holdable h = held.holdable; + int cost = (int) (h.cost * scale); + + msg.add(h.getWearing(), h.getName(), 1, cost, h.getUnits()); + } + } + + return msg; + } + + public DuskMessage createWearingMessage(Game game, int msgid) { + ListMessage msg = new ListMessage(msgid); + + for (Held h : items) { + if (h.where != Wearing.INVENTORY) { + msg.add(h.where, h.holdable.getName()); + } + } + + return msg; + } + + public void describeTo(Active viewer) { + if (items.isEmpty()) + viewer.chatMessage("Nothing at the moment."); + else { + // hack: shopping list + for (Held h : items) { + viewer.chatMessage(String.format("%-20s %s", h.holdable.getName(), h.holdable.description)); + } + } + } + + /** + * Return the first item of the given type + * + * @param key + * @return + */ + public Held get(String key) { + for (Held h : items) { + if (key.equalsIgnoreCase(h.holdable.getName())) + return h; + } + return null; + } + + public void add(Held h) { + items.add(h); + } + + public boolean remove(Held h) { + return items.remove(h); + } + + public List getAll(String key, int maximum) { + ArrayList list = new ArrayList<>(); + for (Held h : items) { + if (h.holdable.getName().equalsIgnoreCase(key)) { + list.add(h); + if (list.size() >= maximum) + break; + } + } + return list; + } + + public boolean contains(Held h) { + return items.contains(h); + } + + public boolean isWearing(String what) { + Held h = get(what); + + return h != null && h.where != Wearing.INVENTORY; + } + + public boolean wear(Held h) { + if (h.holdable.getWearing() == Wearing.INVENTORY) + return false; + + h.where = h.holdable.getWearing(); + return true; + } + + public boolean unwear(int wearing) { + for (Held h : items) { + if (h.where == wearing) { + h.where = Wearing.INVENTORY; + return true; + } + } + return false; + } + + public Held getWorn(int wearing) { + for (Held h : items) { + if (h.where == wearing) { + return h; + } + } + return null; + } + + public int armourCount() { + int count = 0; + for (Held h : items) { + if (h.where >= Wearing.ARMS && h.where <= Wearing.HANDS) + count++; + } + return count; + } + public static final float[] ARMOUR_MOD = { + 0f, 0.05f, 0.05f, 0.40f, 0.15f, 0.05f, 0.20f, 0.05f, 0.05f + }; + + public int armourMod() { + int mod = 0; + + for (Held h : items) { + if (h.where >= Wearing.ARMS && h.where <= Wearing.HANDS) + mod += ARMOUR_MOD[h.where] * ((Armour) h.holdable).mod; + } + return mod; + } + + /** + * Damage the specified item if it exists + * + * @param damage + * @return the weapon if it was destroyed + */ + public Held damageItem(int index, int damage) { + for (Held h : items) { + if (h.where == index) { + Wearable w = (Wearable) h.holdable; + + h.wear += damage; + if (w.durability != -1 && h.wear > w.durability) { + items.remove(h); + return h; + } + return null; + } + } + return null; + } + + public static int toIndex(String where) { + switch (where.toLowerCase()) { + case "wielded": + return WIELD; + case "arms": + return ARMS; + case "legs": + return LEGS; + case "torso": + return TORSO; + case "waist": + return WAIST; + case "neck": + return NECK; + case "skull": + return SKULL; + case "eyes": + return EYES; + case "hands": + return HANDS; + } + return Wearing.INVENTORY; + } +} diff --git a/DuskServer/src/duskz/server/entityz/Mobile.java b/DuskServer/src/duskz/server/entityz/Mobile.java index 1176024..b9e4011 100644 --- a/DuskServer/src/duskz/server/entityz/Mobile.java +++ b/DuskServer/src/duskz/server/entityz/Mobile.java @@ -109,7 +109,7 @@ public class Mobile extends Active { homeY = y; if (faction == null) //throw new IOException("Missing faction on " + name); - System.out.println("Missing faction on " + name); + System.out.println("Missing faction on " + getName()); /* setStat(STAT_HP, getHPMax()); setStat(STAT_MP, getMPMax()); @@ -157,7 +157,7 @@ public class Mobile extends Active { @Override public void chatMessage(Active from, String clan, String msg) { // don't care except for debugging? - System.out.println("mob: " + name + "=" + msg); + System.out.println("mob: " + getName() + "=" + msg); } @Override @@ -198,7 +198,7 @@ public class Mobile extends Active { // FIXME: Invoke "onBatte" if (range > getRangeWithBonus()) { - battle.chatMessage(name + " is out of range, moving closer. distance=" + range + " range=" + getRangeWithBonus() + " moveable=" + isMoveable()); + battle.chatMessage(getName() + " is out of range, moving closer. distance=" + range + " range=" + getRangeWithBonus() + " moveable=" + isMoveable()); travelTo(target.x, target.y, false); } else { clearMoveQueue(); @@ -208,7 +208,7 @@ public class Mobile extends Active { @Override public void killedBattle(Battle battle, Active winner, ArrayList opponents) { - chatMessage(this.name + " is killed."); + chatMessage(this.getName() + " is killed."); splitMoney(1, opponents); splitExp(0, opponents); @@ -236,8 +236,8 @@ public class Mobile extends Active { if (Math.random() < gi.probability) { Holdable h = game.createItem(gi.name); - winner.chatMessage("You got a " + h.name + "."); - winner.addItem(h); + winner.chatMessage("You got a " + h.getName() + "."); + winner.addItem(new Held(h)); } } } @@ -250,7 +250,7 @@ public class Mobile extends Active { @Override public void sayCommand(String text) { - localisedChat("Mob " + name + " says: " + text); + localisedChat("Mob " + getName() + " says: " + text); } void respawn() { diff --git a/DuskServer/src/duskz/server/entityz/Pack.java b/DuskServer/src/duskz/server/entityz/Pack.java index 7ed1720..601f6df 100644 --- a/DuskServer/src/duskz/server/entityz/Pack.java +++ b/DuskServer/src/duskz/server/entityz/Pack.java @@ -51,8 +51,10 @@ public class Pack { */ public boolean containsClanless() { for (Active a : members) { - if (a.clan.equals("none")) - return true; + if (a instanceof Player) { + if (((Player)a).isClanless()) + return true; + } } return false; } @@ -65,9 +67,9 @@ public class Pack { public void addFollower(Active follower) { if (!members.isEmpty()) { for (Active a : members) { - a.chatMessage("You are now being followed by " + follower.name + "."); + a.chatMessage("You are now being followed by " + follower.getName() + "."); } - follower.chatMessage("You are now following " + members.get(members.size() - 1).name + "."); + follower.chatMessage("You are now following " + members.get(members.size() - 1).getName() + "."); } members.add(follower); } @@ -113,9 +115,9 @@ public class Pack { members.remove(follower); for (Active a : members) { - a.chatMessage(follower.name + " is no longer following you."); + a.chatMessage(follower.getName() + " is no longer following you."); } - follower.chatMessage("You are no longer following " + leader.name); + follower.chatMessage("You are no longer following " + leader.getName()); } } } diff --git a/DuskServer/src/duskz/server/entityz/Pet.java b/DuskServer/src/duskz/server/entityz/Pet.java index ac262e0..798edbd 100644 --- a/DuskServer/src/duskz/server/entityz/Pet.java +++ b/DuskServer/src/duskz/server/entityz/Pet.java @@ -20,6 +20,10 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; import duskz.protocol.DuskMessage; import java.util.ArrayList; @@ -28,13 +32,20 @@ import java.util.ArrayList; * * @author Michael Zucchi */ +@Entity public class Pet extends Active { /** * The pet's master. */ + @SecondaryKey(relate = Relationship.ONE_TO_ONE, relatedEntity = Player.class) + long playerid; + @NotPersistent Player master; + public Pet() { + } + public Pet(Game game) { super(game); } @@ -78,7 +89,7 @@ public class Pet extends Active { void leaveCommand() { chatMessage("You cannot leave your master unless he unfollows you."); } - + @Override protected boolean followTo(Active leader, int oldx, int oldy) { @@ -100,7 +111,7 @@ public class Pet extends Active { @Override public void killedBattle(Battle battle, Active winner, ArrayList opponents) { - battle.chatMessage(name + " is wounded."); + battle.chatMessage(getName() + " is wounded."); chatMessage("You have been wounded."); splitMoney(game.goldLoseMod, opponents); splitExp(game.expLoseMod, opponents); @@ -109,6 +120,6 @@ public class Pet extends Active { @Override public void sayCommand(String text) { - localisedChat("Pet " + name + " says: " + text); + localisedChat("Pet " + getName() + " says: " + text); } } diff --git a/DuskServer/src/duskz/server/entityz/Player.java b/DuskServer/src/duskz/server/entityz/Player.java index 66d9bf2..745ef3e 100644 --- a/DuskServer/src/duskz/server/entityz/Player.java +++ b/DuskServer/src/duskz/server/entityz/Player.java @@ -20,6 +20,10 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; import duskz.protocol.DuskMessage; import duskz.protocol.DuskProtocol; import duskz.protocol.EntityUpdateMessage; @@ -36,19 +40,25 @@ import java.util.logging.Logger; * * @author Michael Zucchi */ +@Entity public class Player extends Active implements DuskProtocol { private HashSet ignore = new HashSet<>(); // This shoudln't be stored like this ... protected String password; /** - * Privilege level + * Player clan membership + * FIXME: db table */ - int privs; + String clan; /** * Players can have 1 pet */ - Pet pet; + @SecondaryKey(relate = Relationship.ONE_TO_ONE, relatedEntity = Pet.class) + Long petid = null; + + @NotPersistent +// Pet pet; /* * State tracking */ @@ -76,19 +86,26 @@ public class Player extends Active implements DuskProtocol { /** * Used to optimise network traffic */ - PlayerState state; + @NotPersistent + volatile PlayerState state; /** * Connection to client */ - private final PlayerConnection connection; + @NotPersistent + private volatile PlayerConnection connection; /** * Helper for commands */ - private final PlayerCommands commands; + @NotPersistent + private volatile PlayerCommands commands; /** * Helper for command line */ - private final Commands cmdline; + @NotPersistent + private volatile Commands cmdline; + + public Player() { + } public Player(Game game, PlayerConnection connection) { super(game); @@ -100,6 +117,15 @@ public class Player extends Active implements DuskProtocol { alive = connection != null; } + protected void setConnection(PlayerConnection connection) { + this.connection = connection; + } + + public Pet getPet() { + // lookup/activate pet if not done so + return null; + } + @Override public int getType() { return TYPE_PLAYER; @@ -171,10 +197,10 @@ public class Player extends Active implements DuskProtocol { } @Override - public void wearItem(Wearable w) { - super.wearItem(w); + public boolean wearItem(Held w) { + boolean res = super.wearItem(w); wornChanged(); - + return res; } @Override @@ -212,7 +238,7 @@ public class Player extends Active implements DuskProtocol { // sb.append(s); // sb.append('>'); //} - sb.append(this.name); + sb.append(this.getName()); en.entityName = sb.toString(); en.imageStep = (short) imageStep; @@ -226,6 +252,9 @@ public class Player extends Active implements DuskProtocol { case "password": password = value; break; + case "clan": + clan = value; + break; default: super.setProperty(name, value); } @@ -237,9 +266,11 @@ public class Player extends Active implements DuskProtocol { writeProperty(out, "password", password); super.writeProperties(out); - writeProperty(out, "privs", privs); + writeProperty(out, "clan", clan); + + Pet pet = getPet(); if (pet != null) - writeProperty(out, "pet", pet.name); + writeProperty(out, "pet", pet.getName()); } @@ -258,6 +289,10 @@ public class Player extends Active implements DuskProtocol { return clan == null || clan.equals("none"); } + public boolean inClan(String clan) { + return this.clan != null && this.clan.equals(clan); + } + /** * Whether the acti * FIXME: Who can have clans? if it's only players, fix Active to account for that. @@ -346,6 +381,8 @@ public class Player extends Active implements DuskProtocol { public void fleeBattle(Battle battle, ArrayList opponents) { super.fleeBattle(battle, opponents); + Pet pet = getPet(); + if (pet != null) { battle.removeParticipant(pet); pet.fleeBattle(battle, opponents); @@ -356,17 +393,19 @@ public class Player extends Active implements DuskProtocol { public void killedBattle(Battle battle, Active winner, ArrayList opponents) { clearFollow(); - battle.chatMessage(name + " is killed."); + battle.chatMessage(getName() + " is killed."); chatBattle("You have died."); splitMoney(game.goldLoseMod, opponents); splitExp(game.expLoseMod, opponents); endBattle(); - game.globalChat(null, null, name + " has been killed by " + winner.name); + game.globalChat(null, null, getName() + " has been killed by " + winner.getName()); // FIXME: on player death script game.onDeath(this, winner); + Pet pet = getPet(); + if (pet != null) { // how to pass this to battle? // list2.remove(front2.getFollowing()); @@ -387,7 +426,7 @@ public class Player extends Active implements DuskProtocol { } public void chatMessage(Active from, String clan, String msg) { - if (from != null && from.getType() == TYPE_PLAYER && ignore.contains(from.name)) + if (from != null && from.getType() == TYPE_PLAYER && ignore.contains(from.getName())) return; if (clan != null && !clan.equals(this.clan)) @@ -424,8 +463,8 @@ public class Player extends Active implements DuskProtocol { @Override public void gossipCommand(String text) { if (isVoiceAllowed()) { - String title = name; - if (privs > 2) { + String title = getName(); + if (getPrivs() > 2) { // && hasCondition("invis") // && hasCondition("invis2")) { title = "A god"; @@ -437,8 +476,8 @@ public class Player extends Active implements DuskProtocol { @Override public void sayCommand(String text) { if (isVoiceAllowed()) { - String title = name; - if (privs > 2) { + String title = getName(); + if (getPrivs() > 2) { // && hasCondition("invis") // && hasCondition("invis2")) { title = "A god"; @@ -468,6 +507,9 @@ public class Player extends Active implements DuskProtocol { @Override void leaveCommand() { boolean linkpet = false; + + Pet pet = getPet(); + if (pet != null) { // Not really happy with this design here if (pack.contains(pet)) { @@ -516,7 +558,7 @@ public class Player extends Active implements DuskProtocol { } void parseCommand(String cmd) { - System.out.println(name + ": parse command: " + cmd); + System.out.println(getName() + ": parse command: " + cmd); try { cmdline.execute(cmd); } catch (Exception ex) { @@ -527,14 +569,14 @@ public class Player extends Active implements DuskProtocol { } @Override - public void addItem(Holdable item) { + public void addItem(Held item) { super.addItem(item); inventoryChanged(); } @Override - public boolean removeItem(Holdable item) { + public boolean removeItem(Held item) { if (super.removeItem(item)) { inventoryChanged(); return true; diff --git a/DuskServer/src/duskz/server/entityz/PlayerConnection.java b/DuskServer/src/duskz/server/entityz/PlayerConnection.java index be959dc..f5f9779 100644 --- a/DuskServer/src/duskz/server/entityz/PlayerConnection.java +++ b/DuskServer/src/duskz/server/entityz/PlayerConnection.java @@ -313,8 +313,8 @@ public class PlayerConnection implements DuskProtocol { res.add(FIELD_AUTH_REASON, "Login ok."); player.send(res); - setName("Player thread: " + player.name); - sender.setName("Ouptut thread: " + player.name); + setName("Player thread: " + player.getName()); + sender.setName("Ouptut thread: " + player.getName()); // log successful connection, etc. // diff --git a/DuskServer/src/duskz/server/entityz/PlayerShop.java b/DuskServer/src/duskz/server/entityz/PlayerShop.java index 9238b60..49adb42 100644 --- a/DuskServer/src/duskz/server/entityz/PlayerShop.java +++ b/DuskServer/src/duskz/server/entityz/PlayerShop.java @@ -47,8 +47,8 @@ public class PlayerShop extends Shop { return TYPE_PLAYER_SHOP; } - private void buy(Active buyer, List all) { - for (Holdable h : all) { + private void buy(Active buyer, List all) { + for (Held h : all) { items.remove(h); buyer.addItem(h); } @@ -57,16 +57,16 @@ public class PlayerShop extends Shop { @Override public void buy(Active buyer, String what, int quantity) { - List all = items.getAll(what, quantity); + List all = items.getAll(what, quantity); if (all.isEmpty()) { - buyer.chatMessage(name + " doesn't have that for sale."); + buyer.chatMessage(getName() + " doesn't have that for sale."); } else if (all.size() < quantity) { - buyer.chatMessage(name + " doesn't have that many to sell."); + buyer.chatMessage(getName() + " doesn't have that many to sell."); } else if (buyer == owner) { buy(buyer, all); - } else if (buyer.addGold(-all.get(0).cost * quantity * 3 / 4)) { - gold += all.get(0).cost * quantity * 3 / 4; + } else if (buyer.addGold(-all.get(0).holdable.cost * quantity * 3 / 4)) { + gold += all.get(0).holdable.cost * quantity * 3 / 4; buy(buyer, all); } else { buyer.chatMessage("You can't afford that."); @@ -74,11 +74,11 @@ public class PlayerShop extends Shop { } @Override - public void sell(Active customer, List all) { + public void sell(Active customer, List all) { if (owner != customer) customer.chatMessage("You cannot sell to this shop."); else { - for (Holdable h : all) { + for (Held h : all) { items.add(h); customer.removeItem(h); } diff --git a/DuskServer/src/duskz/server/entityz/PlayerState.java b/DuskServer/src/duskz/server/entityz/PlayerState.java index ed0e04e..1f1764f 100644 --- a/DuskServer/src/duskz/server/entityz/PlayerState.java +++ b/DuskServer/src/duskz/server/entityz/PlayerState.java @@ -119,7 +119,7 @@ public class PlayerState implements DuskProtocol { updateMap(); updateCheckShop(); } else if (overShop != null && overShop.inventoryChanged >= lastUpdate) { - player.send(overShop.createTransactionMessage(MSG_UPDATE_MERCHANT)); + player.send(overShop.createTransactionMessage(player.game, MSG_UPDATE_MERCHANT)); } if (actions >= lastUpdate) @@ -178,7 +178,7 @@ public class PlayerState implements DuskProtocol { if (thing != null) { overShop = thing; - player.send(overShop.createTransactionMessage(MSG_UPDATE_MERCHANT)); + player.send(overShop.createTransactionMessage(player.game, MSG_UPDATE_MERCHANT)); } else if (overShop != null) { player.send(DuskMessage.create(MSG_EXIT_MERCHANT)); overShop = null; @@ -201,12 +201,12 @@ public class PlayerState implements DuskProtocol { } void updateWorn() { - player.send(player.wornItems.toMessage(MSG_EQUIPMENT)); + player.send(player.inventory.createWearingMessage(player.game, MSG_EQUIPMENT)); } void updateInventory() { // FIXME: make player item sale price ratio adjustable - player.send(player.inventory.createTransactionMessage(MSG_INVENTORY, 0.5f)); + player.send(player.inventory.createTransactionMessage(player.game, MSG_INVENTORY, 0.5f)); } void updateConditions() { @@ -309,7 +309,7 @@ public class PlayerState implements DuskProtocol { }*/ if (dx != 0 || dy != 0) { - System.out.println("Thing " + thing.name + " moved: " + dx + ", " + dy); + System.out.println("Thing " + thing.getName() + " moved: " + dx + ", " + dy); // TODO: rather than relative move, send the specific location/faceing direction? diff --git a/DuskServer/src/duskz/server/entityz/Race.java b/DuskServer/src/duskz/server/entityz/Race.java index e4984ef..e409e81 100644 --- a/DuskServer/src/duskz/server/entityz/Race.java +++ b/DuskServer/src/duskz/server/entityz/Race.java @@ -20,6 +20,10 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; import static duskz.server.entityz.Active.STAT_CON; import static duskz.server.entityz.Active.STAT_DEX; import static duskz.server.entityz.Active.STAT_HP; @@ -32,6 +36,7 @@ import static duskz.server.entityz.Active.STAT_WIS; import duskz.server.entityz.PropertyLoader.PropertyEntry; import java.io.File; import java.io.IOException; +import java.util.HashMap; /** * Meta-data about race @@ -40,14 +45,48 @@ import java.io.IOException; * * @author Michael Zucchi */ +@Entity(version = 2) public class Race { + @PrimaryKey(sequence = "RaceID") + long ID; + @SecondaryKey(relate = Relationship.ONE_TO_ONE) public String name; + public String description; public int image; // Uses STAT_* constants from Active public int stats[] = new int[12]; + Inventory2 inventory = new Inventory2(); + ConditionList conditionList = new ConditionList(); + private HashMap skills = new HashMap<>(); + public String onBattle; + public String onDefeated; + + public Race() { + } + + public void addSkill(String name, int level) { + Ability a = skills.get(name); + + if (a != null) { + level += a.getLevel(); + } + skills.put(name, new Ability(name, level)); + } - Race() { + public void setCondition(String name, int duration) { + conditionList.setCondition(new Condition(name, duration)); + } + + public void addInventory(Holdable what, long wear, int used, boolean don) { + Held h = new Held(what); + + h.wear = wear; + h.used = used; + + inventory.add(h); + if (don) + inventory.wear(h); } boolean setProperty(String name, String value) { @@ -96,11 +135,11 @@ public class Race { r.name = file.getName(); try (PropertyLoader pl = new PropertyLoader(file)) { - for (PropertyEntry pe: pl) { + for (PropertyEntry pe : pl) { r.setProperty(pe.name, pe.value); } } - + return r; } } diff --git a/DuskServer/src/duskz/server/entityz/Shop.java b/DuskServer/src/duskz/server/entityz/Shop.java index 8eff71a..9b55a73 100644 --- a/DuskServer/src/duskz/server/entityz/Shop.java +++ b/DuskServer/src/duskz/server/entityz/Shop.java @@ -30,7 +30,7 @@ import java.util.List; */ public abstract class Shop extends Thing { - Inventory items = new Inventory(); + Inventory2 items = new Inventory2(); /** * Tick of last inventory change. */ @@ -46,10 +46,10 @@ public abstract class Shop extends Thing { case "item": Holdable h = game.createItem(value); if (h != null) { - System.out.println(this.name + " sells " + h.name); - items.add(h); + System.out.println(this.getName() + " sells " + h.getName()); + items.add(new Held(h)); } else - game.log.printf(Log.ERROR, "Shop: %s, unkown item: %s", this.name, value); + game.log.printf(Log.ERROR, "Shop: %s, unkown item: %s", this.getName(), value); break; default: super.setProperty(name, value); @@ -62,16 +62,16 @@ public abstract class Shop extends Thing { * @param name * @return */ - public TransactionMessage createTransactionMessage(int name) { - return items.createTransactionMessage(name, 1); + public TransactionMessage createTransactionMessage(Game game, int name) { + return items.createTransactionMessage(game, name, 1); } @Override public void look(Active viewer) { if (description != null) - viewer.chatMessage("You see " + name + ", " + description); + viewer.chatMessage("You see " + getName() + ", " + description); else - viewer.chatMessage("You see " + name); + viewer.chatMessage("You see " + getName()); viewer.chatMessage("Currently for sale:"); items.describeTo(viewer); @@ -129,5 +129,5 @@ public abstract class Shop extends Thing { abstract public void buy(Active buyer, String what, int quantity); - abstract public void sell(Active customer, List items); + abstract public void sell(Active customer, List items); } diff --git a/DuskServer/src/duskz/server/entityz/Sign.java b/DuskServer/src/duskz/server/entityz/Sign.java index d8bc925..8ef44ca 100644 --- a/DuskServer/src/duskz/server/entityz/Sign.java +++ b/DuskServer/src/duskz/server/entityz/Sign.java @@ -20,6 +20,7 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Entity; import java.io.BufferedWriter; import java.io.IOException; @@ -28,8 +29,12 @@ import java.io.IOException; * * @author Michael Zucchi */ +@Entity(version = 0) class Sign extends Thing { + public Sign() { + } + public Sign(Game game) { super(game); } diff --git a/DuskServer/src/duskz/server/entityz/Thing.java b/DuskServer/src/duskz/server/entityz/Thing.java index 0a891af..1f8db8b 100644 --- a/DuskServer/src/duskz/server/entityz/Thing.java +++ b/DuskServer/src/duskz/server/entityz/Thing.java @@ -20,6 +20,11 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Persistent; +import com.sleepycat.persist.model.PrimaryKey; +import com.sleepycat.persist.model.Relationship; +import com.sleepycat.persist.model.SecondaryKey; import duskz.protocol.DuskMessage; import duskz.protocol.EntityUpdateMessage; import duskz.server.entityz.PropertyLoader.PropertyEntry; @@ -39,6 +44,7 @@ import java.util.Comparator; * * @author Michael Zucchi */ +@Persistent public abstract class Thing implements Cloneable { /** @@ -62,18 +68,21 @@ public abstract class Thing implements Cloneable { public final static Comparator cmpName = new Comparator() { @Override public int compare(Thing o1, Thing o2) { - return o1.name.compareTo(o2.name); + return o1.getName().compareTo(o2.getName()); } }; - protected final Game game; + transient protected Game game; /** * Game unique id */ - public final long ID; + @PrimaryKey(sequence = "ID") + public long ID; /** * Name + * FIXME: this wont work for mobs will it? */ - public String name; + @SecondaryKey(relate = Relationship.ONE_TO_ONE) + private String name; /** * Description */ @@ -85,6 +94,7 @@ public abstract class Thing implements Cloneable { * /** * Map object belongs to */ + @NotPersistent public TileMap map; /** * Location on map @@ -93,7 +103,7 @@ public abstract class Thing implements Cloneable { /** * Current image id. TODO: players get images from race instead. */ - protected int image; + public int image; // static long nextid = 1; static Integer idlock = new Integer(0); @@ -109,6 +119,13 @@ public abstract class Thing implements Cloneable { } } + protected Thing() { + } + + protected void setGame(Game game) { + this.game = game; + } + public Thing(Game game) { this.ID = createID(); this.game = game; @@ -164,7 +181,7 @@ public abstract class Thing implements Cloneable { en.name = name; en.id = ID; - en.entityName = this.name; + en.entityName = this.getName(); en.entityType = (byte) getType(); en.x = (short) x; en.y = (short) y; @@ -183,7 +200,7 @@ public abstract class Thing implements Cloneable { void setProperty(String name, String value) { switch (name) { case "name": - this.name = value; + this.setName(value); break; case "description": this.description = value; @@ -235,7 +252,7 @@ public abstract class Thing implements Cloneable { * @throws IOException */ protected void writeProperties(BufferedWriter out) throws IOException { - writeProperty(out, "name", name); + writeProperty(out, "name", getName()); writeProperty(out, "description", description); writeProperty(out, "map", map.name); writeProperty(out, "x", x); @@ -256,7 +273,7 @@ public abstract class Thing implements Cloneable { * @throws IOException */ void writeState(BufferedWriter out) throws IOException { - writeProperty(out, "name", name); + writeProperty(out, "name", getName()); writeProperty(out, "x", x); writeProperty(out, "y", y); } @@ -265,7 +282,7 @@ public abstract class Thing implements Cloneable { out.append("type."); out.append(getClass().getSimpleName()); out.append('='); - out.append(name); + out.append(getName()); out.append('\n'); } @@ -297,6 +314,20 @@ public abstract class Thing implements Cloneable { } } + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + public interface ThingResolver { Thing resolve(Game game, String klass, String name); @@ -321,7 +352,7 @@ public abstract class Thing implements Cloneable { Thing thing = null; try { thing = createThing(game, klass); - thing.name = name; + thing.setName(name); thing.load(new File(base, name)); } catch (ClassNotFoundException | IOException ex) { System.out.println("Cannot load prototype: " + ex); @@ -344,7 +375,7 @@ public abstract class Thing implements Cloneable { Thing thing = null; try { thing = createThing(game, klass); - thing.name = name; + thing.setName(name); } catch (ClassNotFoundException ex) { System.out.println("Cannot load prototype: " + ex); } diff --git a/DuskServer/src/duskz/server/entityz/ThingTable.java b/DuskServer/src/duskz/server/entityz/ThingTable.java index b0e5b52..96196ec 100644 --- a/DuskServer/src/duskz/server/entityz/ThingTable.java +++ b/DuskServer/src/duskz/server/entityz/ThingTable.java @@ -75,7 +75,7 @@ public class ThingTable { add(thing); } } catch (IOException ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } } @@ -96,21 +96,21 @@ public class ThingTable { } public void add(T thing) { - HashSet set = byName.get(thing.name); + HashSet set = byName.get(thing.getName()); if (set == null) { set = new HashSet<>(); - byName.put(thing.name, set); + byName.put(thing.getName(), set); } set.add(thing); byID.put(thing.ID, thing); } public void remove(T thing) { - HashSet set = byName.get(thing.name); + HashSet set = byName.get(thing.getName()); set.remove(thing); if (set.isEmpty()) - byName.remove(thing.name); + byName.remove(thing.getName()); byID.remove(thing.ID); } diff --git a/DuskServer/src/duskz/server/entityz/TileMap.java b/DuskServer/src/duskz/server/entityz/TileMap.java index 7f55cdb..dbbd069 100644 --- a/DuskServer/src/duskz/server/entityz/TileMap.java +++ b/DuskServer/src/duskz/server/entityz/TileMap.java @@ -29,6 +29,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.HashMap; @@ -191,6 +192,65 @@ public class TileMap implements Iterable { // TODO: gzip? public static final int MAGIC_LAYERED = 0x6d61707a; + /** + * Load just the map part of a map. + * + * TODO: sort something out with the alias stuff and loadLayered() + * + * @param is + * @param name + * @return + * @throws IOException + */ + public static TileMap loadLayeredMap(InputStream is, String name) throws IOException { + TileMap map; + + try (DataInputStream mapFile = new DataInputStream((is))) { + int magic = mapFile.readInt(); + int version = mapFile.readInt(); + int flags = mapFile.readInt(); + int cols = mapFile.readInt(); + int rows = mapFile.readInt(); + int groundLayer = mapFile.readInt(); + int layerCount = mapFile.readInt(); + + if (magic != MAGIC_LAYERED + || version != 0) { + throw new IOException("Invalid format/magic/unknown version"); + } + + System.out.println("Load map: " + name); + System.out.printf(" size: %dx%d\n", cols, rows); + System.out.printf(" groundLayer: %d\n", groundLayer); + System.out.printf(" layerCount: %d\n", layerCount); + + map = new TileMap(name, cols, rows); + + map.groundLayer = groundLayer; + map.layers = new TileLayer[layerCount]; + for (int l = 0; l < layerCount; l++) { + int tx = mapFile.readInt(); + int ty = mapFile.readInt(); + int twidth = mapFile.readInt(); + int theight = mapFile.readInt(); + TileLayer tl; + + System.out.printf(" layer %2d: at %3d,%3d size %3dx%3d\n", l, tx, ty, twidth, theight); + if (l == groundLayer) + tl = new TileLayer(tx, ty, twidth, theight, map.tiles); + else + tl = new TileLayer(tx, ty, twidth, theight); + + map.layers[l] = tl; + + for (int i = 0; i < twidth * theight; i++) { + tl.tiles[i] = mapFile.readShort(); + } + } + } + return map; + } + /** * Load a layered map. Format is: * magic: int diff --git a/DuskServer/src/duskz/server/entityz/Training.java b/DuskServer/src/duskz/server/entityz/Training.java index acd3416..3344909 100644 --- a/DuskServer/src/duskz/server/entityz/Training.java +++ b/DuskServer/src/duskz/server/entityz/Training.java @@ -40,6 +40,10 @@ public class Training extends Holdable { public String getUnits() { return "exp"; } + + public void setSkill(String skill) { + this.skill = skill; + } @Override void setProperty(String name, String value) { diff --git a/DuskServer/src/duskz/server/entityz/VariableList.java b/DuskServer/src/duskz/server/entityz/VariableList.java index 0d4aa29..75fa621 100644 --- a/DuskServer/src/duskz/server/entityz/VariableList.java +++ b/DuskServer/src/duskz/server/entityz/VariableList.java @@ -20,6 +20,7 @@ */ package duskz.server.entityz; +import com.sleepycat.persist.model.Persistent; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; @@ -31,6 +32,7 @@ import java.util.Map.Entry; * * @author Michael Zucchi */ +@Persistent public class VariableList { private HashMap map = new HashMap<>(); diff --git a/DuskServer/src/duskz/server/entityz/Weapon.java b/DuskServer/src/duskz/server/entityz/Weapon.java index 964c58a..aebf3b4 100644 --- a/DuskServer/src/duskz/server/entityz/Weapon.java +++ b/DuskServer/src/duskz/server/entityz/Weapon.java @@ -32,7 +32,7 @@ import java.io.IOException; */ public class Weapon extends Wearable { - int range = 1; + public int range = 1; public Weapon(Game game) { super(game); diff --git a/DuskServer/src/duskz/server/entityz/Wearable.java b/DuskServer/src/duskz/server/entityz/Wearable.java index 97d535b..efad839 100644 --- a/DuskServer/src/duskz/server/entityz/Wearable.java +++ b/DuskServer/src/duskz/server/entityz/Wearable.java @@ -30,9 +30,9 @@ import java.io.IOException; */ public abstract class Wearable extends Holdable { - int mod; - long durability; - String onWear, onUnwear; + public int mod; + public long durability; + public String onWear, onUnwear; Wearable(Game game) { super(game); -- 2.39.2