checkpoint db work. dbio origin/trunk
authornotzed <notzed@b8b59bfb-1aa4-4687-8f88-a62eeb14c21e>
Sat, 22 Feb 2014 01:23:56 +0000 (01:23 +0000)
committernotzed <notzed@b8b59bfb-1aa4-4687-8f88-a62eeb14c21e>
Sat, 22 Feb 2014 01:23:56 +0000 (01:23 +0000)
git-svn-id: file:///home/notzed/svn/duskz/trunk@23 b8b59bfb-1aa4-4687-8f88-a62eeb14c21e

33 files changed:
DuskServer/src/duskz/server/entityz/Ability.java
DuskServer/src/duskz/server/entityz/Active.java
DuskServer/src/duskz/server/entityz/Battle.java
DuskServer/src/duskz/server/entityz/Condition.java
DuskServer/src/duskz/server/entityz/ConditionList.java
DuskServer/src/duskz/server/entityz/Container.java
DuskServer/src/duskz/server/entityz/Converter.java
DuskServer/src/duskz/server/entityz/DBTest.java [new file with mode: 0644]
DuskServer/src/duskz/server/entityz/Equipment.java
DuskServer/src/duskz/server/entityz/Faction.java
DuskServer/src/duskz/server/entityz/Game.java
DuskServer/src/duskz/server/entityz/GameShop.java
DuskServer/src/duskz/server/entityz/Held.java [new file with mode: 0644]
DuskServer/src/duskz/server/entityz/Holdable.java
DuskServer/src/duskz/server/entityz/Inventory.java
DuskServer/src/duskz/server/entityz/Inventory2.java [new file with mode: 0644]
DuskServer/src/duskz/server/entityz/Mobile.java
DuskServer/src/duskz/server/entityz/Pack.java
DuskServer/src/duskz/server/entityz/Pet.java
DuskServer/src/duskz/server/entityz/Player.java
DuskServer/src/duskz/server/entityz/PlayerConnection.java
DuskServer/src/duskz/server/entityz/PlayerShop.java
DuskServer/src/duskz/server/entityz/PlayerState.java
DuskServer/src/duskz/server/entityz/Race.java
DuskServer/src/duskz/server/entityz/Shop.java
DuskServer/src/duskz/server/entityz/Sign.java
DuskServer/src/duskz/server/entityz/Thing.java
DuskServer/src/duskz/server/entityz/ThingTable.java
DuskServer/src/duskz/server/entityz/TileMap.java
DuskServer/src/duskz/server/entityz/Training.java
DuskServer/src/duskz/server/entityz/VariableList.java
DuskServer/src/duskz/server/entityz/Weapon.java
DuskServer/src/duskz/server/entityz/Wearable.java

index 3b70c3e..ec3b729 100644 (file)
  */
 package duskz.server.entityz;
 
+import com.sleepycat.persist.model.Persistent;
+
 /**
  *
  * @author Michael Zucchi <notzed@gmail.com>
  */
+@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;
        }
index e3e8af1..edb26f5 100644 (file)
 // 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 <notzed@gmail.com>
  */
+@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<String, Ability> 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<String> moveQueue = new LinkedList<>();
        /**
         * Pending commands, this is only used during battle
         */
+       @NotPersistent
        final private LinkedList<String[]> 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<Holdable> getAllItems(String name) {
+       public List<Held> 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);
        }
 }
index 1637f06..c2f0ff7 100644 (file)
@@ -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);
index 55bd81b..dddfc7b 100644 (file)
@@ -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 <notzed@gmail.com>
  */
+@Persistent
 public class Condition {
 
        /**
index 2ed0916..39dd2cd 100644 (file)
@@ -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 <notzed@gmail.com>
  */
+@Persistent
 public class ConditionList {
 
        private final HashMap<String, Condition> conditions = new HashMap<>();
+       @NotPersistent
        private final List<Condition> endedConditions = new ArrayList<>();
 
        /* ***************
index ddabc4d..ebc649a 100644 (file)
@@ -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() {
index e367e40..182c7ca 100644 (file)
@@ -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 (file)
index 0000000..ce3f906
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * 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 <notzed@gmail.com>
+ */
+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<Long, Player> playerByID = store.getPrimaryIndex(Long.class, Player.class);
+               SecondaryIndex<String, Long, Player> playerByName = store.getSecondaryIndex(playerByID, String.class, "name");
+               PrimaryIndex<Long, Race> raceByID = store.getPrimaryIndex(Long.class, Race.class);
+               SecondaryIndex<String, Long, Race> raceByName = store.getSecondaryIndex(raceByID, String.class, "name");
+
+               PrimaryIndex<Long, Holdable> 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<Long, Sign> 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<Sign> 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();
+
+       }
+}
index 81986b5..4640e02 100644 (file)
@@ -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<worn.length;i++) {
                        Wearable item = worn[i];
                        
-                       if (item != null && what.equalsIgnoreCase(item.name))
+                       if (item != null && what.equalsIgnoreCase(item.getName()))
                                return i;
                }
                return -1;
@@ -92,7 +92,7 @@ public class Equipment {
 
        public boolean isWearing(String what) {
                for (Wearable item : worn) {
-                       if (item != null && what.equalsIgnoreCase(item.name))
+                       if (item != null && what.equalsIgnoreCase(item.getName()))
                                return true;
                }
                return false;
@@ -109,7 +109,7 @@ public class Equipment {
                if (item != null) {
                        if (item.getWearing() != where) {
                                // FIXME: cachable exception?
-                               throw new RuntimeException("can't wear an item " + item.name
+                               throw new RuntimeException("can't wear an item " + item.getName()
                                                + " type " + item.getClass().getSimpleName()
                                                + " at " + Wearing.wornNames[where]
                                                + " should be " + Wearing.wornNames[item.getWearing()]);
@@ -144,7 +144,7 @@ public class Equipment {
                for (int i = 0; i < worn.length; i++) {
                        Wearable item = worn[i];
 
-                       if (item != null && name.equalsIgnoreCase(item.name)) {
+                       if (item != null && name.equalsIgnoreCase(item.getName())) {
                                worn[i] = null;
                                return item;
                        }
index e00a56c..0198dc4 100644 (file)
  */
 package duskz.server.entityz;
 
+import com.sleepycat.persist.model.Entity;
+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 java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -40,17 +46,25 @@ import java.util.HashMap;
 /**
  * Faction is a group of mobs. TODO: should it override/merge the normal group thing
  */
+@Entity
 public class Faction {
 
-       final public String name;
+       @PrimaryKey(sequence = "FactionID")
+       public long ID;
+       @SecondaryKey(relate = Relationship.ONE_TO_ONE)
+       public String name;
        /**
         * This is keyed on both player names and clans. Seems it should be two
         * separate tables
         */
        private final HashMap<String, Relation> 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;
index d7860aa..8f4dff3 100644 (file)
@@ -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);
        }
index fab7450..ffe35b2 100644 (file)
@@ -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<Holdable> items) {
+       public void sell(Active customer, List<Held> 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 (file)
index 0000000..abe95a7
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * 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 <notzed@gmail.com>
+ */
+@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;
+       }
+}
index ddc6689..0f8c71a 100644 (file)
@@ -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 <notzed@gmail.com>
  */
-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);
index 0e6c185..574203e 100644 (file)
@@ -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<Holdable> getAll(String key, int maximum) {
                ArrayList<Holdable> 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 (file)
index 0000000..88ab0ed
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * This file is part of DuskZ, a graphical mud engine.
+ *
+ * Copyright (C) 2000 Tom Weingarten <captaint@home.com>
+ * Copyright (C) 2013 Michael Zucchi <notzed@gmail.com>
+ *
+ * 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 <notzed@gmail.com>
+ */
+@Persistent
+public class Inventory2 {
+
+       final private ArrayList<Held> 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<Held> getAll(String key, int maximum) {
+               ArrayList<Held> 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;
+       }
+}
index 1176024..b9e4011 100644 (file)
@@ -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<Active> 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() {
index 7ed1720..601f6df 100644 (file)
@@ -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());
                }
        }
 }
index ac262e0..798edbd 100644 (file)
  */
 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 <notzed@gmail.com>
  */
+@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<Active> 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);
        }
 }
index 66d9bf2..745ef3e 100644 (file)
  */
 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 <notzed@gmail.com>
  */
+@Entity
 public class Player extends Active implements DuskProtocol {
 
        private HashSet<String> 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<Active> 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<Active> 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;
index be959dc..f5f9779 100644 (file)
@@ -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.
                                //
index 9238b60..49adb42 100644 (file)
@@ -47,8 +47,8 @@ public class PlayerShop extends Shop {
                return TYPE_PLAYER_SHOP;
        }
 
-       private void buy(Active buyer, List<Holdable> all) {
-               for (Holdable h : all) {
+       private void buy(Active buyer, List<Held> 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<Holdable> all = items.getAll(what, quantity);
+               List<Held> 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<Holdable> all) {
+       public void sell(Active customer, List<Held> 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);
                        }
index ed0e04e..1f1764f 100644 (file)
@@ -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?
 
index e4984ef..e409e81 100644 (file)
  */
 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 <notzed@gmail.com>
  */
+@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<String, Ability> 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;
        }
 }
index 8eff71a..9b55a73 100644 (file)
@@ -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<Holdable> items);
+       abstract public void sell(Active customer, List<Held> items);
 }
index d8bc925..8ef44ca 100644 (file)
@@ -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 <notzed@gmail.com>
  */
+@Entity(version = 0)
 class Sign extends Thing {
 
+       public Sign() {
+       }
+       
        public Sign(Game game) {
                super(game);
        }
index 0a891af..1f8db8b 100644 (file)
  */
 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 <notzed@gmail.com>
  */
+@Persistent
 public abstract class Thing implements Cloneable {
 
        /**
@@ -62,18 +68,21 @@ public abstract class Thing implements Cloneable {
        public final static Comparator<Thing> cmpName = new Comparator<Thing>() {
                @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);
                        }
index b0e5b52..96196ec 100644 (file)
@@ -75,7 +75,7 @@ public class ThingTable<T extends Thing> {
                                add(thing);
                        }
                } catch (IOException ex) {
-                       ex.printStackTrace();
+                       ex.printStackTrace(System.out);
                }
        }
 
@@ -96,21 +96,21 @@ public class ThingTable<T extends Thing> {
        }
        
        public void add(T thing) {
-               HashSet<T> set = byName.get(thing.name);
+               HashSet<T> 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<T> set = byName.get(thing.name);
+               HashSet<T> set = byName.get(thing.getName());
 
                set.remove(thing);
                if (set.isEmpty())
-                       byName.remove(thing.name);
+                       byName.remove(thing.getName());
 
                byID.remove(thing.ID);
        }
index 7f55cdb..dbbd069 100644 (file)
@@ -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<TileMap.MapData> {
        // 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
index acd3416..3344909 100644 (file)
@@ -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) {
index 0d4aa29..75fa621 100644 (file)
@@ -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 <notzed@gmail.com>
  */
+@Persistent
 public class VariableList {
 
        private HashMap<String, Object> map = new HashMap<>();
index 964c58a..aebf3b4 100644 (file)
@@ -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);
index 97d535b..efad839 100644 (file)
@@ -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);